diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ebfd037c5c..86785737b11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1555,6 +1555,9 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") # add_check_c_compiler_flag(C_WARNINGS C_WARN_UNUSED_MACROS -Wunused-macros) # add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_UNUSED_MACROS -Wunused-macros) + add_check_c_compiler_flag(C_WARNINGS C_WARN_ERROR_UNGUARDED_AVAILABILITY_NEW -Werror=unguarded-availability-new) + add_check_c_compiler_flag(CXX_WARNINGS CXX_WARN_ERROR_UNGUARDED_AVAILABILITY_NEW -Werror=unguarded-availability-new) + # --------------------- # Suppress Strict Flags diff --git a/build_files/utils/make_update.py b/build_files/utils/make_update.py index e2f6973ad91..f4c16ead87a 100755 --- a/build_files/utils/make_update.py +++ b/build_files/utils/make_update.py @@ -322,6 +322,11 @@ def external_script_initialize_if_needed(args: argparse.Namespace, blender_url = make_utils.git_get_remote_url(args.git_command, origin_name) external_url = resolve_external_url(blender_url, repo_name) + # When running `make update` from a freshly cloned fork check whether the fork of the submodule is + # available, If not, switch to the submodule relative to the main blender repository. + if origin_name == "origin" and not make_utils.git_is_remote_repository(args.git_command, external_url): + external_url = resolve_external_url("https://projects.blender.org/blender/blender", repo_name) + call((args.git_command, "clone", "--origin", origin_name, external_url, str(external_dir))) diff --git a/build_files/windows/check_submodules.cmd b/build_files/windows/check_submodules.cmd deleted file mode 100644 index 9138870f838..00000000000 --- a/build_files/windows/check_submodules.cmd +++ /dev/null @@ -1,20 +0,0 @@ -if NOT exist "%BLENDER_DIR%\source\tools\.git" ( - echo Checking out sub-modules - if not "%GIT%" == "" ( - "%GIT%" submodule update --init --recursive --progress - if errorlevel 1 goto FAIL - "%GIT%" submodule foreach git checkout main - if errorlevel 1 goto FAIL - "%GIT%" submodule foreach git pull --rebase origin main - if errorlevel 1 goto FAIL - goto EOF - ) else ( - echo Blender submodules not found, and git not found in path to retrieve them. - goto FAIL - ) -) -goto EOF - -:FAIL -exit /b 1 -:EOF \ No newline at end of file diff --git a/build_files/windows/format.cmd b/build_files/windows/format.cmd index 95440cb1818..c68286738ab 100644 --- a/build_files/windows/format.cmd +++ b/build_files/windows/format.cmd @@ -14,7 +14,7 @@ if NOT EXIST %PYTHON% ( exit /b 1 ) -set FORMAT_PATHS=%BLENDER_DIR%\source\tools\utils_maintenance\clang_format_paths.py +set FORMAT_PATHS=%BLENDER_DIR%\tools\utils_maintenance\clang_format_paths.py REM The formatting script expects clang-format to be in the current PATH. set PATH=%CF_PATH%;%PATH% diff --git a/intern/cycles/app/opengl/shader.cpp b/intern/cycles/app/opengl/shader.cpp index 4d22fc2b763..906e1979438 100644 --- a/intern/cycles/app/opengl/shader.cpp +++ b/intern/cycles/app/opengl/shader.cpp @@ -41,7 +41,7 @@ static const char *FRAGMENT_SHADER = "void main()\n" "{\n" " vec4 rgba = texture(image_texture, texCoord_interp);\n" - /* Harcoded Rec.709 gamma, should use OpenColorIO eventually. */ + /* Hard-coded Rec.709 gamma, should use OpenColorIO eventually. */ " fragColor = pow(rgba, vec4(0.45, 0.45, 0.45, 1.0));\n" "}\n\0"; diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index 847c7358f7a..3cd762bbf05 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -818,6 +818,23 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b } } +static std::optional find_corner_vert_attribute(BL::Mesh b_mesh) +{ + for (BL::Attribute &b_attribute : b_mesh.attributes) { + if (b_attribute.domain() != BL::Attribute::domain_CORNER) { + continue; + } + if (b_attribute.data_type() != BL::Attribute::data_type_INT) { + continue; + } + if (b_attribute.name() != ".corner_vert") { + continue; + } + return BL::IntAttribute{b_attribute}; + } + return std::nullopt; +} + /* The Random Per Island attribute is a random float associated with each * connected component (island) of the mesh. The attribute is computed by * first classifying the vertices into different sets using a Disjoint Set @@ -864,11 +881,11 @@ static void attr_create_random_per_island(Scene *scene, else { if (polys_num != 0) { const MPoly *polys = static_cast(b_mesh.polygons[0].ptr.data); - const MLoop *loops = static_cast(b_mesh.loops[0].ptr.data); + BL::IntAttribute corner_verts = *find_corner_vert_attribute(b_mesh); for (int i = 0; i < polys_num; i++) { const MPoly &b_poly = polys[i]; - const MLoop &b_loop = loops[b_poly.loopstart]; - data[i] = hash_uint_to_float(vertices_sets.find(b_loop.v)); + const int vert = corner_verts.data[b_poly.loopstart].value(); + data[i] = hash_uint_to_float(vertices_sets.find(vert)); } } } @@ -1036,7 +1053,7 @@ static void create_mesh(Scene *scene, vector vi; const MPoly *polys = static_cast(b_mesh.polygons[0].ptr.data); - const MLoop *loops = static_cast(b_mesh.loops[0].ptr.data); + std::optional corner_verts = find_corner_vert_attribute(b_mesh); for (int i = 0; i < numfaces; i++) { const MPoly &b_poly = polys[i]; @@ -1047,8 +1064,7 @@ static void create_mesh(Scene *scene, vi.resize(n); for (int i = 0; i < n; i++) { /* NOTE: Autosmooth is already taken care about. */ - - vi[i] = loops[b_poly.loopstart + i].v; + vi[i] = corner_verts->data[b_poly.loopstart + i].value(); } /* create subd faces */ diff --git a/intern/cycles/device/cuda/device_impl.cpp b/intern/cycles/device/cuda/device_impl.cpp index c19a0ade332..66fd0e2f937 100644 --- a/intern/cycles/device/cuda/device_impl.cpp +++ b/intern/cycles/device/cuda/device_impl.cpp @@ -536,12 +536,11 @@ void CUDADevice::free_host(void *shared_pointer) cuMemFreeHost(shared_pointer); } -bool CUDADevice::transform_host_pointer(void *&device_pointer, void *&shared_pointer) +void CUDADevice::transform_host_pointer(void *&device_pointer, void *&shared_pointer) { CUDAContextScope scope(this); cuda_assert(cuMemHostGetDevicePointer_v2((CUdeviceptr *)&device_pointer, shared_pointer, 0)); - return true; } void CUDADevice::copy_host_to_device(void *device_pointer, void *host_pointer, size_t size) diff --git a/intern/cycles/device/cuda/device_impl.h b/intern/cycles/device/cuda/device_impl.h index c8cd9bbdac5..818ca5f90f4 100644 --- a/intern/cycles/device/cuda/device_impl.h +++ b/intern/cycles/device/cuda/device_impl.h @@ -68,7 +68,7 @@ class CUDADevice : public GPUDevice { virtual void free_device(void *device_pointer) override; virtual bool alloc_host(void *&shared_pointer, size_t size) override; virtual void free_host(void *shared_pointer) override; - virtual bool transform_host_pointer(void *&device_pointer, void *&shared_pointer) override; + virtual void transform_host_pointer(void *&device_pointer, void *&shared_pointer) override; virtual void copy_host_to_device(void *device_pointer, void *host_pointer, size_t size) override; void mem_alloc(device_memory &mem) override; diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 5dc0919031f..b06a81ca5fd 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -648,7 +648,7 @@ GPUDevice::Mem *GPUDevice::generic_alloc(device_memory &mem, size_t pitch_paddin } if (mem_alloc_result) { - assert(transform_host_pointer(device_pointer, shared_pointer)); + transform_host_pointer(device_pointer, shared_pointer); map_host_used += size; status = " in host memory"; } diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index f586adc34a9..6a598c223a4 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -391,7 +391,7 @@ class GPUDevice : public Device { /* This function should return device pointer corresponding to shared pointer, which * is host buffer, allocated in `alloc_host`. The function should `true`, if such * address transformation is possible and `false` otherwise. */ - virtual bool transform_host_pointer(void *&device_pointer, void *&shared_pointer) = 0; + virtual void transform_host_pointer(void *&device_pointer, void *&shared_pointer) = 0; virtual void copy_host_to_device(void *device_pointer, void *host_pointer, size_t size) = 0; }; diff --git a/intern/cycles/device/hip/device_impl.cpp b/intern/cycles/device/hip/device_impl.cpp index 010470c23ae..9686b26ae98 100644 --- a/intern/cycles/device/hip/device_impl.cpp +++ b/intern/cycles/device/hip/device_impl.cpp @@ -499,12 +499,11 @@ void HIPDevice::free_host(void *shared_pointer) hipHostFree(shared_pointer); } -bool HIPDevice::transform_host_pointer(void *&device_pointer, void *&shared_pointer) +void HIPDevice::transform_host_pointer(void *&device_pointer, void *&shared_pointer) { HIPContextScope scope(this); hip_assert(hipHostGetDevicePointer((hipDeviceptr_t *)&device_pointer, shared_pointer, 0)); - return true; } void HIPDevice::copy_host_to_device(void *device_pointer, void *host_pointer, size_t size) diff --git a/intern/cycles/device/hip/device_impl.h b/intern/cycles/device/hip/device_impl.h index 6039827e58e..707b8f4ee93 100644 --- a/intern/cycles/device/hip/device_impl.h +++ b/intern/cycles/device/hip/device_impl.h @@ -61,7 +61,7 @@ class HIPDevice : public GPUDevice { virtual void free_device(void *device_pointer) override; virtual bool alloc_host(void *&shared_pointer, size_t size) override; virtual void free_host(void *shared_pointer) override; - virtual bool transform_host_pointer(void *&device_pointer, void *&shared_pointer) override; + virtual void transform_host_pointer(void *&device_pointer, void *&shared_pointer) override; virtual void copy_host_to_device(void *device_pointer, void *host_pointer, size_t size) override; void mem_alloc(device_memory &mem) override; diff --git a/intern/cycles/integrator/render_scheduler.cpp b/intern/cycles/integrator/render_scheduler.cpp index 066d6c3bf24..8568fe93a52 100644 --- a/intern/cycles/integrator/render_scheduler.cpp +++ b/intern/cycles/integrator/render_scheduler.cpp @@ -128,9 +128,8 @@ void RenderScheduler::reset(const BufferParams &buffer_params, int num_samples, state_.resolution_divider = 1; } else { - /* NOTE: Divide by 2 because of the way how scheduling works: it advances resolution divider - * first and then initialized render work. */ - state_.resolution_divider = start_resolution_divider_ * 2; + state_.user_is_navigating = true; + state_.resolution_divider = start_resolution_divider_; } state_.num_rendered_samples = 0; @@ -312,7 +311,21 @@ RenderWork RenderScheduler::get_render_work() RenderWork render_work; if (state_.resolution_divider != pixel_size_) { - state_.resolution_divider = max(state_.resolution_divider / 2, pixel_size_); + if (state_.user_is_navigating) { + /* Don't progress the resolution divider as the user is currently navigating in the scene. */ + state_.user_is_navigating = false; + } + else { + /* If the resolution divider is greater than or equal to default_start_resolution_divider_, + * drop the resolution divider down to 4. This is so users with slow hardware and thus high + * resolution dividers (E.G. 16), get an update to let them know something is happening + * rather than having to wait for the full 1:1 render to show up. */ + state_.resolution_divider = state_.resolution_divider > default_start_resolution_divider_ ? + (4 * pixel_size_) : + 1; + } + + state_.resolution_divider = max(state_.resolution_divider, pixel_size_); state_.num_rendered_samples = 0; state_.last_display_update_sample = -1; } @@ -1058,10 +1071,16 @@ void RenderScheduler::update_start_resolution_divider() return; } + /* Calculate the maximum resolution divider possible while keeping the long axis of the viewport + * above our preferred minimum axis size (128). */ + const int long_viewport_axis = max(buffer_params_.width, buffer_params_.height); + const int max_res_divider_for_desired_size = long_viewport_axis / 128; + if (start_resolution_divider_ == 0) { - /* Resolution divider has never been calculated before: use default resolution, so that we have - * somewhat good initial behavior, giving a chance to collect real numbers. */ - start_resolution_divider_ = default_start_resolution_divider_; + /* Resolution divider has never been calculated before: start with a high resolution divider so + * that we have a somewhat good initial behavior, giving a chance to collect real numbers. */ + start_resolution_divider_ = min(default_start_resolution_divider_, + max_res_divider_for_desired_size); VLOG_WORK << "Initial resolution divider is " << start_resolution_divider_; return; } @@ -1089,8 +1108,7 @@ void RenderScheduler::update_start_resolution_divider() /* Don't let resolution drop below the desired one. It's better to be slow than provide an * unreadable viewport render. */ - start_resolution_divider_ = min(resolution_divider_for_update, - default_start_resolution_divider_); + start_resolution_divider_ = min(resolution_divider_for_update, max_res_divider_for_desired_size); VLOG_WORK << "Calculated resolution divider is " << start_resolution_divider_; } diff --git a/intern/cycles/integrator/render_scheduler.h b/intern/cycles/integrator/render_scheduler.h index a0ab17b3794..6fe5a49a55c 100644 --- a/intern/cycles/integrator/render_scheduler.h +++ b/intern/cycles/integrator/render_scheduler.h @@ -332,6 +332,8 @@ class RenderScheduler { }; struct { + bool user_is_navigating = false; + int resolution_divider = 1; /* Number of rendered samples on top of the start sample. */ diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index bfb1a0af97d..84061db91ac 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -741,21 +741,21 @@ if(WITH_CYCLES_DEVICE_ONEAPI) endif() # SYCL_CPP_FLAGS is a variable that the user can set to pass extra compiler options set(sycl_compiler_flags - ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_KERNEL_DEVICE_ONEAPI} - -fsycl - -fsycl-unnamed-lambda - -fdelayed-template-parsing - -mllvm -inlinedefault-threshold=250 - -mllvm -inlinehint-threshold=350 - -fsycl-device-code-split=per_kernel - -fsycl-max-parallel-link-jobs=${SYCL_OFFLINE_COMPILER_PARALLEL_JOBS} - -shared - -DWITH_ONEAPI - -ffast-math - -O2 - -o"${cycles_kernel_oneapi_lib}" - -I"${CMAKE_CURRENT_SOURCE_DIR}/.." - ${SYCL_CPP_FLAGS} + ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_KERNEL_DEVICE_ONEAPI} + -fsycl + -fsycl-unnamed-lambda + -fdelayed-template-parsing + -mllvm -inlinedefault-threshold=250 + -mllvm -inlinehint-threshold=350 + -fsycl-device-code-split=per_kernel + -fsycl-max-parallel-link-jobs=${SYCL_OFFLINE_COMPILER_PARALLEL_JOBS} + -shared + -DWITH_ONEAPI + -ffast-math + -O2 + -o"${cycles_kernel_oneapi_lib}" + -I"${CMAKE_CURRENT_SOURCE_DIR}/.." + ${SYCL_CPP_FLAGS} ) if(WITH_CYCLES_ONEAPI_HOST_TASK_EXECUTION) diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h index f4a01104001..e237317fd07 100644 --- a/intern/cycles/kernel/closure/bsdf_util.h +++ b/intern/cycles/kernel/closure/bsdf_util.h @@ -105,12 +105,18 @@ ccl_device_forceinline Spectrum interpolate_fresnel_color(float3 L, return mix(F0, one_spectrum(), inverse_lerp(real_F0, 1.0f, real_F)); } -ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N) +/* If the shading normal results in specular reflection in the lower hemisphere, raise the shading + * normal towards the geometry normal so that the specular reflection is just above the surface. + * Only used for glossy materials. */ +ccl_device float3 ensure_valid_specular_reflection(float3 Ng, float3 I, float3 N) { - float3 R = 2 * dot(N, I) * N - I; + const float3 R = 2 * dot(N, I) * N - I; + + const float Iz = dot(I, Ng); + kernel_assert(Iz > 0); /* Reflection rays may always be at least as shallow as the incoming ray. */ - float threshold = min(0.9f * dot(Ng, I), 0.01f); + const float threshold = min(0.9f * Iz, 0.01f); if (dot(Ng, R) >= threshold) { return N; } @@ -119,11 +125,8 @@ ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N) * The X axis is found by normalizing the component of N that's orthogonal to Ng. * The Y axis isn't actually needed. */ - float NdotNg = dot(N, Ng); - float3 X = normalize(N - NdotNg * Ng); + const float3 X = normalize(N - dot(N, Ng) * Ng); - /* Keep math expressions. */ - /* clang-format off */ /* Calculate N.z and N.x in the local coordinate system. * * The goal of this computation is to find a N' that is rotated towards Ng just enough @@ -141,74 +144,53 @@ ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N) * * Furthermore, we want N' to be normalized, so N'.x = sqrt(1 - N'.z^2). * - * With these simplifications, - * we get the final equation 2*(sqrt(1 - N'.z^2)*I.x + N'.z*I.z)*N'.z - I.z = t. + * With these simplifications, we get the equation + * 2*(sqrt(1 - N'.z^2)*I.x + N'.z*I.z)*N'.z - I.z = t, + * or + * 2*sqrt(1 - N'.z^2)*I.x*N'.z = t + I.z * (1 - 2*N'.z^2), + * after rearranging terms. + * Raise both sides to the power of two and substitute terms with + * a = I.x^2 + I.z^2, + * b = 2*(a + Iz*t), + * c = (Iz + t)^2, + * we obtain + * 4*a*N'.z^4 - 2*b*N'.z^2 + c = 0. * * The only unknown here is N'.z, so we can solve for that. * - * The equation has four solutions in general: - * - * N'.z = +-sqrt(0.5*(+-sqrt(I.x^2*(I.x^2 + I.z^2 - t^2)) + t*I.z + I.x^2 + I.z^2)/(I.x^2 + I.z^2)) - * We can simplify this expression a bit by grouping terms: - * - * a = I.x^2 + I.z^2 - * b = sqrt(I.x^2 * (a - t^2)) - * c = I.z*t + a - * N'.z = +-sqrt(0.5*(+-b + c)/a) - * - * Two solutions can immediately be discarded because they're negative so N' would lie in the - * lower hemisphere. + * The equation has four solutions in general, two can immediately be discarded because they're + * negative so N' would lie in the lower hemisphere; one solves + * 2*sqrt(1 - N'.z^2)*I.x*N'.z = -(t + I.z * (1 - 2*N'.z^2)) + * instead of the original equation (before squaring both sides). + * Therefore only one root is valid. */ - /* clang-format on */ - float Ix = dot(I, X), Iz = dot(I, Ng); - float Ix2 = sqr(Ix), Iz2 = sqr(Iz); - float a = Ix2 + Iz2; + const float Ix = dot(I, X); - float b = safe_sqrtf(Ix2 * (a - sqr(threshold))); - float c = Iz * threshold + a; + const float a = sqr(Ix) + sqr(Iz); + const float b = 2.0f * (a + Iz * threshold); + const float c = sqr(threshold + Iz); - /* Evaluate both solutions. - * In many cases one can be immediately discarded (if N'.z would be imaginary or larger than - * one), so check for that first. If no option is viable (might happen in extreme cases like N - * being in the wrong hemisphere), give up and return Ng. */ - float fac = 0.5f / a; - float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c); - bool valid1 = (N1_z2 > 1e-5f) && (N1_z2 <= (1.0f + 1e-5f)); - bool valid2 = (N2_z2 > 1e-5f) && (N2_z2 <= (1.0f + 1e-5f)); + /* In order that the root formula solves 2*sqrt(1 - N'.z^2)*I.x*N'.z = t + I.z - 2*I.z*N'.z^2, + * Ix and (t + I.z * (1 - 2*N'.z^2)) must have the same sign (the rest terms are non-negative by + * definition). */ + const float Nz2 = (Ix < 0) ? 0.25f * (b + safe_sqrtf(sqr(b) - 4.0f * a * c)) / a : + 0.25f * (b - safe_sqrtf(sqr(b) - 4.0f * a * c)) / a; - float2 N_new; - if (valid1 && valid2) { - /* If both are possible, do the expensive reflection-based check. */ - float2 N1 = make_float2(safe_sqrtf(1.0f - N1_z2), safe_sqrtf(N1_z2)); - float2 N2 = make_float2(safe_sqrtf(1.0f - N2_z2), safe_sqrtf(N2_z2)); + const float Nx = safe_sqrtf(1.0f - Nz2); + const float Nz = safe_sqrtf(Nz2); - float R1 = 2 * (N1.x * Ix + N1.y * Iz) * N1.y - Iz; - float R2 = 2 * (N2.x * Ix + N2.y * Iz) * N2.y - Iz; + return Nx * X + Nz * Ng; +} - valid1 = (R1 >= 1e-5f); - valid2 = (R2 >= 1e-5f); - if (valid1 && valid2) { - /* If both solutions are valid, return the one with the shallower reflection since it will be - * closer to the input (if the original reflection wasn't shallow, we would not be in this - * part of the function). */ - N_new = (R1 < R2) ? N1 : N2; - } - else { - /* If only one reflection is valid (= positive), pick that one. */ - N_new = (R1 > R2) ? N1 : N2; - } +/* Do not call #ensure_valid_specular_reflection if the primitive type is curve or if the geometry + * normal and the shading normal is the same. */ +ccl_device float3 maybe_ensure_valid_specular_reflection(ccl_private ShaderData *sd, float3 N) +{ + if ((sd->type & PRIMITIVE_CURVE) || isequal(sd->Ng, N)) { + return N; } - else if (valid1 || valid2) { - /* Only one solution passes the N'.z criterium, so pick that one. */ - float Nz2 = valid1 ? N1_z2 : N2_z2; - N_new = make_float2(safe_sqrtf(1.0f - Nz2), safe_sqrtf(Nz2)); - } - else { - return Ng; - } - - return N_new.x * X + N_new.y * Ng; + return ensure_valid_specular_reflection(sd->Ng, sd->wi, N); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/closures_setup.h b/intern/cycles/kernel/osl/closures_setup.h index 01d2c7408b5..462d1405064 100644 --- a/intern/cycles/kernel/osl/closures_setup.h +++ b/intern/cycles/kernel/osl/closures_setup.h @@ -78,7 +78,7 @@ ccl_device void osl_closure_diffuse_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = closure->N; sd->flag |= bsdf_diffuse_setup(bsdf); } @@ -99,7 +99,7 @@ ccl_device void osl_closure_oren_nayar_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = closure->N; bsdf->roughness = closure->roughness; sd->flag |= bsdf_oren_nayar_setup(bsdf); @@ -121,7 +121,7 @@ ccl_device void osl_closure_translucent_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = closure->N; sd->flag |= bsdf_translucent_setup(bsdf); } @@ -142,7 +142,7 @@ ccl_device void osl_closure_reflection_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); sd->flag |= bsdf_reflection_setup(bsdf); } @@ -163,7 +163,7 @@ ccl_device void osl_closure_refraction_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->ior = closure->ior; sd->flag |= bsdf_refraction_setup(bsdf); @@ -204,7 +204,7 @@ ccl_device void osl_closure_dielectric_bsdf_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->ior = closure->ior; @@ -266,7 +266,7 @@ ccl_device void osl_closure_conductor_bsdf_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->ior = 0.0f; @@ -313,7 +313,7 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->ior = ior_from_F0(closure->f0); @@ -375,7 +375,7 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->ior = closure->ior; @@ -440,7 +440,7 @@ ccl_device void osl_closure_microfacet_ggx_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = bsdf->alpha_y = closure->alpha_x; sd->flag |= bsdf_microfacet_ggx_setup(bsdf); @@ -463,7 +463,7 @@ ccl_device void osl_closure_microfacet_ggx_aniso_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->T = closure->T; @@ -488,7 +488,7 @@ ccl_device void osl_closure_microfacet_ggx_refraction_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->ior = closure->ior; @@ -520,7 +520,7 @@ ccl_device void osl_closure_microfacet_ggx_fresnel_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = bsdf->alpha_x; bsdf->ior = closure->ior; @@ -556,7 +556,7 @@ ccl_device void osl_closure_microfacet_ggx_aniso_fresnel_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->ior = closure->ior; @@ -597,7 +597,7 @@ ccl_device void osl_closure_microfacet_multi_ggx_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = bsdf->alpha_x; bsdf->ior = 1.0f; @@ -636,7 +636,7 @@ ccl_device void osl_closure_microfacet_multi_ggx_glass_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = bsdf->alpha_x; bsdf->ior = closure->ior; @@ -675,7 +675,7 @@ ccl_device void osl_closure_microfacet_multi_ggx_aniso_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->ior = 1.0f; @@ -716,7 +716,7 @@ ccl_device void osl_closure_microfacet_multi_ggx_fresnel_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = bsdf->alpha_x; bsdf->ior = closure->ior; @@ -756,7 +756,7 @@ ccl_device void osl_closure_microfacet_multi_ggx_glass_fresnel_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = bsdf->alpha_x; bsdf->ior = closure->ior; @@ -796,7 +796,7 @@ ccl_device void osl_closure_microfacet_multi_ggx_aniso_fresnel_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->ior = closure->ior; @@ -829,7 +829,7 @@ ccl_device void osl_closure_microfacet_beckmann_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = bsdf->alpha_y = closure->alpha_x; sd->flag |= bsdf_microfacet_beckmann_setup(bsdf); @@ -852,7 +852,7 @@ ccl_device void osl_closure_microfacet_beckmann_aniso_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->T = closure->T; @@ -877,7 +877,7 @@ ccl_device void osl_closure_microfacet_beckmann_refraction_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->ior = closure->ior; @@ -903,7 +903,7 @@ ccl_device void osl_closure_ashikhmin_velvet_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->sigma = closure->sigma; sd->flag |= bsdf_ashikhmin_velvet_setup(bsdf); @@ -926,7 +926,7 @@ ccl_device void osl_closure_ashikhmin_shirley_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->alpha_x; bsdf->alpha_y = closure->alpha_y; bsdf->T = closure->T; @@ -950,7 +950,7 @@ ccl_device void osl_closure_diffuse_toon_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->size = closure->size; bsdf->smooth = closure->smooth; @@ -973,7 +973,7 @@ ccl_device void osl_closure_glossy_toon_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->size = closure->size; bsdf->smooth = closure->smooth; @@ -999,7 +999,7 @@ ccl_device void osl_closure_principled_diffuse_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = closure->N; bsdf->roughness = closure->roughness; sd->flag |= bsdf_principled_diffuse_setup(bsdf); @@ -1022,7 +1022,7 @@ ccl_device void osl_closure_principled_sheen_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = closure->N; bsdf->avg_value = 0.0f; sd->flag |= bsdf_principled_sheen_setup(sd, bsdf); @@ -1042,7 +1042,7 @@ ccl_device void osl_closure_principled_clearcoat_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->alpha_x = closure->clearcoat_roughness; bsdf->alpha_y = closure->clearcoat_roughness; bsdf->ior = 1.5f; @@ -1109,7 +1109,7 @@ ccl_device void osl_closure_diffuse_ramp_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = closure->N; bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8); if (!bsdf->colors) { @@ -1134,7 +1134,7 @@ ccl_device void osl_closure_phong_ramp_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->exponent = closure->exponent; bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8); @@ -1185,7 +1185,7 @@ ccl_device void osl_closure_bssrdf_setup(KernelGlobals kg, /* create one closure per color channel */ bssrdf->albedo = closure->albedo; - bssrdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bssrdf->N = closure->N; bssrdf->roughness = closure->roughness; bssrdf->anisotropy = clamp(closure->anisotropy, 0.0f, 0.9f); @@ -1210,7 +1210,7 @@ ccl_device void osl_closure_hair_reflection_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->T = closure->T; bsdf->roughness1 = closure->roughness1; bsdf->roughness2 = closure->roughness2; @@ -1236,7 +1236,7 @@ ccl_device void osl_closure_hair_transmission_setup( return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->T = closure->T; bsdf->roughness1 = closure->roughness1; bsdf->roughness2 = closure->roughness2; @@ -1268,7 +1268,7 @@ ccl_device void osl_closure_principled_hair_setup(KernelGlobals kg, return; } - bsdf->N = ensure_valid_reflection(sd->Ng, sd->wi, closure->N); + bsdf->N = ensure_valid_specular_reflection(sd->Ng, sd->wi, closure->N); bsdf->sigma = closure->sigma; bsdf->v = closure->v; bsdf->s = closure->s; diff --git a/intern/cycles/kernel/osl/shaders/node_bump.osl b/intern/cycles/kernel/osl/shaders/node_bump.osl index 4f830d79ee5..86e9b683fd0 100644 --- a/intern/cycles/kernel/osl/shaders/node_bump.osl +++ b/intern/cycles/kernel/osl/shaders/node_bump.osl @@ -50,6 +50,4 @@ surface node_bump(int invert = 0, if (use_object_space) { NormalOut = normalize(transform("object", "world", NormalOut)); } - - NormalOut = ensure_valid_reflection(Ng, I, NormalOut); } diff --git a/intern/cycles/kernel/osl/shaders/stdcycles.h b/intern/cycles/kernel/osl/shaders/stdcycles.h index f8c84c68b19..6fe0e5987fa 100644 --- a/intern/cycles/kernel/osl/shaders/stdcycles.h +++ b/intern/cycles/kernel/osl/shaders/stdcycles.h @@ -65,67 +65,4 @@ closure color principled_hair(normal N, closure color henyey_greenstein(float g) BUILTIN; closure color absorption() BUILTIN; -normal ensure_valid_reflection(normal Ng, vector I, normal N) -{ - /* The implementation here mirrors the one in kernel_montecarlo.h, - * check there for an explanation of the algorithm. */ - - float sqr(float x) - { - return x * x; - } - - vector R = 2 * dot(N, I) * N - I; - - float threshold = min(0.9 * dot(Ng, I), 0.01); - if (dot(Ng, R) >= threshold) { - return N; - } - - float NdotNg = dot(N, Ng); - vector X = normalize(N - NdotNg * Ng); - - float Ix = dot(I, X), Iz = dot(I, Ng); - float Ix2 = sqr(Ix), Iz2 = sqr(Iz); - float a = Ix2 + Iz2; - - float b = sqrt(Ix2 * (a - sqr(threshold))); - float c = Iz * threshold + a; - - float fac = 0.5 / a; - float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c); - int valid1 = (N1_z2 > 1e-5) && (N1_z2 <= (1.0 + 1e-5)); - int valid2 = (N2_z2 > 1e-5) && (N2_z2 <= (1.0 + 1e-5)); - - float N_new_x, N_new_z; - if (valid1 && valid2) { - float N1_x = sqrt(1.0 - N1_z2), N1_z = sqrt(N1_z2); - float N2_x = sqrt(1.0 - N2_z2), N2_z = sqrt(N2_z2); - - float R1 = 2 * (N1_x * Ix + N1_z * Iz) * N1_z - Iz; - float R2 = 2 * (N2_x * Ix + N2_z * Iz) * N2_z - Iz; - - valid1 = (R1 >= 1e-5); - valid2 = (R2 >= 1e-5); - if (valid1 && valid2) { - N_new_x = (R1 < R2) ? N1_x : N2_x; - N_new_z = (R1 < R2) ? N1_z : N2_z; - } - else { - N_new_x = (R1 > R2) ? N1_x : N2_x; - N_new_z = (R1 > R2) ? N1_z : N2_z; - } - } - else if (valid1 || valid2) { - float Nz2 = valid1 ? N1_z2 : N2_z2; - N_new_x = sqrt(1.0 - Nz2); - N_new_z = sqrt(Nz2); - } - else { - return Ng; - } - - return N_new_x * X + N_new_z * Ng; -} - #endif /* CCL_STDOSL_H */ diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index a8886d8c99c..803cf33c358 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -59,9 +59,6 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, float3 N = stack_valid(data_node.x) ? safe_normalize(stack_load_float3(stack, data_node.x)) : sd->N; - if (!(sd->type & PRIMITIVE_CURVE)) { - N = ensure_valid_reflection(sd->Ng, sd->wi, N); - } float param1 = (stack_valid(param1_offset)) ? stack_load_float(stack, param1_offset) : __uint_as_float(node.z); @@ -119,8 +116,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, /* calculate ior */ float ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta; - // calculate fresnel for refraction - float cosNI = dot(N, sd->wi); + /* Calculate fresnel for refraction. */ + float3 valid_reflection_N = maybe_ensure_valid_specular_reflection(sd, N); + float cosNI = dot(valid_reflection_N, sd->wi); float fresnel = fresnel_dielectric_cos(cosNI, ior); // calculate weights of the diffuse and specular part @@ -142,9 +140,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, float3 clearcoat_normal = stack_valid(data_cn_ssr.x) ? stack_load_float3(stack, data_cn_ssr.x) : sd->N; - if (!(sd->type & PRIMITIVE_CURVE)) { - clearcoat_normal = ensure_valid_reflection(sd->Ng, sd->wi, clearcoat_normal); - } + clearcoat_normal = maybe_ensure_valid_specular_reflection(sd, clearcoat_normal); float3 subsurface_radius = stack_valid(data_cn_ssr.y) ? stack_load_float3(stack, data_cn_ssr.y) : one_float3(); @@ -271,7 +267,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, NULL; if (bsdf && fresnel) { - bsdf->N = N; + bsdf->N = valid_reflection_N; bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f; bsdf->T = T; @@ -333,7 +329,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, NULL; if (bsdf && fresnel) { - bsdf->N = N; + bsdf->N = valid_reflection_N; bsdf->T = zero_float3(); bsdf->fresnel = fresnel; @@ -362,7 +358,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, sizeof(MicrofacetBsdf), rgb_to_spectrum(base_color) * glass_weight * refraction_fresnel); if (bsdf) { - bsdf->N = N; + bsdf->N = valid_reflection_N; bsdf->T = zero_float3(); bsdf->fresnel = NULL; @@ -390,7 +386,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, NULL; if (bsdf && fresnel) { - bsdf->N = N; + bsdf->N = valid_reflection_N; bsdf->fresnel = fresnel; bsdf->T = zero_float3(); @@ -461,7 +457,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, sd, sizeof(DiffuseBsdf), weight); if (bsdf) { - bsdf->N = N; + bsdf->N = maybe_ensure_valid_specular_reflection(sd, N); sd->flag |= bsdf_translucent_setup(bsdf); } break; @@ -490,7 +486,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, float roughness = sqr(param1); - bsdf->N = N; + bsdf->N = maybe_ensure_valid_specular_reflection(sd, N); bsdf->ior = 1.0f; bsdf->fresnel = NULL; @@ -554,7 +550,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, sd, sizeof(MicrofacetBsdf), weight); if (bsdf) { - bsdf->N = N; + bsdf->N = maybe_ensure_valid_specular_reflection(sd, N); bsdf->T = zero_float3(); bsdf->fresnel = NULL; @@ -597,7 +593,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, sd, sizeof(MicrofacetBsdf), weight); if (bsdf) { - bsdf->N = N; + bsdf->N = maybe_ensure_valid_specular_reflection(sd, N); bsdf->T = zero_float3(); bsdf->fresnel = NULL; @@ -646,7 +642,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, break; } - bsdf->N = N; + bsdf->N = maybe_ensure_valid_specular_reflection(sd, N); bsdf->fresnel = fresnel; bsdf->T = zero_float3(); @@ -752,7 +748,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, float coat = stack_load_float_default(stack, coat_ofs, data_node2.y); float m0_roughness = 1.0f - clamp(coat, 0.0f, 1.0f); - bsdf->N = N; + bsdf->N = maybe_ensure_valid_specular_reflection(sd, N); bsdf->v = roughness; bsdf->s = radial_roughness; bsdf->m0_roughness = m0_roughness; @@ -820,7 +816,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, sd, sizeof(HairBsdf), weight); if (bsdf) { - bsdf->N = N; + bsdf->N = maybe_ensure_valid_specular_reflection(sd, N); bsdf->roughness1 = param1; bsdf->roughness2 = param2; bsdf->offset = -stack_load_float(stack, data_node.z); diff --git a/intern/cycles/kernel/svm/displace.h b/intern/cycles/kernel/svm/displace.h index d2be8c4844b..844f7afa90b 100644 --- a/intern/cycles/kernel/svm/displace.h +++ b/intern/cycles/kernel/svm/displace.h @@ -71,7 +71,6 @@ ccl_device_noinline void svm_node_set_bump(KernelGlobals kg, object_normal_transform(kg, sd, &normal_out); } - normal_out = ensure_valid_reflection(sd->Ng, sd->wi, normal_out); stack_store_float3(stack, node.w, normal_out); } else diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp index da30c5c77f6..60ee641d9f0 100644 --- a/intern/cycles/scene/light_tree.cpp +++ b/intern/cycles/scene/light_tree.cpp @@ -205,8 +205,8 @@ LightTree::LightTree(vector &prims, } max_lights_in_leaf_ = max_lights_in_leaf; - int num_prims = prims.size(); - int num_local_lights = num_prims - num_distant_lights; + const int num_prims = prims.size(); + const int num_local_lights = num_prims - num_distant_lights; /* The amount of nodes is estimated to be twice the amount of primitives */ nodes_.reserve(2 * num_prims); @@ -240,8 +240,8 @@ int LightTree::recursive_build( OrientationBounds bcone = OrientationBounds::empty; BoundBox centroid_bounds = BoundBox::empty; float energy_total = 0.0; - int num_prims = end - start; int current_index = nodes_.size(); + const int num_prims = end - start; for (int i = start; i < end; i++) { const LightTreePrimitive &prim = prims.at(i); @@ -254,13 +254,13 @@ int LightTree::recursive_build( nodes_.emplace_back(bbox, bcone, energy_total, bit_trail); - bool try_splitting = num_prims > 1 && len(centroid_bounds.size()) > 0.0f; + const bool try_splitting = num_prims > 1 && len(centroid_bounds.size()) > 0.0f; int split_dim = -1, split_bucket = 0, num_left_prims = 0; bool should_split = false; if (try_splitting) { /* Find the best place to split the primitives into 2 nodes. * If the best split cost is no better than making a leaf node, make a leaf instead. */ - float min_cost = min_split_saoh( + const float min_cost = min_split_saoh( centroid_bounds, start, end, bbox, bcone, split_dim, split_bucket, num_left_prims, prims); should_split = num_prims > max_lights_in_leaf_ || min_cost < energy_total; } @@ -295,8 +295,8 @@ int LightTree::recursive_build( } float LightTree::min_split_saoh(const BoundBox ¢roid_bbox, - int start, - int end, + const int start, + const int end, const BoundBox &bbox, const OrientationBounds &bcone, int &split_dim, @@ -329,7 +329,7 @@ float LightTree::min_split_saoh(const BoundBox ¢roid_bbox, const float inv_extent = 1 / (centroid_bbox.size()[dim]); /* Fill in buckets with primitives. */ - vector buckets(LightTreeBucketInfo::num_buckets); + std::array buckets; for (int i = start; i < end; i++) { const LightTreePrimitive &prim = prims[i]; @@ -348,7 +348,7 @@ float LightTree::min_split_saoh(const BoundBox ¢roid_bbox, } /* Calculate the cost of splitting at each point between partitions. */ - vector bucket_costs(LightTreeBucketInfo::num_buckets - 1); + std::array bucket_costs; float energy_L, energy_R; BoundBox bbox_L, bbox_R; OrientationBounds bcone_L, bcone_R; @@ -379,9 +379,10 @@ float LightTree::min_split_saoh(const BoundBox ¢roid_bbox, /* Calculate the cost of splitting using the heuristic as described in the paper. */ const float area_L = has_area ? bbox_L.area() : len(bbox_L.size()); const float area_R = has_area ? bbox_R.area() : len(bbox_R.size()); - float left = (bbox_L.valid()) ? energy_L * area_L * bcone_L.calculate_measure() : 0.0f; - float right = (bbox_R.valid()) ? energy_R * area_R * bcone_R.calculate_measure() : 0.0f; - float regularization = max_extent * inv_extent; + const float left = (bbox_L.valid()) ? energy_L * area_L * bcone_L.calculate_measure() : 0.0f; + const float right = (bbox_R.valid()) ? energy_R * area_R * bcone_R.calculate_measure() : + 0.0f; + const float regularization = max_extent * inv_extent; bucket_costs[split] = regularization * (left + right) * inv_total_cost; if (bucket_costs[split] < min_cost) { diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp index dfd86f82bb6..da8c5719fa2 100644 --- a/intern/cycles/scene/shader.cpp +++ b/intern/cycles/scene/shader.cpp @@ -153,6 +153,16 @@ static float3 output_estimate_emission(ShaderOutput *output, bool &is_constant) estimate *= node->get_float(strength_in->socket_type); } + /* Lower importance of emission nodes from automatic value/color to shader + * conversion, as these are likely used for previewing and can be slow to + * build a light tree for on dense meshes. */ + if (node->type == EmissionNode::get_node_type()) { + EmissionNode *emission_node = static_cast(node); + if (emission_node->from_auto_conversion) { + estimate *= 0.1f; + } + } + return estimate; } else if (node->type == LightFalloffNode::get_node_type() || diff --git a/intern/cycles/scene/shader_graph.cpp b/intern/cycles/scene/shader_graph.cpp index b9e8892765b..4a653f3345c 100644 --- a/intern/cycles/scene/shader_graph.cpp +++ b/intern/cycles/scene/shader_graph.cpp @@ -260,6 +260,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) if (to->type() == SocketType::CLOSURE) { EmissionNode *emission = create_node(); + emission->from_auto_conversion = true; emission->set_color(one_float3()); emission->set_strength(1.0f); convert = add(emission); diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index 35c5a7a61ac..0c36d17107c 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -723,6 +723,8 @@ class EmissionNode : public ShaderNode { NODE_SOCKET_API(float3, color) NODE_SOCKET_API(float, strength) NODE_SOCKET_API(float, surface_mix_weight) + + bool from_auto_conversion = false; }; class BackgroundNode : public ShaderNode { diff --git a/intern/cycles/util/boundbox.h b/intern/cycles/util/boundbox.h index 982f538f57f..afddb24d5ac 100644 --- a/intern/cycles/util/boundbox.h +++ b/intern/cycles/util/boundbox.h @@ -56,8 +56,8 @@ class BoundBox { __forceinline void grow(const BoundBox &bbox) { - grow(bbox.min); - grow(bbox.max); + min = ccl::min(bbox.min, min); + max = ccl::max(bbox.max, max); } __forceinline void grow_safe(const float3 &pt) @@ -81,8 +81,12 @@ class BoundBox { __forceinline void grow_safe(const BoundBox &bbox) { - grow_safe(bbox.min); - grow_safe(bbox.max); + if (isfinite_safe(bbox.min)) { + min = ccl::min(bbox.min, min); + } + if (isfinite_safe(bbox.max)) { + max = ccl::max(bbox.max, max); + } } __forceinline void intersect(const BoundBox &bbox) diff --git a/locale/po/ab.po b/locale/po/ab.po index c143195f7be..c78de8fab42 100644 --- a/locale/po/ab.po +++ b/locale/po/ab.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" "\"POT-Creation-Date: 2019-02-25 20:41:30\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" diff --git a/locale/po/ar.po b/locale/po/ar.po index 04778f22adb..61b9a9f0f41 100644 --- a/locale/po/ar.po +++ b/locale/po/ar.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2016-04-23 22:41+0300\n" "Last-Translator: Yousef Harfoush \n" "Language-Team: Yousef Harfoush, Amine Moussaoui \n" @@ -16934,6 +16934,10 @@ msgid "Weight of feather point" msgstr "ﺶﻣﺎﻬﻟﺍ ﺔﻄﻘﻧ ﻥﺯﻭ" +msgid "Active Point" +msgstr "ﺔﻟﺎﻌﻔﻟﺍ ﺔﻄﻘﻨﻟﺍ" + + msgid "Alignment" msgstr "ﺓﺍﺫﺎﺤﻤﻟﺍ" @@ -30389,10 +30393,6 @@ msgid "Camera Presets" msgstr "ﺍﺮﻴﻤﻜﻠﻟ ﺔﻘﺒﺴﻤﻟﺍ ﺕﺍﺩﺍﺪﻋﻹﺍ" -msgid "Active Point" -msgstr "ﺔﻟﺎﻌﻔﻟﺍ ﺔﻄﻘﻨﻟﺍ" - - msgid "Footage Settings" msgstr "ﺓﺩﺎﻤﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ" diff --git a/locale/po/ca.po b/locale/po/ca.po index 365c3d31fef..7b4a78a3014 100644 --- a/locale/po/ca.po +++ b/locale/po/ca.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -367,7 +367,7 @@ msgstr "Mostra la IU de glTF per gestionar variants de materials" msgid "Displays glTF Material Output node in Shader Editor (Menu Add > Output)" -msgstr "Mostra el node de material glTF emès a l'editor d'aspecte (Menú afegir > emissió)" +msgstr "Mostra el node de material glTF egressat a l'editor d'aspecte (Menú afegir > egressió)" msgid "Fribidi Library" @@ -1110,6 +1110,10 @@ msgid "Copyright" msgstr "Copyright" +msgid "Copyright notice for this asset. An empty copyright notice does not necessarily indicate that this is copyright-free. Contact the author if any clarification is needed" +msgstr "Avís de copyright d'aquest recurs. Un avís buit no indica necessàriament que estigui lliure de copyright. Contacteu l'autor per qualsevol aclariment" + + msgid "Description" msgstr "Descripció" @@ -1118,6 +1122,14 @@ msgid "A description of the asset to be displayed for the user" msgstr "Descripció del recurs que es mostrarà a la usuària" +msgid "License" +msgstr "Llicència" + + +msgid "The type of license this asset is distributed under. An empty license name does not necessarily indicate that this is free of licensing terms. Contact the author if any clarification is needed" +msgstr "El tipus de llicència sota la que aquest recurs es distribueix. Una llicència buida no indica necessàriament que estigui lliure de condicions de llicència. Contacteu l'autor per qualsevol aclariment" + + msgid "Tags" msgstr "Etiquetes" @@ -1595,7 +1607,7 @@ msgstr "Indirecta" msgid "Diffuse" -msgstr "Difusa" +msgstr "Difusiva" msgid "Glossy" @@ -1635,7 +1647,7 @@ msgstr "Destinació" msgid "Where to output the baked map" -msgstr "[Target]: Lloc d'emissió del mapa precuinat" +msgstr "[Target]: Lloc d'egressió del mapa precuinat" msgid "Image Textures" @@ -1655,7 +1667,7 @@ msgstr "Nom automàtic" msgid "Automatically name the output file with the pass type (external only)" -msgstr "Anomena automàticament el document emès amb el tipus de passada (només extern)" +msgstr "Anomena automàticament el document egressat amb el tipus de passada (només extern)" msgid "Cage" @@ -1679,7 +1691,7 @@ msgstr "Acolorir la passada" msgid "Add diffuse contribution" -msgstr "Afegir contribució de difusió" +msgstr "Afegir contribució difusiva" msgid "Add direct lighting contribution" @@ -4157,11 +4169,11 @@ msgstr "[Hardness]: Gradació des del centre dels traços de punt i caixa (1 cor msgid "Input Samples" -msgstr "Ingressar mostres" +msgstr "Inserir mostres" msgid "Generate intermediate points for very fast mouse movements. Set to 0 to disable" -msgstr "[Input Samples]: Genera punts intermedis amb moviments de ratolí molt ràpids. Posar a 0 per a desactivar" +msgstr "[Input Samples]: Genera punts intermedis quan es mou el ratolí molt ràpid. Posar a 0 per a desactivar" msgid "Material used for strokes drawn using this brush" @@ -5537,7 +5549,7 @@ msgstr "[No Convergence]: El procediment iteratiu no ha convergit" msgid "Invalid Input" -msgstr "Ingrés no vàlid" +msgstr "Ingressió no vàlida" msgid "The inputs are invalid, or the algorithm has been improperly called" @@ -5689,15 +5701,15 @@ msgstr "Gestió del color pròpia de l'aparell des d'on es visualitza" msgid "Display Device" -msgstr "Aparell de visualització" +msgstr "Dispositiu de visualització" msgid "Display device name" -msgstr "[Display Device]: Nom de l'aparell de visualització" +msgstr "[Display Device]: Nom del dispositiu de visualització" msgid "Input color space settings" -msgstr "Ingressar paràmetres d'espai cromàtic" +msgstr "paràmetres d'espai cromàtic d'ingressió" msgid "Is Data" @@ -5709,7 +5721,7 @@ msgstr "[Is Data]: Tracta la imatge com a dades de no-color sense gestió del co msgid "Input Color Space" -msgstr "Ingressar espai cromàtic" +msgstr "Espai cromàtic d'ingressió" msgid "Color space in the image file, to convert to and from when saving and loading the image" @@ -5853,7 +5865,7 @@ msgstr "[Color Mapping]: Configuració del mapejat cromàtic" msgid "Blend color to mix with texture output color" -msgstr "Color de fusió per a mesclar amb el color de textura emès" +msgstr "Color de fusió per a mesclar amb el color de textura egressat" msgid "Blend Factor" @@ -5865,7 +5877,7 @@ msgstr "Tipus de fusió" msgid "Mode used to mix with texture output color" -msgstr "[Blend Type]: Mode utilitzat per a mesclar amb el color de textura emès" +msgstr "[Blend Type]: Mode utilitzat per a mesclar amb el color de textura egressat" msgid "Mix" @@ -6025,11 +6037,11 @@ msgstr "Alfa" msgid "Set alpha of selected color stop" -msgstr "[Alpha]: Defineix l'alfa del pas de color seleccionat" +msgstr "[Alpha]: Defineix l'alfa del salt de color seleccionat" msgid "Set color of selected color stop" -msgstr "Defineix el color del pas de color seleccionat" +msgstr "Defineix el color del salt de color seleccionat" msgid "Position" @@ -6037,7 +6049,7 @@ msgstr "Posició" msgid "Set position of selected color stop" -msgstr "Defineix la posició del pas de color seleccionat" +msgstr "Defineix la posició del salt de color seleccionat" msgid "Color Ramp Elements" @@ -6053,15 +6065,15 @@ msgstr "Borns de sortida de documents" msgid "Collection of File Output node slots" -msgstr "[File Output Slots]: Col·lecció dels borns de node de document d'emissió" +msgstr "[File Output Slots]: Col·lecció dels borns de node de document d'egressió" msgid "Console Input" -msgstr "Ingrés de consola" +msgstr "Ingressió de consola" msgid "Input line for the interactive console" -msgstr "[Console Input]: Línia d'ingrés per a la consola interactiva" +msgstr "[Console Input]: Línia d'ingressió per a la consola interactiva" msgctxt "Text" @@ -6074,15 +6086,15 @@ msgstr "[Line]: Text de la línia" msgid "Console line type when used in scrollback" -msgstr "Tipus de línia de la consola quan es repassa el codi rodolant enrere" +msgstr "Tipus de línia de consola quan es rodola enrere" msgid "Output" -msgstr "Emissió" +msgstr "Egressió" msgid "Input" -msgstr "Ingrés" +msgstr "Ingressió" msgid "Error" @@ -6110,7 +6122,7 @@ msgstr "[Lin Error]: Quantitat d'error residual d'una unitat d'espai Blender per msgid "Rotation error" -msgstr "Error de gir" +msgstr "Error de rotació" msgid "Amount of residual error in radians for constraints that work on orientation" @@ -6138,11 +6150,11 @@ msgstr "La restricció té paràmetres vàlids i es pot avaluar" msgid "Disable" -msgstr "Desactiva" +msgstr "Desactivar" msgid "Enable/Disable Constraint" -msgstr "Activar/desactivar restricció" +msgstr "Activa/desactiva la restricció" msgid "Constraint name" @@ -6262,7 +6274,7 @@ msgstr "Resolutor d'objectes" msgid "Copy Location" -msgstr "Copia la ubicació" +msgstr "Copiar ubicació" msgid "Copy the location of a target (with an optional offset), so that they move together" @@ -6270,7 +6282,7 @@ msgstr "[Copy Location]: Copia la ubicació d'un objectiu (amb una separació op msgid "Copy Rotation" -msgstr "Copia la rotació" +msgstr "Copiar rotació" msgid "Copy the rotation of a target (with an optional offset), so that they rotate together" @@ -6278,7 +6290,7 @@ msgstr "[Copy Rotation]: Copia la rotació d'un objectiu (amb un desplaçament o msgid "Copy Scale" -msgstr "Copia l'escala" +msgstr "Copiar escala" msgid "Copy the scale factors of a target (with an optional offset), so that they are scaled by the same amount" @@ -6286,7 +6298,7 @@ msgstr "[Copy Scale]: Copia els factors d'escala d'un referent (amb una separaci msgid "Copy Transforms" -msgstr "Copia les transformacions" +msgstr "Copiar transformacions" msgid "Copy all the transformations of a target, so that they move together" @@ -6294,7 +6306,7 @@ msgstr "[Copy Transfoms]: Copia totes les transformacions d'un referent, de mane msgid "Limit Distance" -msgstr "Limita la distància" +msgstr "Limitar distància" msgid "Restrict movements to within a certain distance of a target (at the time of constraint evaluation only)" @@ -6302,7 +6314,7 @@ msgstr "[Limit Distance]: Restringeix els moviments dins una certa distància en msgid "Limit Location" -msgstr "Limita la ubicació" +msgstr "Limitar ubicació" msgid "Restrict movement along each axis within given ranges" @@ -6310,7 +6322,7 @@ msgstr "[Limit Location]: Restringeix el moviment seguint els eixos dins uns int msgid "Limit Rotation" -msgstr "Limita la rotació" +msgstr "Limitar rotació" msgid "Restrict rotation along each axis within given ranges" @@ -6318,7 +6330,7 @@ msgstr "[Limit Rotation]: Restringeix la rotació seguint cada eix dins uns inte msgid "Limit Scale" -msgstr "Limita l'escala" +msgstr "Limitar escala" msgid "Restrict scaling along each axis with given ranges" @@ -6326,7 +6338,7 @@ msgstr "[Limit Scale]: Restringeix el redimensionament seguint cada eix dins uns msgid "Maintain Volume" -msgstr "Conserva el volum" +msgstr "Conservar volum" msgid "Compensate for scaling one axis by applying suitable scaling to the other two axes" @@ -6342,7 +6354,7 @@ msgstr "[Transformation]: Utilitza una propietat de transformació del referent msgid "Transform Cache" -msgstr "Transformació en memòria cau" +msgstr "Transformar memòria cau" msgid "Look up the transformation matrix from an external file" @@ -6366,7 +6378,7 @@ msgstr "[Damped Track]: Apunta enver un referent a base de realitzar la rotació msgid "Inverse Kinematics" -msgstr "Cinemàtica inversa" +msgstr "Cinemàtica inversa (CI)" msgid "Control a chain of bones by specifying the endpoint target (Bones only)" @@ -6390,7 +6402,7 @@ msgstr "Alinea la cadena d'ossos al llarg d'una corba (només per a ossos)" msgid "Stretch To" -msgstr "Estira envers" +msgstr "Estirar envers" msgid "Stretch along Y-Axis to point towards a target" @@ -6398,11 +6410,11 @@ msgstr "[Stretch]: Estira seguint l'eix Y per apuntar envers un referent" msgid "Track To" -msgstr "Rastreig dirigit" +msgstr "Rastrejar envers" msgid "Legacy tracking constraint prone to twisting artifacts" -msgstr "[Track to]: Antiga restricció de seguiment de rastres propensa a vinclar artefactes" +msgstr "[Track to]: Antiga restricció de seguiment de rastres propensa a tares de vinclatge" msgid "Use transform property of target to look up pose for owner from an Action" @@ -6422,7 +6434,7 @@ msgstr "Fill de" msgid "Make target the 'detachable' parent of owner" -msgstr "[Child Of]: Fes que el referent sigui el pare «separable» del propietari" +msgstr "[Child Of]: Fa que el referent sigui el pare «separable» del propietari" msgid "Floor" @@ -6430,7 +6442,7 @@ msgstr "Basament" msgid "Use position (and optionally rotation) of target to define a 'wall' or 'floor' that the owner can not cross" -msgstr "[Basament]: Utilitza la posició (i opcionalment la rotació) del referent per a definir una «paret» o un «terra» que el propietari no pot travessar" +msgstr "[Floor]: Utilitza la posició (i opcionalment la rotació) del referent per a definir una «paret» o un «terra» que el propietari no pot travessar" msgid "Follow Path" @@ -6438,11 +6450,11 @@ msgstr "Seguir trajecte" msgid "Use to animate an object/bone following a path" -msgstr "[Follow Path]: Fer que un objecte/os es mogui seguint el trajecte definit" +msgstr "[Follow Path]: Fa que un objecte/os es mogui seguint el trajecte definit" msgid "Change pivot point for transforms (buggy)" -msgstr "Canvia el punt sobre el que pivoten les transformacions (propens a errors)" +msgstr "Canviar el punt sobre el que pivoten les transformacions (propens a errors)" msgid "Shrinkwrap" @@ -6474,11 +6486,11 @@ msgstr "[Evaluation Time]: Interpola entre els fotogrames d'inici i final de l'a msgid "Last frame of the Action to use" -msgstr "Últim fotograma de l'acció a utilitzar" +msgstr "Últim fotograma usat per l'acció" msgid "First frame of the Action to use" -msgstr "Primer fotograma de l'acció a utilitzar" +msgstr "Primer fotograma usat per l'acció" msgid "Maximum" @@ -6634,11 +6646,11 @@ msgstr "[Target]: Ossos referents" msgid "Use Envelopes" -msgstr "Usa fundes" +msgstr "Usar fundes" msgid "Multiply weights by envelope for all bones, instead of acting like Vertex Group based blending. The specified weights are still used, and only the listed bones are considered" -msgstr "[Use Envelopes]: Multiplica els pesos per funda per a tots els ossos, enlloc d'actuar com una fusió basada en grup de vèrtexs. Els pesos definits encara s'utilitzen, i només es té en compte els ossos indicats" +msgstr "[Use Envelopes]: Multiplica els pesos per funda per a tots els ossos, enlloc d'actuar com una fusió basada en grup de vèrtexs. Els pesos definits encara s'usen, i només es tenen en compte els ossos indicats" msgid "Use Current Location" @@ -6650,7 +6662,7 @@ msgstr "[Use Current Location]: Utilitza la ubicació de l'os actual per a funde msgid "Preserve Volume" -msgstr "Conserva volum" +msgstr "Conservar volum" msgid "Deform rotation interpolation with quaternions" @@ -6658,7 +6670,7 @@ msgstr "[Preserve Volume]: Deforma la interpolació de rotació amb quaternions" msgid "Camera Solver Constraint" -msgstr "Restricció del resolutor de càmera" +msgstr "Restricció de resolutor de càmera" msgid "Lock motion to the reconstructed camera movement" @@ -6750,7 +6762,7 @@ msgstr "Utilitza la rotació en Z del pare" msgid "Scale X" -msgstr "Escalat X" +msgstr "Escala X" msgid "Use X Scale of Parent" @@ -6758,7 +6770,7 @@ msgstr "[Scale X]: Usa l'escalat en X del pare" msgid "Scale Y" -msgstr "Escalat Y" +msgstr "Escala Y" msgid "Use Y Scale of Parent" @@ -6766,7 +6778,7 @@ msgstr "Usa l'escalat en Y del pare" msgid "Scale Z" -msgstr "Escalat Z" +msgstr "Escala Z" msgid "Use Z Scale of Parent" @@ -6774,7 +6786,7 @@ msgstr "Usa l'escalat en Z del pare" msgid "Clamp To Constraint" -msgstr "Limita a la restricció" +msgstr "Limitar a la restricció" msgid "Constrain an object's location to the nearest point along the target path" @@ -8390,7 +8402,7 @@ msgstr "Per ordre" msgid "Explicitly specify the output euler rotation order" -msgstr "[To Order]: Consigneu explícitament l'ordre de rotació Euler emès" +msgstr "[To Order]: Consigneu explícitament l'ordre de rotació Euler d'egressió" msgid "To Maximum X" @@ -8824,7 +8836,7 @@ msgstr "Segments" msgid "Segments sampled from control points" -msgstr "[Segments]: Mostra de segments recollida a partir de punts de control" +msgstr "[Segments]: Segments generats a partir de punts de control" msgid "Force the path view to fit a defined boundary" @@ -8832,19 +8844,19 @@ msgstr "Obliga que la visualització de trajecte s'ajusti a un límit definit" msgid "Sample Even Lengths" -msgstr "Pren mostra de longituds uniformes" +msgstr "Generar longituds uniformes" msgid "Sample edges with even lengths" -msgstr "Identifica les arestes de longituds uniformes" +msgstr "Genera arestes de longituds uniformes" msgid "Sample Straight Edges" -msgstr "Identifica les vores rectilínies" +msgstr "Generar arestes rectilínies" msgid "Sample edges with vector handles" -msgstr "Pren mostra de vores amb nanses vectorials" +msgstr "Genera arestes amb nanses vectorials" msgid "Point of a path used to define a profile" @@ -9532,14 +9544,14 @@ msgstr "Inverteix filtre de cerca" msgid "Multi-Word Fuzzy Filter" -msgstr "Filtre difús multimot" +msgstr "Filtre borrós multimot" msgid "" "Perform fuzzy/multi-word matching.\n" "Warning: May be slow" msgstr "" -"[Multi-Word Fuzzy Filter]: Executa la detecció difusa/de múltiples paraules.\n" +"[Multi-Word Fuzzy Filter]: Executa la detecció borrosa/de múltiples paraules.\n" "Avís: pot ser lent" @@ -9616,7 +9628,7 @@ msgstr "Referent de controlador" msgid "Source of input values for driver variables" -msgstr "Font dels valors d'ingrés per a les variables del controlador" +msgstr "Font dels valors d'ingressió per a les variables del controlador" msgid "Bone Name" @@ -9899,7 +9911,7 @@ msgstr "Nom que cal utilitzar en la redacció de protocols/funcions (no es perme msgid "Sources of input data for evaluating this variable" -msgstr "Fonts de les dades d'ingrés per avaluar aquesta variable" +msgstr "Fonts de les dades d'ingressió per avaluar aquesta variable" msgid "Single Property" @@ -10347,7 +10359,7 @@ msgstr "OpenEXR" msgid "Output Path" -msgstr "Camí d'emissions" +msgstr "Camí per egressions" msgid "Directory to save the textures" @@ -10359,7 +10371,7 @@ msgstr "Resolució" msgid "Output image resolution" -msgstr "Resolució de la imatge emesa" +msgstr "Resolució de la imatge egressada" msgid "Initial color of the surface" @@ -10399,11 +10411,11 @@ msgstr "Nom de superfície" msgid "Output Name" -msgstr "Nom d'emissió" +msgstr "Nom de l'egressió" msgid "Name used to save output from this surface" -msgstr "[Output Name]: Nom utilitzat per desar el resultat de la superfície" +msgstr "[Output Name]: Nom utilitzat per desar l'egressió de la superfície" msgid "Point Cache" @@ -10499,11 +10511,11 @@ msgstr "[Incremental]: Tot nou desplaçament s'afegeix acumulativament a sobre d msgid "Use Output" -msgstr "Usar emissió" +msgstr "Usar egressió" msgid "Save this output layer" -msgstr "[Use Output]: Desa aquesta capa d'emissió" +msgstr "[Use Output]: Desa aquesta capa d'egressió" msgid "Premultiply Alpha" @@ -10511,7 +10523,7 @@ msgstr "Premultiplica alfa" msgid "Multiply color by alpha (recommended for Blender input)" -msgstr "[Premultiply Alpha]: Multiplica el color per alfa (recomanat com a ingrés per Blender)" +msgstr "[Premultiply Alpha]: Multiplica el color per alfa (recomanat per a ingressió en Blender)" msgid "Use Shrink" @@ -10963,7 +10975,7 @@ msgstr "Punts de mostreig" msgid "Sampled animation data" -msgstr "Dades d'animació de mostreig" +msgstr "Dades mostrejades d'animació" msgid "F-Curve is selected for editing" @@ -11079,7 +11091,7 @@ msgstr "Sense àudio" msgid "Disables audio output, for video-only renders" -msgstr "[No Audio]: Desactiva l'emissió d'àudio per a revelats de només vídeo" +msgstr "[No Audio]: Desactiva l'egressió d'àudio per a revelats de només vídeo" msgid "AAC" @@ -11115,11 +11127,11 @@ msgstr "Vorbis" msgid "Samplerate" -msgstr "Freqüència de mostreig" +msgstr "Taxa de mostreig" msgid "Audio samplerate(samples/s)" -msgstr "[Samplerate]: Freqüència de mostreig de l'àudio (mostres/s)" +msgstr "[Samplerate]: Freqüència de mostreig d'àudio (mostres/s)" msgctxt "Sound" @@ -11144,7 +11156,7 @@ msgstr "Còdec de vídeo" msgid "FFmpeg codec to use for video output" -msgstr "Còdec FFmpeg a usar per a l'emissió de vídeo" +msgstr "Còdec FFmpeg a usar per a l'egressió de vídeo" msgid "No Video" @@ -11152,7 +11164,7 @@ msgstr "Sense vídeo" msgid "Disables video output, for audio-only renders" -msgstr "[No Video]: Desactiva l'emissió de vídeo per a revelats només d'àudio" +msgstr "[No Video]: Desactiva l'egressió de vídeo per a revelats només d'àudio" msgid "DNxHD" @@ -11208,11 +11220,11 @@ msgstr "AV1" msgid "Output Quality" -msgstr "Qualitat d'emissió" +msgstr "Qualitat d'egressió" msgid "Constant Rate Factor (CRF); tradeoff between video quality and file size" -msgstr "[Output Quality]: Factor de velocitat constant (FVC/CRF); equilibri entre la qualitat del vídeo i la mida del document" +msgstr "[Output Quality]: Factor de taxa constant (FVC/CRF); equilibri entre la qualitat del vídeo i la mida del document" msgid "Constant Bitrate" @@ -11220,7 +11232,7 @@ msgstr "Taxa de bits constant" msgid "Configure constant bit rate, rather than constant output quality" -msgstr "[Constant Bitrate]: Configura la taxa de bits constant, preferiblement a la qualitat constant d'emissió" +msgstr "[Constant Bitrate]: Configura la taxa de bits constant, preferiblement a la qualitat constant d'egressió" msgid "Lossless" @@ -11288,7 +11300,7 @@ msgstr "Contenidor" msgid "Output file container" -msgstr "[Container]: Contenidor de document d'emissió" +msgstr "[Container]: Contenidor de document d'egressió" msgid "MPEG-4" @@ -11368,15 +11380,15 @@ msgstr "[Mux Packet Size]: Mida del paquet multiplexat (byte)" msgid "Autosplit Output" -msgstr "Emissió Autosegmentada" +msgstr "Egressió d'autodivisió" msgid "Autosplit output at 2GB boundary" -msgstr "[Autosplit Output]: L'emissió surt en segments de màxim 2GB" +msgstr "[Autosplit Output]: L'egressió surt en segments de màxim 2GB" msgid "Lossless Output" -msgstr "Emetre sense pèrdua" +msgstr "Egressió sense pèrdua" msgid "Use lossless output for video streams" @@ -13554,11 +13566,11 @@ msgstr "Mètode per al mostreig del flux d'alta resolució" msgid "Full Sample" -msgstr "Mostra completa" +msgstr "Mostreig complet" msgid "Nearest" -msgstr "El més proper" +msgstr "Quasi complet" msgid "Lower Concavity" @@ -13578,7 +13590,7 @@ msgstr "[Upper Concavity]: Límit superior de concavitat de malla (els valors el msgid "Mesh generator" -msgstr "Generador de malles" +msgstr "Generador de malla" msgid "Which particle level set generator to use" @@ -13701,6 +13713,11 @@ msgid "Minimum number of particles per cell (ensures that each cell has at least msgstr "Nombre mínim de partícules per cel·la (s'assegura que cada cel·la té almenys aquesta quantitat de partícules )" +msgctxt "Amount" +msgid "Number" +msgstr "Nombre" + + msgid "Particle number factor (higher value results in more particles)" msgstr "Factor de nombre de partícules (un valor més alt dona més partícules)" @@ -13714,7 +13731,7 @@ msgstr "Aleatorietat" msgid "Randomness factor for particle sampling" -msgstr "[Randomness]: Factor aleatori per al mostreig de partícules" +msgstr "[Randomness]: Factor aleatori per a generar partícules" msgid "Particle scale" @@ -13958,7 +13975,7 @@ msgstr "[Potential Radius]: Radi per a calcular el potencial per a cada cel·la msgid "Trapped Air Sampling" -msgstr "Mostreig d'aire capturat" +msgstr "Mostreig d'aire atrapat" msgid "Maximum number of particles generated per trapped air cell per frame" @@ -15002,7 +15019,7 @@ msgstr "Com a tanda de revelat" msgid "Renders Freestyle output to a separate pass instead of overlaying it on the Combined pass" -msgstr "[As Render Pass]: Revela l'emissió de traç manual en una passada per separat en lloc de sobreposar-lo en la passada combinada" +msgstr "[As Render Pass]: Revela l'egressió de traç manual en una passada per separat en lloc de sobreposar-lo en la passada combinada" msgid "Crease Angle" @@ -15586,7 +15603,7 @@ msgstr "Capa de visualització" msgid "Only include Layer in this View Layer render output (leave blank to include always)" -msgstr "[ViewLayer]: Inclou només la capa dins d'aquesta capa de visualització en el revelat finalment emès (deixa en blanc perquè sempre s'hi inclogui)" +msgstr "[ViewLayer]: Inclou només la capa dins d'aquesta capa de visualització en el revelat finalment egressat (deixa en blanc perquè sempre s'hi inclogui)" msgid "Grease Pencil Masking Layers" @@ -15738,7 +15755,7 @@ msgstr "[Lock Axis]: Alinea els traços al pla de visió actual" msgid "Front (X-Z)" -msgstr "Endavant (X-Z)" +msgstr "Frontal (X-Z)" msgid "Project strokes to plane locked to Y" @@ -15746,7 +15763,7 @@ msgstr "[Front (X-Z)]: Projecta els traços al pla travat en Y" msgid "Side (Y-Z)" -msgstr "De costat (Y-Z)" +msgstr "Lateral (Y-Z)" msgid "Project strokes to plane locked to X" @@ -15754,7 +15771,7 @@ msgstr "[Side (Y-Z)]: Projecta els traços del vers el pla travat en X" msgid "Top (X-Y)" -msgstr "Per damunt (X-Y)" +msgstr "Superior (X-Y)" msgid "Project strokes to plane locked to Z" @@ -16864,7 +16881,7 @@ msgstr "[Delay]: Nombre de fotogrames després de cada fotofita de L-dG abans qu msgid "Output Vertex group" -msgstr "Grup de vèrtexs emès" +msgstr "Grup de vèrtexs egressat" msgid "Timing" @@ -17806,11 +17823,11 @@ msgstr "[Offset Towards Custom Camera]: Els traços se separen anant cap a la c msgid "Match Output" -msgstr "Aparellar emissió" +msgstr "Aparellar egressió" msgid "Match output vertex group based on name" -msgstr "[Match Output]: Aparella els grups de vèrtexs emesos en base al nom" +msgstr "[Match Output]: Aparella els grups de vèrtexs egressats en base al nom" msgid "Overlapping Edge Types" @@ -18082,7 +18099,7 @@ msgstr "[Outline Material]: Material utilitzat per traços perimetrals" msgid "Sample Length" -msgstr "Mostra de llargada" +msgstr "Llargada de mostres" msgid "Subdivisions" @@ -18238,11 +18255,11 @@ msgstr "[Adaptatiu]: Usa un algorisme Ramer-Douglas-Peucker per a simplificar el msgid "Sample" -msgstr "Mostratge" +msgstr "Mostreig" msgid "Re-sample the stroke with segments of the specified length" -msgstr "[Sample]: Re- pobla el traç amb segments de la longitud especificada" +msgstr "[Sample]: Es repobla el traç amb segments de la longitud especificada" msgid "Merge" @@ -18582,7 +18599,7 @@ msgstr "Espai de coordenades" msgid "Invert output weight values" -msgstr "Invertir els valors de pesos emesos" +msgstr "Invertir els valors de pesos egressats" msgid "Multiply Weights" @@ -19043,11 +19060,11 @@ msgstr "[Visible Layers]: Visibilitat de la capa d'esquelet" msgid "Layer Proxy Protection" -msgstr "Protecció de capa de intermediaris" +msgstr "Protecció de capa d'intermediaris" msgid "Protected layers in Proxy Instances are restored to Proxy settings on file reload and undo" -msgstr "[Layer Proxy Protection]: Les capes protegides en instàncies intermediades es retornen a la configuració dels intermediaris mediació quan es recarrega el document i es fa desfer" +msgstr "[Layer Proxy Protection]: Les capes protegides en instàncies d'intermediaris es retornen a la configuració dels intermediaris quan es recarrega el document i es s'activa desfer" msgid "Pose Position" @@ -19119,7 +19136,7 @@ msgstr "Radi d'àrea" msgid "Ratio between the brush radius and the radius that is going to be used to sample the area center" -msgstr "[Area Radius]: Proporció entre el radi del pinzell i el radi que s'utilitzarà per recollir dades de l'àrea central" +msgstr "[Area Radius]: Proporció entre el radi del pinzell i el radi que s'utilitzarà per mostrejar l'àrea central" msgid "Auto-Smooth" @@ -19542,6 +19559,61 @@ msgid "Editable falloff curve" msgstr "Corba editable de decaïment" +msgctxt "Curves" +msgid "Curve Preset" +msgstr "Predefinit de corba" + + +msgctxt "Curves" +msgid "Custom" +msgstr "Personalitzat" + + +msgctxt "Curves" +msgid "Smooth" +msgstr "Suavitzar" + + +msgctxt "Curves" +msgid "Smoother" +msgstr "Suavitzar més" + + +msgctxt "Curves" +msgid "Sphere" +msgstr "Esfera" + + +msgctxt "Curves" +msgid "Root" +msgstr "Arrel" + + +msgctxt "Curves" +msgid "Sharp" +msgstr "Aguda" + + +msgctxt "Curves" +msgid "Linear" +msgstr "Lineal" + + +msgctxt "Curves" +msgid "Sharper" +msgstr "Més aguda" + + +msgctxt "Curves" +msgid "Inverse Square" +msgstr "Quadrat invers" + + +msgctxt "Curves" +msgid "Constant" +msgstr "Constant" + + msgid "Curves Sculpt Settings" msgstr "Configuració de corbes d'escultura" @@ -19599,7 +19671,7 @@ msgstr "Fracció de guionet" msgid "Ratio of samples in a cycle that the brush is enabled" -msgstr "[Dash Ratio]: Relació de moments dins un cicle en el qual el pinzell està habilitat" +msgstr "[Dash Ratio]: Relació de mostres dins un cicle en el qual el pinzell està habilitat" msgid "Dash Length" @@ -19947,7 +20019,7 @@ msgstr "Radi normal" msgid "Ratio between the brush radius and the radius that is going to be used to sample the normal" -msgstr "[Normal Radius]: Relació entre el radi del pinzell i el radi que s'utilitzarà per a recollir la normal" +msgstr "[Normal Radius]: Relació entre el radi del pinzell i el radi que s'utilitzarà per a mostrejar la normal" msgid "Normal Weight" @@ -20327,7 +20399,7 @@ msgstr "Alfa de sobrecobert de textura" msgid "Texture Sample Bias" -msgstr "Biaix de mostra de textura" +msgstr "Biaix de mostreig de textura" msgid "Value added to texture samples" @@ -20483,7 +20555,7 @@ msgstr "Fixa límit de simulació" msgid "Lock the position of the vertices in the simulation falloff area to avoid artifacts and create a softer transition with unaffected areas" -msgstr "[Pin Simulation Boundary]: Bloqueja la posició dels vèrtexs en el decaïment de la simulació per evitar artefactes i crear una transició més suau amb les àrees no afectades" +msgstr "[Pin Simulation Boundary]: Bloqueja la posició dels vèrtexs en el decaïment de la simulació per evitar tares i crear una transició més suau amb les àrees no afectades" msgid "Vector Displacement" @@ -20671,7 +20743,7 @@ msgstr "Usar esculpir" msgid "Use this brush in sculpt mode" -msgstr "[Use Sculpt]: Usa aquest pinzell en el mode d'esculpir" +msgstr "[Use Sculpt]: Usa aquest pinzell en el mode escultura" msgid "Use this brush in sculpt curves mode" @@ -20683,7 +20755,7 @@ msgstr "Usar esculpir UV" msgid "Use this brush in UV sculpt mode" -msgstr "[Use UV Sculpt]: Usa aquest pinzell en el mode d'escultura UV" +msgstr "[Use UV Sculpt]: Usa aquest pinzell en el mode escultura UV" msgid "Use Vertex" @@ -20895,7 +20967,7 @@ msgstr "Radi de pintura humida" msgid "Ratio between the brush radius and the radius that is going to be used to sample the color to blend in wet paint" -msgstr "[Wet Paint Radius]: Relació entre el radi del pinzell i el radi que s'utilitzarà per a treure mostres de cara a la fusió en pintura humida" +msgstr "[Wet Paint Radius]: Relació entre el radi del pinzell i el radi que s'utilitzarà per a mostrejar el color per gradualitzar la pintura humida" msgid "Wet Persistence" @@ -20986,10 +21058,25 @@ msgid "Name of the Alembic attribute used for generating motion blur data" msgstr "[Velocity Attribute]: Nom de l'atribut d'Alembic utilitzat per generar dades de difuminat de moviment" +msgctxt "Unit" +msgid "Velocity Unit" +msgstr "Unitat de velocitat" + + msgid "Define how the velocity vectors are interpreted with regard to time, 'frame' means the delta time is 1 frame, 'second' means the delta time is 1 / FPS" msgstr "[Velocity Unit]: Defineix com s'interpreten els vectors de velocitat respecte del temps, «fotograma» implica que el temps delta és 1 fotograma, «segon» significa que el temps delta és 1 / FPS" +msgctxt "Unit" +msgid "Second" +msgstr "Segon" + + +msgctxt "Unit" +msgid "Frame" +msgstr "Fotograma" + + msgid "Camera data-block for storing camera settings" msgstr "Bloc de dades de càmera per guardar-hi la configuració de la càmera" @@ -22175,7 +22262,7 @@ msgstr "Angle màxim 2D" msgid "Maximum 2D angle for splitting chains" -msgstr "Angle màxim 2D perquè les cadenes es parteixin" +msgstr "Angle màxim 2D perquè les cadenes es divideixin" msgid "Min 2D Angle" @@ -22183,7 +22270,7 @@ msgstr "Angle mínim 2D" msgid "Minimum 2D angle for splitting chains" -msgstr "Angle mínim 2D perquè les cadenes es parteixin" +msgstr "Angle mínim 2D perquè les cadenes es divideixin" msgid "Caps" @@ -22379,7 +22466,7 @@ msgstr "[Min 2D Length]: Longitud mínima curvilínia 2D per a la selecció de c msgid "If true, chains of feature edges are split at material boundaries" -msgstr "Si es defineix com a ver, les cadenes de secs es divideixen en els límits dels materials" +msgstr "Si es defineix com a ver, les cadenes de secs es parteixen en els límits dels materials" msgid "Node Tree" @@ -23075,7 +23162,7 @@ msgstr "BMP" msgid "Output image in bitmap format" -msgstr "Imatge emesa en format de mapa de bits" +msgstr "Imatge egressada en format de mapa de bits" msgid "Iris" @@ -23083,11 +23170,11 @@ msgstr "Iris" msgid "Output image in SGI IRIS format" -msgstr "Imatge emesa en format SGI IRIS" +msgstr "Imatge egressada en format SGI IRIS" msgid "Output image in PNG format" -msgstr "Imatge emesa en format PNG" +msgstr "Imatge egressada en format PNG" msgid "JPEG" @@ -23095,7 +23182,7 @@ msgstr "JPEG" msgid "Output image in JPEG format" -msgstr "Imatge emesa en format JPEG" +msgstr "Imatge egressada en format JPEG" msgid "JPEG 2000" @@ -23103,7 +23190,7 @@ msgstr "JPEG 2000" msgid "Output image in JPEG 2000 format" -msgstr "Imatge emesa en format JPEG 2000" +msgstr "Imatge egressada en format JPEG 2000" msgid "Targa" @@ -23111,7 +23198,7 @@ msgstr "Targa" msgid "Output image in Targa format" -msgstr "Imatge emesa en format Targa" +msgstr "Imatge egressada en format Targa" msgid "Targa Raw" @@ -23119,7 +23206,7 @@ msgstr "Targa brut" msgid "Output image in uncompressed Targa format" -msgstr "Imatge emesa en format Targa sense comprimir" +msgstr "Imatge egressada en format Targa sense comprimir" msgid "Cineon" @@ -23127,7 +23214,7 @@ msgstr "Cineon" msgid "Output image in Cineon format" -msgstr "Imatge emesa en format Cineon" +msgstr "Imatge egressada en format Cineon" msgid "DPX" @@ -23135,7 +23222,7 @@ msgstr "DPX" msgid "Output image in DPX format" -msgstr "Imatge emesa en format DPX" +msgstr "Imatge egressada en format DPX" msgid "OpenEXR MultiLayer" @@ -23143,11 +23230,11 @@ msgstr "OpenEXR multicapa" msgid "Output image in multilayer OpenEXR format" -msgstr "Imatge emesa en format OpenEXR multicapa" +msgstr "Imatge egressada en format OpenEXR multicapa" msgid "Output image in OpenEXR format" -msgstr "Imatge emesa en format OpenEXR" +msgstr "Imatge egressada en format OpenEXR" msgid "Radiance HDR" @@ -23155,7 +23242,7 @@ msgstr "Radiance HDR o RGBE" msgid "Output image in Radiance HDR format" -msgstr "Imatge emesa en format Radiance HDR o RGBE" +msgstr "Imatge egressada en format Radiance HDR o RGBE" msgid "TIFF" @@ -23163,7 +23250,7 @@ msgstr "TIFF" msgid "Output image in TIFF format" -msgstr "Imatge emesa en format TIFF" +msgstr "Imatge egressada en format TIFF" msgid "WebP" @@ -23171,7 +23258,7 @@ msgstr "WebP" msgid "Output image in WebP format" -msgstr "Imatge emesa en format WebP" +msgstr "Imatge egressada en format WebP" msgid "AVI JPEG" @@ -23179,7 +23266,7 @@ msgstr "AVI JPEG" msgid "Output video in AVI JPEG format" -msgstr "Vídeo emesa en format AVI JPEG" +msgstr "Vídeo egressada en format AVI JPEG" msgid "AVI Raw" @@ -23187,7 +23274,7 @@ msgstr "AVI brut" msgid "Output video in AVI Raw format" -msgstr "Vídeo emesa en format AVI Raw o brut" +msgstr "Vídeo egressada en format AVI Raw o brut" msgid "FFmpeg Video" @@ -23628,7 +23715,7 @@ msgstr "Factor difusió" msgid "Diffuse reflection multiplier" -msgstr "[Diffuse Factor]: Multiplicador de reflex de difusió" +msgstr "[Diffuse Factor]: Multiplicador de reflex difusiu" msgid "Falloff distance - the light is at half the original intensity at this point" @@ -23838,7 +23925,7 @@ msgstr "Mostres" msgid "Number of shadow buffer samples" -msgstr "[Samples]: Nombre de mostres que agafa el regulador d'ombra" +msgstr "[Samples]: Nombre de mostres al regulador d'ombra" msgid "Shadow Buffer Size" @@ -24226,7 +24313,7 @@ msgstr "Alfa resumit" msgid "Use noise to dither the binary visibility (works well with multi-samples)" -msgstr "[Alfa Hashed]: Utilitza el soroll per distorsionar la visibilitat binària (funciona bé amb múlti-mostres)" +msgstr "[Alfa Hashed]: Utilitza el soroll per distorsionar la visibilitat binària (funciona bé amb multi-mostres)" msgid "Alpha Blend" @@ -24246,7 +24333,7 @@ msgstr "[Cycles Material Settings]: Paràmetres de materials en Cycles" msgid "Diffuse Color" -msgstr "Color de difusió" +msgstr "Color difusiu" msgid "Diffuse color of the material" @@ -24474,7 +24561,7 @@ msgstr "Autosuavitzar angle" msgid "Maximum angle between face normals that will be considered as smooth (unused if custom split normals data are available)" -msgstr "[Auto Smooth Angle]: Angle màxim entre les normals de les cares que es consideraran com a suaus (no s'utilitza si hi ha presents dades de normals partits personalitzades)" +msgstr "[Auto Smooth Angle]: Angle màxim entre les normals de les cares que es consideraran com a suaus (no s'utilitza si hi ha presents dades de normals dividides personalitzades)" msgid "Edge Creases" @@ -24530,7 +24617,7 @@ msgstr "Té normals personalitzats" msgid "True if there are custom split normals data in this mesh" -msgstr "[Has Custom Normals]: Ver si hi ha dades de normals partides personalitzades en aquesta malla" +msgstr "[Has Custom Normals]: Ver si hi ha dades de normals dividides personalitzades en aquesta malla" msgid "Loop Triangles" @@ -24682,7 +24769,7 @@ msgstr "Autosuavitzar" msgid "Auto smooth (based on smooth/sharp faces/edges and angle between faces), or use custom split normals data if available" -msgstr "[Auto Smooth]: Suavitzat automàtic (basat en cares/vores suaus/sobtades i en l'angle entre les cares), o usa dades de normals partides personalitzades si estan disponibles" +msgstr "[Auto Smooth]: Suavitzat automàtic (basat en cares/vores suaus/sobtades i en l'angle entre les cares), o usa dades de normals dividides personalitzades si estan disponibles" msgid "Topology Mirror" @@ -24942,11 +25029,11 @@ msgstr "Document de vídeo" msgid "Use Proxy / Timecode" -msgstr "Usar simulació / timecode" +msgstr "Usar simulació / cronofita" msgid "Use a preview proxy and/or timecode index for this clip" -msgstr "[Use Proxy / Timecode]: Usa un vídeo de simulació per previsualitzar i /o un índex de timecodes per a aquest clip" +msgstr "[Use Proxy / Timecode]: Usa un vídeo de simulació per previsualitzar i /o un índex de cronofites per a aquest clip" msgid "Proxy Custom Directory" @@ -24962,19 +25049,19 @@ msgstr "Arbre de nodes que consisteix en nodes enllaçats utilitzats per a l'asp msgid "Active Input" -msgstr "Ingrés actiu" +msgstr "Entrada activa" msgid "Index of the active input" -msgstr "Índex de l'ingrés activa" +msgstr "Índex de l'entrada activa" msgid "Active Output" -msgstr "Emissió activa" +msgstr "Sortida activa" msgid "Index of the active output" -msgstr "[Active Output]: Índex de l'emissió activa" +msgstr "[Active Output]: Índex de la sortida activa" msgid "ID Name" @@ -24998,7 +25085,7 @@ msgstr "[Grease Pencil Data]: Bloc de dades del llapis de greix" msgid "Inputs" -msgstr "Borns d'ingrés" +msgstr "Borns d'entrada" msgid "Node tree inputs" @@ -25018,7 +25105,7 @@ msgstr "Sortides" msgid "Node tree outputs" -msgstr "[Outputs]: Sortides de l'arbre de nodes" +msgstr "[Outputs]: Egressors de l'arbre de nodes" msgid "Node Tree type (deprecated, bl_idname is the actual node tree type identifier)" @@ -25654,7 +25741,7 @@ msgstr "[Material Slots]: Epígrafs amb els materials de l'objecte" msgid "Input Matrix" -msgstr "Matriu d'ingrés" +msgstr "Matriu d'ingressió" msgid "Matrix access to location, rotation and scale (including deltas), before constraints and parenting are applied" @@ -26042,7 +26129,7 @@ msgstr "Usar alfa" msgid "Use alpha blending instead of alpha test (can produce sorting artifacts)" -msgstr "[Use Alpha]: Usa la fusió d'alfa en lloc del test alfa (pot desencadenar l'ordenació d'artefactes)" +msgstr "[Use Alpha]: Usa la fusió d'alfa en lloc del test alfa (pot desencadenar tares d'ordenació)" msgid "Lights affect grease pencil object" @@ -26102,7 +26189,7 @@ msgstr "[Camera Visibility]: Visibilitat de l'objecte als raigs de la càmera" msgid "Diffuse Visibility" -msgstr "Visibilitat difusa" +msgstr "Visibilitat difusiva" msgid "Object visibility to diffuse rays" @@ -27824,7 +27911,7 @@ msgstr "Document de mostra de so utilitzat per aquest bloc de dades de so" msgid "Samplerate of the audio in Hz" -msgstr "Freqüència de mostratge de l'àudio en Hz" +msgstr "Taxa de mostreig d'àudio en Hz" msgid "Caching" @@ -28012,6 +28099,11 @@ msgid "Text file on disk is different than the one in memory" msgstr "[Modified]: El document de text del disc és diferent del de la memòria" +msgctxt "Text" +msgid "Lines" +msgstr "Línies" + + msgid "Lines of text" msgstr "Línies del text" @@ -28369,7 +28461,7 @@ msgstr "Mida del soroll" msgid "Scaling for noise input" -msgstr "Escalat per a l'ingrés de soroll" +msgstr "Escalat per a la ingressió de soroll" msgid "Noise Type" @@ -28539,7 +28631,7 @@ msgstr "Filtre" msgid "Texture filter to use for sampling image" -msgstr "Filtre de textura a usar per recollir mostres de la imatge" +msgstr "Filtre de textura per al mostreig d'imatge" msgid "EWA" @@ -28631,7 +28723,7 @@ msgstr "Filtre gaussià de mapa MIP" msgid "Use Gauss filter to sample down MIP maps" -msgstr "[MIP Map Gaussian filter]: Usa el filtre de Gauss per a seleccionar en els mapes MIP" +msgstr "[MIP Map Gaussian filter]: Usa el filtre de Gauss per a mostrejar en els mapes MIP" msgid "Mirror X" @@ -28891,7 +28983,7 @@ msgstr "Mètrica de distància" msgid "Algorithm used to calculate distance of sample points to feature points" -msgstr "[Distance Metric]: Algorisme utilitzat per calcular la distància dels punts de mostra als punts destacats" +msgstr "[Distance Metric]: Algorisme utilitzat per calcular la distància dels punts generats als punts destacats" msgid "Actual Distance" @@ -29271,7 +29363,7 @@ msgstr "Mode edició llapis de greix" msgid "Grease Pencil Sculpt Mode" -msgstr "Mode escultura llapis de greix" +msgstr "Mode escultura amb llapis de greix" msgid "Grease Pencil Draw" @@ -29859,7 +29951,7 @@ msgstr "J2K" msgid "Output color space settings" -msgstr "Paràmetres d'espai de color emès" +msgstr "Paràmetres d'espai de color egressat" msgid "Quality for image formats that support lossy compression" @@ -31143,7 +31235,7 @@ msgstr ">>|" msgctxt "UI_Events_KeyMaps" msgid "Text Input" -msgstr "Ingrés de text" +msgstr "Ingressió de text" msgid "TxtIn" @@ -31610,7 +31702,7 @@ msgstr "NDOF" msgid "Text Input" -msgstr "Introducció de text" +msgstr "Ingressió de text" msgid "Timer" @@ -32575,7 +32667,7 @@ msgstr "Interval màxim" msgid "Upper bound of the input range the mapping is applied" -msgstr "[Range Max]: Límit superior de l'interval d'ingrés que s'aplica al mapejat" +msgstr "[Range Max]: Límit superior de l'interval d'ingressió que s'aplica al mapejat" msgid "Range Min" @@ -32583,7 +32675,7 @@ msgstr "Interval mínim" msgid "Lower bound of the input range the mapping is applied" -msgstr "[Range Min]: Límit inferior de l'interval d'ingrés que s'aplica el mapejat" +msgstr "[Range Min]: Límit inferior de l'interval d'ingressió que s'aplica el mapejat" msgid "Change alpha transparency based on the distance from an object" @@ -32623,15 +32715,15 @@ msgstr "Color de línia alfa" msgid "Diffuse Color Red" -msgstr "Color difusió Vermell" +msgstr "Color difusiu Vermell" msgid "Diffuse Color Green" -msgstr "Color difusió verd" +msgstr "Color difusiu verd" msgid "Diffuse Color Blue" -msgstr "Color difusió blau" +msgstr "Color difusiu blau" msgid "Specular Color Red" @@ -32791,7 +32883,7 @@ msgstr "Soroll espacial" msgid "Tip Remover" -msgstr "Treure les pistes" +msgstr "Treure puntes" msgid "Displacement that is applied to the X coordinates of stroke vertices" @@ -33063,11 +33155,11 @@ msgstr "Treu un tros de traç al començament i al final del nervi del traç" msgid "Tip Length" -msgstr "Llargada de pistes" +msgstr "Llargada de puntes" msgid "Length of tips to be removed" -msgstr "[Tip Length]: Longitud de les pistes que s'eliminaran" +msgstr "[Tip Length]: Longitud de les puntes que s'eliminaran" msgid "Line Style Thickness Modifier" @@ -33091,7 +33183,7 @@ msgstr "Valor màxim" msgid "Maximum output value of the mapping" -msgstr "[Value Max]: Valor màxim d'emissió del mapejat" +msgstr "[Value Max]: Valor màxim d'egressió del mapejat" msgid "Value Min" @@ -33099,7 +33191,7 @@ msgstr "Valor mínim" msgid "Minimum output value of the mapping" -msgstr "[Value Min]: Valor mínim d'emissió del mapejat" +msgstr "[Value Min]: Valor mínim d'egressió del mapejat" msgid "Change line thickness so that stroke looks like made with a calligraphic pen" @@ -33507,6 +33599,10 @@ msgid "Active spline of masking layer" msgstr "Spline activa de la capa d'emmascarament" +msgid "Active Point" +msgstr "Punt actiu" + + msgid "Grease Pencil Color" msgstr "Color del llapis de greix" @@ -34044,6 +34140,11 @@ msgid "Write" msgstr "Escriptura" +msgctxt "NodeTree" +msgid "Constant" +msgstr "Constant" + + msgid "Instances" msgstr "Instàncies" @@ -34478,7 +34579,7 @@ msgstr "Punt de vista" msgid "Landmark Controls" -msgstr "Controls de punts de referència" +msgstr "Controls de senyaler" msgid "Lightgroup Sync" @@ -34638,11 +34739,11 @@ msgstr "[Edge Index]: L'índex d'aquest bucle" msgid "Local space unit length split normal vector of this vertex for this polygon (must be computed beforehand using calc_normals_split or calc_tangents)" -msgstr "Vector normal unitari escindit en llargada dins l'espai local per a aquest vèrtex d'aquest polígon (s'ha de calcular d'avançada amb calc_normals_split o calc_tangents)" +msgstr "El vector d'unitat de normal dividida en llargada dins l'espai local per a aquest vèrtex d'aquest polígon (s'ha de calcular d'avançada amb calc_normals_split o calc_tangents)" msgid "Local space unit length tangent vector of this vertex for this polygon (must be computed beforehand using calc_tangents)" -msgstr "Vector tangent unitari en llargada dins l'espai local per a aquest vèrtex d'aquest polígon (s'ha de calcular d'avançada amb calc_tangents)" +msgstr "El vector d'unitat de llargada de tangent dividida d'aquest vèrtex en aquest polígon (s'ha de calcular d'avançada amb calc_tangents)" msgid "Vertex index" @@ -34734,7 +34835,7 @@ msgstr "Normals escindides" msgid "Local space unit length split normals vectors of the vertices of this triangle (must be computed beforehand using calc_normals_split or calc_tangents)" -msgstr "[Split Normals]: Vectors normals unitaris escindits en llargada dins l'espai local dels vèrtexs d'aquest triangle (s'han de calcular d'avançada amb calc_normals_split o calc_tangents)" +msgstr "[Split Normals]: Els vectors d'unitat de normal dividida en llargada en l'espai local dels vèrtexs d'aquest triangle (s'han de calcular d'avançada amb calc_normals_split o calc_tangents)" msgid "Indices of triangle vertices" @@ -37454,7 +37555,7 @@ msgstr "Nombre aproximat de vòxels al llarg d'un eix" msgid "Smaller values result in a higher resolution output" -msgstr "Els valors més petits emeten en una resolució més alta" +msgstr "Els valors més petits egressen en una resolució més alta" msgid "Mirroring modifier" @@ -37622,7 +37723,7 @@ msgstr "Nivells d'esculpir" msgid "Number of subdivisions to use in sculpt mode" -msgstr "[Sculpt Levels]: Nombre de subdivisions a utilitzar en el mode d'escultura" +msgstr "[Sculpt Levels]: Nombre de subdivisions a utilitzar en el mode escultura" msgid "Optimal Display" @@ -37662,7 +37763,7 @@ msgstr "Malla base d'escultura" msgid "Make Sculpt Mode tools deform the base mesh while previewing the displacement of higher subdivision levels" -msgstr "[Sculpt Base Mesh]: Fa que les eines del mode d'esculpir deformin la malla base mentre es previsualitza la separació de nivells de subdivisió més alts" +msgstr "[Sculpt Base Mesh]: Fa que les eines del mode escultura deformin la malla base mentre es previsualitza la separació de nivells de subdivisió més alts" msgid "UV Smooth" @@ -38026,7 +38127,7 @@ msgstr "Genera normals" msgid "Output normals for bump mapping - disabling can speed up performance if it's not needed" -msgstr "[Generate Normals]: Normals emeses per a mapejat de relleu - desactivant-ho pot millorar el rendiment si no és necessari" +msgstr "[Generate Normals]: Normals egressades per a mapejar relleu - desactivant-ho pot millorar el rendiment si no és necessari" msgid "Generate Spray Map" @@ -38235,19 +38336,19 @@ msgstr "Blocs" msgid "Output a blocky surface with no smoothing" -msgstr "[Blocks]: Emet una superfície cantelluda sense suavitzar" +msgstr "[Blocks]: Egressa una superfície cantelluda sense suavitzar" msgid "Output a smooth surface with no sharp-features detection" -msgstr "Emet una superfície llisa sense elements cantelluts" +msgstr "Egressa una superfície llisa sense elements cantelluts" msgid "Output a surface that reproduces sharp edges and corners from the input mesh" -msgstr "Emet una superfície que reprodueix vores i cantonades agudes de la malla ingressada" +msgstr "Egressa una superfície que reprodueix vores i cantonades agudes de la malla ingressada" msgid "Output a mesh corresponding to the volume of the original mesh" -msgstr "Emet una malla corresponent al volum de la malla original" +msgstr "Egressa una malla corresponent al volum de la malla original" msgid "Octree Depth" @@ -38267,7 +38368,7 @@ msgstr "Agudesa" msgid "Tolerance for outliers; lower values filter noise while higher values will reproduce edges closer to the input" -msgstr "[Sharpness]: Tolerància per a valors atípics; els valors menors filtren soroll mentre valors ,majors reprodueixen arestes més semblants a l'ingressat" +msgstr "[Sharpness]: Tolerància per a valors atípics; els valors menors filtren soroll mentre valors ,majors reprodueixen arestes més semblants a la ingressió" msgid "If removing disconnected pieces, minimum size of components to preserve as a ratio of the number of polygons in the largest component" @@ -38283,7 +38384,7 @@ msgstr "Aspecte suau" msgid "Output faces with smooth shading rather than flat shaded" -msgstr "[Smooth Shading]: Emet cares d'aspecte suau més que no aplanat" +msgstr "[Smooth Shading]: Egressa cares d'aspecte suau més que no aplanat" msgid "Screw Modifier" @@ -38607,7 +38708,7 @@ msgstr "Selecciona l'algorisme utilitzat" msgid "Output a solidified version of a mesh by simple extrusion" -msgstr "Emet una versió solidificada d'una malla per simple extrusió" +msgstr "Egressa una versió solidificada d'una malla per simple extrusió" msgid "Complex" @@ -38615,7 +38716,7 @@ msgstr "Complex" msgid "Output a manifold mesh even if the base mesh is non-manifold, where edges have 3 or more connecting faces. This method is slower" -msgstr "Emet una malla complexa fins i tot si la malla base no és conplexa, on les arestes tenen 3 o més cares que es toquen. Aquest mètode és més lent" +msgstr "Egressa una malla complexa fins i tot si la malla base no és conplexa, on les arestes tenen 3 o més cares que es toquen. Aquest mètode és més lent" msgid "Thickness of the shell" @@ -39330,7 +39431,7 @@ msgstr "[Texture Mid Level]: Se sostreu del color de la textura per a treure'n u msgid "Texture Sample Radius" -msgstr "Radi de mostra de textura" +msgstr "Radi de mostreig de textura" msgid "Smaller values result in better performance but might cut off the volume" @@ -39518,7 +39619,7 @@ msgstr "Mantenir agut" msgid "Keep sharp edges as computed for default split normals, instead of setting a single weighted normal for each vertex" -msgstr "[Keep Sharp]: Manté els cantells aguts segons còmput per a normals partides per defecte, en lloc de definir una normal amb pesos per a cada vèrtex" +msgstr "[Keep Sharp]: Manté els cantells aguts segons còmput per a normals dividides per defecte, en lloc de definir una normal amb pesos per a cada vèrtex" msgid "Weighting Mode" @@ -39750,7 +39851,7 @@ msgstr "Projecció lliure" msgid "Build free run time code index" -msgstr "[Free Run]: Crea un índex de timecodes per a projecció lliure" +msgstr "[Free Run]: Crea un índex de cronofites per a projecció lliure" msgid "Free Run (Rec Date)" @@ -39758,7 +39859,7 @@ msgstr "Projecció lliure (data de gravació)" msgid "Build free run time code index using Record Date/Time" -msgstr "[Free Run (Rec Date)]: Crea índex de timecodes de projecció en base al temps/data de gravació" +msgstr "[Free Run (Rec Date)]: Crea índex de cronofites de projecció en base al temps/data de gravació" msgid "Rec Run" @@ -39766,7 +39867,7 @@ msgstr "Porjecció de gravació" msgid "Build record run time code index" -msgstr "[Rec Run]: Crea índex de timecodes de projecció de gravació" +msgstr "[Rec Run]: Crea índex de cronofites de projecció de gravació" msgid "Build proxy resolution 100% of the original undistorted footage dimension" @@ -39774,15 +39875,15 @@ msgstr "Crear resolució de la simulació al 100% de la dimensió original del m msgid "Build proxy resolution 25% of the original undistorted footage dimension" -msgstr "Crear resolució de la silmulació al 25% de la dimensió original del metratge sense distorsió" +msgstr "Crear resolució de la simulació al 25% de la dimensió original del metratge sense distorsió" msgid "Build proxy resolution 50% of the original undistorted footage dimension" -msgstr "Crear resolució de la silmulació al 50% de la dimensió original del metratge sense distorsió" +msgstr "Crear resolució de la simulació al 50% de la dimensió original del metratge sense distorsió" msgid "Build proxy resolution 75% of the original undistorted footage dimension" -msgstr "Crear resolució de la silmulació al 75% de la dimensió original del metratge sense distorsió" +msgstr "Crear resolució de la simulació al 75% de la dimensió original del metratge sense distorsió" msgid "Location to store the proxy files" @@ -39794,7 +39895,7 @@ msgstr "Qualitat JPEG de les imatges simulades" msgid "Timecode" -msgstr "Timecode" +msgstr "Cronofita" msgid "Record Run" @@ -39822,7 +39923,7 @@ msgstr "Projecció lliure sense espais" msgid "Record run, but ignore timecode, changes in framerate or dropouts" -msgstr "[Free Run No Gaps]: Projecció de gravació, però ignora el segell de temps, els canvis en fotogrames/s o els orfes" +msgstr "[Free Run No Gaps]: Projecció de gravació, però ignora la cronofita, els canvis en fotogrames/s o els orfes" msgid "Scopes for statistical view of a movie clip" @@ -39842,7 +39943,7 @@ msgstr "Número del fotograma actual del vídeo o seqüència d'imatges" msgid "Proxy Render Size" -msgstr "Mida de revelat simulat" +msgstr "Mida de revelat de la simulació" msgid "Display preview using full resolution or different proxy resolutions" @@ -41268,7 +41369,7 @@ msgstr "Enllaços interns" msgid "Internal input-to-output connections for muting" -msgstr "Connexions internes d'ingrés a emissió per silenciar" +msgstr "Connexions internes d'ingressió-egressió per silenciar" msgid "Optional custom node label" @@ -41348,7 +41449,7 @@ msgstr "Límit de contrast" msgid "How much to eliminate spurious edges to avoid artifacts (the larger value makes less active; the value 2.0, for example, means discard a detected edge if there is a neighboring edge that has 2.0 times bigger contrast than the current one)" -msgstr "[Contrast Limit]: Fins a quin punt s'han d'eliminar les arestes espúries per evitar artefactes (el valor més gran ho fa menys actiu; el valor 2.0, per exemple, significa descartar una aresta detectada si hi ha una aresta veïna que té 2,0 vegades més contrast que l'actual)" +msgstr "[Contrast Limit]: Fins a quin punt s'han d'eliminar les arestes espúries per evitar tares (el valor més gran ho fa menys actiu; el valor 2.0, per exemple, significa descartar una aresta detectada si hi ha una aresta veïna que té 2,0 vegades més contrast que l'actual)" msgid "Corner Rounding" @@ -41440,7 +41541,7 @@ msgstr "Mida variable" msgid "Support variable blur per pixel when using an image for size input" -msgstr "[Variable Size]: Permet el difuminat variable per píxel quan s'utilitza una imatge per a ingressar la mida" +msgstr "[Variable Size]: Permet el difuminat variable per píxel quan s'utilitza una imatge per a ingressar-ne la mida" msgid "Bokeh Blur" @@ -41532,7 +41633,7 @@ msgstr "Brillantor/Contrast" msgid "Keep output image premultiplied alpha" -msgstr "Mantén l'alfa premultiplicada de la imatge emesa" +msgstr "Mantén l'alfa premultiplicada de la imatge egressada" msgid "Channel Key" @@ -42048,7 +42149,7 @@ msgstr "Destí" msgid "Color space of the output image" -msgstr "Espai cromàtic de la imatge emesa" +msgstr "Espai cromàtic de la imatge egressada " msgid "Corner Pin" @@ -42288,7 +42389,7 @@ msgstr "Usar estalvi-Z" msgid "Disable when using an image as input instead of actual z-buffer (auto enabled if node not image based, eg. time node)" -msgstr "[Use Z-Buffer]: Desactivar quan s'usi una imatge com a ingrés enlloc de les dades d'estalvi de z (s'autoactiva si el node no és d'imatge, p. ex. el node temps)" +msgstr "[Use Z-Buffer]: Desactivar quan s'usi una imatge com a ingressió enlloc de les dades d'estalvi de z (s'autoactiva si el node no és d'imatge, p. ex. el node temps)" msgid "Z-Scale" @@ -42296,15 +42397,15 @@ msgstr "Escala-Z" msgid "Scale the Z input when not using a z-buffer, controls maximum blur designated by the color white or input value 1" -msgstr "[Escala Z]: Escala l'ingrés de Z quan no s'usa l'estalvi-Z, controla el difuminat màxim designat pel color blanc o el valor d'entrada 1" +msgstr "[Escala Z]: Escala la ingressió de Z quan no s'usa l'estalvi-Z, controla el difuminat màxim designat pel color blanc o el valor d'entrada 1" msgid "Denoise" -msgstr "Desempolsegar" +msgstr "Desorollar" msgid "Denoising prefilter" -msgstr "[Denoise]: Prefiltre de treure la pols" +msgstr "[Denoise]: Prefiltre de desorolleig" msgid "No prefiltering, use when guiding passes are noise-free" @@ -42312,7 +42413,7 @@ msgstr "Sense prefiltrat, usar quan les passades guia no tinguin pols" msgid "Denoise image and guiding passes together. Improves quality when guiding passes are noisy using least amount of extra processing time" -msgstr "Desempolsegat d'imatges i passades guia alhora. Millora la qualitat quan les passades guia tenen pols tot emprant el mínim temps de processament afegit" +msgstr "Desorolla imatges i passades guia alhora. Millora la qualitat quan les passades guia tenen pols tot emprant el mínim temps de processament afegit" msgid "Accurate" @@ -42790,7 +42891,7 @@ msgstr "Usar mínim" msgid "Number of motion blur samples" -msgstr "Nombre de mostres de difuminat de moviment" +msgstr "Nombre de mostres en difuminat de moviment" msgid "Shutter" @@ -42834,7 +42935,7 @@ msgstr "Difuminat de moviment" msgid "Use multi-sampled motion blur of the mask" -msgstr "Usa difuminat de moviment multimostra de la màscara" +msgstr "Usa difuminat de moviment multimostrejat de la màscara" msgctxt "NodeTree" @@ -43024,7 +43125,7 @@ msgstr "[Round]: Arrodoneix A a l'enter més proper. Arrodoneix cap amunt si la msgctxt "NodeTree" msgid "Floor" -msgstr "Sòl" +msgstr "Basament" msgid "The largest integer smaller than or equal A" @@ -43203,7 +43304,7 @@ msgstr "Converteix radiants a graus" msgid "Include alpha of second input in this operation" -msgstr "Inclou l'alfa del segon ingrés en aquesta operació" +msgstr "Inclou l'alfa de la segona ingressió en aquesta operació" msgid "Movie Distortion" @@ -43215,15 +43316,15 @@ msgstr "[Movie Distortion]: Distorsió a usar per a filtrar la imatge" msgid "File Output" -msgstr "Document d'emissió" +msgstr "Document d'egressió" msgid "Active Input Index" -msgstr "Índex de l'ingrés actiu" +msgstr "Índex d'ingressió actiu" msgid "Active input index in details view list" -msgstr "[Active Input Index]: Índex de l'ingrés actiu a la llista de visualització de detalls" +msgstr "[Active Input Index]: Índex d'ingressió actiu a la llista de visualització de detalls" msgid "Base Path" @@ -43231,7 +43332,7 @@ msgstr "Camí base" msgid "Base output path for the image" -msgstr "[Base Path]: Camí base d'emissió per a la imatge" +msgstr "[Base Path]: Camí base d'egressió per a la imatge" msgid "File Slots" @@ -43463,11 +43564,11 @@ msgstr "[Track Position]: fotograma a utilitzar per a la ubicació relativa" msgid "Which marker position to use for output" -msgstr "Quina posició de marcador cal usar per a l'emissió" +msgstr "Quina posició de marcador cal usar per a l'egressió" msgid "Output absolute position of a marker" -msgstr "Emetre la posició absoluta d'un marcador" +msgstr "Egressar la posició absoluta d'un marcador" msgid "Relative Start" @@ -43475,7 +43576,7 @@ msgstr "Inici relatiu" msgid "Output position of a marker relative to first marker of a track" -msgstr "Emetre la posició d'un marcador en relació amb el primer marcador d'un rastre" +msgstr "Egressar la posició d'un marcador en relació amb el primer marcador d'un rastre" msgid "Relative Frame" @@ -43483,7 +43584,7 @@ msgstr "Fotograma relatiu" msgid "Output position of a marker relative to marker at given frame number" -msgstr "Emetre la posició d'un marcador en relació amb el marcador en un número de fotograma determinat" +msgstr "Egressar la posició d'un marcador en relació amb el marcador en un número de fotograma determinat" msgid "Absolute Frame" @@ -43491,7 +43592,7 @@ msgstr "Fotograma absolut" msgid "Output absolute position of a marker at given frame number" -msgstr "Emetre la posició absoluta d'un marcador en un número de fotograma determinat" +msgstr "Egressar la posició absoluta d'un marcador en un número de fotograma determinat" msgid "Method to use to filter transform" @@ -43627,7 +43728,7 @@ msgstr "Antialiàsing Z" msgid "Anti-alias the z-buffer to try to avoid artifacts, mostly useful for Blender renders" -msgstr "[Anti-Alias Z]: Fa antialiàsing del regulador z per mirar d'evitar artefactes, útil sobretot per a revelats del Blender" +msgstr "[Anti-Alias Z]: Fa antialiàsing del regulador z per mirar d'evitar tares, útil sobretot per a revelats del Blender" msgid "Function Node" @@ -43687,7 +43788,7 @@ msgstr "I" msgid "True when both inputs are true" -msgstr "Ver quan tots dos ingressos són vers" +msgstr "Ver quan totes dues ingressions són veres" msgid "Or" @@ -43695,11 +43796,11 @@ msgstr "O" msgid "True when at least one input is true" -msgstr "Ver quan almenys un ingrés és ver" +msgstr "Ver quan almenys una ingressió és vera" msgid "Opposite of the input" -msgstr "El contrari de l'ingressat" +msgstr "El contrari de la ingressió" msgid "Not And" @@ -43707,7 +43808,7 @@ msgstr "No I" msgid "True when at least one input is false" -msgstr "Ver quan almenys un ingrés és fals" +msgstr "Ver quan almenys una ingressió és falsa" msgid "Nor" @@ -43715,7 +43816,7 @@ msgstr "Ni" msgid "True when both inputs are false" -msgstr "Ver quan ambdós ingressos són falsos" +msgstr "Ver quan ambdues ingressions són falses" msgid "Equal" @@ -43723,7 +43824,7 @@ msgstr "Igual" msgid "True when both inputs are equal (exclusive nor)" -msgstr "Ver quan ambdós ingressos són iguals (exclusiu ni)" +msgstr "Ver quan ambdues ingressions són iguals (ni exclusiu)" msgid "Not Equal" @@ -43731,7 +43832,7 @@ msgstr "No igual" msgid "True when both inputs are different (exclusive or)" -msgstr "Ver quan ambdós ingressos són diferents (exclusiu o)" +msgstr "Ver quan ambdues ingressions són diferents (o exclusiu)" msgid "Imply" @@ -43739,11 +43840,11 @@ msgstr "Ergo" msgid "True unless the first input is true and the second is false" -msgstr "Ver llevat que el primer ingrés sigui ver i el segon fals" +msgstr "Ver llevat que la primera ingressió sigui vera i la segona falsa" msgid "True when the first input is true and the second is false (not imply)" -msgstr "Ver quan el primer ingrés és ver i el segon és fals (no implica)" +msgstr "Ver quan la primera ingressió és vera i la segona és falsa (no implicació)" msgid "Compare" @@ -43751,7 +43852,7 @@ msgstr "Comparar" msgid "Input Type" -msgstr "Tipus d'ingrés" +msgstr "Tipus d'ingressió" msgid "Element-Wise" @@ -43787,7 +43888,7 @@ msgstr "Menys de" msgid "True when the first input is smaller than second input" -msgstr "Ver quan el primer ingrés és menor que el segon" +msgstr "Ver quan la primera ingressió és menor que la segona" msgid "Less Than or Equal" @@ -43795,7 +43896,7 @@ msgstr "Menys de o igual" msgid "True when the first input is smaller than the second input or equal" -msgstr "Ver quan el primer ingrés és menor or igual que el segon" +msgstr "Ver quan la primera ingressió és menor or igual que la segona" msgid "Greater Than" @@ -43803,7 +43904,7 @@ msgstr "Més que" msgid "True when the first input is greater than the second input" -msgstr "Ver quan el primer ingrés és major que el segona" +msgstr "Ver quan la primera ingressió és major que la segona" msgid "Greater Than or Equal" @@ -43811,15 +43912,15 @@ msgstr "Major o igual que" msgid "True when the first input is greater than the second input or equal" -msgstr "Ver quan el primer ingrés és major o igual que el segon" +msgstr "Ver quan la primera ingressió és major o igual que la segona" msgid "True when both inputs are approximately equal" -msgstr "Ver quan ambdós ingressos són aproximadament iguals" +msgstr "Ver quan ambdues ingressions són aproximadament iguals" msgid "True when both inputs are not approximately equal" -msgstr "Ver quan ambdós ingressos no són aproximadament iguals" +msgstr "Ver quan ambdues ingressions no són aproximadament iguals" msgid "Brighter" @@ -43827,7 +43928,7 @@ msgstr "Més brillant" msgid "True when the first input is brighter" -msgstr "[Brighter]: Ver quan el primer ingrés és més brillant" +msgstr "[Brighter]: Ver quan la primera ingressió és més brillant" msgid "Darker" @@ -43835,7 +43936,7 @@ msgstr "Més fosc" msgid "True when the first input is darker" -msgstr "[Darker]: Ver quan el primer ingrés és més fosc" +msgstr "[Darker]: Ver quan la primera ingressió és més fosca" msgid "Float to Integer" @@ -43869,11 +43970,11 @@ msgstr "Arrodonir el número flotant per dalt a l'enter més pròxim" msgid "Round the float to the closest integer in the direction of zero (floor if positive; ceiling if negative)" -msgstr "Arrodonir el número flotant a l'enter més proper en direcció al zero (sòl si és positiu; sostre si és negatiu)" +msgstr "Arrodonir el número flotant a l'enter més proper en direcció al zero (basament si és positiu; sostre si és negatiu)" msgid "Input value used for unconnected socket" -msgstr "Valor d'ingrés usat per al born no connectat" +msgstr "Valor d'ingressió usat per al born no connectat" msgid "Random Value" @@ -43893,11 +43994,11 @@ msgstr "Orientació base per a la rotació" msgid "Rotate the input rotation in the local space of the object" -msgstr "Rotació de la rotació d'ingrés dins l'espai local de l'objecte" +msgstr "Rotació de la rotació d'ingressió dins l'espai local de l'objecte" msgid "Rotate the input rotation in its local space" -msgstr "Rotació de la rotació d'ingrés en el seu espai local" +msgstr "Rotació de la rotació d'ingressió en el seu espai local" msgid "Method used to describe the rotation" @@ -43933,7 +44034,7 @@ msgstr "Camp d'acumulació" msgid "Add the values of an evaluated field together and output the running total for each element" -msgstr "[Accumulate Field]: Suma els valors d'un camp avaluat i emet el total d'execució per a cada element" +msgstr "[Accumulate Field]: Suma els valors d'un camp avaluat i egressa el total d'execució per a cada element" msgid "Domain Size" @@ -43997,7 +44098,7 @@ msgstr "Atribut captura" msgid "Store the result of a field on a geometry and output the data as a node socket. Allows remembering or interpolating data as the geometry changes, such as positions before deformation" -msgstr "[Capture Attribute]: Guarda el resultat d'un camp en una geometria i emet les dades com a born de node. Permet recordar o interpolar dades a mesura que canvia la geometria, com ara posicions abans d'una deformació" +msgstr "[Capture Attribute]: Guarda el resultat d'un camp en una geometria i egressa les dades com a born de node. Permet recordar o interpolar dades a mesura que canvia la geometria, com ara posicions abans d'una deformació" msgid "Which domain to store the data in" @@ -44013,7 +44114,7 @@ msgstr "Extreu instàncies de geometria d'una col·lecció" msgid "The transformation of the instances output. Does not affect the internal geometry" -msgstr "La transformació de les instàncies emeses. No afecta la geometria interna" +msgstr "La transformació de les instàncies egressades. No afecta la geometria interna" msgid "Original" @@ -44021,7 +44122,7 @@ msgstr "Original" msgid "Output the geometry relative to the collection offset" -msgstr "Emet la geometria relativa al desplaçament de la col·lecció" +msgstr "Egressa la geometria relativa al desplaçament de la col·lecció" msgid "Bring the input collection geometry into the modified object, maintaining the relative position between the objects in the scene" @@ -44285,11 +44386,11 @@ msgstr "Corba a punts" msgid "Generate a point cloud by sampling positions along curves" -msgstr "[Curve to Points]: Genera un núvol de punts prenent mostres d'ubicacions al llarg de corbes" +msgstr "[Curve to Points]: Genera un núvol de punts generant ubicacions al llarg de corbes" msgid "How to generate points from the input curve" -msgstr "Com generar punts des de la corba d'ingrés" +msgstr "Com generar punts des de la corba d'ingressió" msgid "Evaluated" @@ -44301,11 +44402,11 @@ msgstr "[Evaluated]: Crea punts a partir dels punts avaluats de la corba, basats msgid "Sample each spline by evenly distributing the specified number of points" -msgstr "Pren mostres de cada spline en base a distribuir uniformement el nombre especificat de punts" +msgstr "Generar cada spline en base a distribuir uniformement el nombre especificat de punts" msgid "Sample each spline by splitting it into segments with the specified length" -msgstr "Pren mostres de cada spline en base a dividir-lo en segments de la longitud especificada" +msgstr "Generar cada spline en base a dividir-lo en segments de la longitud especificada" msgid "Geometry Custom Group" @@ -44397,7 +44498,7 @@ msgstr "Normal antiga" msgid "Output the normal and rotation values that have been output before the node started taking smooth normals into account" -msgstr "[Legacy Normal]: Emet els valors de normal i rotació que s'havien emès abans que el node comencés a tenir en compte les normals de suavitzat" +msgstr "[Legacy Normal]: Egressa els valors de normal i rotació que s'havien emès abans que el node comencés a tenir en compte les normals de suavitzat" msgid "Dual Mesh" @@ -44413,7 +44514,7 @@ msgstr "Duplicar elements" msgid "Generate an arbitrary number copies of each selected input element" -msgstr "Genera un nombre arbitrari de còpies de cadascun dels elements d'ingrés seleccionats" +msgstr "Genera un nombre arbitrari de còpies de cadascun dels elements d'ingressió seleccionats" msgid "Which domain to duplicate" @@ -44545,7 +44646,7 @@ msgstr "Extreu informació sobre una imatge" msgid "Sample values from an image texture" -msgstr "Treu mostres dels valors a partir d'una imatge textura" +msgstr "Mostrejar valors a partir d'una imatge textura" msgctxt "Image" @@ -44566,7 +44667,7 @@ msgstr "Interpolació lineal" msgid "No interpolation (sample closest texel)" -msgstr "Sense interpolació (recull el texel més pròxim)" +msgstr "Sense interpolació (mostreja el texel més pròxim)" msgid "Cubic interpolation" @@ -44594,7 +44695,7 @@ msgstr "Extreu un valor estable d'identificador aleatori a partir de l'atribut msgid "Input image" -msgstr "Imatge d'ingrés" +msgstr "Imatge d'ingressió" msgid "Retrieve an integer value indicating the position of each element in the list, starting at zero" @@ -44618,7 +44719,7 @@ msgstr "[Instance Scale]: Extreu l'escala de cada instància en la geometria" msgid "Output a single material" -msgstr "Emet un sol material" +msgstr "Egressa un sol material" msgid "Retrieve the index of the material used for each element in the geometry's list of materials" @@ -44657,10 +44758,6 @@ msgid "Is Face Planar" msgstr "És cara planar" -msgid "Retrieve whether all triangles in a face are on the same plane, i.e. whether have the same normal" -msgstr "[Is Face Planar]: Extreu si tots els triangles d'una cara estan en el mateix pla, és a dir, si tenen la mateixa normal" - - msgid "Face Neighbors" msgstr "Veïns de cara" @@ -44754,7 +44851,7 @@ msgstr "Instància en punts" msgid "Generate a reference to geometry at each of the input points, without duplicating its underlying data" -msgstr "[Instance on Points]: Genera una referència a la geometria en cadascun dels punts d'ingrés, sense duplicar-ne les dades subjacents" +msgstr "[Instance on Points]: Genera una referència a la geometria en cadascun dels punts d'ingressió, sense duplicar-ne les dades subjacents" msgid "Instances to Points" @@ -44962,11 +45059,11 @@ msgstr "Extreu la informació d'un objecte" msgid "The transformation of the vector and geometry outputs" -msgstr "La transformació de les emissions de vectors i geometries" +msgstr "La transformació de les egressions de vectors i geometries" msgid "Output the geometry relative to the input object transform, and the location, rotation and scale relative to the world origin" -msgstr "Emet la geometria relativa a la transformació de l'objecte ingressat, i la ubicació, rotació i escala relativa a l'origen del món" +msgstr "Egressa la geometria relativa a la transformació de l'objecte ingressat, i la ubicació, rotació i escala relativa a l'origen del món" msgid "Bring the input object geometry, location, rotation and scale into the modified object, maintaining the relative position between the two objects in the scene" @@ -45118,11 +45215,11 @@ msgstr "Com especificar la quantitat de mostres" msgid "Output the input spline's evaluated points, based on the resolution attribute for NURBS and Bezier splines. Poly splines are unchanged" -msgstr "Emetre els punts avaluats de l'spline ingressada, basats en l'atribut de resolució per als splines NURBS i Bézier. Els splines poligonals no canvien" +msgstr "Egressar els punts avaluats de l'spline ingressada, basats en l'atribut de resolució per als splines NURBS i Bézier. Els splines poligonals no canvien" msgid "Sample the specified number of points along each spline" -msgstr "Mostrejar el nombre especificat de punts al llarg de cada spline" +msgstr "Generar el nombre especificat de punts al llarg de cada spline" msgid "Calculate the number of samples by splitting each spline into segments with the specified length" @@ -45154,15 +45251,15 @@ msgstr "[Sample Curve]: Extreu dades des d'un punt d'una corba a una certa dist msgid "Method for sampling input" -msgstr "Mètode per mostrejar allò ingressat" +msgstr "Mètode per mostrejar ingressió" msgid "Find sample positions on the curve using a factor of its total length" -msgstr "Cerca posicions de mostreig a la corba tot usant un factor de la seva longitud total" +msgstr "Trobar ubicacions de mostreig a la corba tot usant un factor de la seva longitud total" msgid "Find sample positions on the curve using a distance from its beginning" -msgstr "Cerca posicions de mostreig a la corba tot usant una distància des del seu inici" +msgstr "Trobar ubicacions de mostreig a la corba tot usant una distància des del seu inici" msgid "All Curves" @@ -45170,15 +45267,15 @@ msgstr "Totes les corbes" msgid "Sample lengths based on the total length of all curves, rather than using a length inside each selected curve" -msgstr "[All Curves]: Mostreja les longituds basades en la longitud total de totes les corbes, preferiblement a usar una longitud dins de cada corba seleccionada" +msgstr "[All Curves]: Mostrejar les longituds basades en la longitud total de totes les corbes, preferiblement a usar una longitud dins de cada corba seleccionada" msgid "Sample Index" -msgstr "Mostreig d'índex" +msgstr "Mostrejar índex" msgid "Retrieve values from specific geometry elements" -msgstr "[Sample Index]: Extreu els valors d'elements de geometria específics" +msgstr "[Sample Index]: Extreu valors d'elements de geometria específics" msgid "Clamp the indices to the size of the attribute domain instead of outputting a default value for invalid indices" @@ -45186,7 +45283,7 @@ msgstr "Constrènyer els índexs a la mida del domini de l'atribut en lloc de ge msgid "Sample Nearest" -msgstr "Mostreja més pròxims" +msgstr "Mostrejar més pròxims" msgid "Find the element of a geometry closest to a position" @@ -45194,7 +45291,7 @@ msgstr "[Sample Nearest]: Troba l'element d'una geometria que està més proper msgid "Sample Nearest Surface" -msgstr "Mostreja superfície més pròxima" +msgstr "Mostrejar superfície més pròxima" msgid "Calculate the interpolated value of a mesh attribute on the closest point of its surface" @@ -45262,7 +45359,7 @@ msgstr "Separar components" msgid "Split a geometry into a separate output for each type of data in the geometry" -msgstr "[Separate Components]: Divideix una geometria emetent-la separadament per a cada tipus de dada de la mateixa" +msgstr "[Separate Components]: Divideix una geometria egressant-la separadament per a cada tipus de dada de la mateixa" msgid "Separate Geometry" @@ -45270,7 +45367,7 @@ msgstr "Separar geometria" msgid "Split a geometry into two geometry outputs based on a selection" -msgstr "[Separate Geometry]: Divideix una geometria en dues emissions de geometria basades en una selecció" +msgstr "[Separate Geometry]: Divideix una geometria en dues egressions de geometria basades en una selecció" msgid "Which domain to separate on" @@ -45430,7 +45527,7 @@ msgstr "Unir cadenes" msgid "Combine any number of input strings" -msgstr "[Join Strings]: Combina qualsevol nombre de cadenes d'ingrés" +msgstr "[Join Strings]: Combina qualsevol nombre de cadenes d'ingressió" msgid "String to Curves" @@ -45470,7 +45567,7 @@ msgstr "[Scale To Fit]: Escala la mida del text perquè s'ajusti dins l'amplada msgid "Only output curves that fit within the width and height. Output the remainder to the \"Remainder\" output" -msgstr "Només emet corbes que s'ajustin a l'amplada i l'alçada. Emet la resta al resultat «Romanent»" +msgstr "Només egressa corbes que s'ajustin a l'amplada i l'alçada. Egressa la resta al resultat «Romanent»" msgid "Pivot point position relative to character" @@ -45522,7 +45619,7 @@ msgstr "Divideix les cares de malla per formar una superfície suau, amb l'ús d msgid "Switch between two inputs" -msgstr "Alterna entre dos ingressos" +msgstr "Alterna entre dues ingressions" msgid "Transform Geometry" @@ -45655,15 +45752,15 @@ msgstr "[Group Input]: Exposa les dades connectades des de dins d'un grup de nod msgid "Group Output" -msgstr "Emissió de grup" +msgstr "Egressió de grup" msgid "Output data from inside of a node group" -msgstr "[Group Output]: Dades emeses de l'interior d'un grup de nodes" +msgstr "[Group Output]: Dades egressades de l'interior d'un grup de nodes" msgid "True if this node is used as the active group output" -msgstr "Ver si el node s'usa com l'emissió del grup actiu" +msgstr "Ver si el node s'usa com l'egressió del grup actiu" msgid "Reroute" @@ -45671,7 +45768,7 @@ msgstr "Redireccionar" msgid "A single-socket organization tool that supports one input and multiple outputs" -msgstr "[Reroute]: Una eina d'organització d'un sol circuit que admet un ingrés i múltiples emissions" +msgstr "[Reroute]: Una eina d'organització d'un sol circuit que admet una ingressió i múltiples egressions " msgid "Shader Node" @@ -45762,7 +45859,7 @@ msgid "" "Add background light emission.\n" "Note: This node should only be used for the world surface output" msgstr "" -"[Background]: Afegeix emissió de llum de fons.\n" +"[Background]: Afegeix egressió de llum de fons.\n" "Nota: Aquest node només s'ha d'utilitzar per a generar la superfície del món" @@ -45823,11 +45920,11 @@ msgstr "Ashikhmin-Shirley" msgid "Diffuse BSDF" -msgstr "BSDF Difús" +msgstr "BSDF Difusiu" msgid "Lambertian and Oren-Nayar diffuse reflection" -msgstr "[Diffuse BSDF]: Reflexió difusa de Lambert i Oren-Nayar" +msgstr "[Diffuse BSDF]: Reflexió difusiva de Lambert i Oren-Nayar" msgid "Glass BSDF" @@ -45967,7 +46064,7 @@ msgstr "BSDF ninotaire" msgid "Diffuse and Glossy shaders with cartoon light effects" -msgstr "[Toon BSDF]: Aspectors difusos i setinats amb efectes de llum de còmic" +msgstr "[Toon BSDF]: Aspectors difusius i setinats amb efectes de llum de còmic" msgid "Toon BSDF component to use" @@ -45975,7 +46072,7 @@ msgstr "Component BSDF de ninotaire disponible" msgid "Use diffuse BSDF" -msgstr "Usar BSDF difús" +msgstr "Usar BSDF difusiu" msgid "Use glossy BSDF" @@ -45987,7 +46084,7 @@ msgstr "BSDF translúcid" msgid "Lambertian diffuse transmission" -msgstr "Transmissió difusa de Lambert" +msgstr "Transmissió difusiva de Lambert" msgid "Transparent BSDF" @@ -46007,11 +46104,11 @@ msgid "" "Typically mixed with other shaders (such as a Diffuse Shader) and is not particularly useful on its own" msgstr "" "[Velvet BSDF]: Reflex per a materials tipus tela.\n" -"Típicament barrejat amb altres aspectors (com ara un de difús), perquè per si sol no és particularment útil" +"Típicament barrejat amb altres aspectors (com ara un de difusiu), perquè per si sol no és particularment útil" msgid "Bump" -msgstr "Bonys" +msgstr "Relleu" msgid "Generate a perturbed normal from a height texture for bump mapping. Typically used for faking highly detailed surfaces" @@ -46019,7 +46116,7 @@ msgstr "[Bump]: Genera una normal pertorbada a partir d'una textura d'alçada pe msgid "Invert the bump mapping direction to push into the surface instead of out" -msgstr "Invertir la direcció del mapejat de bonys per a empènyer cap a la superfície en lloc d'enfora" +msgstr "Invertir la direcció del mapejat de relleu per a empènyer cap a la superfície en lloc d'enfora" msgid "Camera Data" @@ -46087,7 +46184,7 @@ msgstr "Desplaça la superfície seguint la seva normal" msgid "Space of the input height" -msgstr "Espai de l'alçada de l'ingrés" +msgstr "Espai de l'alçada de l'ingressió" msgid "Object Space" @@ -46123,7 +46220,7 @@ msgstr "Corba de coma flotant" msgid "Map an input float to a curve and outputs a float value" -msgstr "[Float Curve]: Mapeja l'ingrés d'un nombre de coma flotant en una corba i emet un valor flotant" +msgstr "[Float Curve]: Mapeja la ingressió d'un nombre de coma flotant en una corba i egressa un valor flotant" msgid "Fresnel" @@ -46239,7 +46336,7 @@ msgstr "[Smoother Step]: Interpolació de la vora d'Hermite més suau entre els msgid "Transform the input vector by applying translation, rotation, and scale" -msgstr "Transformar el vector d'ingrés aplicant-hi translació, la rotació i escalat" +msgstr "Transformar el vector d'ingressió aplicant-hi translació, la rotació i escalat" msgid "Type of vector that the mapping transforms" @@ -46307,7 +46404,7 @@ msgstr "Mescla RGB" msgid "Mix two input colors" -msgstr "[MixRGB]: Barreja dos colors d'ingrés" +msgstr "[MixRGB]: Barreja dos colors d'ingressió" msgid "Mix Shader" @@ -46375,14 +46472,14 @@ msgstr "Extreu informació sobre la instància de l'objecte" msgid "AOV Output" -msgstr "Emissió VEA" +msgstr "Egressió VEA" msgid "" "Arbitrary Output Variables.\n" "Provide custom render passes for arbitrary shader node outputs" msgstr "" -"[VEA Output]: Variables d'Emissió arbitràries.\n" +"[VEA Output]: Variables d'egressió arbitràries.\n" "Proporciona passades de revelat personalitzades per a borns de sortides de nodes d'aspectors arbitraris" @@ -46391,15 +46488,15 @@ msgstr "Nom de la VEA on escriu aquest born de sortida" msgid "Light Output" -msgstr "Emissió de llum" +msgstr "Egressió de llum" msgid "Output light information to a light object" -msgstr "[Light Output]: Emet la informació de llum a un objecte de llum" +msgstr "[Light Output]: Egressa la informació de llum a un objecte de llum" msgid "True if this node is used as the active output" -msgstr "Ver si aquest node s'usa com a emissió activa" +msgstr "Ver si aquest node s'usa com a egressió activa" msgid "Which renderer and viewport shading types to use the shaders for" @@ -46407,7 +46504,7 @@ msgstr "Per a quins tipus de revelat i aspectes de mirador es vol usar els aspec msgid "Use shaders for all renderers and viewports, unless there exists a more specific output" -msgstr "Usar aspectors per a tots els revelats i miradors , a menys que hi hagi alguna emissió més específica" +msgstr "Usar aspectors per a tots els revelats i miradors , a menys que hi hagi alguna egressió més específica" msgid "Use shaders for Eevee renderer" @@ -46423,23 +46520,23 @@ msgstr "Usa aspectors per al revelat de Cycles" msgid "Line Style Output" -msgstr "Emissió d'estil de línia" +msgstr "Egressió d'estil de línia" msgid "Material Output" -msgstr "Emissió de material" +msgstr "Egressió de material" msgid "Output surface material information for use in rendering" -msgstr "[Material Output]: Emet la informació del material de superfície de cara al revelat" +msgstr "[Material Output]: Egressa la informació del material de superfície de cara al revelat" msgid "World Output" -msgstr "Emissió a món" +msgstr "Egressió a món" msgid "Output light color information to the scene's World" -msgstr "Emet la informació de color de llum al món de l'escena" +msgstr "Egressa la informació de color de llum al món de l'escena" msgid "Particle Info" @@ -46655,7 +46752,7 @@ msgid "" "Typically used as inputs for texture nodes" msgstr "" "[Texture Coordinate]: Extreu diversos tipus de coordenades de textura.\n" -"S'utilitza normalment com a ingrés per a nodes textura" +"S'utilitza normalment com a ingressió per a nodes textura" msgid "From Instancer" @@ -46667,7 +46764,7 @@ msgstr "[From Instancer]: Utilitza el pare de l'objecte instància si es pot" msgid "Use coordinates from this object (for object texture coordinates output)" -msgstr "Usa les coordenades d'aquest objecte (per a l'emissió de les coordenades de l'objecte textura)" +msgstr "Usa les coordenades d'aquest objecte (per a l'egressió de les coordenades de l'objecte textura)" msgid "Environment Texture" @@ -46675,7 +46772,7 @@ msgstr "Textura atmosfera" msgid "Sample an image file as an environment texture. Typically used to light the scene with the background node" -msgstr "[Environment Texture]: Treu mostres d'un document d'imatge com una textura ambiental. D'ús típic per il·luminar l'escena amb el node de rerefons" +msgstr "[Environment Texture]: Mostrejar document d'imatge com a textura ambiental. D'ús típic per il·luminar l'escena amb el node de rerefons" msgid "Texture interpolation" @@ -46695,7 +46792,7 @@ msgstr "Projecció" msgid "Projection of the input image" -msgstr "Projecció de la imatge d'ingrés" +msgstr "Projecció de la imatge d'ingressió" msgid "Equirectangular" @@ -46719,7 +46816,7 @@ msgstr "Textura degradat" msgid "Generate interpolated color and intensity values based on the input vector" -msgstr "[Gradient Texture]: Genera valors de color i intensitat interpolats basats en el vector d'ingrés" +msgstr "[Gradient Texture]: Genera valors de color i intensitat interpolats basats en el vector d'ingressió" msgid "IES Texture" @@ -46751,7 +46848,7 @@ msgstr "Usa un document .ies extern" msgid "Sample an image file as a texture" -msgstr "Treu mostres de document d'imatge com a textura" +msgstr "Mostrejar document d'imatge com a textura" msgid "Method to project 2D image on object with a 3D texture vector" @@ -46799,23 +46896,23 @@ msgstr "Genera soroll fractal de Perlin. Permet un control més gran sobre com e msgid "Number of dimensions to output noise for" -msgstr "Nombre de dimensions per a les que s'emet el soroll" +msgstr "Nombre de dimensions per a les que s'egressa el soroll" msgid "Use the scalar value W as input" -msgstr "Usa el valor escalar W com a ingrés" +msgstr "Usa el valor escalar W com a ingressió" msgid "Use the 2D vector (X, Y) as input. The Z component is ignored" -msgstr "Usa el vector 2D (X, Y) com a ingrés. El component Z s'ignora" +msgstr "Usa el vector 2D (X, Y) com a ingressió. El component Z s'ignora" msgid "Use the 3D vector (X, Y, Z) as input" -msgstr "Usa el vector 3D (X, Y, Z) com a ingrés" +msgstr "Usa el vector 3D (X, Y, Z) com a ingressió" msgid "Use the 4D vector (X, Y, Z, W) as input" -msgstr "Usa el vector 4D (X, Y, Z, W) com a ingrés" +msgstr "Usa el vector 4D (X, Y, Z, W) com a ingressió" msgid "Type of the Musgrave texture" @@ -47035,7 +47132,7 @@ msgstr "Disc solar" msgid "Include the sun itself in the output" -msgstr "[Sun Disc]: Incloure el propi sol en l'emissió" +msgstr "[Sun Disc]: Incloure el propi sol en l'egressió" msgid "Sun Elevation" @@ -47111,7 +47208,7 @@ msgstr "Distància Minkowski" msgid "Feature Output" -msgstr "Disseny d'emissió" +msgstr "Disseny d'egressió" msgid "The Voronoi feature that the node will compute" @@ -47267,7 +47364,7 @@ msgstr "S'utilitza per introduir valors numèrics a altres nodes de l'arbre" msgid "Map an input vectors to curves, used to fine-tune the interpolation of the input" -msgstr "Mapeja un vector d'ingrés sobre corbes, usat per afinar la interpolació del que s'ingressa" +msgstr "Mapeja un vector d'ingressió sobre corbes, usat per afinar la interpolació del que s'ingressa" msgid "Displace the surface along an arbitrary direction" @@ -47680,11 +47777,11 @@ msgstr "Col·lecció d'enllaços de nodes" msgid "Output File Slot" -msgstr "Epígraf del document d'emissió" +msgstr "Epígraf del document d'egressió" msgid "Single layer file slot of the file output node" -msgstr "[Output File Slot]: Inscripció de document unicapa per al node del document d'emissió" +msgstr "[Output File Slot]: Inscripció de document unicapa per al node del document d'egressió" msgid "Subpath used for this slot" @@ -47704,11 +47801,11 @@ msgstr "Usar format de node" msgid "Output File Layer Slot" -msgstr "Epígraf de capa de document d'emissió" +msgstr "Epígraf de capa de document d'egressió" msgid "Multilayer slot of the file output node" -msgstr "Epígraf multicapa del node de de document d'emissió" +msgstr "Epígraf multicapa del node de document d'egressió" msgid "OpenEXR layer name used for this slot" @@ -47724,7 +47821,7 @@ msgstr "Born de node" msgid "Input or output socket of a node" -msgstr "Born d'ingrés o sortida d'un node" +msgstr "Born d'entrada o sortida d'un node" msgid "Type Label" @@ -47776,7 +47873,7 @@ msgstr "Amaga el valor" msgid "Hide the socket input value" -msgstr "Amaga el valor d'ingrés del born" +msgstr "Amaga el valor d'ingressió del born" msgid "Unique identifier for mapping sockets" @@ -47792,11 +47889,11 @@ msgstr "[Linked]: Ver si el born té connexió" msgid "Multi Input" -msgstr "Multiingrés" +msgstr "Multiingressió" msgid "True if the socket can accept multiple ordered input links" -msgstr "[Multi Input]: Ver si el born pot acceptar múltiples enllaços d'ingrés ordenats" +msgstr "[Multi Input]: Ver si el born pot acceptar múltiples enllaços d'entrada ordenats" msgid "Is Output" @@ -47972,7 +48069,7 @@ msgstr "Domini de l'atribut" msgid "Attribute domain used by the geometry nodes modifier to create an attribute output" -msgstr "[Attribute Domain]: Domini d'atribut usat pels nodes modificadors de geometria per emetre atributs" +msgstr "[Attribute Domain]: Domini d'atribut usat pels nodes modificadors de geometria per egressar atributs" msgid "Default Attribute" @@ -47988,7 +48085,7 @@ msgstr "Ocult al modificador" msgid "Don't show the input value in the geometry nodes modifier interface" -msgstr "[Hide in Modifier]: No mostra el valor d'ingrés en la interfície dels nodes de geometria del modificador" +msgstr "[Hide in Modifier]: No mostra el valor d'ingressió en la interfície dels nodes de geometria del modificador" msgid "Hide the socket input value even when the socket is not connected" @@ -48056,7 +48153,7 @@ msgstr "Interfície de born del node de vector" msgid "Node Tree Inputs" -msgstr "Ingressos d'arbre de nodes" +msgstr "Entrades d'arbre de nodes" msgid "Collection of Node Tree Sockets" @@ -48248,7 +48345,7 @@ msgstr "Propietats de l'operador" msgid "Input properties of an operator" -msgstr "[Operator Properties]: Propietats d'ingrés d'un operador" +msgstr "[Operator Properties]: Propietats d'ingressió d'un operador" msgctxt "Operator" @@ -48642,7 +48739,7 @@ msgstr "[Push Down Action]: Espitja l'acció en avall a l'estiba ANL com a nou s msgctxt "Operator" msgid "Sample Keyframes" -msgstr "Redistribuir fotofites" +msgstr "Generar fotofites" msgid "Add keyframes on every frame between the selected keyframes" @@ -48720,7 +48817,7 @@ msgstr "L'operador s'ha activat mitjançant un esdeveniment de clic-i-arrossega" msgid "Wait for Input" -msgstr "Esperar ingrés" +msgstr "Esperar ingressió" msgid "X Max" @@ -50425,7 +50522,7 @@ msgstr "Eina" msgid "Translation" -msgstr "Translació" +msgstr "Traducció" msgid "Primary" @@ -50650,7 +50747,7 @@ msgstr "Afegir marcador i desplaçar" msgid "Add new marker and slide it with mouse until mouse button release" -msgstr "[Add Marker and Slide]: Afegeix un marcador nou que es desplaça amb el ratolí fins que es deixa anar el botó" +msgstr "[Add Marker and Slide]: Afegeix un marcador nou que es desplaça amb el ratolí fins que s'amolla el botó" msgctxt "Operator" @@ -51191,11 +51288,11 @@ msgstr "Precarrega fotogrames des del disc per a una reproducció/rastreig més msgctxt "Operator" msgid "Rebuild Proxy and Timecode Indices" -msgstr "Recompon els índexs del vídeo simulat i del timecode" +msgstr "Recompon els índexs del vídeo simulat i de la cronofita" msgid "Rebuild all selected proxies and timecode indices in the background" -msgstr "Reconstrueix tots els índexs dels vídeos simulats i de timecode en segon pla" +msgstr "Reconstrueix tots els índexs dels vídeos simulats i de cronofita en segon pla" msgctxt "Operator" @@ -52271,11 +52368,11 @@ msgstr "Suprimir punts de control o corbes seleccionats" msgctxt "Operator" msgid "Curve Sculpt Mode Toggle" -msgstr "Revesar mode d'escultura per corbes" +msgstr "Revesar mode escultura per corbes" msgid "Enter/Exit sculpt mode for curves" -msgstr "Entra/surt del mode d'escultura per corbes" +msgstr "Entra/surt del mode escultura per corbes" msgid "(De)select all control points" @@ -52330,7 +52427,7 @@ msgstr "Determinar mode de selecció" msgid "Change the mode used for selection masking in curves sculpt mode" -msgstr "Canvia el mode utilitzat de màscares de selecció en el mode d'escultura de corbes" +msgstr "Canvia el mode utilitzat de màscares de selecció en el mode escultura de corbes" msgctxt "Operator" @@ -52654,7 +52751,7 @@ msgstr "En fer clic" msgid "Spline closes on release if not dragged" -msgstr "[On Cliclk]: El spline es tanca en deixar anar si no s'arrossega" +msgstr "[On Cliclk]: El spline es tanca en amollar si no s'arrossega" msgid "Cycle Handle Type" @@ -53081,27 +53178,27 @@ msgstr "Ubicació on afegir el nou vèrtex" msgctxt "Operator" msgid "Denoise Animation" -msgstr "Desempolsegar animació" +msgstr "Desorollar animació" msgid "Denoise rendered animation sequence using current scene and view layer settings. Requires denoising data passes and output to OpenEXR multilayer files" -msgstr "[Denoise Animation]: Treu la pols de la seqüència d'animació revelada amb la configuració de l'escena actual i capa de visualització. Requereix passades de dades de desempolsegat i emissió als documents multicapa OpenEXR" +msgstr "[Denoise Animation]: Desorolla la seqüència d'animació revelada amb la configuració de l'escena actual i capa de visualització. Requereix passades de dades de desorollat i egressió als documents multicapa OpenEXR" msgid "Input Filepath" -msgstr "Ingressa camí" +msgstr "Camí d'ingressió" msgid "File path for image to denoise. If not specified, uses the render file path and frame range from the scene" -msgstr "[Input Filepath]: Camí al document per a què la imatge es desempolsegui. Si no s'especifica, utilitza el camí del document de revelat i l'interval de fotogrames de l'escena" +msgstr "[Input Filepath]: Camí al document per a què la imatge es desorolli. Si no s'especifica, utilitza el camí del document de revelat i l'interval de fotogrames de l'escena" msgid "Output Filepath" -msgstr "Camí d'emissió" +msgstr "Camí d'egressió" msgid "If not specified, renders will be denoised in-place" -msgstr "[Output Filepath]: Si no s'especifica, es desempolsegaran els revelats a lloc" +msgstr "[Output Filepath]: Si no s'especifica, es desorollaran els revelats al lloc" msgctxt "Operator" @@ -53110,7 +53207,7 @@ msgstr "Fusiona imatges" msgid "Combine OpenEXR multi-layer images rendered with different sample ranges into one image with reduced noise" -msgstr "[Merge Images]: Combina les imatges multicapa OpenEXR revelades amb diferents intervals de mostreig en una imatge amb poca pols" +msgstr "[Merge Images]: Combina les imatges multicapa OpenEXR revelades amb diferents intervals de mostreig en una imatge amb soroll reduït" msgid "File path for image to merge" @@ -53141,23 +53238,23 @@ msgstr "[Dynamic Paint Bake]: Superfície de seqüència d'imatge de pintura din msgctxt "Operator" msgid "Toggle Output Layer" -msgstr "Revesar capa d'emissió" +msgstr "Revesar capa d'egressió" msgid "Add or remove Dynamic Paint output data layer" -msgstr "[Toggle Output Layer]: Afegeix o elimina la capa de dades d'emissió de pintura dinàmica" +msgstr "[Toggle Output Layer]: Afegeix o elimina la capa de dades d'egressió de pintura dinàmica" msgid "Output Toggle" -msgstr "Revesar emissió" +msgstr "Revesar egressió" msgid "Output A" -msgstr "Emissió A" +msgstr "Egressió A" msgid "Output B" -msgstr "Emissió B" +msgstr "Egressió B" msgctxt "Operator" @@ -53665,7 +53762,7 @@ msgstr "Quant cal simplificar els valors precuinats (0.0 per a inhabilitar, com msgid "Sampling Rate" -msgstr "Freqüència de mostreig" +msgstr "Taxa de mostreig" msgid "How often to evaluate animated values (in frames)" @@ -53833,7 +53930,7 @@ msgstr "Coincidir" msgid "Match absolute/relative setting with input path" -msgstr "[Match]: Fa coincidir la configuració absoluta/relativa amb el camí d'ingrés" +msgstr "[Match]: Fa coincidir la configuració absoluta/relativa amb el camí d'ingressió" msgid "Strip Path" @@ -54126,7 +54223,7 @@ msgstr "[Always Sample Animations]: Aplica el mostreig a totes les animacions" msgid "Output format and embedding options. Binary is most efficient, but JSON (embedded or separate) may be easier to edit later" -msgstr "Emet format i opcions d'integració. El binari és el més eficient, però JSON (integrat o separat) pot ser més fàcil d'editar posteriorment" +msgstr "Egressa format i opcions d'integració. El binari és el més eficient, però JSON (integrat o separat) pot ser més fàcil d'editar posteriorment" msgid "glTF Binary (.glb)" @@ -54162,7 +54259,7 @@ msgstr "[Limit to Playback Range]: Retalla les animacions a l'interval seleccion msgid "Output format for images. PNG is lossless and generally preferred, but JPEG might be preferable for web applications due to the smaller file size. Alternatively they can be omitted if they are not needed" -msgstr "Format d'emissió per a les imatges. PNG és sense pèrdua i generalment preferible, però JPEG podria ser preferible per a aplicacions web a causa de la mida menor dels documents. Alternativament, es poden ometre si no són necessaris" +msgstr "Format d'egressió per a les imatges. PNG és sense pèrdua i generalment preferible, però JPEG podria ser preferible per a aplicacions web a causa de la mida menor dels documents. Alternativament, es poden ometre si no són necessaris" msgid "Save PNGs as PNGs and JPEGs as JPEGs. If neither one, use PNG" @@ -55361,7 +55458,7 @@ msgstr "Mode accents" msgid "Next typed character will strike through previous, for special character input" -msgstr "El següent caràcter teclejat cobrirà l'anterior, per a l'entrada de caràcters especials" +msgstr "El següent caràcter teclejat cobrirà l'anterior, per a la ingressió de caràcters especials" msgctxt "Operator" @@ -56968,7 +57065,7 @@ msgstr "Revesar mode escultura de traç" msgid "Enter/Exit sculpt mode for Grease Pencil strokes" -msgstr "Entra/Surt del mode d'escultura de traç de llapis de greix" +msgstr "Entra/Surt del mode escultura de traç de llapis de greix" msgctxt "Operator" @@ -57524,11 +57621,11 @@ msgstr "Reiniciar el color del vèrtex al traç i l'emplenat" msgctxt "Operator" msgid "Sample Stroke" -msgstr "Mostreig de traç" +msgstr "Generar traç" msgid "Sample stroke points to predefined segment length" -msgstr "[Sample Stroke]: Treu mostres de punts de traç a una longitud del segment predefinida" +msgstr "[Sample Stroke]: Genera punts de traç amb una longitud de segment predefinida" msgctxt "Operator" @@ -57696,7 +57793,7 @@ msgstr "Resolució de les corbes generades" msgid "Distance to sample points, zero to disable" -msgstr "Distància als punts de mostreig, zero per a desactivar" +msgstr "Distància als punts generats, zero per a desactivar" msgid "Scale of the final stroke" @@ -57952,7 +58049,7 @@ msgstr "Precuinar corba" msgid "Bake selected F-Curves to a set of sampled points defining a similar curve" -msgstr "[Bake Curve]: Precuina les corbes-F seleccionades fent-ne un conjunt de punts mostrejats que defineixen una corba similar" +msgstr "[Bake Curve]: Precuina les corbes-F seleccionades fent-ne un conjunt de punts generats que defineixen una corba similar" msgctxt "Operator" @@ -58386,7 +58483,7 @@ msgstr "[Lowest Frequency]: Freqüència de tall d'un filtre passada alta que s' msgid "Release Time" -msgstr "Moment de deixar anar" +msgstr "Temps d'amollar" msgid "Value for the hull curve calculation that tells how fast the hull curve can fall (the lower the value the steeper it can fall)" @@ -58406,7 +58503,7 @@ msgstr "Valor d'amplitud mínima necessari per a influir en la corba de closca" msgid "Only the positive differences of the hull curve amplitudes are summarized to produce the output" -msgstr "Només es resumeixen les diferències positives de les amplituds de la corba de closca a l'hora de produir el que s'emet" +msgstr "Només es resumeixen les diferències positives de les amplituds de la corba de closca a l'hora de produir el que s'egressa " msgid "The amplitudes of the hull curve are summarized (or, when Accumulate is enabled, both positive and negative differences are accumulated)" @@ -58414,7 +58511,7 @@ msgstr "Les amplituds de la corba de closca es resumeixen (o, quan s'habilita Ac msgid "The output is a square curve (negative values always result in -1, and positive ones in 1)" -msgstr "L'emissió és una corba quadrada (els valors negatius sempre resulten en -1, i els positius en 1)" +msgstr "L'egressió és una corba quadrada (els valors negatius sempre resulten en -1, i els positius en 1)" msgctxt "Operator" @@ -58694,7 +58791,7 @@ msgstr "[Remove Render Slot]: Suprimeix l'epígraf de revelat actual" msgctxt "Operator" msgid "Render Region" -msgstr "Regió de revelat" +msgstr "Revelar regió" msgid "Set the boundaries of the render region and enable render region" @@ -58721,7 +58818,7 @@ msgstr "[Resize the image]: Canvia la mida de la imatge" msgctxt "Operator" msgid "Sample Color" -msgstr "Mostrejar color" +msgstr "Pescar color" msgid "Use mouse to sample a color in current image" @@ -58730,7 +58827,7 @@ msgstr "[Sample Color]: Utilitza el ratolí per recollir un color de la imatge a msgctxt "Operator" msgid "Sample Line" -msgstr "Mostrekar línia" +msgstr "Pescar línia" msgid "Sample a line and show it in Scope panels" @@ -58799,7 +58896,7 @@ msgid "" msgstr "" "Desa la imatge amb la gestió del color de revelat.\n" "Per a formats d'imatge com PNG, aplicar la transformació de la visualització en pantalla.\n" -"Per als formats d'imatge intermedis com l'OpenEXR, usar l'espai de color d'emissió de revelat predeterminat" +"Per als formats d'imatge intermedis com l'OpenEXR, usar l'espai de color d'egressió de revelat predeterminat" msgctxt "Operator" @@ -59916,19 +60013,11 @@ msgid "Clear Restrict View" msgstr "Descartar restricció de vista" -msgid "Reveal the layer by setting the hide flag" -msgstr "[Clear Restrict View]: Evidencia la capa operant l'indicador d'ocultació" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Aplicar restricció de vista" -msgid "Hide the layer by setting the hide flag" -msgstr "[Set Restrict View]: Oculta la capa operant l'indicador d'ocultació" - - msgctxt "Operator" msgid "Move Layer" msgstr "Moure capa" @@ -61735,7 +61824,7 @@ msgstr "Copia les coordenades absolutes o el Vector de normal" msgid "Mode of tools taking input from interface" -msgstr "Mode d'eines que agafen l'ingrés des de la interfície" +msgstr "Mode d'eines que agafen ingressió des de la interfície" msgid "Copy Normal" @@ -62002,7 +62091,7 @@ msgstr "Crear quads" msgid "Automatically split edges in triangles to maintain quad topology" -msgstr "[Create Quads]: Divideix automàticament les arestes de triangles per a mantenir la topologia quad" +msgstr "[Create Quads]: Parteix automàticament les arestes de triangles per a mantenir la topologia quad" msgctxt "Operator" @@ -62535,7 +62624,7 @@ msgstr "Cardan" msgid "Align each axis to the Euler rotation axis as used for input" -msgstr "[Gimbal]: Alinea cada eix a l'eix de rotació d'Euler utilitzat com a ingrés" +msgstr "[Gimbal]: Alinea cada eix a l'eix de rotació d'Euler utilitzat com a ingressió" msgid "Align the transformation axes to the window" @@ -63904,16 +63993,16 @@ msgstr "Mou el node de fons" msgctxt "Operator" msgid "Backimage Sample" -msgstr "Mostreig d'imatge de rerefons" +msgstr "Pescar en imatge de rerefons" msgid "Use mouse to sample background image" -msgstr "[Backimage Sample]: Usa el ratolí per fer mostreig de la imatge de refons" +msgstr "[Backimage Sample]: Usa el ratolí per recollir una mostra de la imatge de refons" msgctxt "Operator" msgid "Background Image Zoom" -msgstr "Zoom imatge de fons" +msgstr "Zoom d'imatge de fons" msgid "Zoom in/out the background image" @@ -63956,7 +64045,7 @@ msgstr "Afegir born de criptoclapa" msgid "Add a new input layer to a Cryptomatte node" -msgstr "[Add Cryptomatte Socket]: Afegeix una nova capa d'ingrés en un node criptoclapa" +msgstr "[Add Cryptomatte Socket]: Afegeix una nova capa d'ingressió en un node criptoclapa" msgctxt "Operator" @@ -64072,7 +64161,7 @@ msgstr "Cerca un node per nom, l'enfoca i el selecciona" msgctxt "Operator" msgid "glTF Material Output" -msgstr "Sortida de material glTF" +msgstr "Egressió de material glTF" msgid "Add a node to the active tree for glTF export" @@ -64370,7 +64459,7 @@ msgstr "[Add File Node Socket]: Afegeix una entrada nova a un node de sortida de msgid "Subpath of the output file" -msgstr "Subcamí del document a emetre" +msgstr "Subcamí del document a egressar" msgctxt "Operator" @@ -64379,7 +64468,7 @@ msgstr "Moure el born de node per a document" msgid "Move the active input of a file output node up or down the list" -msgstr "Mou l'entrada activa d'un node d'emissió de document amunt o avall de la llista" +msgstr "Mou l'entrada activa d'un node d'egressió de document amunt o avall de la llista" msgctxt "Operator" @@ -64388,7 +64477,7 @@ msgstr "Eliminar born de node de document" msgid "Remove the active input from a file output node" -msgstr "Elimina l'entrada activa d'un node d'emissió de document" +msgstr "Elimina l'entrada activa d'un node d'egressió de document" msgid "Attach selected nodes" @@ -64755,7 +64844,7 @@ msgstr "Quin algorisme s'ha d'utilitzar per a generar el marge" msgid "Filter to combined, diffuse, glossy, transmission and subsurface passes" -msgstr "Filtrar a passades combinades, de difusió, setinades, de transmissió i de subsuperfície" +msgstr "Filtrar a passades combinades, difusives, setinades, de transmissió i de subsuperfície" msgid "Type of pass to bake, some of them may not be supported by the current render engine" @@ -64763,7 +64852,7 @@ msgstr "Tipus de passada per al precuinat, algunes poden no ser compatibles amb msgid "Automatically name the output file with the pass type" -msgstr "Nomena automàticament el document d'emissió amb el tipus de passada" +msgstr "Nomena automàticament el document d'egressió amb el tipus de passada" msgid "Clear images before baking (only for internal saving)" @@ -64771,7 +64860,7 @@ msgstr "Descartar imatges abans de precuinar (només per a desar internament)" msgid "Split baked maps per material, using material name in output file (external only)" -msgstr "Dividir els mapes precuinats per material, usant el nom del material al document emès (només extern)" +msgstr "Dividir els mapes precuinats per material, usant el nom del material al document egressat (només extern)" msgid "UV layer to override active" @@ -65292,7 +65381,7 @@ msgstr "Copia el grup actiu de nodes de geometria i l'assigna al modificador act msgctxt "Operator" msgid "Input Attribute Toggle" -msgstr "Revesar atribut d'ingrés" +msgstr "Revesar ingressió d'atribut" msgid "Switch between an attribute and a single value to define the data for every element" @@ -65309,7 +65398,7 @@ msgstr "Moure a nodes" msgid "Move inputs and outputs from in the modifier to a new node group" -msgstr "Mou ingressos i emissions de l'interior del modificador a un nou grup de nodes" +msgstr "Mou entrades i sortides de l'interior del modificador a un nou grup de nodes" msgctxt "Operator" @@ -66582,7 +66671,7 @@ msgstr "Suavitzar normals" msgid "Set the output mesh normals to smooth" -msgstr "[Smooth Normals]: Defineix les normals emeses de la malla com a suavitzades" +msgstr "[Smooth Normals]: Defineix les normals egressades de la malla com a suavitzades" msgid "Target edge length in the new mesh" @@ -69143,15 +69232,15 @@ msgstr "[Project Image]: Projecta un revelat editat des de la càmera activa de msgid "Use the mouse to sample a color in the image" -msgstr "Usar ratolí per mostrejar un color a la imatge" +msgstr "Usar ratolí per pescar un color a la imatge" msgid "Sample Merged" -msgstr "Mostreig fusionat" +msgstr "Pescar fusionat" msgid "Sample the output display color" -msgstr "Mostreja el color emès de visualització" +msgstr "Treu mostra del color egressat de visualització" msgid "Add to Palette" @@ -69354,16 +69443,16 @@ msgstr "Revesa el mode de pintura de pesos en la vista 3D" msgctxt "Operator" msgid "Weight Paint Sample Weight" -msgstr "Mostra de pes de pintura de pesos" +msgstr "Pescar pes de pintura de pesos" msgid "Use the mouse to sample a weight in the 3D view" -msgstr "[Weight Paint Sample Weight]: Utilitza el ratolí per a mostrejar un pes en la vista 3D" +msgstr "[Weight Paint Sample Weight]: Usa el ratolí per a treure una mostra d'un pes en la vista 3D" msgctxt "Operator" msgid "Weight Paint Sample Group" -msgstr "Grup de mostra de pintura de força" +msgstr "Grup de mostra de pintura de pesos" msgid "Select one of the vertex groups available under current mouse position" @@ -70930,7 +71019,7 @@ msgstr "Escriure imatge" msgid "Save rendered the image to the output path (used only when animation is disabled)" -msgstr "Desa la imatge revelada al camí d'emissió (només usat quan l'animació està desactivada)" +msgstr "Desa la imatge revelada al camí d'egressió (només usat quan l'animació està desactivada)" msgctxt "Operator" @@ -73177,12 +73266,12 @@ msgstr "[Reveal All]: Desoculta tota la geometria" msgid "Sample the vertex color of the active vertex" -msgstr "Mostrejar el color de vèrtex del vèrtex actiu" +msgstr "Pescar el color de vèrtex del vèrtex actiu" msgctxt "Operator" msgid "Sample Detail Size" -msgstr "Mostrejar mida del detall" +msgstr "Pescar mida del detall" msgid "Sample the mesh detail on clicked point" @@ -73198,7 +73287,7 @@ msgstr "Mode detall" msgid "Target sculpting workflow that is going to use the sampled size" -msgstr "Flux de treball d'escultura buscat que farà servir la mida mostrejada" +msgstr "Flux de treball d'escultura on es farà ús la mida recollida" msgid "Dyntopo" @@ -73206,11 +73295,11 @@ msgstr "Dyntopo" msgid "Sample dyntopo detail" -msgstr "Mostreja detalls del dyntopo" +msgstr "Pescar detalls del dyntopo" msgid "Sample mesh voxel size" -msgstr "Mostrejar mida de vòxel de malla" +msgstr "Pescar mida de vòxel de malla" msgctxt "Operator" @@ -73219,7 +73308,7 @@ msgstr "Mode escultura" msgid "Toggle sculpt mode in 3D view" -msgstr "Alterna el mode d'esculpir en la vista 3D" +msgstr "Alterna el mode esculpir en la vista 3D" msgctxt "Operator" @@ -73386,7 +73475,7 @@ msgstr "Canviar ingressió d'efecte" msgid "The effect inputs to swap" -msgstr "Ingressos d'efecte a intercanviar" +msgstr "Ingressions d'efecte a intercanviar" msgid "A -> B" @@ -73929,15 +74018,15 @@ msgstr "Mantenir en enganxar desplaçament de segment en relació amb el fotogra msgctxt "Operator" msgid "Reassign Inputs" -msgstr "Reassignar ingressos" +msgstr "Reassignar ingressions" msgid "Reassign the inputs for the effect strip" -msgstr "[Reassign Inputs]: Reassigna els ingressos per al segment d'efecte" +msgstr "[Reassign Inputs]: Reassigna les ingressions per al segment d'efecte" msgid "Rebuild all selected proxies and timecode indices using the job system" -msgstr "Recomposa totes les simulacions i índexs de codis de temps seleccionats usant el sistema de tasques" +msgstr "Recomposa totes les simulacions i índexs de cronofites seleccionats usant el sistema de tasques" msgctxt "Operator" @@ -73981,7 +74070,7 @@ msgstr "[Set Render Size]: Estableix la mida i l'aspecte del revelat a partir de msgid "Use mouse to sample color in current frame" -msgstr "Usare ratolí per a mostrejar el color en el fotograma actual" +msgstr "Usar ratolí per a pescar un color en el fotograma actual" msgctxt "Operator" @@ -74475,11 +74564,11 @@ msgstr "Intercanvia 2 segments de seqüenciador" msgctxt "Operator" msgid "Swap Inputs" -msgstr "Intercanviar ingressos" +msgstr "Intercanviar ingressions" msgid "Swap the first two inputs for the effect strip" -msgstr "[Swap Inputs]: Intercanvia els primers dos ingressos pel segment d'efecte" +msgstr "[Swap Inputs]: Intercanvia les primeres dues ingressions pel segment d'efecte" msgctxt "Operator" @@ -75728,7 +75817,7 @@ msgstr "Copiar com a controlador nou" msgid "Create a new driver with this property as input, and copy it to the clipboard. Use Paste Driver to add it to the target property, or Paste Driver Variables to extend an existing driver" -msgstr "Crea un controlador nou amb aquesta propietat com a ingrés i la copia al porta-retalls. Usa Enganxar controlador per afegir-lo a la propietat de referència, o Enganxar variables de controlador per ampliar un controlador existent" +msgstr "Crea un controlador nou amb aquesta propietat com a ingressió i la copia al porta-retalls. Usa Enganxar controlador per afegir-lo a la propietat de referència, o Enganxar variables de controlador per ampliar un controlador existent" msgctxt "Operator" @@ -75932,7 +76021,7 @@ msgstr "Pista del control definit per l'ARN, si n'hi ha" msgid "Flags about the RNA-defined tip of the button" -msgstr "Indicadors sobre la pista del botñi definida per l'ARN" +msgstr "Indicadors sobre la pista del botó definida per l'ARN" msgid "Stats from opened po" @@ -75957,7 +76046,7 @@ msgstr "Pipeta" msgid "Sample a color from the Blender window to store in a property" -msgstr "[Eyedropper]: Mostreja un color des de la finestra del Blender per a emmagatzemar-lo en una propietat" +msgstr "[Eyedropper]: Pesca un color des de la finestra del Blender per a emmagatzemar-lo en una propietat" msgctxt "Operator" @@ -75966,7 +76055,7 @@ msgstr "Banda de color amb pipeta" msgid "Sample a color band" -msgstr "Mostreja una banda de color" +msgstr "Pesca una banda de color" msgctxt "Operator" @@ -75975,7 +76064,7 @@ msgstr "Banda de color amb pipeta (punts)" msgid "Point-sample a color band" -msgstr "Mostreja amb punts una banda de color" +msgstr "Pesca amb punts una banda de color" msgctxt "Operator" @@ -75984,7 +76073,7 @@ msgstr "Profunditat de pipeta" msgid "Sample depth from the 3D view" -msgstr "Mostreja profunditat des de la vista 3D" +msgstr "Pesca profunditat des de la vista 3D" msgctxt "Operator" @@ -76050,7 +76139,7 @@ msgstr "Pipeta de llapis de greix" msgid "Sample a color from the Blender Window and create Grease Pencil material" -msgstr "Mostreja un color des de la finestra del Blender i crea material amb llapis de greix" +msgstr "Pesca un color des de la finestra del Blender i crea material amb llapis de greix" msgctxt "Operator" @@ -76059,7 +76148,7 @@ msgstr "Bloc de dades de pipeta" msgid "Sample a data-block from the 3D View to store in a property" -msgstr "Mostra un bloc de dades des de la vista 3D per a emmagatzemar en una propietat" +msgstr "Pesca un bloc de dades des de la vista 3D per a emmagatzemar en una propietat" msgctxt "Operator" @@ -76811,7 +76900,7 @@ msgstr "Sumar simplement el marge, ignorant qualsevol escala UV" msgid "Specify a precise fraction of final UV output" -msgstr "Especificar una fracció precisa de l'emissió final d'UV" +msgstr "Especificar una fracció precisa de l'egressió final d'UV" msgid "Rotate islands for best fit" @@ -78322,7 +78411,7 @@ msgstr "Zoom de càmera 1:1" msgid "Match the camera to 1:1 to the render output" -msgstr "Fa coincidir la càmera en un 1:1 de l'emissió del revelat" +msgstr "Fa coincidir la càmera en un 1:1 de l'egressió del revelat" msgctxt "Operator" @@ -78419,11 +78508,11 @@ msgstr "Valor pel qual s'amplien o redueixen els objectes respecte de l'origen d msgid "Geometry Samples" -msgstr "Mostres de geometria" +msgstr "Mostretjos de geometria" msgid "Number of times per frame object data are sampled" -msgstr "[Geometry Samples]: Nombre de cops per fotograma que es prenen mostres de dades d'objecte" +msgstr "[Geometry Samples]: Nombre de cops per fotograma que es mostregen dades d'objecte" msgid "Export normals" @@ -78503,11 +78592,11 @@ msgstr "Exporta només objectes que siguin visibles" msgid "Transform Samples" -msgstr "Transformar mostres" +msgstr "Transformar mostretjos" msgid "Number of times per frame transformations are sampled" -msgstr "Nombre de vegades per fotograma que es prenen mostres de transformacions" +msgstr "Nombre de vegades per fotograma que es mostregen transformacions" msgctxt "Operator" @@ -78751,11 +78840,11 @@ msgstr "Tipus de fites" msgid "Type for exported animations (use sample keys or Curve keys)" -msgstr "[Key Type]: Tipus per a les animacions exportades (s'usen fites redistribuïdes of fites de corba)" +msgstr "[Key Type]: Tipus per a les animacions exportades (s'usen fites generades of fites de corba)" msgid "Export Sampled points guided by sampling rate" -msgstr "Exportar punts mostrejats guiats per la freqüència de mostreig" +msgstr "Exportar punts generats guiats per la freqüència de mostreig" msgid "Export Curves (note: guided by curve keys)" @@ -78903,7 +78992,7 @@ msgstr "Mantenir fotofites" msgid "Use existing keyframes as additional sample points (this helps when you want to keep manual tweaks)" -msgstr "Utilitza les fotofites existents com a punts de distribució addicionals ( això ajuda quan vols mantenir ajustos fets manualment )" +msgstr "Utilitza les fotofites existents com a punts de mostreig addicionals ( això ajuda quan vols mantenir ajustos fets manualment )" msgid "Keep Smooth curves" @@ -79134,7 +79223,7 @@ msgstr "Ratolí modal de context" msgid "Adjust arbitrary values with mouse input" -msgstr "Ajusta els valors arbitraris amb ingressos del ratolí" +msgstr "Ajusta els valors arbitraris amb ingressions del ratolí" msgid "Header Text" @@ -79150,7 +79239,7 @@ msgstr "Escalar el moviment del ratolí per aquest valor abans d'aplicar el delt msgid "Invert the mouse input" -msgstr "Invertir ingrés de ratolí" +msgstr "Invertir ingressió de ratolí" msgctxt "Operator" @@ -79460,7 +79549,7 @@ msgstr "Incloure tots els objectes visibles" msgid "Precision of stroke sampling. Low values mean a more precise result, and zero disables sampling" -msgstr "Precisió del mostreig del traç. Els valors baixos donen un resultat més precís, i zero inhabilita el mostreig" +msgstr "Precisió del generador de traç. Els valors baixos donen un resultat més precís, i zero inhabilita la generació" msgid "Export strokes with fill enabled" @@ -80231,7 +80320,7 @@ msgstr "Camí de l'identificador que s'utilitza per a generar una imatge per al msgid "Confirm On Release" -msgstr "Confirmar en deixar anar" +msgstr "Confirmar en amollar" msgid "Finish operation on key release" @@ -80985,7 +81074,7 @@ msgstr "Definir fusió de material" msgid "If the Import USD Preview option is enabled, the material blend method will automatically be set based on the shader's opacity and opacityThreshold inputs" -msgstr "[Set Material Blend]: Si l'opció d'importar previsualització USD està activada, el mètode de fusió de material es configurarà automàticament en funció dels ingressos d'opacitat i d'interval d'opacitat de l'aspector" +msgstr " [Set Material Blend]: Si l'opció d'importar previsualització USD està activada, el mètode de fusió de material es configurarà automàticament en funció de les ingressions d'opacitat i d'interval d'opacitat de l'aspector" msgid "File Name Collision" @@ -81406,7 +81495,7 @@ msgstr "Corba de cavitat editable" msgid "Average multiple input samples together to smooth the brush stroke" -msgstr "Mitjana de múltiples mostres juntes d'ingrés per a suavitzar la pinzellada" +msgstr "Mitjana de múltiples mostres juntes d'ingressió per a suavitzar la pinzellada" msgid "Active Palette" @@ -81985,10 +82074,6 @@ msgid "2D Cursor" msgstr "Cursor 2D" -msgid "Active Point" -msgstr "Punt actiu" - - msgid "Predefined tracking camera intrinsics" msgstr "Intrínsecs de seguiment de càmera predefinits" @@ -82018,7 +82103,7 @@ msgstr "Visualització de màscara" msgid "Proxy/Timecode" -msgstr "Simulació/Timecode" +msgstr "Simulació/Cronofita" msgid "Stabilization" @@ -82340,7 +82425,7 @@ msgstr "Abast" msgid "Sample Line" -msgstr "Línia de mostra" +msgstr "Línia de mostreig" msgid "Snapping" @@ -82349,11 +82434,11 @@ msgstr "Acoblament" msgctxt "Operator" msgid "Sample" -msgstr "Mostrar" +msgstr "Pescar" msgid "Sample pixel values under the cursor" -msgstr "Fa un mostreig de valors dels píxels sota el cursor" +msgstr "Mostreja valors dels píxels sota el cursor" msgctxt "Operator" @@ -82863,7 +82948,7 @@ msgstr "Memòria cau de pista" msgid "Strip Proxy & Timecode" -msgstr "Timecode i simulació de pista" +msgstr "Cronofita i simulació de pista" msgctxt "Operator" @@ -83574,12 +83659,12 @@ msgstr "Degradat" msgctxt "Operator" msgid "Sample Weight" -msgstr "Mostrejar pesos" +msgstr "Pescar pesos" msgctxt "Operator" msgid "Sample Vertex Group" -msgstr "Mostrejar grup de vèrtexs" +msgstr "Pescar grup de vèrtexs" msgctxt "Operator" @@ -83973,11 +84058,11 @@ msgstr "Mode selecció de punts" msgid "Tip" -msgstr "Consell" +msgstr "Punta" msgid "Tip select mode" -msgstr "[Tip]: Mode selecció de consells" +msgstr "[Tip]: Mode selecció de puntes" msgid "Shape Object" @@ -84665,7 +84750,7 @@ msgstr "Col·lecció de memòria cau de punts" msgid "Polygon Float Properties" -msgstr "Propietats flotanta del polígon " +msgstr "Propietats flotants del polígon" msgid "Collection of float properties" @@ -85057,7 +85142,7 @@ msgstr "Camins per defecte a documents externs" msgid "Settings for input devices" -msgstr "Paràmetres per als dispositius d'ingrés" +msgstr "Paràmetres per als dispositius d'ingressió" msgid "Preferences have changed" @@ -85065,7 +85150,7 @@ msgstr "Les preferències han canviat" msgid "Shortcut setup for keyboards and other input devices" -msgstr "Configuració de dreceres de teclats i altres dispositius d'ingrés" +msgstr "Configuració de dreceres de teclats i altres dispositius d'ingressió" msgid "System & OpenGL" @@ -85321,42 +85406,4850 @@ msgid "Causes camera data to be duplicated with the object" msgstr "Fa que les dades de la càmera es dupliquin amb l'objecte" +msgid "Causes curve data to be duplicated with the object" +msgstr "Fa que les dades de la corba es dupliquin amb l'objecte" + + +msgid "Duplicate Curves" +msgstr "Duplicar corbes" + + +msgid "Causes curves data to be duplicated with the object" +msgstr "Fa que les dades de corbes es dupliquin amb l'objecte" + + +msgid "Duplicate GPencil" +msgstr "Duplicar Llapis-dG" + + +msgid "Causes grease pencil data to be duplicated with the object" +msgstr "[Duplicate GPencil]: Fa que les dades del llapis de greix es dupliquin amb l'objecte" + + +msgid "Duplicate Lattice" +msgstr "Duplicar retícula" + + +msgid "Causes lattice data to be duplicated with the object" +msgstr "[Duplicate Lattice]: Fa que les dades de la retícula es dupliquin amb l'objecte" + + +msgid "Duplicate Light" +msgstr "Duplicar llum" + + +msgid "Causes light data to be duplicated with the object" +msgstr "Fa que les dades del llum es dupliquin amb l'objecte" + + +msgid "Duplicate Light Probe" +msgstr "Duplicar sonda de llum" + + +msgid "Causes light probe data to be duplicated with the object" +msgstr "Fa que les dades de la sonda llum es dupliquin amb l'objecte" + + +msgid "Duplicate Material" +msgstr "Duplicar material" + + +msgid "Causes material data to be duplicated with the object" +msgstr "Fa que les dades materials es dupliquin amb l'objecte" + + +msgid "Duplicate Mesh" +msgstr "Duplicar malla" + + +msgid "Causes mesh data to be duplicated with the object" +msgstr "Fa que les dades de malla es dupliquin amb l'objecte" + + +msgid "Duplicate Metaball" +msgstr "Duplicar metabola" + + +msgid "Causes metaball data to be duplicated with the object" +msgstr "Fa que les dades de la metabola es dupliquin amb l'objecte" + + +msgid "Duplicate Node Tree" +msgstr "Duplicar arbre de nodes" + + +msgid "Make copies of node groups when duplicating nodes in the node editor" +msgstr "Fes còpies dels grups de nodes quan es dupliquen nodes a l'editor de nodes" + + +msgid "Duplicate Particle" +msgstr "Duplicar partícules" + + +msgid "Causes particle systems to be duplicated with the object" +msgstr "Fa que els sistemes de partícules es dupliquin amb l'objecte" + + +msgid "Duplicate Point Cloud" +msgstr "Duplicar núvol de punts" + + +msgid "Causes point cloud data to be duplicated with the object" +msgstr "Fa que les dades del núvol de punts es dupliquin amb l'objecte" + + +msgid "Duplicate Speaker" +msgstr "Duplicar altaveu" + + +msgid "Causes speaker data to be duplicated with the object" +msgstr "Fa que les dades de l'altaveu es dupliquin amb l'objecte" + + +msgid "Duplicate Surface" +msgstr "Duplicar superfície" + + +msgid "Causes surface data to be duplicated with the object" +msgstr "Fa que les dades de la superfície es dupliquin amb l'objecte" + + +msgid "Duplicate Text" +msgstr "Duplicar text" + + +msgid "Causes text data to be duplicated with the object" +msgstr "Fa que les dades de text es dupliquin amb l'objecte" + + +msgid "Duplicate Volume" +msgstr "Duplicar volum" + + +msgid "Causes volume data to be duplicated with the object" +msgstr "Fa que les dades del volum es dupliquin amb l'objecte" + + +msgid "Enter edit mode automatically after adding a new object" +msgstr "Entrar en mode d'edició automàticament després d'afegir un objecte nou" + + +msgid "Global Undo" +msgstr "Desfer globalment" + + +msgid "Global undo works by keeping a full copy of the file itself in memory, so takes extra memory" +msgstr "El desfer global funciona mantenint una còpia completa del document en memòria, de manera que necessita memòria extra" + + +msgid "New F-Curve Colors - XYZ to RGB" +msgstr "Nous nous de corba-F - d'XYZ a RGB" + + +msgid "Color for newly added transformation F-Curves (Location, Rotation, Scale) and also Color is based on the transform axis" +msgstr "[New F-Curve Colors - XYZ to RGB]: Color per a les transformacions de les corbes-F afegides de nou (ubicació, rotació, escala) i el color també es basa en l'eix de transformació" + + +msgid "Auto Keyframe Insert Available" +msgstr "Disponible la inserció de fotofita automàtica" + + +msgid "Automatic keyframe insertion in available F-Curves" +msgstr "[Auto Keyframe Insert Available]: Inserció automàtica de fotofites en les corbes-F disponibles" + + +msgid "Keyframe Insert Needed" +msgstr "Inserció de fotofita requerida" + + +msgid "Keyframe insertion only when keyframe needed" +msgstr "[Keyframe Insert Needed]: Inserció de la fotofita només quan la fotofita és necessària" + + +msgid "Cursor Surface Project" +msgstr "Projecció de cursor a superfície" + + +msgid "Use the surface depth for cursor placement" +msgstr "Usa la profunditat de la superfície per a la col·locació del cursor" + + +msgid "Allow Negative Frames" +msgstr "Permetre fotogrames negatius" + + +msgid "Current frame number can be manually set to a negative value" +msgstr "El número del fotograma actual es pot establir manualment a un valor negatiu" + + +msgid "Auto Close Character Pairs" +msgstr "Autotanca parells de caràcters" + + +msgid "Automatically close relevant character pairs when typing in the text editor" +msgstr "Tanca automàticament els parells de caràcters pertinents en escriure en l'editor de text" + + +msgid "Use Visual keying automatically for constrained objects" +msgstr "Usar fites visuals automàtiques per a objectes restringits" + + +msgid "Experimental features" +msgstr "Característiques experimentals" + + +msgid "EEVEE Next" +msgstr "EEVEE següent" + + +msgid "Enable the new EEVEE codebase, requires restart" +msgstr "Activa el codi base nou d'EEVEE, cal reiniciar" + + +msgid "Workbench Next" +msgstr "Workbench següent" + + +msgid "Enable the new Workbench codebase, requires restart" +msgstr "Activa el codi base nou de Workbench, cal reiniciar" + + +msgid "Override Auto Resync" +msgstr "Autoresincronització de sobreseïments" + + +msgid "Enable library overrides automatic resync detection and process on file load. Disable when dealing with older .blend files that need manual Resync (Enforce) handling" +msgstr "[Override Auto Resync]: Activa en carregar el document el processament i la detecció de la resincronització automàtica de sobreseïments de biblioteques. Inhabilitar amb documents .blend antics que necessiten gestionar (forçar) la resincronització manual" + + +msgid "Asset Debug Info" +msgstr "Info de depuració de recursos" + + +msgid "Enable some extra fields in the Asset Browser to aid in debugging" +msgstr "Activa alguns camps addicionals al navegador d'actius per assistir en la depuració" + + +msgid "All Linked Data Direct" +msgstr "Dades enllaçades totes directes" + + +msgid "Forces all linked data to be considered as directly linked. Workaround for current issues/limitations in BAT (Blender studio pipeline tool)" +msgstr "[All Linked Data Direct]: Força que totes les dades enllaçades es considerin directament enllaçades. Solució temporal per als problemes/limitacions actuals del BAT (eina de flux canonada d'estudi Blender)" + + +msgid "Asset Indexing" +msgstr "Indexació de recursos" + + +msgid "Disabling the asset indexer forces every asset library refresh to completely reread assets from disk" +msgstr "Desactivar l'indexador de recursos obliga a totes les biblioteques de recursos a rellegir da dalt a baix els recursos del disc" + + +msgid "Cycles Debug" +msgstr "Depuració de Cycles" + + +msgid "Enable Cycles debugging options for developers" +msgstr "Activa les opcions de depuració de Cycles per als desenvolupadors" + + +msgid "Extended Asset Browser" +msgstr "Navegador de recursos ampliat" + + +msgid "Enable Asset Browser editor and operators to manage regular data-blocks as assets, not just poses" +msgstr "Habilita l'editor i operadors del navegador de recursos perquè gestioni blocs de dades regulars com a recursos, no només poses" + + +msgid "Full Frame Compositor" +msgstr "Conjuminador complet de fotogrames" + + +msgid "Enable compositor full frame execution mode option (no tiling, reduces execution time and memory usage)" +msgstr "[Full Frame Compositor]: Activa l'opció del mode d'execució completa de fotogrames en el conjuminador (no tessel·la, redueix el temps d'execució i l'ús de memòria)" + + +msgid "New Curves Tools" +msgstr "Eines de noves corbes" + + +msgid "Enable additional features for the new curves data block" +msgstr "Habilita característiques addicionals per al bloc de dades de corbes noves" + + +msgid "New Point Cloud Type" +msgstr "Tipus nou de núvol de punts" + + +msgid "Enable the new point cloud type in the ui" +msgstr "Habilita el nou tipus de núvol de punts a la IU" + + +msgid "New Volume Nodes" +msgstr "Nous nodes de volum" + + +msgid "Enables visibility of the new Volume nodes in the UI" +msgstr "Habilita la visibilitat dels nous nodes de volum a la IU" + + +msgid "Override Templates" +msgstr "Sobreseure plantilles" + + msgid "Enable library override template in the python API" -msgstr "Activa la plantilla de sobreseïment de la biblioteca a l'API de python" +msgstr "Habilita la plantilla de sobreseïment de biblioteca a l'API de python" + + +msgid "Sculpt Texture Paint" +msgstr "Esculpir pintant textura" + + +msgid "Use texture painting in Sculpt Mode" +msgstr "Usa la pintura de textura en el mode escultura" + + +msgid "Sculpt Mode Tilt Support" +msgstr "Suport d'inclinació en mode escultura" + + +msgid "Support for pen tablet tilt events in Sculpt Mode" +msgstr "[Sculpt Mode Tilt Support]: Suport per a esdeveniments d'inclinació del pen de tauleta en mode escultura" + + +msgid "Undo Legacy" +msgstr "Desfer antic" + + +msgid "Use legacy undo (slower than the new default one, but may be more stable in some cases)" +msgstr "Usa el desfer d'abans (més lent que el predeterminat nou, però pot ser més estable en alguns casos)" + + +msgid "Enable viewport debugging options for developers in the overlays pop-over" +msgstr "Activa les opcions de depuració de miradir per als desenvolupadors en les bambolines emergents" + + +msgid "Active Asset Library" +msgstr "Biblioteca de recursos activa" + + +msgid "Index of the asset library being edited in the Preferences UI" +msgstr "Índex de la biblioteca de recursos en edició en les preferències de la IU" + + +msgid "Animation Player" +msgstr "Reproductor d'animacions" + + +msgid "Path to a custom animation/frame sequence player" +msgstr "Camí cap a un reproductor personalitzat de seqüències d'animació/fotogrames" + + +msgid "Animation Player Preset" +msgstr "Reproductor d'animacions predefinit" + + +msgid "Preset configs for external animation players" +msgstr "Configuracions predefinides per als reproductors d'animació externs" + + +msgid "Built-in animation player" +msgstr "Reproductor d'animacions integrat" + + +msgid "DJV" +msgstr "DJV" + + +msgid "Open source frame player" +msgstr "Reproductor de fotogrames de codi obert" + + +msgid "FrameCycler" +msgstr "FrameCycler" + + +msgid "Frame player from IRIDAS" +msgstr "Reproductor de fotogrames d'IRIDAS" + + +msgid "RV" +msgstr "RV" + + +msgid "Frame player from Tweak Software" +msgstr "Reproductor de fotogrames de Tweak Software" + + +msgid "MPlayer" +msgstr "MPlayer" + + +msgid "Media player for video and PNG/JPEG/SGI image sequences" +msgstr "Reproductor multimèdia per a vídeo i seqüències d'imatges PNG/JPEG/SGI" + + +msgid "Custom animation player executable path" +msgstr "Camí executable al reproductor d'animacions personalitzat" + + +msgid "Auto Save Time" +msgstr "Temps d'autodesats" + + +msgid "The time (in minutes) to wait between automatic temporary saves" +msgstr "[Auto Save Time]: El temps (en minuts) d'espera entre desats temporals automàtics" + + +msgid "File Preview Type" +msgstr "Tipus de previsualització de document" + + +msgid "What type of blend preview to create" +msgstr "El tipus de vista prèvia de blend a crear" + + +msgid "Do not create blend previews" +msgstr "No crear previsualitzacions de blends" + + +msgid "Automatically select best preview type" +msgstr "Triar automàticament el millor tipus de vista prèvia" + + +msgid "Screenshot" +msgstr "Pantallada" + + +msgid "Capture the entire window" +msgstr "Captura tota la finestra" + + +msgid "Camera View" +msgstr "Vista de càmera" + + +msgid "Workbench render of scene" +msgstr "Revelat d'escena del Workbench" + + +msgid "Fonts Directory" +msgstr "Directori de tipografies" + + +msgid "The default directory to search for loading fonts" +msgstr "El directori predeterminat on cercar les tipografies a carregar" + + +msgid "Translation Branches Directory" +msgstr "Directori de branques de traducció" + + +msgid "The path to the '/branches' directory of your local svn-translation copy, to allow translating from the UI" +msgstr "El camí al directori «/branches» de la teva còpia de la traducció SVN local, que permet traduir des de la IU" + + +msgid "Image Editor" +msgstr "Editor d'imatges" + + +msgid "Path to an image editor" +msgstr "Camí a un editor d'imatges" + + +msgid "Recent Files" +msgstr "Documents recents" + + +msgid "Maximum number of recently opened files to remember" +msgstr "Nombre màxim de documents recents a recordar" + + +msgid "Render Cache Path" +msgstr "Camí de la cau de revelat" + + +msgid "Where to cache raw render results" +msgstr "On s'emmagatzemaran en memòria cau els resultats de revelat en brut" + + +msgid "Render Output Directory" +msgstr "Directori d'egressió de revelat" + + +msgid "The default directory for rendering output, for new scenes" +msgstr "El directori predeterminat per a la sortida del revelat, per a escenes noves" + + +msgid "Save Versions" +msgstr "Desar versions" + + +msgid "The number of old versions to maintain in the current directory, when manually saving" +msgstr "El nombre de versions antigues a mantenir en el directori actual, en desar manualment" msgid "Python Scripts Directory" msgstr "Directori de protocols en python" +msgid "Alternate script path, matching the default layout with subdirectories: `startup`, `addons`, `modules`, and `presets` (requires restart)" +msgstr "Camí alternatiu de protocols, que coincideix amb la disposició predeterminada amb els subdirectoris: inici, complements, mòduls i predefinits (cal reiniciar)" + + +msgid "Show Hidden Files/Data-Blocks" +msgstr "Mostrar documents/blocs de dades ocults" + + +msgid "Show files and data-blocks that are normally hidden" +msgstr "Mostra els documents i blocs de dades que normalment estan ocults" + + +msgid "Show Recent Locations" +msgstr "Mostrar ubicacions recents" + + +msgid "Show Recent locations list in the File Browser" +msgstr "Mostra la llista d'ubicacions recents al navegador de documents" + + +msgid "Show System Locations" +msgstr "Mostrar ubicacions del sistema" + + +msgid "Show System locations list in the File Browser" +msgstr "Mostra la llista d'ubicacions del sistema al navegador de documents" + + +msgid "Sounds Directory" +msgstr "Directori de sons" + + +msgid "The default directory to search for sounds" +msgstr "El directori predeterminat per a cercar-hi sons" + + +msgid "Temporary Directory" +msgstr "Directori temporal" + + +msgid "The directory for storing temporary save files" +msgstr "El directori per emmagatzemar documents temporals desats" + + +msgid "The default directory to search for textures" +msgstr "El directori predeterminat per a cercar textures" + + +msgid "Auto Save Temporary Files" +msgstr "Desar automàticament documents temporals" + + +msgid "" +"Automatic saving of temporary files in temp directory, uses process ID.\n" +"Warning: Sculpt and edit mode data won't be saved" +msgstr "" +"Desament automàtic de documents temporals al directori temp, usa l'ID de procés.\n" +"Avís: No es desaran les dades del mode escultura i edició" + + +msgid "Compress File" +msgstr "Comprimir document" + + +msgid "Enable file compression when saving .blend files" +msgstr "Habilita la compressió de documents quan es desen documents .blend" + + +msgid "Enable filtering of files in the File Browser" +msgstr "Habilita el filtratge de documents al navegador de documents" + + +msgid "Load user interface setup when loading .blend files" +msgstr "Carregar la configuració de la interfície d'usuari en carregar documents .blend" + + +msgid "Default relative path option for the file selector, when no path is defined yet" +msgstr "Opció de camí relatiu per defecte per al selector de documents, quan encara no se n'ha definit cap" + + +msgid "Allow any .blend file to run scripts automatically (unsafe with blend files from an untrusted source)" +msgstr "Permet que qualsevol document .blend executi protocols automàticament (insegur amb documents blend d'una font no fiable)" + + +msgid "Tabs as Spaces" +msgstr "Tabuladors com a espais" + + +msgid "Automatically convert all new tabs into spaces for new and loaded text files" +msgstr "[Tabs as Spaces]: Converteix automàticament tots els nous tabuladors en espais per als documents de text nous i carregats" + + +msgid "Drag Threshold" +msgstr "Llindar d'arrossegament" + + +msgid "Number of pixels to drag before a drag event is triggered for keyboard and other non mouse/tablet input (otherwise click events are detected)" +msgstr "[Drag Threshold]: Nombre de píxels a arrossegar abans que s'activi un esdeveniment d'arrossegament per al teclat i altres ingressions de ratolí/tauleta(en cas contrari es detecten esdeveniments de clic)" + + +msgid "Mouse Drag Threshold" +msgstr "Llindar d'arrossegament del ratolí" + + +msgid "Number of pixels to drag before a drag event is triggered for mouse/track-pad input (otherwise click events are detected)" +msgstr "Nombre de píxels a arrossegar abans que s'activi un esdeveniment d'arrossegament per a la ingressió de ratolí normal/tàctil (en cas contrari es detecten esdeveniments de clic)" + + +msgid "Tablet Drag Threshold" +msgstr "Llindar d'arrossegament de tauleta" + + +msgid "Number of pixels to drag before a drag event is triggered for tablet input (otherwise click events are detected)" +msgstr "[Tablet Drag Threshold]: Nombre de píxels a arrossegar abans que s'activi un esdeveniment d'arrossegament per a la ingressió de tauleta (en cas contrari es detecten esdeveniments de clic)" + + +msgid "Invert Zoom Direction" +msgstr "Invertir direcció de zoom" + + +msgid "Invert the axis of mouse movement for zooming" +msgstr "Inverteix l'eix del moviment del ratolí per a fer zoom" + + +msgid "Wheel Invert Zoom" +msgstr "Inverteix el zoom de roda" + + +msgid "Swap the Mouse Wheel zoom direction" +msgstr "[Wheel Invert Zoom]: Intercanvia la direcció de zoom de la roda del ratolí" + + +msgid "Double Click Timeout" +msgstr "Temps d'espera del doble clic" + + +msgid "Time/delay (in ms) for a double click" +msgstr "[Double Click Timeout]: Temps/retard (en ms) d'un doble clic" + + +msgid "Emulate 3 Button Modifier" +msgstr "Emular modificador de botó 3" + + +msgid "Hold this modifier to emulate the middle mouse button" +msgstr "Sostenir aquest modificador per a emular el botó central del ratolí" + + +msgid "OS-Key" +msgstr "Clau del SO" + + +msgid "Motion Threshold" +msgstr "Llindar de moviment" + + +msgid "Number of pixels to before the cursor is considered to have moved (used for cycling selected items on successive clicks)" +msgstr "[Motion Threshold]: Nombre de píxels abans que es consideri que s'ha mogut el cursor (utilitzat per a ciclitzar els elements seleccionats en clics successius)" + + +msgid "View Navigation" +msgstr "Visualitzar navegació" + + +msgid "Which method to use for viewport navigation" +msgstr "Quin mètode utilitzar per a la navegació del mirador" + + +msgid "Interactively walk or free navigate around the scene" +msgstr "Caminar o navegar lliurement per l'escena" + + +msgid "Fly" +msgstr "Volar" + + +msgid "Use fly dynamics to navigate the scene" +msgstr "[Fly]: Utilitza una dinàmica de vol per navegar per l'escena" + + +msgid "Deadzone" +msgstr "Zona morta" + + +msgid "Threshold of initial movement needed from the device's rest position" +msgstr "Llindar del moviment inicial necessari des de la posició de descans del dispositiu" + + +msgid "Helicopter Mode" +msgstr "Mode helicòpter" + + +msgid "Device up/down directly controls the Z position of the 3D viewport" +msgstr "Amunt i avall en el dispositiu controla directament la posició Z del mirador" + + msgid "Lock Camera Pan/Zoom" -msgstr "Bloqueja escombratge/zoom de la càmera" +msgstr "Bloquejar escombratge/zoom de càmera" msgid "Pan/zoom the camera view instead of leaving the camera view when orbiting" msgstr "Escombratge/zoom la vista de la càmera en lloc de deixar-la en òrbita" +msgid "Lock Horizon" +msgstr "Bloquejar horitzó" + + +msgid "Keep horizon level while flying with 3D Mouse" +msgstr "Manté el nivell de l'horitzó mentre es vola amb el ratolí 3D" + + +msgid "Orbit Sensitivity" +msgstr "Sensibilitat d'òrbita" + + +msgid "Overall sensitivity of the 3D Mouse for orbiting" +msgstr "Sensibilitat genèrica del ratolí 3D en orbitar" + + +msgid "Y/Z Swap Axis" +msgstr "Eix d'intercanvi Y/Z" + + msgid "Pan using up/down on the device (otherwise forward/backward)" msgstr "Escombratge usant amunt/avall al dispositiu (en cas contrari endavant/endarrere)" +msgid "Invert X Axis" +msgstr "Invertir eix X" + + +msgid "Invert Y Axis" +msgstr "Invertir eix Y" + + +msgid "Invert Z Axis" +msgstr "Invertir eix Z" + + +msgid "Invert Pitch (X) Axis" +msgstr "Invertir capcineig (X)" + + +msgid "Invert Yaw (Y) Axis" +msgstr "Invertir balanceig (Y)" + + +msgid "Invert Roll (Z) Axis" +msgstr "Invertir guinyada (Z)" + + +msgid "Overall sensitivity of the 3D Mouse for panning" +msgstr "Sensibilitat general del ratolí 3D per a l'escombratge" + + +msgid "Show Navigation Guide" +msgstr "Mostrar guia de navegació" + + +msgid "Display the center and axis during rotation" +msgstr "Mostra el centre i l'eix durant la rotació" + + +msgid "NDOF View Navigate" +msgstr "Navegar amb vista NDOF" + + +msgid "Navigation style in the viewport" +msgstr "Estil de navegació del mirador" + + +msgid "Use full 6 degrees of freedom by default" +msgstr "Usar 6 graus sencers de llibertat per defecte" + + +msgid "Orbit about the view center by default" +msgstr "Orbitar predeterminat entorn del centre de visió" + + +msgid "NDOF View Rotation" +msgstr "Rotació de vista NDOF" + + +msgid "Rotation style in the viewport" +msgstr "Estil de rotació del mirador" + + +msgid "Turntable" +msgstr "Tocadiscs" + + +msgid "Use turntable style rotation in the viewport" +msgstr "[Turntable]: Usa una rotació de tocadiscs al mirador" + + +msgid "Use trackball style rotation in the viewport" +msgstr "Usa rotació estil ratolí de bola al mirador" + + +msgid "Invert Zoom" +msgstr "Invertir zoom" + + +msgid "Zoom using opposite direction" +msgstr "Fa el zoom en la direcció oposada" + + +msgid "Softness" +msgstr "Suavitat" + + +msgid "Adjusts softness of the low pressure response onset using a gamma curve" +msgstr "Ajusta la suavitat de l'inici de resposta de baixa pressió usant una corba gamma" + + +msgid "Max Threshold" +msgstr "Llindar màx" + + +msgid "Raw input pressure value that is interpreted as 100% by Blender" +msgstr "[Max Threshold]: Valor brut de pressió d'ingressió que Blender interpreta com a 100%" + + +msgid "Tablet API" +msgstr "API de tauleta" + + +msgid "Select the tablet API to use for pressure sensitivity (may require restarting Blender for changes to take effect)" +msgstr "Selecciona l'API de la tauleta que gestiona la sensibilitat a la pressió (pot requerir reiniciar el Blender perquè els canvis tinguin efecte)" + + +msgid "Automatically choose Wintab or Windows Ink depending on the device" +msgstr "Triar automàticament Wintab o Windows Ink segons el dispositiu" + + +msgid "Windows Ink" +msgstr "Windows Ink" + + +msgid "Use native Windows Ink API, for modern tablet and pen devices. Requires Windows 8 or newer" +msgstr "Usa l'API nativa de Windows Ink, per dispositius de tauleta i pen moderns. Requereix Windows 8 o més recent" + + +msgid "Wintab" +msgstr "Wintab" + + +msgid "Use Wintab driver for older tablets and Windows versions" +msgstr "Usa el controlador Wintab per a tauletes i versions de Windows antigues" + + +msgid "Auto Perspective" +msgstr "Autoperspectiva" + + +msgid "Automatically switch between orthographic and perspective when changing from top/front/side views" +msgstr "[Auto Perspective]: Alterna automàticament entre vista ortogràfica i perspectiva en canviar de superior/frontal/lateral" + + +msgid "Release Confirms" +msgstr "Confirmacions d'amollar" + + +msgid "Moving things with a mouse drag confirms when releasing the button" +msgstr "[Release Confirms]: En arrossegar les coses amb el ratolí, es confirma quan s'amolla el botó" + + +msgid "Emulate Numpad" +msgstr "Emular teclat numèric" + + +msgid "Main 1 to 0 keys act as the numpad ones (useful for laptops)" +msgstr "Les tecles principals d'1 a 0 actuen com les del teclat numèric (útil per als portàtils)" + + +msgid "Continuous Grab" +msgstr "Agafades contínues" + + +msgid "Let the mouse wrap around the view boundaries so mouse movements are not limited by the screen size (used by transform, dragging of UI controls, etc.)" +msgstr "Permet que el ratolí passi al voltant dels límits de la vista, de manera que la mida de la pantalla no li limita els moviments (usada per la transformació, l'arrossegament dels controls de la IU, etc.)" + + +msgid "Auto Depth" +msgstr "Autoprofunditat" + + msgid "Use the depth under the mouse to improve view pan/rotate/zoom functionality" msgstr "Usa la profunditat sota el ratolí per a millorar la funcionalitat escombratge/rotació/zoom de la vista" +msgid "Emulate 3 Button Mouse" +msgstr "Emular ratolí de 3 botons" + + +msgid "Emulate Middle Mouse with Alt+Left Mouse" +msgstr "Emula el botó del mig del ratolí amb Alt+Botó esquerre" + + +msgid "Multi-touch Gestures" +msgstr "Gestos multitàctils" + + +msgid "Use multi-touch gestures for navigation with touchpad, instead of scroll wheel emulation" +msgstr "[Multi-touch Gestures]: Usa gestos multitàctils per navegar amb ratolí tàctil, en lloc d'emular la roda de desplaçament" + + +msgid "Default to Advanced Numeric Input" +msgstr "Ingressió numèrica avançada per defecte" + + +msgid "When entering numbers while transforming, default to advanced mode for full math expression evaluation" +msgstr "[Default to Advanced Numeric Input]: En introduir nombres durant la transformació, es posa per defecte en mode avançat per a avaluar l'expressió matemàtica sencera" + + +msgid "Orbit Around Selection" +msgstr "Orbitar entorn de la selecció" + + +msgid "Use selection as the pivot point" +msgstr "Usar selecció com a punt de gir" + + +msgid "Zoom to Mouse Position" +msgstr "Fer zoom fins al ratolí" + + +msgid "Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center" +msgstr "Amplia la vista (3D) anant vers el punter del ratolí, en lloc del centre de la finestra 2D" + + +msgid "Orbit Method" +msgstr "Mètode d'orbitar" + + +msgid "Orbit method in the viewport" +msgstr "[Orbit Method]: Manera d'orbitar en el mirador" + + +msgid "Turntable keeps the Z-axis upright while orbiting" +msgstr "El tocadiscs manté l'eix Z vertical mentre orbita" + + +msgid "Trackball allows you to tumble your view at any angle" +msgstr "El ratolí de bola retombar la vista en qualsevol angle" + + +msgid "Scale trackball orbit sensitivity" +msgstr "Escalar sensibilitat d'orbitar amb ratolí de bola" + + +msgid "Rotation amount per pixel to control how fast the viewport orbits" +msgstr "[Scale trackball orbit sensitivity]: Quantitat de rotació per píxel per a controlar la rapidesa de les òrbites del mirador" + + +msgid "Zoom Axis" +msgstr "Eix de zoom" + + +msgid "Axis of mouse movement to zoom in or out on" +msgstr "[Zoom Axis]: Eix del moviment del ratolí per a apropar o allunyar-se" + + +msgid "Zoom in and out based on vertical mouse movement" +msgstr "Apropar i allunyar-se en funció del moviment vertical del ratolí" + + +msgid "Zoom in and out based on horizontal mouse movement" +msgstr "Apropar i allunyar-se en funció del moviment horitzontal del ratolí" + + +msgid "Zoom Style" +msgstr "Estil de zoom" + + +msgid "Which style to use for viewport scaling" +msgstr "Quin estil usar en l'escalat del mirador" + + +msgid "Continue" +msgstr "Continu" + + +msgid "Continuous zooming. The zoom direction and speed depends on how far along the set Zoom Axis the mouse has moved" +msgstr "Zoom continu. La direcció i rapidesa del zoom depenen de com s'ha mogut el ratolí al llarg de l'eix de zoom establert" + + +msgid "Dolly" +msgstr "Dolly" + + +msgid "Zoom in and out based on mouse movement along the set Zoom Axis" +msgstr "Apropa i allunya en funció del moviment del ratolí al llarg de l'eix de zoom establert" + + +msgid "Zoom in and out as if you are scaling the view, mouse movements relative to center" +msgstr "Apropa i allunya com si estiguéssiu escalant la vista, els moviments del ratolí van en relació amb el centre" + + +msgid "Walk Navigation" +msgstr "Navegació a peu" + + +msgid "Settings for walk navigation mode" +msgstr "Paràmetres per al mode de navegació de caminar" + + +msgid "Key Config" +msgstr "Configuració de teclari" + + +msgid "The name of the active key configuration" +msgstr "El nom de la configuració de teclari activa" + + +msgid "Show UI Key-Config" +msgstr "Mostrar configuració de teclari de la IU" + + +msgid "Anisotropic Filtering" +msgstr "Filtratge anisotròpic" + + +msgid "Quality of anisotropic filtering" +msgstr "Qualitat del filtratge anisotròpic" + + +msgid "2x" +msgstr "2x" + + +msgid "4x" +msgstr "4x" + + +msgid "8x" +msgstr "8x" + + +msgid "16x" +msgstr "16x" + + +msgid "Audio Device" +msgstr "Dispositiu àudio" + + +msgid "Audio output device" +msgstr "Dispositiu d'egressió d'àudio" + + +msgid "No device - there will be no audio output" +msgstr "Sense dispositiu - no hi haurà egressió d'àudio" + + +msgid "Audio Mixing Buffer" +msgstr "Memòria intermèdia de mescla d'àudio" + + +msgid "Number of samples used by the audio mixing buffer" +msgstr "[Audio Mixing Buffer]: Nombre de mostres usades per la memòria intermèdia de mescla d'àudio" + + +msgid "256 Samples" +msgstr "256 mostres" + + +msgid "Set audio mixing buffer size to 256 samples" +msgstr "[256 Samples]: Fixa la mida de la memòria intermèdia de mescla d'àudio a 256 mostres" + + +msgid "512 Samples" +msgstr "512 mostres" + + +msgid "Set audio mixing buffer size to 512 samples" +msgstr "Fixa la mida de la memòria intermèdia de mescla d'àudio a 512 mostres" + + +msgid "1024 Samples" +msgstr "1024 mostres" + + +msgid "Set audio mixing buffer size to 1024 samples" +msgstr "Fixa la mida de la memòria intermèdia de mescla d'àudio a 1024 mostres" + + +msgid "2048 Samples" +msgstr "2048 mostres" + + +msgid "Set audio mixing buffer size to 2048 samples" +msgstr "Fixa la mida de la memòria intermèdia de mescla d'àudio a 2048 mostres" + + +msgid "4096 Samples" +msgstr "4096 mostres" + + +msgid "Set audio mixing buffer size to 4096 samples" +msgstr "Fixa la mida de la memòria intermèdia de mescla d'àudio a 4096 mostres" + + +msgid "8192 Samples" +msgstr "8192 mostres" + + +msgid "Set audio mixing buffer size to 8192 samples" +msgstr "Fixa la mida de la memòria intermèdia de mescla d'àudio a 8192 mostres" + + +msgid "16384 Samples" +msgstr "16384 mostres" + + +msgid "Set audio mixing buffer size to 16384 samples" +msgstr "Fixa la mida de la memòria intermèdia de mescla d'àudio a 16384 mostres" + + +msgid "32768 Samples" +msgstr "32768 mostres" + + +msgid "Set audio mixing buffer size to 32768 samples" +msgstr "Fixa la mida de la memòria intermèdia de mescla d'àudio a 32768 mostres" + + +msgid "Audio Sample Format" +msgstr "Format de mostreig d'àudio" + + +msgid "Audio sample format" +msgstr "Format de mostreig d'àudio" + + +msgid "8-bit Unsigned" +msgstr "8 bits no signat" + + +msgid "Set audio sample format to 8-bit unsigned integer" +msgstr "Fixa el format de mostreig d'àudio a un enter de 8 bits no signat" + + +msgid "16-bit Signed" +msgstr "16 bits signat" + + +msgid "Set audio sample format to 16-bit signed integer" +msgstr "Fixa el format de mostreig d'àudio a enter signat de 16 bits" + + +msgid "24-bit Signed" +msgstr "24 bits signat" + + +msgid "Set audio sample format to 24-bit signed integer" +msgstr "Fixa el format de mostreig d'àudio a enter signat de 24 bits" + + +msgid "32-bit Signed" +msgstr "32 bits signat" + + +msgid "Set audio sample format to 32-bit signed integer" +msgstr "Fixa el format de mostreig d'àudio a enter signat de 32 bits" + + +msgid "Set audio sample format to 32-bit float" +msgstr "Fixa el format de mostreig d'àudio a flotant de 32 bits" + + +msgid "64-bit Float" +msgstr "64 bits flotant" + + +msgid "Set audio sample format to 64-bit float" +msgstr "Fixa el format de mostreig d'àudio a flotant de 64 bits" + + +msgid "Audio Sample Rate" +msgstr "Taxa de mostreig d'àudio" + + +msgid "Audio sample rate" +msgstr "Freqüència de mostreig de l'àudio" + + +msgid "44.1 kHz" +msgstr "44.1 kHz" + + +msgid "Set audio sampling rate to 44100 samples per second" +msgstr "Fixa la freqüència de mostreig de l'àudio a 44100 mostres per segon" + + +msgid "48 kHz" +msgstr "48 kHz" + + +msgid "Set audio sampling rate to 48000 samples per second" +msgstr "Fixa la freqüència de mostreig de l'àudio a 44800 mostres per segon" + + +msgid "96 kHz" +msgstr "96 kHz" + + +msgid "Set audio sampling rate to 96000 samples per second" +msgstr "Fixa la freqüència de mostreig de l'àudio a 96000 mostres per segon" + + +msgid "192 kHz" +msgstr "192 kHz" + + +msgid "Set audio sampling rate to 192000 samples per second" +msgstr "Fixa la freqüència de mostreig de l'àudio a 192000 mostres per segon" + + +msgid "Clip Alpha" +msgstr "Segar alfa" + + +msgid "Clip alpha below this threshold in the 3D textured view" +msgstr "[Clip Alpha]: Retalla l'alfa per sota d'aquest llindar a la vista 3D texturada" + + +msgid "GL Texture Limit" +msgstr "Límit de la textura GL" + + +msgid "Limit the texture size to save graphics memory" +msgstr "[GL Texture Limit]: Limita la mida de la textura per estalviar memòria gràfica" + + +msgid "GPU backend to use (requires restarting Blender for changes to take effect)" +msgstr "Internador de GPU a usar (Requereix reiniciar el Blender perquè els canvis tinguin efecte)" + + +msgid "OpenGL" +msgstr "OpenGL" + + +msgid "Use OpenGL backend" +msgstr "Utilitza l'internador OpenGL" + + +msgid "Metal" +msgstr "Metal" + + +msgid "Use Metal backend" +msgstr "Utilitza l'internador Metal" + + +msgid "Vulkan" +msgstr "Vulkan" + + +msgid "Use Vulkan backend" +msgstr "Utilitza l'internador Vulkan" + + +msgid "Image Display Method" +msgstr "Mètode de mostrar imatges" + + +msgid "Method used for displaying images on the screen" +msgstr "Mètode utilitzat per mostrar imatges a la pantalla" + + +msgid "Automatically choose method based on GPU and image" +msgstr "Triar automàticament el mètode basat en la GPU i la imatge" + + +msgid "2D Texture" +msgstr "Textura 2D" + + +msgid "Use CPU for display transform and display image with 2D texture" +msgstr "Usa la CPU per a la transformació de pantalla i la imatge de pantalla amb textura 2D" + + +msgid "GLSL" +msgstr "GLSL" + + +msgid "Use GLSL shaders for display transform and display image with 2D texture" +msgstr "Usa aspectors GLSL per a la transformació de pantalla i la imatge de pantalla amb textura 2D" + + +msgid "Legacy Compute Device Type" +msgstr "Tipus de dispositiu de càlcul antic" + + +msgid "For backwards compatibility only" +msgstr "Només per compatibilitat enrere" + + +msgid "Ambient Color" +msgstr "Color ambiental" + + +msgid "Color of the ambient light that uniformly lit the scene" +msgstr "[Ambient Color]: Color de la llum ambiental que il·lumina uniformement l'escena" + + +msgid "Memory Cache Limit" +msgstr "Límit de memòria cau" + + +msgid "Memory cache limit (in megabytes)" +msgstr "Límit de memòria cau (en megabytes)" + + +msgid "Maximum number of lines to store for the console buffer" +msgstr "Nombre màxim de línies d'emmagatzematge per a la memòria intermèdia de la consola" + + +msgid "Disk Cache Compression Level" +msgstr "Nivell de compressió de la memòria cau de disc" + + +msgid "Smaller compression will result in larger files, but less decoding overhead" +msgstr "Una compressió menor dona documents més grans, però menys càrrega de descodificació" + + +msgid "Requires fast storage, but uses minimum CPU resources" +msgstr "Requereix un emmagatzematge ràpid, però utilitza recursos mínims de la CPU" + + +msgid "Doesn't require fast storage and uses less CPU resources" +msgstr "No requereix un emmagatzematge ràpid i utilitza menys recursos de CPU" + + +msgid "Works on slower storage devices and uses most CPU resources" +msgstr "Funciona amb dispositius d'emmagatzematge més lents i utilitza la majoria dels recursos de la CPU" + + +msgid "Disk Cache Directory" +msgstr "Directori de memòria cau del disc" + + +msgid "Override default directory" +msgstr "[Disk Cache Directory]: Sobreseure directori predeterminat" + + +msgid "Disk Cache Limit" +msgstr "Límit de memòria cau del disc" + + +msgid "Disk cache limit (in gigabytes)" +msgstr "Límit de la memòria cau del disc (en gigabytes)" + + +msgid "Proxy Setup" +msgstr "Configuració de simulacions" + + +msgid "When and how proxies are created" +msgstr "[Proxy Setup]: Quan i com es creen les simulacions" + + +msgid "Manual" +msgstr "Manual" + + +msgid "Set up proxies manually" +msgstr "Configura simulacions manualment" + + +msgid "Build proxies for added movie and image strips in each preview size" +msgstr "[Set up proxies manually]: Construir simulacions per a els segments de pel·lícula i imatge afegits en cada mida de previsualització" + + +msgid "Solid Lights" +msgstr "Llums sòlides" + + +msgid "Lights used to display objects in solid shading mode" +msgstr "[Solid Lights]: Llums usades per a mostrar objectes en el mode d'aspecció sòlida" + + +msgid "Texture Collection Rate" +msgstr "Taxa de recol·lecció de textures" + + +msgid "Number of seconds between each run of the GL texture garbage collector" +msgstr "[Texture Collection Rate]: Nombre de segons entre cada execució del recol·lector d'escombraries de textures de la GL" + + +msgid "Texture Time Out" +msgstr "Temps d'expiració de textura" + + +msgid "Time since last access of a GL texture in seconds after which it is freed (set to 0 to keep textures allocated)" +msgstr "[Texture Time Out]: Temps des de l'últim accés d'una textura GL en segons després del qual s'allibera (posar a 0 per a mantenir les textures assignades)" + + +msgid "UI Line Width" +msgstr "Amplada de línia de la IU" + + +msgid "Suggested line thickness and point size in pixels, for add-ons displaying custom user interface elements, based on operating system settings and Blender UI scale" +msgstr "Gruix de línia suggerit i mida de punts en píxels, per a complements que mostren elements personalitzats d'interfície d'usuària, basats en la configuració del sistema operatiu i l'escala de la IU del Blender" + + +msgid "UI Scale" +msgstr "Escala de la IU" + + +msgid "Size multiplier to use when displaying custom user interface elements, so that they are scaled correctly on screens with different DPI. This value is based on operating system DPI settings and Blender display scale" +msgstr "Multiplicador de mida per quan es mostren elements personalitzats de la interfície d'usuària, de manera que s'escalaran correctament en pantalles amb diferents PPP. Aquest valor es basa en la configuració del PPP del sistema operatiu i l'escala de visualització del Blender" + + +msgid "Edit Mode Smooth Wires" +msgstr "Suavitzar cables en mode edició" + + +msgid "Enable edit mode edge smoothing, reducing aliasing (requires restart)" +msgstr "Activa el suavitzat d'arestes en mode d'edició, reduint aliasing (cal reiniciar)" + + +msgid "GPU Subdivision" +msgstr "Subdivisió de GPU" + + +msgid "Enable GPU acceleration for evaluating the last subdivision surface modifiers in the stack" +msgstr "Activa l'acceleració de la GPU per avaluar els últims modificadors de subdivisió de superfície de l'estiba" + + +msgid "Overlay Smooth Wires" +msgstr "Suavitzar cables amb bambolines" + + +msgid "Enable overlay smooth wires, reducing aliasing" +msgstr "Habilita la suavització de cables amb bambolines, reduint l'aliasing" + + +msgid "Region Overlap" +msgstr "Superposar regió" + + +msgid "Display tool/property regions over the main region" +msgstr "Mostra eines/propietats de regions sobre la regió principal" + + +msgid "GPU Depth Picking" +msgstr "Selector de profunditat de GPU" + + +msgid "When making a selection in 3D View, use the GPU depth buffer to ensure the frontmost object is selected first" +msgstr "Quan se selecciona en una vista 3D, usa la memòria intermèdia de profunditat de la GPU per assegurar que l'objecte de davant de tot és seleccionat primer" + + +msgid "Use Disk Cache" +msgstr "Usar disc de memòria cau" + + +msgid "Store cached images to disk" +msgstr "Emmagatzema les imatges de la memòria cau al disc" + + +msgid "Edit Studio Light" +msgstr "Editar llum d'estudi" + + +msgid "View the result of the studio light editor in the viewport" +msgstr "Visualitza el resultat de l'editor de llum d'estudi al mirador" + + +msgid "VBO Collection Rate" +msgstr "Taxa de recol·lecció de VBO" + + +msgid "Number of seconds between each run of the GL vertex buffer object garbage collector" +msgstr "[VBO Collection Rate]: Nombre de segons entre cada execució del recol·lector d'escombraries d'objectes de de la memòria intermèdia de vèrtexs de GL" + + +msgid "VBO Time Out" +msgstr "Temps d'expiració de VBO" + + +msgid "Time since last access of a GL vertex buffer object in seconds after which it is freed (set to 0 to keep VBO allocated)" +msgstr "Temps des de l'últim accés d'un objecte de la memòria intermèdia de vèrtexs de GL en segons després del qual s'allibera (poar a 0 per mantenir VBO assignat)" + + +msgid "Viewport Anti-Aliasing" +msgstr "Antialiàsing del mirador" + + +msgid "Method of anti-aliasing in 3d viewport" +msgstr "Mètode d'antialiàsing per al mirador en 3d" + + +msgid "No Anti-Aliasing" +msgstr "Sense antialiàsing" + + +msgid "Scene will be rendering without any anti-aliasing" +msgstr "L'escena es revelarà sense cap antialiàsing" + + +msgid "Single Pass Anti-Aliasing" +msgstr "Antialiàsing de passada única" + + +msgid "Scene will be rendered using a single pass anti-aliasing method (FXAA)" +msgstr "[Single Pass Anti-Aliasing]: L'escena es revelarà utilitzant un únic mètode d'antialiàsing (FXAA)" + + +msgid "5 Samples" +msgstr "5 mostres" + + +msgid "Scene will be rendered using 5 anti-aliasing samples" +msgstr "L'escena es revelarà usant 5 mostres d'antialiàsing" + + +msgid "8 Samples" +msgstr "8 Mostres" + + +msgid "Scene will be rendered using 8 anti-aliasing samples" +msgstr "L'escena es revelarà usant 8 mostres d'antialiàsing" + + +msgid "11 Samples" +msgstr "11 mostres" + + +msgid "Scene will be rendered using 11 anti-aliasing samples" +msgstr "L'escena es revelarà usant 11 mostres d'antialiàsing" + + +msgid "16 Samples" +msgstr "16 mostres" + + +msgid "Scene will be rendered using 16 anti-aliasing samples" +msgstr "L'escena es revelarà usant 16 mostres d'antialiàsing" + + +msgid "32 Samples" +msgstr "32 Mostres" + + +msgid "Scene will be rendered using 32 anti-aliasing samples" +msgstr "L'escena es revelarà usant 32 mostres d'antialiàsing" + + +msgid "Color Picker Type" +msgstr "Tipus de selector de color" + + +msgid "Different styles of displaying the color picker widget" +msgstr "Diferents estils de visualització del giny selector de color" + + +msgid "Circle (HSV)" +msgstr "Cercle (HSV)" + + +msgid "A circular Hue/Saturation color wheel, with Value slider" +msgstr "Una roda cromàtica circular de to/saturació, amb lliscador de Valor" + + +msgid "Circle (HSL)" +msgstr "Cercle (HSL)" + + +msgid "A circular Hue/Saturation color wheel, with Lightness slider" +msgstr "Una roda cromàtica circular de to/saturació, amb lliscador de claredat" + + +msgid "Square (SV + H)" +msgstr "Quadrat (SV + H)" + + +msgid "A square showing Saturation/Value, with Hue slider" +msgstr "Un quadrat que mostra saturació/valor, amb lliscador de tonalitat" + + +msgid "Square (HS + V)" +msgstr "Quadrat (HS + V)" + + +msgid "A square showing Hue/Saturation, with Value slider" +msgstr "Un quadrat que mostra To/Saturació, amb lliscador de Valor" + + +msgid "Square (HV + S)" +msgstr "Quadrat (HV + S)" + + +msgid "A square showing Hue/Value, with Saturation slider" +msgstr "Un quadrat que mostra To/Valor, amb lliscador de saturació" + + +msgid "Factor Display Type" +msgstr "Tipus de factor de visualització" + + +msgid "How factor values are displayed" +msgstr "Com es mostren els valors de factor" + + +msgid "Display factors as values between 0 and 1" +msgstr "Mostrar els factors com a valors entre 0 i 1" + + +msgid "Percentage" +msgstr "Percentatge" + + +msgid "Display factors as percentages" +msgstr "Mostra els factors com a percentatges" + + +msgid "File Browser Display Type" +msgstr "Tipus de visualització del navegador de documents" + + +msgid "Default location where the File Editor will be displayed in" +msgstr "Ubicació predeterminada on es mostrarà l'editor de documents" + + +msgid "Maximized Area" +msgstr "Àrea maximitzada" + + +msgid "Open the temporary editor in a maximized screen" +msgstr "Obre l'editor temporal en una pantalla maximitzada" + + +msgid "New Window" +msgstr "Nova finestra" + + +msgid "Open the temporary editor in a new window" +msgstr "Obre l'editor temporal en una finestra nova" + + +msgid "Interface Font" +msgstr "Tipografia de la interfície" + + +msgid "Path to interface font" +msgstr "Camí a la tipografia de la interfície" + + +msgid "Monospaced Font" +msgstr "Tipografia monoespaiada" + + +msgid "Path to interface monospaced Font" +msgstr "Camí a la tipografia monoespaiada de la interfície" + + +msgid "Gizmo Size" +msgstr "Mida del flòstic" + + +msgid "Diameter of the gizmo" +msgstr "[Gizmo Size]: Diàmetre del flòstic" + + +msgid "Navigate Gizmo Size" +msgstr "Mida del flòstic de navegació" + + +msgid "The Navigate Gizmo size" +msgstr "La mida del flòstic de navegació" + + +msgid "Header Position" +msgstr "Posició de capçalera" + + +msgid "Default header position for new space-types" +msgstr "Posició predeterminada de capçalera per a nous tipus d'espai" + + +msgid "Keep Existing" +msgstr "Mantenir el que hi ha" + + +msgid "Keep existing header alignment" +msgstr "Mantén l'alineació existent de capçalera" + + +msgid "Top aligned on load" +msgstr "Alinear al capdamunt en carregar" + + +msgid "Bottom align on load (except for property editors)" +msgstr "Alinear al capdavall en carregar (excepte per als editors de propietats)" + + +msgid "Language used for translation" +msgstr "Llengua usada per traduir" + + +msgid "Automatic (Automatic)" +msgstr "Automàtica (automàtica)" + + +msgid "Automatically choose system's defined language if available, or fall-back to English" +msgstr "Tria automàticament la llengua definida del sistema si està disponible, o recorre a l'anglès" + + +msgid "HDRI Preview Size" +msgstr "Mida de previsualització d'HDRI" + + +msgid "Diameter of the HDRI preview spheres" +msgstr "[HDRI Preview Size]: Diàmetre de les esferes de previsualització d'HDRI" + + +msgid "Mini Axes Brightness" +msgstr "Brillantor dels minieixos" + + +msgid "Brightness of the icon" +msgstr "[Mini Axes Brightness]: Brillantor de la icona" + + +msgid "Mini Axes Size" +msgstr "Mida dels minieixos" + + +msgid "The axes icon's size" +msgstr "La mida de la icona dels eixos" + + +msgid "Mini Axes Type" +msgstr "Tipus de minieixos" + + +msgid "Interactive Navigation" +msgstr "Navegació interactiva" + + +msgid "Sub Level Menu Open Delay" +msgstr "Retard d'obertura de menú del nivell inferior" + + +msgid "Time delay in 1/10 seconds before automatically opening sub level menus" +msgstr "Retard de temps en 1/10 segons abans d'obrir automàticament els menús de subnivell" + + +msgid "Top Level Menu Open Delay" +msgstr "Retard d'obertura del menú del nivell superior" + + +msgid "Time delay in 1/10 seconds before automatically opening top level menus" +msgstr "Retard de temps en 1/10 segons abans d'obrir automàticament els menús de nivell superior" + + +msgid "Animation Timeout" +msgstr "Lapse d'animació" + + +msgid "Time needed to fully animate the pie to unfolded state (in 1/100ths of sec)" +msgstr "Temps necessari per a animar completament el pastís fins que queda desplegat (en 1/100ens seg)" + + +msgid "Recenter Timeout" +msgstr "Recentrar lapse" + + +msgid "Pie menus will use the initial mouse position as center for this amount of time (in 1/100ths of sec)" +msgstr "Els menús de pastís agafaran la posició inicial del ratolí com a centre per durant aquesta quantitat de temps (en 1/100ens seg)" + + +msgid "Confirm Threshold" +msgstr "Confirmar llindar" + + +msgid "Distance threshold after which selection is made (zero to disable)" +msgstr "Llindar de distància després del qual es fa la selecció (zero per a desactivar)" + + +msgid "Pie menu size in pixels" +msgstr "Mida del menú de pastís en píxels" + + +msgid "Distance from center needed before a selection can be made" +msgstr "Distància que cal des del centre abans de poder fer una selecció" + + +msgid "Tap Key Timeout" +msgstr "Lapse de teclejat" + + +msgid "Pie menu button held longer than this will dismiss menu on release.(in 1/100ths of sec)" +msgstr "[Tap Key Timeout]: El botó de menú de pastís que es mantingui més temps que això descartarà el menú en amollar (en 1/100ens de segon)" + + +msgid "Render Display Type" +msgstr "Tipus de visualització de revelat" + + +msgid "Default location where rendered images will be displayed in" +msgstr "Ubicació predeterminada on es mostraran les imatges revelades" + + +msgid "Keep User Interface" +msgstr "Mantenir interfície d'usuària" + + +msgid "Images are rendered without changing the user interface" +msgstr "Les imatges es revelen sense canviar la interfície d'usuari" + + +msgid "Images are rendered in a maximized Image Editor" +msgstr "Les imatges es revelen en un editor d'imatges maximitzat" + + +msgid "Images are rendered in an Image Editor" +msgstr "Les imatges es revelen en un editor d'imatges" + + +msgid "Images are rendered in a new window" +msgstr "Les imatges es revelen en una finestra nova" + + +msgid "Rotation step for numerical pad keys (2 4 6 8)" +msgstr "Pas de rotació per a teclat numèric (2 4 6 8)" + + +msgid "Enabled Add-ons Only" +msgstr "Sols complements activats" + + +msgid "Only show enabled add-ons. Un-check to see all installed add-ons" +msgstr "Mostra només els complements habilitats. Desmarcar per veure tots els complements instal·lats" + + +msgid "Toolbox Column Layout" +msgstr "Disposició de columna d'eines" + + +msgid "Use a column layout for toolbox" +msgstr "Utilitza una disposició de columna per a la caixa d'eines" + + +msgid "Developer Extras" +msgstr "Extras per desenvolupadors" + + +msgid "Show options for developers (edit source in context menu, geometry indices)" +msgstr "Mostra les opcions per als desenvolupadors (editar codi font al menú contextual, índexs de geometria)" + + +msgid "Use transform gizmos by default" +msgstr "Usar transformar flòstics per defecte" + + +msgid "Navigation Controls" +msgstr "Controls de navegació" + + +msgid "Show navigation controls in 2D and 3D views which do not have scroll bars" +msgstr "Mostra els controls de navegació en vistes 2D i 3D que no tenen rodoladors" + + +msgid "Display Object Info" +msgstr "Mostrar informació d'objecte" + + +msgid "Include the name of the active object and the current frame number in the text info overlay" +msgstr "Inclou el nom de l'objecte actiu i el número del fotograma actual al text de la bambolina informativa" + + +msgid "Display Playback Frame Rate (FPS)" +msgstr "Mostrar fotogrames p/s de reproducció (FPS)" + + +msgid "Include the number of frames displayed per second in the text info overlay while animation is played back" +msgstr "Inclou el nombre de fotogrames mostrats per segon al text de la bambolina informativa mentre es reprodueix l'animació" + + msgid "Show Splash" msgstr "Mostrar careta" +msgid "Display splash screen on startup" +msgstr "[Show Splash]: Mostra la careta d'inici a l'engegar" + + +msgid "Show Memory" +msgstr "Mostrar memòria" + + +msgid "Show Blender memory usage" +msgstr "Mostra l'ús de memòria del Blender" + + +msgid "Show Statistics" +msgstr "Mostrar estadístiques" + + +msgid "Show scene statistics" +msgstr "Mostra les estadístiques de l'escena" + + +msgid "Show Version" +msgstr "Mostrar versió" + + +msgid "Show Blender version string" +msgstr "Mostra la cadena de versió del Blender" + + +msgid "Show VRAM" +msgstr "Mostrar VRAM" + + +msgid "Show GPU video memory usage" +msgstr "Mostra l'ús de la memòria de vídeo de la GPU" + + +msgid "Tooltips" +msgstr "Pistes" + + +msgid "Display tooltips (when disabled, hold Alt to force display)" +msgstr "Mostra els consells d'eina (si està desactivat, mantenir premuda la tecla Alt per forçar-ne la visualització)" + + +msgid "Python Tooltips" +msgstr "Pistes de python" + + +msgid "Show Python references in tooltips" +msgstr "Mostra les referències de python als consells d'eina" + + +msgid "Display View Name" +msgstr "Mostrar nom de visualització" + + +msgid "Include the name of the view orientation in the text info overlay" +msgstr "Inclou el nom de l'orientació de la vista en la bambolina de text informatiu" + + +msgid "Smooth View" +msgstr "Suavitzar visualització" + + +msgid "Time to animate the view in milliseconds, zero to disable" +msgstr "[Smooth View]: Temps per animar la vista en mil·lisegons, zero per desactivar" + + +msgid "Text Hinting" +msgstr "Destacar text" + + +msgid "Method for making user interface text render sharp" +msgstr "Mètode per a fer que el text de la interfície d'usuari sigui més contrastat" + + +msgid "Slight" +msgstr "Lleuger" + + +msgid "TimeCode Style" +msgstr "Estil de cronofites" + + +msgid "Format of Time Codes displayed when not displaying timing in terms of frames" +msgstr "[TimeCode Style]: Format de les cronofites que es mostren quan no es mostra el temps en termes de fotogrames" + + +msgid "Minimal Info" +msgstr "Informació mínima" + + +msgid "Most compact representation, uses '+' as separator for sub-second frame numbers, with left and right truncation of the timecode as necessary" +msgstr "La representació més compacta, usa «+» com a separador per als nombres de fotogrames per sota del segon, amb truncament esquerre i dret de la cronofita si cal" + + +msgid "SMPTE (Full)" +msgstr "SMPTE (completa)" + + +msgid "Full SMPTE timecode (format is HH:MM:SS:FF)" +msgstr "[SMPTE (Full)]: Cronofita SMPTE completa (format HH:MM:SS:FF)" + + +msgid "SMPTE (Compact)" +msgstr "SMPTE (compacta)" + + +msgid "SMPTE timecode showing minutes, seconds, and frames only - hours are also shown if necessary, but not by default" +msgstr "Cronofita SMPTE que mostra només minuts, segons i fotogrames - les hores també es mostren si cal, però no per defecte" + + +msgid "Compact with Milliseconds" +msgstr "Compacta amb mil·lisegons" + + +msgid "Similar to SMPTE (Compact), except that instead of frames, milliseconds are shown instead" +msgstr "Similar a SMPTE (compacta), excepte que en lloc de fotogrames, es mostren mil·lisegons" + + +msgid "Only Seconds" +msgstr "Només segons" + + +msgid "Direct conversion of frame numbers to seconds" +msgstr "Conversió directa dels números de fotograma a segons" + + +msgid "Changes the thickness of widget outlines, lines and dots in the interface" +msgstr "Canvia el gruix dels contorns de ginys, línies i punts de la interfície" + + +msgid "Thin" +msgstr "Fines" + + +msgid "Thinner lines than the default" +msgstr "[Fines]: Línies més primes que les predeterminades" + + +msgid "Automatic line width based on UI scale" +msgstr "Amplada de línia automàtica basada en l'escala de la interfície" + + +msgid "Thick" +msgstr "Gruixudes" + + +msgid "Thicker lines than the default" +msgstr "[Thick]: Línies més gruixudes que les predeterminades" + + +msgid "Changes the size of the fonts and widgets in the interface" +msgstr "Canvia la mida de les tipografies i ginys de la interfície" + + +msgid "Contents Follow Opening Direction" +msgstr "Els continguts segueixen l'obertura" + + +msgid "Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction" +msgstr "[Contents Follow Opening Direction]: Altrament, els menús, etc, sempre seran de dalt a baix, d'esquerra a dreta, sense importar la direcció d'obertura" + + +msgid "Open menu buttons and pulldowns automatically when the mouse is hovering" +msgstr "Obrir botons del menú i desplegables automàticament quan el ratolí hi passi per sobre" + + +msgid "Save Prompt" +msgstr "Confirmar desar" + + +msgid "Ask for confirmation when quitting with unsaved changes" +msgstr "[Save Prompt]: Demana confirmació quan se surt amb canvis sense desar" + + +msgid "Text Anti-Aliasing" +msgstr "Antialiàsing del text" + + +msgid "Smooth jagged edges of user interface text" +msgstr "Suavitzar les vores irregulars del text de la interfície d'usuària" + + +msgid "Translate Interface" +msgstr "Interfície de traducció" + + +msgid "Translate all labels in menus, buttons and panels (note that this might make it hard to follow tutorials or the manual)" +msgstr "Tradueix totes les etiquetes en els menús, botons i plafons (en català, les pistes de molts controls inclouen la versió original anglesa per facilitar l'accés a tutorials, guies d'aprenentatge o el manual)" + + +msgid "Translate New Names" +msgstr "Traduir noms nous" + + +msgid "Translate the names of new data-blocks (objects, materials...)" +msgstr "Tradueix els noms dels nous blocs de dades (objectes, materials...)" + + +msgid "Translate Tooltips" +msgstr "Traduir pistes" + + +msgid "Translate the descriptions when hovering UI elements (recommended)" +msgstr "Tradueix les descripcions en passar per sobre dels elements de la IU (recomanat)" + + msgid "Use Weight Color Range" -msgstr "Usa l'interval de color força" +msgstr "Usar interval de pesos en colors" + + +msgid "Enable color range used for weight visualization in weight painting mode" +msgstr "[Use Weight Color Range]: Activa un interval de color per a visualitzar els pesos en el mode pintura de pesos" + + +msgid "2D View Minimum Grid Spacing" +msgstr "Vista 2D d'espaiat mínim de graella" + + +msgid "Minimum number of pixels between each gridline in 2D Viewports" +msgstr "[2D View Minimum Grid Spacing]: Nombre mínim de píxels entre cada línia de graella en miradors 2D" + + +msgid "Zoom Keyframes" +msgstr "Ampliar fotofites" + + +msgid "Keyframes around cursor that we zoom around" +msgstr "[Zoom Keyframes]: Fotofites entorn del cursor que acostem" + + +msgid "Zoom Seconds" +msgstr "Segons de zoom" + + +msgid "Seconds around cursor that we zoom around" +msgstr "Segons al voltant del cursor que acostem" + + +msgid "Zoom to Frame Type" +msgstr "Ampliar a tipus de fotograma" + + +msgid "How zooming to frame focuses around current frame" +msgstr "[Zoom to Frame Type]: Com ampliar al fotograma se centra al voltant del fotograma actual" + + +msgid "Keep Range" +msgstr "Mantenir l'interval" + + +msgid "Seconds" +msgstr "Segons" + + +msgid "Weight Color Range" +msgstr "Interval de color de pesos" + + +msgid "Color range used for weight visualization in weight painting mode" +msgstr "Interval de color utilitzat per a la visualització de pesos en el mode de pintura de pesos" + + +msgid "ID Property Group" +msgstr "Grup de propietats d'ID" + + +msgid "Group of ID properties" +msgstr "Grup de propietats de l'ID" + + +msgid "Asset Handle" +msgstr "Ansa de recurs" + + +msgid "Reference to some asset" +msgstr "Referència a algun recurs" + + +msgid "File Entry" +msgstr "Entrada del document" + + +msgid "TEMPORARY, DO NOT USE - File data used to refer to the asset" +msgstr "TEMPORAL, NO UTILITZEU - Dades de document utilitzades per referir-se al recurs" + + +msgid "The local data-block this asset represents; only valid if that is a data-block in this file" +msgstr "El bloc de dades local que representa aquest recurs; només vàlid si aquest és un bloc de dades en aquest document" + + +msgid "Case" +msgstr "Caixa" + + +msgid "Upper Case" +msgstr "Majúscules" + + +msgid "Lower Case" +msgstr "Majúscules" + + +msgid "Title Case" +msgstr "Inicials en majúscules" + + +msgid "Find" +msgstr "Trobar" + + +msgid "Strip Characters" +msgstr "Estripar caràcters" + + +msgid "Digits" +msgstr "Dígits" + + +msgid "Punctuation" +msgstr "Puntuació" + + +msgid "Strip Part" +msgstr "Part estripada" + + +msgid "Find/Replace" +msgstr "Buscar/substituir" + + +msgid "Replace text in the name" +msgstr "Substituir el text en el nom" + + +msgid "Set Name" +msgstr "Posar nom" + + +msgid "Set a new name or prefix/suffix the existing one" +msgstr "[Set Name]: Estableix un nom o prefixa/sufixa l'existent" + + +msgid "Strip leading/trailing text from the name" +msgstr "Estripa el text inicial/final del nom" + + +msgid "Change Case" +msgstr "Canviar caixa" + + +msgid "Change case of each name" +msgstr "[Change Case]: Canvia les majúscules i minúscules de cada nom" + + +msgid "Regular Expression Replace" +msgstr "Substitir amb expressió regular" + + +msgid "Use regular expression for the replacement text (supporting groups)" +msgstr "[Regular Expression Replace]: Usa una expressió regular per al text de substitució (grups de suport)" + + +msgid "Regular Expression Find" +msgstr "Trobar expressió regular" + + +msgid "Use regular expressions to match text in the 'Find' field" +msgstr "Usa expressions regulars per identificar text al camp «Troba»" + + +msgid "Field of view for the fisheye lens" +msgstr "Camp de visió per a la lent d'ull de peix" + + +msgid "Fisheye Lens" +msgstr "Lent d'ull de peix" + + +msgid "Lens focal length (mm)" +msgstr "[Fisheye Lens]: Distància focal de la lent (mm)" + + +msgid "Fisheye Polynomial K0" +msgstr "Polinomi d'ull de peix K0" + + +msgid "Coefficient K0 of the lens polynomial" +msgstr "Coeficient K0 del polinomi de la lent" + + +msgid "Fisheye Polynomial K1" +msgstr "Polinomi d'ull de peix K1" + + +msgid "Coefficient K1 of the lens polynomial" +msgstr "Coeficient K1 del polinomi de la lent" + + +msgid "Fisheye Polynomial K2" +msgstr "Polinomi d'ull de peix K2" + + +msgid "Coefficient K2 of the lens polynomial" +msgstr "Coeficient K2 del polinomi de la lent" + + +msgid "Fisheye Polynomial K3" +msgstr "Polinomial d'ull de peix K3" + + +msgid "Coefficient K3 of the lens polynomial" +msgstr "Coeficient K3 del polinomi de la lent" + + +msgid "Fisheye Polynomial K4" +msgstr "Polinomi d'ull de peix K4" + + +msgid "Coefficient K4 of the lens polynomial" +msgstr "Coeficient K4 del polinomi de la lent" + + +msgid "Max Latitude" +msgstr "Latitud màxima" + + +msgid "Maximum latitude (vertical angle) for the equirectangular lens" +msgstr "La latitud màxima (angle vertical) per a la lent equirectangular" + + +msgid "Min Latitude" +msgstr "Latitud mínima" + + +msgid "Minimum latitude (vertical angle) for the equirectangular lens" +msgstr "La latitud mínima (angle vertical) per a la lent equirectangular" + + +msgid "Max Longitude" +msgstr "Longitud màxima" + + +msgid "Maximum longitude (horizontal angle) for the equirectangular lens" +msgstr "Longitud màxima (angle horitzontal) per a la lent equirectangular" + + +msgid "Min Longitude" +msgstr "Longitud mínima" + + +msgid "Minimum longitude (horizontal angle) for the equirectangular lens" +msgstr "Longitud mínima (angle horitzontal) per a la lent equirectangular" + + +msgid "Panorama Type" +msgstr "Tipus de panorama" + + +msgid "Distortion to use for the calculation" +msgstr "Distorsió a usar per al càlcul" + + +msgid "Spherical camera for environment maps, also known as Lat Long panorama" +msgstr "Càmera esfèrica per a mapes d'entorn, també coneguda com a panorama Lat Long" + + +msgid "Equiangular Cubemap Face" +msgstr "Cara de cubografia equiangular" + + +msgid "Single face of an equiangular cubemap" +msgstr "Cara única d'una cubografia equiangular" + + +msgid "Mirror ball mapping for environment maps" +msgstr "[Equiangular Cubemap Face]: Emmirallar mapejat de bola als mapes d'entorn" + + +msgid "Fisheye Equidistant" +msgstr "UIl de peix equidistant" + + +msgid "Ideal for fulldomes, ignore the sensor dimensions" +msgstr "Ideal per als fulldomes, ignora les dimensions del sensor" + + +msgid "Fisheye Equisolid" +msgstr "Ull de peix equisòlida" + + +msgid "Similar to most fisheye modern lens, takes sensor dimensions into consideration" +msgstr "Similar a la majoria de les lents modernes d'ull de peix, té en compte les dimensions del sensor" + + +msgid "Fisheye Lens Polynomial" +msgstr "Polinomial de la lent d'ull de peix" + + +msgid "Defines the lens projection as polynomial to allow real world camera lenses to be mimicked" +msgstr "[Fisheye Lens Polynomial]: Defineix la projecció de la lent com a polinòmica per permetre d'imitar les lents de càmera del món real" + + +msgid "Form of curves" +msgstr "Forma de corbes" + + +msgid "Rounded Ribbons" +msgstr "Llacets arrodonits" + + +msgid "Render curves as flat ribbons with rounded normals, for fast rendering" +msgstr "Revela les corbes com a llacets planes amb normals arrodonides, per a una representació ràpida" + + +msgid "3D Curves" +msgstr "Corbes 3D" + + +msgid "Render curves as circular 3D geometry, for accurate results when viewing closely" +msgstr "Revela les corbes com a geometria circular 3D, per a obtenir resultats precisos vist de prop" + + +msgid "Number of subdivisions used in Cardinal curve intersection (power of 2)" +msgstr "Nombre de subdivisions utilitzades en la intersecció de corbes cardinals (potència de 2)" + + +msgid "CPU" +msgstr "CPU" + + +msgid "CUDA" +msgstr "CUDA" + + +msgid "OptiX" +msgstr "OptiX" + + +msgid "HIP" +msgstr "HIP" + + +msgid "oneAPI" +msgstr "oneAPI" + + +msgid "Cast Shadow" +msgstr "Projectar ombra" + + +msgid "Light casts shadows" +msgstr "La llum projecta ombres" + + +msgid "Shadow Caustics" +msgstr "Càustica d'ombra" + + +msgid "Generate approximate caustics in shadows of refractive surfaces. Lights, caster and receiver objects must have shadow caustics options set to enable this" +msgstr "[Shadow Caustics]: Genera càustiques aproximades en ombres de superfícies refractives. Els objectes llum, projectors i receptors han de contenir opcions de càustica d'ombra definides per poder-ho habilitar" + + +msgid "Is Portal" +msgstr "És portal" + + +msgid "Use this area light to guide sampling of the background, note that this will make the light invisible" +msgstr "[Is Portal]: Usa aquesta llum d'àrea per a guiar el mostreig del rerefons, tingueu en compte que això farà que la llum sigui invisible" + + +msgid "Maximum number of bounces the light will contribute to the render" +msgstr "Nombre màxim de rebots que la llum aportarà al revelat" + + +msgid "Multiple Importance Sample" +msgstr "Mostreig d'importància múltiple" + + +msgid "Use multiple importance sampling for the light, reduces noise for area lights and sharp glossy materials" +msgstr "Usa un mostreig d'importància múltiple per a la llum, redueix el soroll per als llums d'àrea i els materials brillants" + + +msgid "Displacement Method" +msgstr "Mètode de desplaçament" + + +msgid "Method to use for the displacement" +msgstr "Mètode a usar per al desplaçament" + + +msgid "Bump Only" +msgstr "Només relleu" + + +msgid "Bump mapping to simulate the appearance of displacement" +msgstr "Mapejat de relleu per a simular l'aparença de desplaçament" + + +msgid "Displacement Only" +msgstr "Només desplaçament" + + +msgid "Use true displacement of surface only, requires fine subdivision" +msgstr "Usa només el desplaçament real de la superfície, requereix una subdivisió fina" + + +msgid "Displacement and Bump" +msgstr "Desplaçament i relleu" + + +msgid "Combination of true displacement and bump mapping for finer detail" +msgstr "Combinació de desplaçament real i mapejat de relleu per a detalls més fins" + + +msgid "Emission Sampling" +msgstr "Mostreig d'emissió" + + +msgid "Sampling strategy for emissive surfaces" +msgstr "Estratègia de mostreig per a superfícies d'emissió" + + +msgid "Do not use this surface as a light for sampling" +msgstr "No usar aquesta superfície com a llum per al mostreig" + + +msgid "Automatically determine if the surface should be treated as a light for sampling, based on estimated emission intensity" +msgstr "Determina automàticament si la superfície s'ha de tractar com una llum per al mostreig, basat en la intensitat d'emissió estimada" + + +msgid "Treat only front side of the surface as a light, usually for closed meshes whose interior is not visible" +msgstr "Tracta només el costat frontal de la superfície com a llum, generalment per a malles tancades l'interior de les quals no és visible" + + +msgid "Treat only back side of the surface as a light for sampling" +msgstr "Tracta només la part posterior de la superfície com a llum per al mostreig" + + +msgid "Front and Back" +msgstr "Frontal i posterior" + + +msgid "Treat surface as a light for sampling, emitting from both the front and back side" +msgstr "[Front and Back]: Tracta la superfície com una llum per al mostreig, emetent-se tant des del costat frontal com des del posterior" + + +msgid "Homogeneous Volume" +msgstr "Volum homogeni" + + +msgid "When using volume rendering, assume volume has the same density everywhere (not using any textures), for faster rendering" +msgstr "[Homogeneous Volume]: Quan s'utilitza el revelat del volum, s'assumeix que el volum té la mateixa densitat a tot arreu (no s'utilitza cap textura), per a un revelat més ràpid" + + +msgid "Transparent Shadows" +msgstr "Ombres transparents" + + +msgid "Use transparent shadows for this material if it contains a Transparent BSDF, disabling will render faster but not give accurate shadows" +msgstr "Usa ombres transparents per a aquest material si conté un BSDF transparent, la inhabilitació farà revelar més ràpid però no donarà ombres precises" + + +msgid "Volume Interpolation" +msgstr "Interpolació de volums" + + +msgid "Interpolation method to use for smoke/fire volumes" +msgstr "Mètode d'interpolació per als volums de fum/foc" + + +msgid "Volume Sampling" +msgstr "Mostreig del volum" + + +msgid "Sampling method to use for volumes" +msgstr "[Volume Sampling]: Mètode de mostreig a usar per als volums" + + +msgid "Use distance sampling, best for dense volumes with lights far away" +msgstr "Usar el mostreig de distància, el millor per a volums densos amb llums llunyanes" + + +msgid "Equiangular" +msgstr "Equiangular" + + +msgid "Use equiangular sampling, best for volumes with low density with light inside or near the volume" +msgstr "Usa mostreig equiangular, el millor per als volums amb baixa densitat amb llum dins o prop del volum" + + +msgid "Multiple Importance" +msgstr "Importància múltiple" + + +msgid "Combine distance and equi-angular sampling for volumes where neither method is ideal" +msgstr "Combina la distància i el mostreig equiangular per als volums on cap dels dos mètodes és ideal" + + +msgid "Step Rate" +msgstr "Ritme de pas" + + +msgid "Scale the distance between volume shader samples when rendering the volume (lower values give more accurate and detailed results, but also increased render time)" +msgstr "[Step Rate]: Escala la distància entre les mostres d'aspector del volum en revelar el volum (els valors més baixos donen resultats més precisos i detallats, però també incrementen el temps de revelat)" + + +msgid "AO Distance" +msgstr "Distància OA" + + +msgid "AO distance used for approximate global illumination (0 means use world setting)" +msgstr "[AO Distance]: La distància d'OA utilitzada per a la il·luminació global aproximada (0 significa agafar la configuració del món)" + + +msgid "Dicing Scale" +msgstr "Escala de fraccionament" + + +msgid "Multiplier for scene dicing rate (located in the Subdivision panel)" +msgstr "[Dicing Scale]: Multiplicador per a la taxa de fraccionament de l'escena (ubicada al plafó de subdivisió)" + + +msgid "Cast Shadow Caustics" +msgstr "Càustica de projecció d'ombra" + + +msgid "With refractive materials, generate approximate caustics in shadows of this object. Up to 10 bounces inside this object are taken into account. Lights, caster and receiver objects must have shadow caustics options set to enable this" +msgstr "[Cast Shadow Caustics]: Amb materials refractius, genera càustiques aproximades en les ombres d'aquest objecte. Es tenen en compte fins a 10 rebots dins d'aquest objecte. Els objectes llum, projector i receptor han de tenir les opcions de càustica d'ombra definides per poder-ho activar" + + +msgid "Receive Shadow Caustics" +msgstr "Rebre càustica d'ombra" + + +msgid "Receive approximate caustics from refractive materials in shadows on this object. Lights, caster and receiver objects must have shadow caustics options set to enable this" +msgstr "Rep càustiques aproximades de materials refractius en les ombres d'aquest objecte. Els objectes llum, projector i receptor han de tenir les opcions de càustica d'ombra definides per poder activar-ho" + + +msgid "Motion Steps" +msgstr "Passades de moviment" + + +msgid "Control accuracy of motion blur, more steps gives more memory usage (actual number of steps is 2^(steps - 1))" +msgstr "[Motion Steps]: Controla la precisió del difuminat de moviment, més passades impliquen més ús de memòria (el nombre real de passades és 2^)(passades - 1))" + + +msgid "Shadow Terminator Geometry Offset" +msgstr "Desplaçament de l'anul·lador d'ombres" + + +msgid "Offset rays from the surface to reduce shadow terminator artifact on low poly geometry. Only affects triangles at grazing angles to light" +msgstr "[Shadow Terminator Geometry Offset]: Desplaça els rajos de superfície per reduir tares d'anul·lació d'ombres en geometria de baixa poligonació. Només afecta els triangles en angles rasants de llum" + + +msgid "Shadow Terminator Shading Offset" +msgstr "Desplaçament d'asècció d'anul·lació d'ombres" + + +msgid "Push the shadow terminator towards the light to hide artifacts on low poly geometry" +msgstr "Empeny l'anul·lador d'ompbres envers la llum per amagar les tares de la geometria de baixa poligonació" + + +msgid "Use Adaptive Subdivision" +msgstr "Usar subdivisió adaptativa" + + +msgid "Use adaptive render time subdivision" +msgstr "Usa una subdivisió de temps de revelat adaptativa" + + +msgid "Use Camera Cull" +msgstr "Usar esporgació de càmera" + + +msgid "Allow this object and its duplicators to be culled by camera space culling" +msgstr "Permet que aquest objecte i els seus duplicats se subjectin a l'esporgació de l'espai de la càmera" + + +msgid "Use Deformation Motion" +msgstr "Usar moviment de deformació" + + +msgid "Use deformation motion blur for this object" +msgstr "[Use Deformation Motion]: Usa el difuminat de moviment de deformació per a aquest objecte" + + +msgid "Use Distance Cull" +msgstr "Usar esporgament per distància" + + +msgid "Allow this object and its duplicators to be culled by distance from camera" +msgstr "[Use Distance Cull]: Permet que aquest objecte i els seus duplicats s'esporguin a distància de la càmera" + + +msgid "Use Motion Blur" +msgstr "Usar difuminat de moviment" + + +msgid "Use motion blur for this object" +msgstr "[Use Motion Blur]: Usa el difuminat de moviment per a aquest objecte" + + +msgid "Store Denoising Passes" +msgstr "Guardar passades de desoroll" + + +msgid "Store the denoising feature passes and the noisy image. The passes adapt to the denoiser selected for rendering" +msgstr "[Store Denoising Passes]: Emmagatzema les passades de la característica de desorollar i de la imatge sorollosa. Les passades s'adapten al desorollador escollit per al revelat" + + +msgid "Debug Sample Count" +msgstr "Recompte de mostres per ajustaments" + + +msgid "Number of samples/camera rays per pixel" +msgstr "[Debug Sample Count]: Nombre de mostres/rajos de càmera per píxel" + + +msgid "Use Denoising" +msgstr "Fer desorollar" + + +msgid "Denoise the rendered image" +msgstr "[Use Denoising]: Desorollar la imatge revelada" + + +msgid "Pass containing shadows and light which is to be multiplied into backdrop" +msgstr "Passada amb ombres i llum que es multiplicarà en el darrere" + + +msgid "Volume Direct" +msgstr "Volum directe" + + +msgid "Deliver direct volumetric scattering pass" +msgstr "[Volume Direct]: Administra una passada de dispersió volumètrica directa" + + +msgid "Volume Indirect" +msgstr "Volum indirecte" + + +msgid "Deliver indirect volumetric scattering pass" +msgstr "Administra una passada de dispersió volumètrica indirecta" + + +msgid "Adaptive Min Samples" +msgstr "Mín mostreig adaptatiu" + + +msgid "Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on noise threshold" +msgstr "Mostres mínimes d'AA del mostreig adaptatiu, per descobrir característiques de soroll abans d'aturar el mostreig. Zero per a la configuració automàtica basada en el llindar de soroll" + + +msgid "Adaptive Sampling Threshold" +msgstr "Llindar de mostreig adaptatiu" + + +msgid "Noise level step to stop sampling at, lower values reduce noise at the cost of render time. Zero for automatic setting based on number of AA samples" +msgstr "Pas del nivell de soroll on es deixa de mostrejar, els valors més baixos redueixen el soroll a costa del temps de revelat. Zero per a la configuració automàtica basada en el nombre de mostres d'AA" + + +msgid "AO Bounces" +msgstr "Rebots d'OA" + + +msgid "After this number of light bounces, use approximate global illumination. 0 disables this feature" +msgstr "[AO Bounces]: Després d'aquest nombre de rebots de llum, usar il·luminació global aproximada. 0 inhabilita aquesta característica" + + +msgid "AO Bounces Render" +msgstr "Revelat de rebots d'OA" + + +msgid "Automatic Scrambling Distance" +msgstr "Distància automàtica d'esbarriat" + + +msgid "Automatically reduce the randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts" +msgstr "[Automatic Scrambling Distance]: Redueix automàticament l'aleatorietat entre píxels per a millorar el rendiment del revelat de la GPU, a costa de possibles tares de revelat" + + +msgid "Bake Type" +msgstr "Tipus de precuinat" + + +msgid "Type of pass to bake" +msgstr "[Bake Type]: Tipus de passada a precuinar" + + +msgid "Filter Glossy" +msgstr "Filtrar brillants" + + +msgid "Adaptively blur glossy shaders after blurry bounces, to reduce noise at the cost of accuracy" +msgstr "[Filter Glossy]: Difuminat adaptatiu d'aspectors brillants després de rebots borrosos, per a reduir el soroll a costa de la precisió" + + +msgid "Camera Cull Margin" +msgstr "Marge d'esporgat de càmera" + + +msgid "Margin for the camera space culling" +msgstr "Marge d'espai d'esporgament per a la càmera" + + +msgid "Reflective Caustics" +msgstr "Càustica reflectiva" + + +msgid "Use reflective caustics, resulting in a brighter image (more noise but added realism)" +msgstr "[Reflective Caustics]: Usa càustiques reflectives, resultant en una imatge més brillant (més soroll però més realisme)" + + +msgid "Refractive Caustics" +msgstr "Càustica refractiva" + + +msgid "Use refractive caustics, resulting in a brighter image (more noise but added realism)" +msgstr "Usa càustiques de refracció, resultant en una imatge més brillant (més soroll però més realisme)" + + +msgid "BVH Layout" +msgstr "Disposició BVH" + + +msgid "BVH2" +msgstr "BVH2" + + +msgid "Embree" +msgstr "Embree" + + +msgid "BVH Time Steps" +msgstr "Passos de temps BVH" + + +msgid "Split BVH primitives by this number of time steps to speed up render time in cost of memory" +msgstr "[BVH Time Steps]: Divideix els primitius BVH per aquest nombre de passos de temps per accelerar el temps de revelat a cost de la memòria" + + +msgid "Viewport BVH Type" +msgstr "Tipus de BVH de mirador" + + +msgid "Choose between faster updates, or faster render" +msgstr "Triar entre actualitzacions més ràpides o revelat més ràpid" + + +msgid "Dynamic BVH" +msgstr "BVH dinàmic" + + +msgid "Objects can be individually updated, at the cost of slower render time" +msgstr "Els objectes es poden actualitzar individualment, a costa d'un temps de revelat més lent" + + +msgid "Static BVH" +msgstr "BVH estàtic" + + +msgid "Any object modification requires a complete BVH rebuild, but renders faster" +msgstr "Qualsevol modificació d'objectes requereix una reconstrucció completa de BVH, però es revela més ràpidament" + + +msgid "Use Compact BVH" +msgstr "Usar BVH compacte" + + +msgid "Use compact BVH structure (uses less ram but renders slower)" +msgstr "Usa una estructura BVH compacta (usa menys ram, però revela més lent)" + + +msgid "AVX2" +msgstr "AVX2" + + +msgid "SSE2" +msgstr "SSE2" + + +msgid "SSE41" +msgstr "SSE41" + + +msgid "Adaptive Compile" +msgstr "Compilat adaptatiu" + + +msgid "Use Curves BVH" +msgstr "Usar corbes BVH" + + +msgid "Use special type BVH optimized for curves (uses more ram but renders faster)" +msgstr "[Use Curves BVH]: Usa un tipus especial BVH optimitzat per a corbes (usa més ram, però revela més ràpid)" + + +msgid "OptiX Module Debug" +msgstr "Depuració del mòdul OptiX" + + +msgid "Load OptiX module in debug mode: lower logging verbosity level, enable validations, and lower optimization level" +msgstr "[OptiX Module Debug]: Carrega el mòdul OptiX en mode de depuració: abaixar nivell de detall del registre més baix, activar les validacions i abaixar el nivell d'optimització" + + +msgid "Use Spatial Splits" +msgstr "Usar separacions espacials" + + +msgid "Use BVH spatial splits: longer builder time, faster render" +msgstr "[Use Spatial Splits]: Usa separacions espacials de BVH: temps de composició més llarg, revelat més ràpit" + + +msgid "Denoiser" +msgstr "Desorollador" + + +msgid "Denoise the image with the selected denoiser. For denoising the image after rendering" +msgstr "[Denoiser]: Desorolla la imatge amb el plomall seleccionat. És per a desorollar la imatge després del revelat" + + +msgid "Denoising Input Passes" +msgstr "Passades d'ingressió de desorollat" + + +msgid "Passes used by the denoiser to distinguish noise from shader and geometry detail" +msgstr "[Denoising Input Passes]: Passades que fa el desorollador per a distingir la pols de l'aspector del detall de la geometria" + + +msgid "Don't use utility passes for denoising" +msgstr "No usar passades tècniques per desorollar" + + +msgid "Albedo" +msgstr "Albedo" + + +msgid "Use albedo pass for denoising" +msgstr "Usar passada d'albedo per desorollar" + + +msgid "Albedo and Normal" +msgstr "Albedo i normal" + + +msgid "Use albedo and normal passes for denoising" +msgstr "Usar passades albedo i normals per a desorollar" + + +msgid "Denoising Prefilter" +msgstr "Prefiltre de desorollar" + + +msgid "Prefilter noisy guiding (albedo and normal) passes to improve denoising quality when using OpenImageDenoiser" +msgstr "Prefiltre de passades orientadores (albedo i normal) del soroll per millorar la qualitat del desorollat del OpenImageDenoiser" + + +msgid "Denoise color and guiding passes together. Improves quality when guiding passes are noisy using least amount of extra processing time" +msgstr "Passades d'orientació i color alhora pel desorollament. Millora la qualitat quan les passades orientadores duen soroll fent-ho amb el mínim temps de processament extra" + + +msgid "Prefilter noisy guiding passes before denoising color. Improves quality when guiding passes are noisy using extra processing time" +msgstr "Prefiltrar passades orientadores de soroll abans de desorollar el color. Millora la qualitat quan les passades orientadores duen soroll i ho fa amb un temps de processament extra" + + +msgid "Device" +msgstr "Dispositiu" + + +msgid "Device to use for rendering" +msgstr "[Device]: Dispositiu usat per a revelar" + + +msgid "Use CPU for rendering" +msgstr "Usar la CPU per al revelat" + + +msgid "GPU Compute" +msgstr "Càlcul de GPU" + + +msgid "Use GPU compute device for rendering, configured in the system tab in the user preferences" +msgstr "Usa el dispositiu de càlcul de la GPU per revelar, configurat a la pestanya del sistema en les preferències de la usuària" + + +msgid "Dicing Camera" +msgstr "Càmera de fraccionament" + + +msgid "Camera to use as reference point when subdividing geometry, useful to avoid crawling artifacts in animations when the scene camera is moving" +msgstr "Càmera d'ús com a punt de referència en subdividir geometria, útil per evitar tares pul·lulants en animacions quan la càmera d'escena es mou" + + +msgid "Dicing Rate" +msgstr "Taxa de fragmentació" + + +msgid "Size of a micropolygon in pixels" +msgstr "[Dicing Rate]: Mida en píxels d'un micropolígon" + + +msgid "Diffuse Bounces" +msgstr "Rebots difusius" + + +msgid "Maximum number of diffuse reflection bounces, bounded by total maximum" +msgstr "[Diffuse Bounces]: Nombre màxim de rebots de reflex difusiu, delimitats pel màxim total" + + +msgid "Direct Light Sampling" +msgstr "Mostreig de llum directa" + + +msgid "The type of strategy used for sampling direct light contributions" +msgstr "[Direct Light Sampling]: La mena d'estratègia per a mostreig de les aportacions de llum directa" + + +msgid "Multiple Importance Sampling" +msgstr "Mostreig d'importància múltiple" + + +msgid "Multiple importance sampling is used to combine direct light contributions from next-event estimation and forward path tracing" +msgstr "[Multiple Importance Sampling]: El mostreig d'importància múltiple s'utilitza per combinar aportacions de llum directa des de l'estimació de l'esdeveniment següent i des del traçat endavant" + + +msgid "Forward Path Tracing" +msgstr "Traçat endavant" + + +msgid "Direct light contributions are only sampled using forward path tracing" +msgstr "[Forward Path Tracing]: Les aportacions de llum directa només es mostregen usant el traçat de trajecte endavant" + + +msgid "Next-Event Estimation" +msgstr "Estimació d'esdeveniment següent" + + +msgid "Direct light contributions are only sampled using next-event estimation" +msgstr "[Next-Event Estimation]: Les aportacions de llum directa només es mostregen usant l'estimació de l'esdeveniment següent" + + +msgid "Cull Distance" +msgstr "Distància d'esporgament" + + +msgid "Cull objects which are further away from camera than this distance" +msgstr "[Cull Distance]: Retira els objectes que estan més lluny de la càmera que aquesta distància" + + +msgid "Fast GI Method" +msgstr "Mètode IG ràpid" + + +msgid "Fast GI approximation method" +msgstr "[Fast GI Method]: Mètode d'aproximació IG ràpid" + + +msgid "Replace global illumination with ambient occlusion after a specified number of bounces" +msgstr "Substituir la il·luminació global per l'oclusió ambiental després d'un nombre especificat de rebots" + + +msgid "Add ambient occlusion to diffuse surfaces" +msgstr "Afegir oclusió ambiental a superfícies difusives" + + +msgid "Feature Set" +msgstr "Conjunt de característiques" + + +msgid "Feature set to use for rendering" +msgstr "[Feature Set]: Joc de característiques per al revelat" + + +msgid "Supported" +msgstr "Suportades" + + +msgid "Only use finished and supported features" +msgstr "Utilitza només les característiques acabades i admeses" + + +msgid "Use experimental and incomplete features that might be broken or change in the future" +msgstr "Usa característiques experimentals i incompletes que es poden desgavellar o canviar en el futur" + + +msgid "Image brightness scale" +msgstr "Escala de brillantor d'imatge" + + +msgid "Transparent Glass" +msgstr "Vidre transparent" + + +msgid "Render transmissive surfaces as transparent, for compositing glass over another background" +msgstr "[Transparent Glass]: Revela superfícies transmissives com a transparents, per a conjuminar vidre sobre un fons diferent" + + +msgid "Transparent Roughness Threshold" +msgstr "Llindar de rugositat transparent" + + +msgid "For transparent transmission, keep surfaces with roughness above the threshold opaque" +msgstr "[Transparent Roughness Threshold]: Per a una transmissió transparent, manté opaques les superfícies amb rugositat per sobre de llindar" + + +msgid "Filter Width" +msgstr "Ample de filtre" + + +msgid "Pixel filter width" +msgstr "[Filter Width]: Amplada del filtre de píxels" + + +msgid "Glossy Bounces" +msgstr "Rebots brillants" + + +msgid "Maximum number of glossy reflection bounces, bounded by total maximum" +msgstr "[Glossy Bounces]: Nombre màxim de rebots de reflex brillant, delimitats pel màxim total" + + +msgid "Guiding Distribution Type" +msgstr "Tipus de distribució de guiatge" + + +msgid "Type of representation for the guiding distribution" +msgstr "[Guiding Distribution Type]: Tipus de representació per a la distribució de guiatge" + + +msgid "Parallax-Aware VMM" +msgstr "GMV amb paral·laxi" + + +msgid "Use Parallax-aware von Mises-Fisher models as directional distribution" +msgstr "[Parallax-Aware VMM]: Usa els models de von Mises-Fisher en base a paral·laxis com a distribució direccional" + + +msgid "Directional Quad Tree" +msgstr "Arbre de Quads direccional" + + +msgid "Use Directional Quad Trees as directional distribution" +msgstr "[Directional Quad Tree]: Usa els Arbres de Quads direccionals com a distribució direccional" + + +msgid "VMM" +msgstr "GMV" + + +msgid "Use von Mises-Fisher models as directional distribution" +msgstr "[VMM]: Usa els models von Mises-Fisher com a distribució direccional" + + +msgid "Training Samples" +msgstr "Mostres d'entrenament" + + +msgid "The maximum number of samples used for training path guiding. Higher samples lead to more accurate guiding, however may also unnecessarily slow down rendering once guiding is accurate enough. A value of 0 will continue training until the last sample" +msgstr "[Training Samples]: El nombre màxim de mostres usades en l'entrenament de guiatge de trajecte. Els mostrejos més alts fan el guiatge més precís, però també poden alentir el revelat innecessàriament una cop el guiatge és prou precís. Un valor de 0 continuarà entrenament fins a l'última mostra" + + +msgid "Light Sampling Threshold" +msgstr "Llindar del mostreig de llum" + + +msgid "Probabilistically terminate light samples when the light contribution is below this threshold (more noise but faster rendering). Zero disables the test and never ignores lights" +msgstr "[Light Sampling Threshold]: Elimina probabilísticament les mostres de llum quan l'aportació de llum està per sota d'aquest llindar (més soroll, però revelat més ràpid). El zero desactiva la prova i mai no ignora llums" + + +msgid "Total maximum number of bounces" +msgstr "Nombre màxim de rebots totals" + + +msgid "Max Subdivisions" +msgstr "Subdivisions màx" + + +msgid "Stop subdividing when this level is reached even if the dice rate would produce finer tessellation" +msgstr "[Max Subdivisions]: Atura la subdivisió quan s'assoleix aquest nivell encara que la taxa de fragmentació pogués produir una tessel·lació més fina" + + +msgid "Min Light Bounces" +msgstr "Rebots de llum mín" + + +msgid "Minimum number of light bounces. Setting this higher reduces noise in the first bounces, but can also be less efficient for more complex geometry like curves and volumes" +msgstr "Nombre mínim de rebots de llum. Posant-ho més alt es redueix el soroll en els primers rebots, però també pot ser menys eficient per a geometries més complexes com les de corbes i volums" + + +msgid "Min Transparent Bounces" +msgstr "Rebots transparents mín" + + +msgid "Minimum number of transparent bounces. Setting this higher reduces noise in the first bounces, but can also be less efficient for more complex geometry like curves and volumes" +msgstr "Nombre mínim de rebots transparents. Posant-ho més alt es redueix el soroll en els primers rebots, però també pot ser menys eficient per a geometries més complexes com corbes i volums" + + +msgid "Motion Blur Position" +msgstr "Posició de difuminat de moviment" + + +msgid "Offset for the shutter's time interval, allows to change the motion blur trails" +msgstr "[Motion Blur Position]: Desplaçament per a l'interval de temps de l'obturador, permet canviar les pistes de difuminat del moviment" + + +msgid "Start on Frame" +msgstr "Iniciar al fotograma" + + +msgid "The shutter opens at the current frame" +msgstr "L'obturador s'obre al fotograma actual" + + +msgid "Center on Frame" +msgstr "Centrar al fotograma" + + +msgid "The shutter is open during the current frame" +msgstr "L'obturador està obert durant el fotograma actual" + + +msgid "End on Frame" +msgstr "Finalitzar al fotograma" + + +msgid "The shutter closes at the current frame" +msgstr "L'obturador es tanca al fotograma actual" + + +msgid "Offscreen Dicing Scale" +msgstr "Escala de fragmentació fora de pantalla" + + +msgid "Multiplier for dicing rate of geometry outside of the camera view. The dicing rate of objects is gradually increased the further they are outside the camera view. Lower values provide higher quality reflections and shadows for off screen objects, while higher values use less memory" +msgstr "[Offscreen Dicing Scale]: Multiplicador per a la taxa de fragmentació de la geometria fora de l'abast de la càmera. La taxa de fragmentació dels objectes augmenta gradualment com més lluny estan de l'angle de visió de la càmera. Els valors més baixos proporcionen reflexos de major qualitat i ombres per als objectes fora de pantalla, mentre que els valors més alts utilitzen menys memòria" + + +msgid "Pixel filter type" +msgstr "Tipus de filtre de píxels" + + +msgid "Box filter" +msgstr "Filtre de caixa" + + +msgid "Gaussian filter" +msgstr "Filtre gaussià" + + +msgid "Blackman-Harris" +msgstr "Blackman-Harris" + + +msgid "Blackman-Harris filter" +msgstr "Filtre Blackman-Harris" + + +msgid "Minimum AA samples for adaptive sampling, to discover noisy features before stopping sampling. Zero for automatic setting based on noise threshold, for viewport renders" +msgstr "Mostrejos mínims d'AA per al mostreig adaptatiu, per descobrir característiques sorolloses abans d'aturar el mostreig. Zero per a la configuració automàtica basada en el llindar de soroll, per a revelats de mirador" + + +msgid "Noise level step to stop sampling at, lower values reduce noise at the cost of render time. Zero for automatic setting based on number of AA samples, for viewport renders" +msgstr "Fase de nivell de soroll per aturar el mostreig, els valors més baixos redueixen el soroll a costa del temps de revelat. Zero per a la configuració automàtica basada en el nombre de mostres d'AA, per a revelats de mirador" + + +msgid "Viewport Denoiser" +msgstr "Desorollador de mirador" + + +msgid "Denoise the image after each preview update with the selected denoiser" +msgstr "[Viewport Denoiser]: Desorolla la imatge després de cada actualització de la vista prèvia amb el desorollador seleccionat" + + +msgid "Viewport Denoising Input Passes" +msgstr "Passos d'ingressió de desorollat del mirador" + + +msgid "Viewport Denoising Prefilter" +msgstr "Prefiltre per desorollar el mirador" + + +msgid "Start Denoising" +msgstr "Començar desorollar" + + +msgid "Sample to start denoising the preview at" +msgstr "[Start Denoising]: Mostreig d'inici de desorollament de la vista prèvia" + + +msgid "Viewport Dicing Rate" +msgstr "Taxa de fragmentació de mirador" + + +msgid "Size of a micropolygon in pixels during preview render" +msgstr "Mida d'un micropolígon en píxels durant el revelat de previsualització" + + +msgid "Pause Preview" +msgstr "Pausar previsualització" + + +msgid "Pause all viewport preview renders" +msgstr "Posa en pausa tots els revelats de previsualització de mirador" + + +msgid "Viewport Samples" +msgstr "Mostrejos de mirador" + + +msgid "Number of samples to render in the viewport, unlimited if 0" +msgstr "[Viewport Samples]: Nombre de mostres a revelar en el mirador, sense límit si 0" + + +msgid "Scrambling Distance viewport" +msgstr "Esbarriat de distància en el mirador" + + +msgid "Uses the Scrambling Distance value for the viewport. Faster but may flicker" +msgstr "Utilitza el valor d'esbarriat de distància per al mirador. Més ràpid, però pot titil·lar" + + +msgid "Rolling Shutter Duration" +msgstr "Durada d'obturador corredís" + + +msgid "Scanline \"exposure\" time for the rolling shutter effect" +msgstr "[Rolling Shutter Duration]: Temps de «exposició» a l'escaneig per a l'efecte de l'anomenat obturador enrotllable" + + +msgid "Shutter Type" +msgstr "Tipus d'obturador" + + +msgid "Type of rolling shutter effect matching CMOS-based cameras" +msgstr "[Shutter Type]: Tipus d'efecte d'obturador corredís a semblança de les càmeres basades en CMOS" + + +msgid "No rolling shutter effect used" +msgstr "No s'usa cap efecte corredís d'obturació" + + +msgid "Sensor is being scanned from top to bottom" +msgstr "S'està escanejant el sensor de dalt a baix" + + +msgid "Clamp Direct" +msgstr "Constrenyiment directe" + + +msgid "If non-zero, the maximum value for a direct sample, higher values will be scaled down to avoid too much noise and slow convergence at the cost of accuracy" +msgstr "Si no és zero, el valor màxim per a una mostra directa, els valors més alts es reduiran per evitar massa soroll i una convergència lenta a costa de la precisió" + + +msgid "Clamp Indirect" +msgstr "Constrenyiment indirecte" + + +msgid "If non-zero, the maximum value for an indirect sample, higher values will be scaled down to avoid too much noise and slow convergence at the cost of accuracy" +msgstr "Si no és zero, el valor màxim per a una mostra indirecta, els valors més alts es reduiran per evitar massa soroll i una convergència lenta a costa de la precisió" + + +msgid "Sample Offset" +msgstr "Mostreig ignorat" + + +msgid "Number of samples to skip when starting render" +msgstr "Nombre de mostres a saltar-se en iniciar el revelat" + + +msgid "Number of samples to render for each pixel" +msgstr "Nombre de mostres a revelar per a cada píxel" + + +msgid "Sampling Pattern" +msgstr "Patró de mostreig" + + +msgid "Random sampling pattern used by the integrator" +msgstr "Patró de mostreig aleatori utilitzat per l'integrador" + + +msgid "Sobol-Burley" +msgstr "Sobol-Burley" + + +msgid "Use on-the-fly computed Owen-scrambled Sobol for random sampling" +msgstr "Usa el Sobol amb l'esbarriat d'Owen calculat sobre la marxa a guisa de mostreig aleatori" + + +msgid "Tabulated Sobol" +msgstr "Sobol tabulat" + + +msgid "Use pre-computed tables of Owen-scrambled Sobol for random sampling" +msgstr "[Tabulated Sobol]: Usa taules precalculades de Sobol amb esbarriat d'Owen per al mostreig aleatori" + + +msgid "Scrambling Distance" +msgstr "Distància d'esbarriat" + + +msgid "Reduce randomization between pixels to improve GPU rendering performance, at the cost of possible rendering artifacts if set too low" +msgstr "Redueix l'aleatorietat entre píxels per a millorar el rendiment del revelat amb GPU, a costa de possibles tares de revelat si es posa massa baix" + + +msgid "Seed value for integrator to get different noise patterns" +msgstr "Valor llavor perquè l'integrador obtingui diferents patrons de soroll" + + +msgid "Use Open Shading Language" +msgstr "Usar «Open Shading Language»" + + +msgid "Surface Guiding Probability" +msgstr "Probabilitat de guiatge en superfície" + + +msgid "The probability of guiding a direction on a surface" +msgstr "[Surface Guiding Probability]: La probabilitat d'orientar en una direcció en una superfície" + + +msgid "Viewport Texture Limit" +msgstr "Límit de textura en mirador" + + +msgid "Limit texture size used by viewport rendering" +msgstr "[Viewport Texture Limit]: Limita la mida de la textura usada al revelat de mirador" + + +msgid "No Limit" +msgstr "Sense límit" + + +msgid "No texture size limit" +msgstr "Sense límit de mida de textura" + + +msgid "Limit texture size to 128 pixels" +msgstr "Limit de mida de textura a 128 píxels" + + +msgid "Limit texture size to 256 pixels" +msgstr "Limit de mida de textura a 256 píxels" + + +msgid "Limit texture size to 512 pixels" +msgstr "Limit de mida de textura a 512 píxels" + + +msgid "Limit texture size to 1024 pixels" +msgstr "Limit de mida de textura a 1024 píxels" + + +msgid "Limit texture size to 2048 pixels" +msgstr "Limit de mida de textura a 2048 píxels" + + +msgid "Limit texture size to 4096 pixels" +msgstr "Limit de mida de textura a 4096 píxels" + + +msgid "Limit texture size to 8192 pixels" +msgstr "Limit de mida de textura a 8192 píxels" + + +msgid "Render Texture Limit" +msgstr "Límit de revelat de textura" + + +msgid "Limit texture size used by final rendering" +msgstr "Limita la mida de la textura usada per al revelat final" + + +msgid "Tile Size" +msgstr "Mida de tessel·la" + + +msgid "Limit the render time (excluding synchronization time).Zero disables the limit" +msgstr "Limita el temps de revelat (excloent-ne el temps de sincronització). Zero inhabilita el límit" + + +msgid "Transmission Bounces" +msgstr "Rebots de transmissió" + + +msgid "Maximum number of transmission bounces, bounded by total maximum" +msgstr "Nombre màxim de rebots de transmissió, delimitats pel màxim total" + + +msgid "Transparent Max Bounces" +msgstr "Rebots màxims transparents" + + +msgid "Maximum number of transparent bounces. This is independent of maximum number of other bounces" +msgstr "Nombre màxim de rebots transparents. És independent del nombre màxim d'altres rebots" + + +msgid "Use Adaptive Sampling" +msgstr "Usar mostreig adaptatiu" + + +msgid "Automatically reduce the number of samples per pixel based on estimated noise level" +msgstr "Redueix automàticament el nombre de mostres per píxel en funció del nivell de soroll estimat" + + +msgid "Use Animated Seed" +msgstr "Usar llavor animada" + + +msgid "Use different seed values (and hence noise patterns) at different frames" +msgstr "Usa valors de llavor diferents (i, per tant, patrons de soroll) en fotogrames diferents" + + +msgid "Use Tiling" +msgstr "Usar tessel·lació" + + +msgid "Render high resolution images in tiles to reduce memory usage, using the specified tile size. Tiles are cached to disk while rendering to save memory" +msgstr "Revela imatges d'alta resolució en les tessel·les per a reduir l'ús de la memòria, en base a la mida de tessel·la especificada. Les tessel·les s'emmagatzemen al disc durant el revelat per estalviar memòria" + + +msgid "Allow objects to be culled based on the camera frustum" +msgstr "Permetre que s'esporguin objectes en base al tronc de la càmera" + + +msgid "Deterministic" +msgstr "Determinista" + + +msgid "Makes path guiding deterministic which means renderings will be reproducible with the same pixel values every time. This feature slows down training" +msgstr "[Deterministic]: Fa determinista el guiatge de camí, que vol dir que els revelats seran reproduïbles amb els mateixos valors de píxel cada vegada. Aquesta característica alenteix l'entrenament" + + +msgid "Allow objects to be culled based on the distance from camera" +msgstr "Permet esporgar els objectes en base a la distància des de la càmera" + + +msgid "Approximate diffuse indirect light with background tinted ambient occlusion. This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality" +msgstr "Llum indirecta difusiva aproximada amb oclusió ambiental tenyida del rerefons. Això dona una alternativa ràpida a la il·luminació global completa, per al revelat interactiu de mirador o per revelats finals amb una qualitat reduïda" + + +msgid "Guiding" +msgstr "Guiatge" + + +msgid "Use path guiding for sampling paths. Path guiding incrementally learns the light distribution of the scene and guides path into directions with high direct and indirect light contributions" +msgstr "[Guiding]: Usa el guiatge de trajectes per al mostreig de trajectes. El guiatge de trajectes aprèn incrementalment la distribució de llum de l'escena i guia el trajecte en direccions amb altes aportacions de llum directa i indirecta" + + +msgid "Guide Direct Light" +msgstr "Guia de llum directa" + + +msgid "Consider the contribution of directly visible light sources during guiding" +msgstr "[Guide Direct Light]: Considera la contribució de fonts de llum directament visible durant el guiatge" + + +msgid "Use MIS Weights" +msgstr "Usar pesos MIM" + + +msgid "Use the MIS weight to weight the contribution of directly visible light sources during guiding" +msgstr "[Use MIS Weights]: Usa pesos de Mostreig d'Importància Múltiple per ponderar la contribució de les fonts de llum directament visible durant el guiatge" + + +msgid "Layer Samples" +msgstr "Mostres per capa" + + +msgid "How to use per view layer sample settings" +msgstr "[Layer Samples]: Com usar la configuració de mostreig per capes de visualització" + + +msgid "Per render layer number of samples override scene samples" +msgstr "El nombre de mostres per capa de revelat sobreseu les mostres d'escena" + + +msgid "Bounded" +msgstr "Limitat" + + +msgid "Bound per render layer number of samples by global samples" +msgstr "[Bounded]: Límit per capa de revelat del nombre de mostres per mostres globals" + + +msgid "Ignore per render layer number of samples" +msgstr "Ignora el nombre de mostres per capa de revelat" + + +msgid "Light Tree" +msgstr "Arbre de llum" + + +msgid "Sample multiple lights more efficiently based on estimated contribution at every shading point" +msgstr "[Light Tree]: Mostreja múltiples llums de forma més eficient en funció de la contribució estimada en cada punt d'aspecció" + + +msgid "Automatically reduce the number of samples per pixel based on estimated noise level, for viewport renders" +msgstr "Redueix automàticament el nombre de mostres per píxel en funció del nivell de soroll estimat, per a velelats de miradorvisualització" + + +msgid "Use Viewport Denoising" +msgstr "Usar desorollat al mirador" + + +msgid "Denoise the image in the 3D viewport" +msgstr "Desorolla la imatge al mirador en 3D" + + +msgid "Surface Guiding" +msgstr "Guiatge de superfície" + + +msgid "Use guiding when sampling directions on a surface" +msgstr "[Surface Guiding]: Usa el guiatge quan es mostregen trajectes en una superfície" + + +msgid "Volume Guiding" +msgstr "Guiatge del volum" + + +msgid "Use guiding when sampling directions inside a volume" +msgstr "Usa el guiatge quan es mostregen les direccions dins d'un volum" + + +msgid "Volume Bounces" +msgstr "Rebots del volum" + + +msgid "Maximum number of volumetric scattering events" +msgstr "Nombre màxim d'esdeveniments de dispersió volumètrica" + + +msgid "Volume Guiding Probability" +msgstr "Probabilitat de guiatge del volum" + + +msgid "The probability of guiding a direction inside a volume" +msgstr "La probabilitat de guiar en una direcció dins d'un volum" + + +msgid "Max Steps" +msgstr "Passos màxims" + + +msgid "Maximum number of steps through the volume before giving up, to avoid extremely long render times with big objects or small step sizes" +msgstr "Nombre màxim de passos a través del volum abans de renunciar, per evitar temps de revelat extremadament llargs amb objectes grans o passos de mida petita" + + +msgid "Globally adjust detail for volume rendering, on top of automatically estimated step size. Higher values reduce render time, lower values render with more detail" +msgstr "Ajustar globalment el detall per a revelat de volum, a sobre de la mida del pas estimada automàticament. Els valors més alts redueixen el temps de revelat, els valors més baixos revelen amb més detall" + + +msgid "Render pass to show in the 3D Viewport" +msgstr "Passada de revelat a mostrar al mirador 3D" + + +msgid "Show the Combined Render pass" +msgstr "Mostrar la passada de revelat combinada" + + +msgid "Show the Emission render pass" +msgstr "Mostrar la passada de revelat d'emissió" + + +msgid "Show the Background render pass" +msgstr "Mostrar la passada de revelat de rerefons" + + +msgid "Show the Ambient Occlusion render pass" +msgstr "Mostrar la passada de revelat d'oclusió ambiental" + + +msgid "Show the Shadow Catcher render pass" +msgstr "Mostrar la passada de revelat del capturador d'ombres" + + +msgid "Diffuse Direct" +msgstr "Difusiu directe" + + +msgid "Show the Diffuse Direct render pass" +msgstr "Mostra la passada de revelat de difusió directa" + + +msgid "Diffuse Indirect" +msgstr "Difusiu indirecte" + + +msgid "Show the Diffuse Indirect render pass" +msgstr "Mostra la passada de revelat de difusió indirecta" + + +msgid "Show the Diffuse Color render pass" +msgstr "Show the Diffuse Color render pass" + + +msgid "Glossy Direct" +msgstr "Brillant directe" + + +msgid "Show the Glossy Direct render pass" +msgstr "Mostra la passada de revelat de brillant directe" + + +msgid "Glossy Indirect" +msgstr "Brillant indirecte" + + +msgid "Show the Glossy Indirect render pass" +msgstr "Mostra la passada de revelat de brillant indirecte" + + +msgid "Glossy Color" +msgstr "Color brillant" + + +msgid "Show the Glossy Color render pass" +msgstr "Mostra la passada de revelat de color brillant" + + +msgid "Transmission Direct" +msgstr "Transmissió directa" + + +msgid "Show the Transmission Direct render pass" +msgstr "Mostra la passada de revelat de transmissió directa" + + +msgid "Transmission Indirect" +msgstr "Transmissió indirecta" + + +msgid "Show the Transmission Indirect render pass" +msgstr "Mostra la passada de revelat de transmissió indirecta" + + +msgid "Transmission Color" +msgstr "Color de transmissió" + + +msgid "Show the Transmission Color render pass" +msgstr "Mostra la passada de revelat de color de transmissió" + + +msgid "Show the Volume Direct render pass" +msgstr "Mostrar la passada de revelat de volum directe" + + +msgid "Show the Volume Indirect render pass" +msgstr "Mostrar la passada de revelat de volum indirecte" + + +msgid "Show the Position render pass" +msgstr "Mostrar la passada de revelat d'ubicació" + + +msgid "Show the Normal render pass" +msgstr "Mostrar la passada de revelat de normal" + + +msgid "Show the UV render pass" +msgstr "Mostrar el passada de revelat d'UV" + + +msgid "Show the Mist render pass" +msgstr "Mostrar el passi de revelat de la boira" + + +msgid "Denoising Albedo" +msgstr "Desorollar amb Albedo" + + +msgid "Albedo pass used by denoiser" +msgstr "Pas d'albedo utilitzat per a desorollar" + + +msgid "Denoising Normal" +msgstr "Normal desorolladora" + + +msgid "Normal pass used by denoiser" +msgstr "Passada de normals usada pel desorollador" + + +msgid "Sample Count" +msgstr "Recompte de mostres" + + +msgid "Per-pixel number of samples" +msgstr "Nombre de mostres per píxel" + + +msgid "Show Active Pixels" +msgstr "Mostrar píxels actius" + + +msgid "When using adaptive sampling highlight pixels which are being sampled" +msgstr "[Show Active Pixels]: En usar mostreig adaptatiu, ressalta els píxels que s'estan mostrejant" + + +msgid "Object visibility for camera rays" +msgstr "Visibilitat d'objecte per als raigs de càmera" + + +msgid "Object visibility for diffuse reflection rays" +msgstr "Visibilitat de l'objecte per als rajos de reflexió difusiva" + + +msgid "Object visibility for glossy reflection rays" +msgstr "Visibilitat de l'objecte per als raigs de reflexos brillants" + + +msgid "Object visibility for volume scatter rays" +msgstr "Visibilitat de l'objecte per als raigs de dispersió de volum" + + +msgid "Object visibility for shadow rays" +msgstr "Visibilitat de l'objecte per als raigs d'ombra" + + +msgid "Object visibility for transmission rays" +msgstr "Visibilitat de l'objecte per als raigs de transmissió" + + +msgid "Maximum number of bounces the background light will contribute to the render" +msgstr "Nombre màxim de rebots que la llum de rerefons aportarà al revelat" + + +msgid "Map Resolution" +msgstr "Resolució de mapa" + + +msgid "Importance map size is resolution x resolution/2; higher values potentially produce less noise, at the cost of memory and speed" +msgstr "[Map Resolution]: La mida del mapa d'importància és la resolució x resolució/2; els valors més alts poden produir menys soroll, a costa de memòria i velocitat" + + +msgid "Sampling Method" +msgstr "Mètode de mostreig" + + +msgid "How to sample the background light" +msgstr "[Sampling Method]: Com mostrejar la llum de rerefons" + + +msgid "Don't sample the background, faster but might cause noise for non-solid backgrounds" +msgstr "No mostrejar el rerefons, més ràpid, però pot causar soroll amb rerefons no sòlids" + + +msgid "Automatically try to determine the best setting" +msgstr "Intentar determinar automàticament la millor configuració" + + +msgid "Manually set the resolution of the sampling map, higher values are slower and require more memory but reduce noise" +msgstr "Establir manualment la resolució del mapa de mostreig, els valors més alts són més lents i gasten més memòria, però redueixen el soroll" + + +msgid "Interpolation method to use for volumes" +msgstr "Mètode d'interpolació per als volums" + + +msgid "Distance between volume shader samples when rendering the volume (lower values give more accurate and detailed results, but also increased render time)" +msgstr "Distància entre les mostres d'aspecció de volum en revelar el volum (els valors més baixos donen resultats més precisos i detallats, però també major temps de revelat)" + + +msgid "Settings/info about a language" +msgstr "Configuració/informació d'una llengua" + + +msgid "MO File Path" +msgstr "Camí al document MO" + + +msgid "Path to the relevant mo file" +msgstr "Camí al document MO pertinent" + + +msgid "Language Name" +msgstr "Nom de l'idioma" + + +msgid "Language label (eg. \"French (Français)\")" +msgstr "Etiqueta d'idioma (p. ex. «Francès (Français)«)" + + +msgid "Numeric ID" +msgstr "ID numèric" + + +msgid "Numeric ID (read only!)" +msgstr "ID numèric (només de lectura!)" + + +msgid "PO File Path" +msgstr "Camí al document PO" + + +msgid "Path to the relevant po file in branches" +msgstr "Camí al document PO pertinent a «branches»" + + +msgid "PO Git Master File Path" +msgstr "Camí al document mestre de PO Git" + + +msgid "Path to the relevant po file in Blender's translations git repository" +msgstr "Camí al document PO corresponent al repositori git de traduccions del Blender" + + +msgid "PO Trunk File Path" +msgstr "Camí al document PO troncal" + + +msgid "Path to the relevant po file in trunk" +msgstr "Camí cap al document PO corresponent al «trunk»" + + +msgid "Language ID" +msgstr "ID d'idioma" + + +msgid "ISO code (eg. \"fr_FR\")" +msgstr "Codi ISO (p. ex. «fr_FR»)" + + +msgid "If this language should be used in the current operator" +msgstr "Si aquest idioma s'ha d'utilitzar en l'operador actual" + + +msgid "Active Language" +msgstr "Idioma actiu" + + +msgid "Index of active language in langs collection" +msgstr "Índex de l'idioma actiu a la col·lecció «langs»" + + +msgid "Whether these settings have already been auto-set or not" +msgstr "Si aquests paràmetres ja s'han establert automàticament o no" + + +msgid "Languages" +msgstr "Idiomes" + + +msgid "Languages to update in branches" +msgstr "[Languages]: Idiomes a actualitzar a «branches»" + + +msgid "POT File Path" +msgstr "Camí al document POT" + + +msgid "Path to the pot template file" +msgstr "Camí al document de plantilla pot" + + +msgid "Hide BBoxes" +msgstr "Ocultar Capses-C" + + +msgid "Hide the bounding boxes rendered for Matrix like items" +msgstr "Amaga les capses contenidores revelades per a elements semblants a matrius" + + +msgid "Scale factor" +msgstr "Factor d'escala" + + +msgid "Resize the Bounding Box and the coordinate lines for the display of Matrix items" +msgstr "Redimensiona la capsa contenidora i les línies de coordenades per a la visualització d'elements matricials" + + +msgid "Always In Front" +msgstr "Sempre al davant" + + +msgid "Draw Points and lines always in front" +msgstr "Dibuixa els punts i les línies sempre al davant" + + +msgid "Hide Names" +msgstr "Ocultar noms" + + +msgid "Hide the names of the rendered items" +msgstr "Amaga els noms dels elements revelats" + + +msgid "Python expression to be evaluated as the initial node setting" +msgstr "Expressió python per avaluar com a paràmetre inicial del node" + + +msgid "The amount of objects per unit on the line" +msgstr "La quantitat d'objectes per unitat en la línia" + + +msgid "Normal Offset" +msgstr "Desplaçament de normals" + + +msgid "Distance from the surface" +msgstr "Distància de la superfície" + + +msgid "Maximum distance of the objects to the line" +msgstr "Distància màxima dels objectes a la línia" + + +msgid "Random Scale Percentage" +msgstr "Percentatge d'escala aleatori" + + +msgid "Increase to get a larger range of sizes" +msgstr "Incrementar per a obtenir un rang més gran de mides" + + +msgid "Maximum rotation of the generated objects" +msgstr "Rotació màxima dels objectes generats" + + +msgid "Size of the generated objects" +msgstr "Mida dels objectes generats" + + +msgid "Change it to get a different scatter pattern" +msgstr "Canviar-ho per a obtenir un patró de dispersió diferent" + + +msgid "Use Normal Rotation" +msgstr "Usar rotació de normal" + + +msgid "Rotate the instances according to the surface normals" +msgstr "Fa girar les instàncies segons les normals de superfície" + + +msgid "Operator File List Element" +msgstr "Element de llista de documents d'operador" + + +msgid "Name of a file or directory within a file list" +msgstr "Nom d'un document o directori dins d'una llista de documents" + + +msgid "Operator Mouse Path" +msgstr "Camí del ratolí per a operadors" + + +msgid "Mouse path values for operators that record such paths" +msgstr "Valors del camí del ratolí per als operadors que enregistren aquests camins" + + +msgid "Time of mouse location" +msgstr "Hora de la ubicació del ratolí" + + +msgid "Operator Stroke Element" +msgstr "Element de traç per a operadors" + + +msgid "Is Stroke Start" +msgstr "És inici de traç" + + +msgid "Mouse Event" +msgstr "Esdeveniment de ratolí" + + +msgid "Tablet pressure" +msgstr "Pressió a tauleta" + + +msgid "Brush Size" +msgstr "Mida de pinzell" + + +msgid "Brush size in screen space" +msgstr "Mida del pinzell a l'espai de pantalla" + + +msgid "Tilt X" +msgstr "Inclinació X" + + +msgid "Tilt Y" +msgstr "Inclinació Y" + + +msgid "Implements the properties for the SVG exporter" +msgstr "Implementa les propietats de l'exportador SVG" + + +msgid "Line Join" +msgstr "Confluència de línies" + + +msgid "Miter" +msgstr "Mitra" + + +msgid "Corners are sharp" +msgstr "Les cantonades són agudes" + + +msgid "Corners are smoothed" +msgstr "Les cantonades estan suavitzades" + + +msgid "Corners are beveled" +msgstr "Les cantonades estan bisellades" + + +msgid "Export a single frame" +msgstr "Exportar un sol fotograma" + + +msgid "Export an animation" +msgstr "Exportar una animació" + + +msgid "Fill Contours" +msgstr "Emplenar contorns" + + +msgid "Fill the contour with the object's material color" +msgstr "Omple el contorn amb el color de material de l'objecte" + + +msgid "Split at Invisible" +msgstr "Dividir quan invisible" + + +msgid "Split the stroke at an invisible vertex" +msgstr "Divideix el traç on hi ha un vèrtex invisible" + + +msgid "SVG Export" +msgstr "Exportar SVG" + + +msgid "Export Freestyle edges to an .svg format" +msgstr "Exporta les vores de traç manual a un format .svg" + + +msgid "Format type to export to" +msgstr "Tipus de format al qual exportar" + + +msgid "OBJ" +msgstr "OBJ" + + +msgid "PLY" +msgstr "PLY" + + +msgid "STL" +msgstr "STL" + + +msgid "X3D" +msgstr "X3D" + + +msgid "Export Directory" +msgstr "Exportar directori" + + +msgid "Path to directory where the files are created" +msgstr "Camí al directori on es creen els documents" + + +msgid "Limit for checking zero area/length" +msgstr "Límit per comprovar l'àrea/llargada zero" + + +msgid "Face Areas" +msgstr "Àrees de cares" + + +msgid "Normalize normals proportional to face areas" +msgstr "Normalitza les normals proporcionalment a les àrees de cares" + + +msgid "Apply Scale" +msgstr "Aplicar escala" + + +msgid "Apply scene scale setting on export" +msgstr "En exportar, aplica la configuració d'escala d'escena" + + +msgid "Data Layers" +msgstr "Capes de dades" + + +msgid "Export normals, UVs, vertex colors and materials for formats that support it significantly increasing file size" +msgstr "[Data Layers]: Exporta les normals, UVs, colors dels vèrtexs i materials per als formats que ho suporten, augmentant significativament la mida del document" + + +msgid "Copy Textures" +msgstr "Copiar textures" + + +msgid "Copy textures on export to the output path" +msgstr "En exportar, copia les textures al camí d'egressió" + + +msgid "Selected UV Element" +msgstr "Element UV seleccionat" + + +msgid "Element Index" +msgstr "Índex d'elements" + + +msgid "Face Index" +msgstr "Índex de cares" + + +msgid "Base Pose Angle" +msgstr "Angle de posa base" + + +msgid "Base Pose Location" +msgstr "Ubicació del posa base" + + +msgid "Base Scale" +msgstr "Escala base" + + +msgid "Viewer reference scale associated with this landmark" +msgstr "Escala de referència del visor associada amb aquesta marca de terme" + + +msgid "VR Landmark" +msgstr "Marca de terme d'RV" + + +msgid "Scene Camera" +msgstr "Càmera d'escena" + + +msgid "Use scene's currently active camera to define the VR view base location and rotation" +msgstr "Utilitza la càmera activa de l'escena per definir la ubicació base i la rotació de la vista d'RV" + + +msgid "Use an existing object to define the VR view base location and rotation" +msgstr "Utilitza un objecte existent per definir la ubicació base i rotació de la vista d'RV" + + +msgid "Custom Pose" +msgstr "Posa personalitzada" + + +msgid "Allow a manually defined position and rotation to be used as the VR view base pose" +msgstr "Permet que s'utilitzi una posició i rotació manualment definides com a posa base de visualització d'RV" + + +msgid "ID Property" +msgstr "Propietat d'ID" + + +msgid "Property that stores arbitrary, user defined properties" +msgstr "Propietat que es guarda propietats arbitràries, definides per la usuària" + + +msgid "Region in a subdivided screen area" +msgstr "Regió en una àrea de pantalla dividida" + + +msgid "Alignment of the region within the area" +msgstr "Alineació de la regió dins de l'àrea" + + +msgid "Don't use any fixed alignment, fill available space" +msgstr "No usar cap alineació fixa, omplir l'espai disponible" + + +msgid "Horizontal Split" +msgstr "Dividir horitzontalment" + + +msgid "Vertical Split" +msgstr "Dividir verticalment" + + +msgid "Region floats on screen, doesn't use any fixed alignment" +msgstr "Flotants de regió en pantalla, no usa cap alineació fixa" + + +msgid "Quad Split" +msgstr "Dividir quadd" + + +msgid "Region is split horizontally and vertically" +msgstr "[Quad Split]: La regió es divideix horitzontalment i verticalment" + + +msgid "Region Data" +msgstr "Dades de regió" + + +msgid "Region specific data (the type depends on the region type)" +msgstr "Dades específiques de la regió (el tipus depèn del tipus de regió)" + + +msgid "Region height" +msgstr "Alçada de regió" + + +msgid "Type of this region" +msgstr "Tipus d'aquesta regió" + + +msgid "View2D" +msgstr "Vista 2D" + + +msgid "2D view of the region" +msgstr "Visualització 2D de la regió" + + +msgid "Region width" +msgstr "Amplada de regió" + + +msgid "The window relative vertical location of the region" +msgstr "La ubicació vertical relativa de la finestra de la regió" + + +msgid "The window relative horizontal location of the region" +msgstr "La ubicació horitzontal relativa de la finestra de la regió" + + +msgid "3D View Region" +msgstr "Regió de vista 3D" + + +msgid "3D View region data" +msgstr "Dades de visualització 3D de la regió" + + +msgid "Clip Planes" +msgstr "Segar plans" + + +msgid "Is Axis Aligned" +msgstr "És alineat a eix" + + +msgid "Is current view aligned to an axis (does not check the view is orthographic use \"is_perspective\" for that). Assignment sets the \"view_rotation\" to the closest axis aligned view" +msgstr "[Is Axis Aligned]: És la vista actual alineada a un eix. ( no es comprova que la vista sigui ortogràfica, usa «is perspective» per a això). L'assignació estableix el «view_rotation» a la visualització alineada més propera a l'eix" + + +msgid "Is Perspective" +msgstr "És perspectiva" + + +msgid "Lock view rotation of side views to Top/Front/Right" +msgstr "Bloqueja la rotació de visualitzacions laterals a Superior/Frontal/Dreta" + + +msgid "Perspective Matrix" +msgstr "Matriu de perspectiva" + + +msgid "Current perspective matrix (``window_matrix * view_matrix``)" +msgstr "Matriu de perspectiva actual (``window_matrix * view_matrix``)" msgid "Sync Zoom/Pan" msgstr "Sincronitzar zoom/escombratge" +msgid "Sync view position between side views" +msgstr "[Sync Zoom/Pan]: Sincronitza la posició de la visualització entre vistes laterals" + + +msgid "Clip Contents" +msgstr "[Clip Contents]: Segar contingut" + + +msgid "Clip view contents based on what is visible in other side views" +msgstr "Retalla el contingut visualitzat en base al que és visible en altres visualitzacions laterals" + + +msgid "Use Clip Planes" +msgstr "Usar plans de segat" + + +msgid "Camera Offset" +msgstr "Desplaçament de càmera" + + +msgid "View shift in camera view" +msgstr "Desplaçament de visualització en la visualització de càmera" + + +msgid "Camera Zoom" +msgstr "Zoom de càmera" + + +msgid "Zoom factor in camera view" +msgstr "Factor de zoom en la visualització de càmera" + + +msgid "Distance to the view location" +msgstr "Distància a la ubicació de visualització" + + +msgid "View Location" +msgstr "Visualitzar ubicació" + + +msgid "View pivot location" +msgstr "Visualitzar ubicació pivot" + + +msgid "View Matrix" +msgstr "Visualitzar matriu" + + +msgid "Current view matrix" +msgstr "Matriu de la visualització actual" + + +msgid "View Perspective" +msgstr "Visualitzar perspectiva" + + +msgid "View Rotation" +msgstr "Visualitzar rotació" + + +msgid "Rotation in quaternions (keep normalized)" +msgstr "Rotació en quaternions (mantenir normalitzada)" + + +msgid "Window Matrix" +msgstr "Matriu de finestra" + + +msgid "Current window matrix" +msgstr "Matriu de finestra actual" + + +msgid "View layer name" +msgstr "Mostrar nom de capa" + + +msgid "Render Ambient Occlusion in this Layer" +msgstr "Revelar oclusió ambiental en aquesta capa" + + +msgid "Render motion blur in this Layer, if enabled in the scene" +msgstr "Revelar difuminat de moviment en aquesta capa, si està habilitat en l'escena" + + +msgid "Deliver Ambient Occlusion pass" +msgstr "Fer passada d'oclusió ambiental" + + +msgid "Deliver full combined RGBA buffer" +msgstr "Fer memòria intermèdia RGBA de combinació completa" + + +msgid "Deliver diffuse color pass" +msgstr "Fer passada de difusió de color" + + +msgid "Deliver diffuse direct pass" +msgstr "Fer passada de difusió directa" + + +msgid "Deliver diffuse indirect pass" +msgstr "Fer passada de difusió indirecta" + + +msgid "Deliver emission pass" +msgstr "Fer passada emissiva" + + +msgid "Deliver environment lighting pass" +msgstr "Fer passada d'il·luminació d'entorn" + + +msgid "Deliver glossy color pass" +msgstr "Fer passada de color brillant" + + +msgid "Deliver glossy direct pass" +msgstr "Fer passada de brillant directe" + + +msgid "Deliver glossy indirect pass" +msgstr "Fer passada de brillant indirecte" + + +msgid "Deliver material index pass" +msgstr "Fer passada d'índex de material" + + +msgid "Deliver mist factor pass (0.0 to 1.0)" +msgstr "Fer passada de factor de boira (de 0,0 a 1,0)" + + +msgid "Deliver normal pass" +msgstr "Fer passada de normals" + + +msgctxt "Scene" +msgid "Object Index" +msgstr "Índex d'objecte" + + +msgid "Deliver object index pass" +msgstr "Fer passada d'índex d'objecte" + + +msgid "Deliver position pass" +msgstr "Fer passada d'ubicació" + + +msgid "Deliver shadow pass" +msgstr "Fer passada d'ombra" + + +msgid "Subsurface Color" +msgstr "Color de sotssuperfície" + + +msgid "Deliver subsurface color pass" +msgstr "Fer passada de color de sotssuperfície" + + +msgid "Subsurface Direct" +msgstr "Sotsuperfície directa" + + +msgid "Deliver subsurface direct pass" +msgstr "Fa passada de sotssuperfície directa" + + +msgid "Subsurface Indirect" +msgstr "Sotssuperfície indirecta" + + +msgid "Deliver subsurface indirect pass" +msgstr "Fer passada de sotssuperfície indirecta" + + +msgid "Deliver transmission color pass" +msgstr "Fer passada de transmissió de color" + + +msgid "Deliver transmission direct pass" +msgstr "Fer passada de transmissió directa" + + +msgid "Deliver transmission indirect pass" +msgstr "Fer passada de transmissió indirecta" + + +msgid "Deliver texture UV pass" +msgstr "Fer passada de textura UV" + + +msgid "Deliver speed vector pass" +msgstr "Fer passa el vector de rapidesa" + + +msgid "Deliver Z values pass" +msgstr "Fer passada de valors Z" + + +msgid "Sky" +msgstr "Cel" + + +msgid "Render Sky in this Layer" +msgstr "Revela el cel en aquesta capa" + + +msgid "Render Solid faces in this Layer" +msgstr "Revela cares sòlides en aquesta capa" + + +msgid "Strand" +msgstr "Fils" + + +msgid "Render Strands in this Layer" +msgstr "Revela fils en aquesta capa" + + +msgid "Render volumes in this Layer" +msgstr "Revelar volums en aquesta capa" + + +msgid "Render Passes" +msgstr "Passades de revelat" + + +msgid "Collection of render passes" +msgstr "Col·lecció de passades de revelat" + + +msgid "Result of rendering, including all layers and passes" +msgstr "Resultat del revelat, incloent-hi totes les capes i passades" + + +msgid "Rendering settings for a Scene data-block" +msgstr "Configuració de revelat per a un bloc de dades d'escena" + + +msgid "Bias" +msgstr "Biaix" + + +msgid "Bias towards faces further away from the object (in blender units)" +msgstr "Biaix cap a cares més llunyanes l'objecte (en unitats de blender)" + + +msgid "Algorithm to generate the margin" +msgstr "Algorisme per a generar el marge" + + +msgid "Number of samples used for ambient occlusion baking from multires" +msgstr "Nombre de mostres utilitzades per al precuinat de l'oclusió ambiental des del multires" + + +msgid "Choose shading information to bake into the image" +msgstr "Triar informació d'aspecció a precuinar en la imatge" + + +msgid "Bake normals" +msgstr "Precuinar normals" + + +msgid "Bake displacement" +msgstr "Precuinar desplaçament" + + +msgid "Instead of automatically normalizing to the range 0 to 1, apply a user scale to the derivative map" +msgstr "En lloc de normalitzar automàticament a l'interval 0 a 1, aplica una escala d'usuària al mapa derivatiu" + + +msgid "Region Maximum X" +msgstr "Màxim X de regió" + + +msgid "Maximum X value for the render region" +msgstr "Valor màxim X per a la regió de revelat" + + +msgid "Region Maximum Y" +msgstr "Màxim Y de regió" + + +msgid "Maximum Y value for the render region" +msgstr "Valor Y màxim per a la regió de revelat" + + +msgid "Region Minimum X" +msgstr "Mínim X de regió" + + +msgid "Minimum X value for the render region" +msgstr "Valor mínim X per a la regió de revelat" + + +msgid "Region Minimum Y" +msgstr "Mínim Y de regió" + + +msgid "Minimum Y value for the render region" +msgstr "Valor Y mínim per a la regió de revelat" + + +msgid "Dither Intensity" +msgstr "Intensitat de variació" + + +msgid "Amount of dithering noise added to the rendered image to break up banding" +msgstr "Quantitat de soroll de variació afegit a la imatge revelada per trencar l'efecte faixa" + + +msgid "Engine" +msgstr "Motor" + + +msgid "Engine to use for rendering" +msgstr "Motor per a revelar" + + +msgid "The file extension used for saving renders" +msgstr "Extensió dels documents en què es desen els revelats" + + +msgid "Directory/name to save animations, # characters defines the position and length of frame numbers" +msgstr "Directori/nom per a desar les animacions, # caràcters defineix la posició i la longitud dels números de fotograma" + + +msgid "World background is transparent, for compositing the render over another background" +msgstr "El rerefons del món és transparent, per a confegir el revelat sobre un altre rerefons" + + +msgid "Width over which the reconstruction filter combines samples" +msgstr "Amplada sobre la qual el filtre de reconstrucció combina mostres" + + +msgid "FPS" +msgstr "FPS" + + +msgid "Framerate, expressed in frames per second" +msgstr "Taxa de fotogrames, expressada en fotogrames per segon" + + +msgid "FPS Base" +msgstr "FPS Base" + + +msgid "Framerate base" +msgstr "Base de la taxa de fotogrames" + + +msgid "Frame Map New" +msgstr "Mapa de fotogrames nou" + + +msgid "How many frames the Map Old will last" +msgstr "Quants fotogrames durarà el mapa antic" + + +msgid "Frame Map Old" +msgstr "Mapa de fotogrames antic" + + +msgid "Old mapping value in frames" +msgstr "Valor de mapejat antic en fotogrames" + + +msgid "Additional Subdivision" +msgstr "Subdivisió addicional" + + +msgid "Additional subdivision along the curves" +msgstr "Subdivisió addicional seguint les corbes" + + +msgctxt "Curves" +msgid "Curves Shape Type" +msgstr "Tipus de forma de corbes" + + +msgid "Curves shape type" +msgstr "Tipus de forma de les corbes" + + +msgctxt "Curves" +msgid "Strand" +msgstr "Fil" + + +msgctxt "Curves" +msgid "Strip" +msgstr "Segment" + + +msgid "Multiple Engines" +msgstr "Motors múltiples" + + +msgid "More than one rendering engine is available" +msgstr "Hi ha disponible més d'un motor de revelat" + + +msgid "Movie Format" +msgstr "Format de pel·lícula" + + +msgid "When true the format is a movie" +msgstr "Quan és ver, el format és una pel·lícula" + + +msgid "Line thickness in pixels" +msgstr "Gruix de línia en píxels" + + +msgid "Line Thickness Mode" +msgstr "Mode gruix de línia" + + +msgid "Line thickness mode for Freestyle line drawing" +msgstr "Mode de gruix de línia per al dibuix de línies d'estil manual" + + +msgid "Specify unit line thickness in pixels" +msgstr "Especificar la unitat de gruix de línia en píxels" + + +msgid "Unit line thickness is scaled by the proportion of the present vertical image resolution to 480 pixels" +msgstr "La unitat del gruix de línia s'escala per la proporció de la present resolució vertical de la imatge a 480 píxels" + + +msgid "Metadata Input" +msgstr "Ingressió de metadades" + + +msgid "Where to take the metadata from" +msgstr "D'on agafar les metadades" + + +msgid "Use metadata from the current scene" +msgstr "Usar metadades de l'escena actual" + + +msgid "Sequencer Strips" +msgstr "Segments del seqüenciador" + + +msgid "Use metadata from the strips in the sequencer" +msgstr "Usa les metadades dels segments del seqüenciador" + + +msgid "Time taken in frames between shutter open and close" +msgstr "Temps que es triga en fotogrames entre l'obrir i tancar de l'obturador" + + +msgid "Curve defining the shutter's openness over time" +msgstr "Corba que defineix l'obertura de l'obturador en el temps" + + +msgid "Pixel Aspect X" +msgstr "Aspecte de píxel X" + + +msgid "Horizontal aspect ratio - for anamorphic or non-square pixel output" +msgstr "Relació d'aspecte horitzontal - per a l'egressió de píxels anamòrfics o no quadrats" + + +msgid "Pixel Aspect Y" +msgstr "Aspecte de píxel Y" + + +msgid "Vertical aspect ratio - for anamorphic or non-square pixel output" +msgstr "Relació d'aspecte vertical - per a l'egressió de píxels anamòrfics o no quadrats" + + +msgid "Render Region" +msgstr "Revelar regió" + + +msgid "Apply blur to each jittered sample to reduce under-sampling artifacts" +msgstr "Aplica el difuminat a cada mostra dispersada per reduir els tares de sotamostreig" + + +msgid "Take more samples during cubemap filtering to remove artifacts" +msgstr "Pren més mostres durant el filtratge del cubemap per eliminar tares" + + msgid "Frames per second" msgstr "Fotogrames/segon" @@ -85514,6 +90407,11 @@ msgid "Zoom Region..." msgstr "Zoom de regió..." +msgctxt "Operator" +msgid "Render Region..." +msgstr "Revelar regió..." + + msgctxt "Operator" msgid "Cube" msgstr "Cube" @@ -86453,6 +91351,10 @@ msgid "Boid" msgstr "Floc" +msgid "Constructive modifier cannot be applied to multi-res data in sculpt mode" +msgstr "El modificador constructiu no es pot aplicar a les dades multires en el mode escultura" + + msgid "If the profile spline is cyclic, fill the ends of the generated mesh with N-gons" msgstr "Si el spline del perfil és cíclic, ompliu els extrems de la malla generada amb N-gons" diff --git a/locale/po/cs.po b/locale/po/cs.po index 27e02909827..4116a5ac3c7 100644 --- a/locale/po/cs.po +++ b/locale/po/cs.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: \n" "Last-Translator: Martin Tabačan \n" "Language-Team: Taby \n" @@ -14385,6 +14385,10 @@ msgid "Weight of feather point" msgstr "Váha této vazby" +msgid "Active Point" +msgstr "Aktivní bod" + + msgid "Alignment" msgstr "Zarovnaný" @@ -23901,19 +23905,11 @@ msgid "Clear Restrict View" msgstr "Obnovit pohled" -msgid "Reveal the layer by setting the hide flag" -msgstr "Ukáže objekt dle nastavení skrývající vazby" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Obnovit pohled" -msgid "Hide the layer by setting the hide flag" -msgstr "Skryje objekt dle nastavení skrývající vazby" - - msgctxt "Operator" msgid "Move Layer" msgstr "Přesunout do vrstvy" @@ -32915,10 +32911,6 @@ msgid "2D Cursor" msgstr "2D Kursor" -msgid "Active Point" -msgstr "Aktivní bod" - - msgid "Predefined tracking camera intrinsics" msgstr "Předdefinovaná vnitřní nastavení tracking kamery" @@ -35408,10 +35400,6 @@ msgid "Mini Axes Size" msgstr "Osa Zrcadlení" -msgid "Simple Axis" -msgstr "Jednoduchá Osa" - - msgid "Interactive Navigation" msgstr "Interaktivní Navigace" @@ -43645,10 +43633,6 @@ msgid "View Name" msgstr "Zobrazit Název" -msgid "3D Viewport Axis" -msgstr "Osy 3D Pohledu" - - msgid "Smooth Wires" msgstr "Hladké Dráty" diff --git a/locale/po/de.po b/locale/po/de.po index 0d1053546c4..de8012221fb 100644 --- a/locale/po/de.po +++ b/locale/po/de.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: \n" "Last-Translator: Martin Reininger \n" "Language-Team: German translation team\n" @@ -20560,6 +20560,10 @@ msgid "Active spline of masking layer" msgstr "Aktiver Spline der Maskierungsebene" +msgid "Active Point" +msgstr "Aktive Punkte" + + msgid "Grease Pencil Color" msgstr "Wachsstift-Farbe" @@ -43123,10 +43127,6 @@ msgid "2D Cursor" msgstr "2D Cursor" -msgid "Active Point" -msgstr "Aktive Punkte" - - msgid "Footage Settings" msgstr "Filmmaterial-Einstellungen" @@ -46324,10 +46324,6 @@ msgid "Mini Axes Type" msgstr "Mini Achsentyp" -msgid "Simple Axis" -msgstr "Einfache Achse" - - msgid "Pie menu size in pixels" msgstr "Kreismenügröße in Pixel" @@ -58755,10 +58751,6 @@ msgid "View Name" msgstr "Ansichtnamen" -msgid "3D Viewport Axis" -msgstr "3D Viewport Achsen" - - msgid "Smooth Wires" msgstr "Weichet Draht" diff --git a/locale/po/es.po b/locale/po/es.po index b9e77f72d79..885a04ff06b 100644 --- a/locale/po/es.po +++ b/locale/po/es.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: \n" "Last-Translator: Gabriel Gazzán \n" "Language-Team: Español \n" @@ -33447,6 +33447,10 @@ msgid "Active spline of masking layer" msgstr "Curva activa de la capa de máscara" +msgid "Active Point" +msgstr "Punto activo" + + msgid "Grease Pencil Color" msgstr "Color del lápiz de cera" @@ -44381,10 +44385,6 @@ msgid "Is Face Planar" msgstr "Es cara plana" -msgid "Retrieve whether all triangles in a face are on the same plane, i.e. whether have the same normal" -msgstr "Proporciona información acerca de si todos los triángulos de una cara se encuentran sobre un mismo plano o, lo que es lo mismo, si tienen normales idénticas" - - msgid "Face Neighbors" msgstr "Cercanos a la cara" @@ -59451,19 +59451,11 @@ msgid "Clear Restrict View" msgstr "Eliminar restricción visibilidad" -msgid "Reveal the layer by setting the hide flag" -msgstr "Revela la capa, restableciendo su indicador de ocultamiento" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Impedir visibilidad" -msgid "Hide the layer by setting the hide flag" -msgstr "Oculta la capa, activando su indicador de ocultamiento" - - msgctxt "Operator" msgid "Move Layer" msgstr "Mover capa" @@ -81106,10 +81098,6 @@ msgid "2D Cursor" msgstr "Cursor 2D" -msgid "Active Point" -msgstr "Punto activo" - - msgid "Predefined tracking camera intrinsics" msgstr "Ajustes predefinidos de cámara para el rastreo" @@ -86097,14 +86085,6 @@ msgid "Mini Axes Type" msgstr "Tipo de mini ejes" -msgid "Show a small rotating 3D axes in the top right corner of the 3D viewport" -msgstr "Muestra pequeños ejes 3D rotatorios en la esquina superior derecha de la vista 3D" - - -msgid "Simple Axis" -msgstr "Ejes simples" - - msgid "Interactive Navigation" msgstr "Navegación interactiva" @@ -110010,10 +109990,6 @@ msgid "Playback Frame Rate (FPS)" msgstr "Velocidad de reproducción (fps)" -msgid "3D Viewport Axis" -msgstr "Ejes de vista 3D" - - msgid "Smooth Wires" msgstr "Suavizar estructura" diff --git a/locale/po/eu.po b/locale/po/eu.po index 4cd37cd95df..4f92df33579 100644 --- a/locale/po/eu.po +++ b/locale/po/eu.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Ainhize & Miriam \n" "Language-Team: Euskara \n" diff --git a/locale/po/fa.po b/locale/po/fa.po index 8181d8021ea..cf639c521a7 100644 --- a/locale/po/fa.po +++ b/locale/po/fa.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2012-10-31 17:00-0800\n" "Last-Translator: Amin Babaeipanah \n" "Language-Team: LeoMoon Studios \n" diff --git a/locale/po/fi.po b/locale/po/fi.po index 639dc18cd4f..51f4a4b1a15 100644 --- a/locale/po/fi.po +++ b/locale/po/fi.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -8550,10 +8550,6 @@ msgid "View Name" msgstr "Katso nimeä" -msgid "3D Viewport Axis" -msgstr "3D-näkymän akselit" - - msgid "Limit Size" msgstr "Rajoita kokoa" diff --git a/locale/po/fr.po b/locale/po/fr.po index 31281e4bab7..3eec0cd8727 100644 --- a/locale/po/fr.po +++ b/locale/po/fr.po @@ -1,10 +1,10 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" -"PO-Revision-Date: 2023-03-12 17:34+0100\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" +"PO-Revision-Date: 2023-03-15 23:26+0100\n" "Last-Translator: Damien Picard (pioverfour) \n" "Language-Team: French https://wiki.blender.org/wiki/Process/Translate_Blender/French_Team\n" "Language: fr\n" @@ -1110,6 +1110,10 @@ msgid "Copyright" msgstr "Copyright" +msgid "Copyright notice for this asset. An empty copyright notice does not necessarily indicate that this is copyright-free. Contact the author if any clarification is needed" +msgstr "Avis de droit d’auteur pour cet asset. Un champ vide ne signifie pas forcément que l’asset n’est soumis à aucun droit d’auteur. Contacter l’auteur pour obtenir toute clarification nécessaire" + + msgid "Description" msgstr "Description" @@ -1118,6 +1122,14 @@ msgid "A description of the asset to be displayed for the user" msgstr "Une description de l’asset affichée à l’utilisateur" +msgid "License" +msgstr "Licence" + + +msgid "The type of license this asset is distributed under. An empty license name does not necessarily indicate that this is free of licensing terms. Contact the author if any clarification is needed" +msgstr "Le type de licence selon laquelle cet asset est distribué. Un champ vide ne signifie pas forcément que l’asset n’est soumis à aucune condition. Contacter l’auteur pour obtenir toute clarification nécessaire" + + msgid "Tags" msgstr "Étiquettes" @@ -13701,6 +13713,11 @@ msgid "Minimum number of particles per cell (ensures that each cell has at least msgstr "Nombre minimum de particules par cellules (garantit que chaque cellule a au moins cette quantité de particules)" +msgctxt "Amount" +msgid "Number" +msgstr "Nombre" + + msgid "Particle number factor (higher value results in more particles)" msgstr "Facteur de nombre de particules (des valeurs plus élevées donnent plus de particules)" @@ -19542,6 +19559,61 @@ msgid "Editable falloff curve" msgstr "Courbe d’atténuation éditable" +msgctxt "Curves" +msgid "Curve Preset" +msgstr "Préréglage de courbe" + + +msgctxt "Curves" +msgid "Custom" +msgstr "Personnalisée" + + +msgctxt "Curves" +msgid "Smooth" +msgstr "Douce" + + +msgctxt "Curves" +msgid "Smoother" +msgstr "Plus douce" + + +msgctxt "Curves" +msgid "Sphere" +msgstr "Sphère" + + +msgctxt "Curves" +msgid "Root" +msgstr "Racine carrée" + + +msgctxt "Curves" +msgid "Sharp" +msgstr "Dure" + + +msgctxt "Curves" +msgid "Linear" +msgstr "Linéaire" + + +msgctxt "Curves" +msgid "Sharper" +msgstr "Plus dure" + + +msgctxt "Curves" +msgid "Inverse Square" +msgstr "Quadratique inverse" + + +msgctxt "Curves" +msgid "Constant" +msgstr "Constante" + + msgid "Curves Sculpt Settings" msgstr "Réglages de peinture de courbes" @@ -20986,10 +21058,25 @@ msgid "Name of the Alembic attribute used for generating motion blur data" msgstr "Nom de l’attribut Alembic utilisé pour générer les données de flou cinétique" +msgctxt "Unit" +msgid "Velocity Unit" +msgstr "Unité de vélocité" + + msgid "Define how the velocity vectors are interpreted with regard to time, 'frame' means the delta time is 1 frame, 'second' means the delta time is 1 / FPS" msgstr "Définir comment les vecteurs vélocité sont interprétés par rapport au temps, « frame » signifie que le différentiel de temps est de 1 image, « seconde » que le différentiel de temps est de 1 / FPS" +msgctxt "Unit" +msgid "Second" +msgstr "Seconde" + + +msgctxt "Unit" +msgid "Frame" +msgstr "Frame" + + msgid "Camera data-block for storing camera settings" msgstr "Bloc de données caméra pour stocker les réglages de caméra" @@ -26934,7 +27021,7 @@ msgstr "Afficher la santé des boids" msgid "Number" -msgstr "Numéro/Nombre" +msgstr "Numéro" msgid "Show particle number" @@ -28012,6 +28099,11 @@ msgid "Text file on disk is different than the one in memory" msgstr "Le fichier texte sur le disque est différent de celui en mémoire" +msgctxt "Text" +msgid "Lines" +msgstr "Lignes" + + msgid "Lines of text" msgstr "Lignes de texte" @@ -33507,6 +33599,10 @@ msgid "Active spline of masking layer" msgstr "Courbe active du calque de masque" +msgid "Active Point" +msgstr "Point actif" + + msgid "Grease Pencil Color" msgstr "Couleur de crayon gras" @@ -34044,6 +34140,11 @@ msgid "Write" msgstr "Écriture" +msgctxt "NodeTree" +msgid "Constant" +msgstr "Constante" + + msgid "Instances" msgstr "Instances" @@ -41482,11 +41583,11 @@ msgstr "Nombre de lames" msgid "Rounding" -msgstr "Arrondis" +msgstr "Arrondi" msgid "Level of rounding of the bokeh" -msgstr "Niveau d’arrondis du bokeh" +msgstr "Niveau d’arrondi du bokeh" msgid "Lens Shift" @@ -44659,10 +44760,6 @@ msgid "Is Face Planar" msgstr "La face est plane" -msgid "Retrieve whether all triangles in a face are on the same plane, i.e. whether have the same normal" -msgstr "Savoir si tous les triangles d’une face sont sur le même plan, c-à-d s’ils ont la même normale" - - msgid "Face Neighbors" msgstr "Voisins de face" @@ -47694,11 +47791,11 @@ msgstr "Sous-chemin utilisé pour cet emplacement" msgid "Save as Render" -msgstr "Enregistrer rendu sous" +msgstr "Enregistrer comme rendu" msgid "Apply render part of display transform when saving byte image" -msgstr "Appliquer la partie rendu des transformations d’affichage à l’enregistrement binaire de l’image" +msgstr "Appliquer la partie rendu des transformations d’affichage à l’enregistrement d’une image 8-bits" msgid "Use Node Format" @@ -50162,7 +50259,7 @@ msgstr "Annule la dernière modification des catalogues d’assets" msgctxt "Operator" msgid "Store undo snapshot for asset catalog edits" -msgstr "Enregistrer instantané d’annulation pour les modifications des catalogues d’assets" +msgstr "Enregistrer un instantané d’annulation pour les modifications des catalogues d’assets" msgid "Store the current state of the asset catalogs in the undo buffer" @@ -50171,11 +50268,11 @@ msgstr "Enregistrer l’état actuel des catalogues d’assets dans le tampon d msgctxt "Operator" msgid "Save Asset Catalogs" -msgstr "Enregistrer catalogues d’assets" +msgstr "Enregistrer les catalogues d’assets" msgid "Make any edits to any catalogs permanent by writing the current set up to the asset library" -msgstr "Rendre toutes les modifications de catalogues permanentes en enregistrant l’état actuel dans la bibliothèque d’assets" +msgstr "Rendre permanentes toutes les modifications de catalogues en enregistrant l’état actuel dans la bibliothèque d’assets" msgctxt "Operator" @@ -53510,7 +53607,7 @@ msgstr "Exporter STL" msgid "Save STL triangle mesh data" -msgstr "Enregistrer données de maillage triangulé STL" +msgstr "Enregistrer des données de maillage triangulé STL" msgid "Ascii" @@ -54176,7 +54273,7 @@ msgstr "Format JPEG (.jpg)" msgid "Save images as JPEGs. (Images that need alpha are saved as PNGs though.) Be aware of a possible loss in quality" -msgstr "Enregistrer des images en JPEG. (Les images qui ont besoin d’alpha sont quand même enregistrées en PNG.) Attention : une perte de qualité est possible" +msgstr "Enregistrer les images en JPEG. (Les images qui ont besoin d’alpha sont quand même enregistrées en PNG.) Attention : une perte de qualité est possible" msgid "Don't export images" @@ -57063,7 +57160,7 @@ msgstr "Inverser la sélection existante" msgid "Intersect existing selection" -msgstr "Intersecter la sélection actuelle" +msgstr "Intersecter avec la sélection existante" msgid "Select Grease Pencil strokes using brush selection" @@ -58761,7 +58858,7 @@ msgstr "Début Y" msgctxt "Operator" msgid "Save Image" -msgstr "Enregistrer image" +msgstr "Enregistrer l’image" msgid "Save the image with current name and settings" @@ -58779,7 +58876,7 @@ msgstr "Enregistrer toutes les images modifiées" msgctxt "Operator" msgid "Save As Image" -msgstr "Enregistrer image sous" +msgstr "Enregistrer l’image sous" msgid "Save the image with another name and/or settings" @@ -58791,7 +58888,7 @@ msgstr "Créer un nouveau fichier image, sans modifier l’image actuelle dans b msgid "Save As Render" -msgstr "Enregistrer rendu sous" +msgstr "Enregistrer comme rendu" msgid "" @@ -59918,19 +60015,11 @@ msgid "Clear Restrict View" msgstr "Annuler cacher dans la vue" -msgid "Reveal the layer by setting the hide flag" -msgstr "Afficher les calques de masque temporairement cachés" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Définir cacher dans la vue" -msgid "Hide the layer by setting the hide flag" -msgstr "Cacher temporairement les calques de masque" - - msgctxt "Operator" msgid "Move Layer" msgstr "Déplacer calque" @@ -60285,11 +60374,11 @@ msgstr "Biseauter" msgid "Cut into selected items at an angle to create bevel or chamfer" -msgstr "Couper dans l’élément sélectionné selon un angle, afin de créer un biseau ou un chanfrein" +msgstr "Couper les éléments sélectionnés en biais, afin de créer un biseau ou un chanfrein" msgid "Do not allow beveled edges/vertices to overlap each other" -msgstr "Interdire aux arêtes/sommets biseautés de se recouvrir mutuellement" +msgstr "Interdire aux arêtes/sommets biseautés de se chevaucher" msgid "Face Strength Mode" @@ -70754,11 +70843,11 @@ msgstr "Installer éclairages studio personnalisés" msgctxt "Operator" msgid "Save Custom Studio Light" -msgstr "Enregistrer éclairages studio personnalisés" +msgstr "Enregistrer les éclairages studio personnalisés" msgid "Save custom studio light from the studio light editor settings" -msgstr "Enregistrer éclairages studio personnalisés depuis les réglages de l’éditeur d’éclairage studio" +msgstr "Enregistrer les éclairages studio personnalisés depuis les réglages de l’éditeur d’éclairage studio" msgid "Show light preferences" @@ -70928,7 +71017,7 @@ msgstr "Utiliser la vue 3D actuelle pour le rendu, sinon utiliser les réglages msgid "Write Image" -msgstr "Enregistrer image" +msgstr "Enregistrer l’image" msgid "Save rendered the image to the output path (used only when animation is disabled)" @@ -72084,7 +72173,7 @@ msgstr "Alterner entre les dispositions d’écran disponibles" msgctxt "Operator" msgid "Save Screenshot" -msgstr "Enregistrer capture d’écran" +msgstr "Enregistrer une capture d’écran" msgid "Capture a picture of the whole Blender window" @@ -72093,7 +72182,7 @@ msgstr "Capturer une image de toute la fenêtre Blender" msgctxt "Operator" msgid "Save Screenshot (Editor)" -msgstr "Enregistrer capture d’écran (éditeur)" +msgstr "Enregistrer une capture d’écran (éditeur)" msgid "Capture a picture of an editor" @@ -79547,7 +79636,7 @@ msgstr "Lier" msgid "Link from a Library .blend file" -msgstr "Lier depuis autre fichier .blend bibliothèque" +msgstr "Lier depuis un autre fichier .blend bibliothèque" msgctxt "Operator" @@ -80278,7 +80367,7 @@ msgstr "Charger les réglages d’usine" msgid "Load factory default startup file and preferences. To make changes permanent, use \"Save Startup File\" and \"Save Preferences\"" -msgstr "Charger le fichier de démarrage et les préférences d’usine par défaut. Pour rendre les changements permanents, utiliser « Enregistrer fichier de démarrage » et « Enregistrer préférences »" +msgstr "Charger le fichier de démarrage et les préférences d’usine par défaut. Pour rendre les changements permanents, utiliser « Enregistrer le fichier de démarrage » et « Enregistrer préférences »" msgid "Factory Startup App-Template Only" @@ -80300,7 +80389,7 @@ msgstr "Recharger le fichier d’historique" msgid "Reloads history and bookmarks" -msgstr "Recharge l’historique et les signets" +msgstr "Recharger l’historique et les signets" msgctxt "Operator" @@ -80309,7 +80398,7 @@ msgstr "Recharger le fichier de démarrage" msgid "Open the default file (doesn't save the current file)" -msgstr "Ouvre le fichier par défaut (ne sauvegarde pas le fichier en cours)" +msgstr "Ouvrir le fichier par défaut (ne pas sauvegarder le fichier en cours)" msgid "Path to an alternative start-up file" @@ -80326,7 +80415,7 @@ msgstr "Démarrage d’usine" msgctxt "Operator" msgid "Load Preferences" -msgstr "Charger préférences" +msgstr "Charger les préférences" msgid "Load last saved preferences" @@ -80335,20 +80424,20 @@ msgstr "Charger les dernières préférences enregistrées" msgctxt "Operator" msgid "Recover Auto Save" -msgstr "Récupérer sauvegarde auto" +msgstr "Récupérer une sauvegarde auto" msgid "Open an automatically saved file to recover it" -msgstr "Ouvre un fichier automatiquement sauvegardé" +msgstr "Ouvrir un fichier sauvegardé automatiquement" msgctxt "Operator" msgid "Recover Last Session" -msgstr "Récupérer dernière session" +msgstr "Récupérer la dernière session" msgid "Open the last closed file (\"quit.blend\")" -msgstr "Ouvre la sauvegarde effectuée à la fermeture (« quit.blend »)" +msgstr "Ouvrir la sauvegarde effectuée à la fermeture (« quit.blend »)" msgctxt "Operator" @@ -80446,7 +80535,7 @@ msgstr "Écrire un fichier .blend compressé" msgid "Save Copy" -msgstr "Enregistrer copie" +msgstr "Enregistrer une copie" msgid "Save a copy of the actual working state but does not make saved file active" @@ -80463,7 +80552,7 @@ msgstr "Actualiser les chemins relatifs lors d’un enregistrement dans un autre msgctxt "Operator" msgid "Save Startup File" -msgstr "Enregistrer fichier de démarrage" +msgstr "Enregistrer le fichier de démarrage" msgid "Make the current file the default .blend file" @@ -80472,7 +80561,7 @@ msgstr "Faire du fichier actuel le fichier .blend par défaut" msgctxt "Operator" msgid "Save Blender File" -msgstr "Enregistrer fichier Blender" +msgstr "Enregistrer le fichier Blender" msgid "Save the current Blender file" @@ -80485,7 +80574,7 @@ msgstr "Quitter Blender après avoir enregistré" msgctxt "Operator" msgid "Save Preferences" -msgstr "Enregistrer préférences" +msgstr "Enregistrer les préférences" msgid "Make the current preferences default" @@ -80639,7 +80728,7 @@ msgstr "Valider et corriger les maillages importés (lent)" msgctxt "Operator" msgid "Save System Info" -msgstr "Enregistrer infos système" +msgstr "Enregistrer les infos système" msgid "Generate system information, saved into a text file" @@ -81987,10 +82076,6 @@ msgid "2D Cursor" msgstr "Curseur 2D" -msgid "Active Point" -msgstr "Point actif" - - msgid "Predefined tracking camera intrinsics" msgstr "« Intrinsèques » de caméra de suivi prédéfinis" @@ -83009,7 +83094,7 @@ msgstr "Paramètres de souris 3D" msgid "Save Preferences" -msgstr "Enregistrer préférences" +msgstr "Enregistrer les préférences" msgid "Auto Run Python Scripts" @@ -85800,11 +85885,11 @@ msgstr "Le répertoire par défaut de sortie des rendus, pour les nouvelles scè msgid "Save Versions" -msgstr "Enregistrer versions" +msgstr "Versions de sauvegarde" msgid "The number of old versions to maintain in the current directory, when manually saving" -msgstr "Nombre de précédentes versions à maintenir dans le dossier actuel,lors d’une sauvegarde manuelle" +msgstr "Nombre de précédentes versions à garder dans le dossier actuel, lors d’une sauvegarde manuelle" msgid "Python Scripts Directory" @@ -87051,14 +87136,6 @@ msgid "Mini Axes Type" msgstr "Type des mini axes" -msgid "Show a small rotating 3D axes in the top right corner of the 3D viewport" -msgstr "Afficher des petits axes 3D tournants dans le coin supérieur droit de la vue 3D" - - -msgid "Simple Axis" -msgstr "Axes simples" - - msgid "Interactive Navigation" msgstr "Navigation interactive" @@ -90064,10 +90141,25 @@ msgid "Additional subdivision along the curves" msgstr "Subdivision supplémentaire le long des courbes" +msgctxt "Curves" +msgid "Curves Shape Type" +msgstr "Type de forme des courbes" + + msgid "Curves shape type" msgstr "Type de forme des courbes" +msgctxt "Curves" +msgid "Strand" +msgstr "Fibre" + + +msgctxt "Curves" +msgid "Strip" +msgstr "Bande" + + msgid "Multiple Engines" msgstr "Plusieurs moteurs" @@ -106349,6 +106441,10 @@ msgid "Previews clear process failed for file '%s'!" msgstr "Le processus de nettoyage des prévisualisations a échoué pour le fichier « %s »" +msgid "No active camera in the scene" +msgstr "Aucune caméra active dans la scène" + + msgid "Unexpected modifier type: " msgstr "Type de modificateur inattendu : " @@ -111128,7 +111224,7 @@ msgstr "Revenir au précédent" msgctxt "Operator" msgid "Save Copy..." -msgstr "Enregistrer copie…" +msgstr "Enregistrer une copie…" msgctxt "Operator" @@ -111425,10 +111521,6 @@ msgid "Playback Frame Rate (FPS)" msgstr "Framerate durant la lecture (FPS)" -msgid "3D Viewport Axis" -msgstr "Axes de la vue 3D" - - msgid "Smooth Wires" msgstr "Adoucir filaire" @@ -111692,7 +111784,7 @@ msgstr "Caméra" msgctxt "Operator" msgid "Orbit Opposite" -msgstr "Orbiter en sens opposé" +msgstr "Orbiter de l’autre côté" msgctxt "Operator" @@ -116417,6 +116509,10 @@ msgid "Error evaluating number, see Info editor for details" msgstr "Erreur lors de l’évaluation du nombre, voir l’éditeur infos pour plus de détails" +msgid "Press a key" +msgstr "Appuyer sur une touche" + + msgid "Missing Panel: %s" msgstr "Panneau manquant : %s" @@ -119600,7 +119696,7 @@ msgstr "Impossible de créer un tampon OpenGL hors-écran : %s" msgid "Missing%s%s%s%s detected!" -msgstr "%s%s%s%s manquant détecté !" +msgstr "%s%s%s%s manquants détectés !" msgid "Active group is locked, aborting" @@ -123703,6 +123799,31 @@ msgid "UNDEFINED" msgstr "INDÉFINI" +msgctxt "NodeTree" +msgid "Functions" +msgstr "Fonctions" + + +msgctxt "NodeTree" +msgid "Comparison" +msgstr "Comparaison" + + +msgctxt "NodeTree" +msgid "Rounding" +msgstr "Arrondi" + + +msgctxt "NodeTree" +msgid "Trigonometric" +msgstr "Trigonométrie" + + +msgctxt "NodeTree" +msgid "Conversion" +msgstr "Conversion" + + msgid "Same input/output direction of sockets" msgstr "Même direction d’entrée/sortie des prises" diff --git a/locale/po/ha.po b/locale/po/ha.po index e0442f3f2bf..c12f8d73bd6 100644 --- a/locale/po/ha.po +++ b/locale/po/ha.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2017-12-25 14:01+0100\n" "Last-Translator: UMAR HARUNA ABDULLAHI \n" "Language-Team: BlenderNigeria \n" diff --git a/locale/po/he.po b/locale/po/he.po index 424f42927aa..b1539f79e61 100644 --- a/locale/po/he.po +++ b/locale/po/he.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2012-10-07 13:56+0300\n" "Last-Translator: Barak Itkin \n" "Language-Team: LANGUAGE \n" diff --git a/locale/po/hi.po b/locale/po/hi.po index ea25519b0ca..2f57a52a1c1 100644 --- a/locale/po/hi.po +++ b/locale/po/hi.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2015-03-03 16:21+0530\n" "Last-Translator: Roshan Lal Gumasta \n" "Language-Team: Hindi \n" diff --git a/locale/po/hu.po b/locale/po/hu.po index 538df7249b8..66eae43a249 100644 --- a/locale/po/hu.po +++ b/locale/po/hu.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2015-02-21 19:17+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -13,9 +13,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.7.4\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -25,9 +25,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -37,9 +37,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -49,9 +49,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -61,9 +61,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -73,9 +73,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -85,9 +85,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -97,9 +97,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -109,9 +109,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -121,9 +121,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -133,9 +133,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -145,9 +145,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -157,9 +157,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -169,9 +169,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -181,9 +181,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -193,9 +193,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -205,9 +205,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -217,9 +217,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -229,9 +229,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -241,9 +241,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -253,9 +253,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -265,9 +265,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -277,9 +277,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -289,9 +289,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -301,9 +301,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -313,9 +313,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -325,9 +325,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -337,9 +337,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -349,9 +349,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -361,9 +361,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-12-27 18:52+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -373,9 +373,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.7.1\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -385,9 +385,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -397,9 +397,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -409,9 +409,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -421,9 +421,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -433,9 +433,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -445,9 +445,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -457,9 +457,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -469,9 +469,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -481,9 +481,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -493,9 +493,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -505,9 +505,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -517,9 +517,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -529,9 +529,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -541,9 +541,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -553,9 +553,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -565,9 +565,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -577,9 +577,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -589,9 +589,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -601,9 +601,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -613,9 +613,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -625,9 +625,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -637,9 +637,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -649,9 +649,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -661,9 +661,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -673,9 +673,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -685,9 +685,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -697,9 +697,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -709,9 +709,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -721,9 +721,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 17:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -733,9 +733,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -745,9 +745,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -757,9 +757,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -769,9 +769,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -781,9 +781,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -793,9 +793,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -805,9 +805,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -817,9 +817,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -829,9 +829,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -841,9 +841,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -853,9 +853,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -865,9 +865,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -877,9 +877,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -889,9 +889,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -901,9 +901,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -913,9 +913,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -925,9 +925,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -937,9 +937,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -949,9 +949,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -961,9 +961,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -973,9 +973,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -985,9 +985,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -997,9 +997,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1009,9 +1009,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1021,9 +1021,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1033,9 +1033,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1045,9 +1045,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1057,9 +1057,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1069,9 +1069,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1081,9 +1081,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2015-01-10 20:46+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1093,9 +1093,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.7.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1105,9 +1105,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1117,9 +1117,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1129,9 +1129,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1141,9 +1141,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1153,9 +1153,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1165,9 +1165,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1177,9 +1177,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1189,9 +1189,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1201,9 +1201,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1213,9 +1213,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1225,9 +1225,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1237,9 +1237,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1249,9 +1249,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1261,9 +1261,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1273,9 +1273,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1285,9 +1285,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1297,9 +1297,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1309,9 +1309,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1321,9 +1321,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1333,9 +1333,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1345,9 +1345,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1357,9 +1357,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1369,9 +1369,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1381,9 +1381,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1393,9 +1393,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1405,9 +1405,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1417,9 +1417,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1429,9 +1429,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1441,9 +1441,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-12-27 18:52+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1453,9 +1453,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.7.1\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1465,9 +1465,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1477,9 +1477,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1489,9 +1489,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1501,9 +1501,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1513,9 +1513,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1525,9 +1525,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1537,9 +1537,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1549,9 +1549,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1561,9 +1561,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1573,9 +1573,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1585,9 +1585,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1597,9 +1597,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1609,9 +1609,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1621,9 +1621,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1633,9 +1633,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1645,9 +1645,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1657,9 +1657,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1669,9 +1669,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1681,9 +1681,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1693,9 +1693,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1705,9 +1705,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1717,9 +1717,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1729,9 +1729,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1741,9 +1741,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1753,9 +1753,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1765,9 +1765,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1777,9 +1777,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1789,9 +1789,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1801,9 +1801,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 17:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1813,9 +1813,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1825,9 +1825,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1837,9 +1837,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1849,9 +1849,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1861,9 +1861,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1873,9 +1873,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1885,9 +1885,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1897,9 +1897,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1909,9 +1909,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1921,9 +1921,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1933,9 +1933,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1945,9 +1945,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1957,9 +1957,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1969,9 +1969,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -1981,9 +1981,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -1993,9 +1993,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2005,9 +2005,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2017,9 +2017,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2029,9 +2029,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2041,9 +2041,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2053,9 +2053,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2065,9 +2065,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2077,9 +2077,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2089,9 +2089,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2101,9 +2101,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2113,9 +2113,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2125,9 +2125,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2137,9 +2137,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2149,9 +2149,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2161,9 +2161,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2015-01-30 16:20+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2173,9 +2173,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.7.4\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2185,9 +2185,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2197,9 +2197,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2209,9 +2209,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2221,9 +2221,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2233,9 +2233,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2245,9 +2245,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2257,9 +2257,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2269,9 +2269,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2281,9 +2281,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2293,9 +2293,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2305,9 +2305,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2317,9 +2317,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2329,9 +2329,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2341,9 +2341,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2353,9 +2353,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2365,9 +2365,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2377,9 +2377,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2389,9 +2389,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2401,9 +2401,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2413,9 +2413,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2425,9 +2425,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2437,9 +2437,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2449,9 +2449,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2461,9 +2461,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2473,9 +2473,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2485,9 +2485,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2497,9 +2497,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2509,9 +2509,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2521,9 +2521,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-12-27 18:52+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2533,9 +2533,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.7.1\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2545,9 +2545,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2557,9 +2557,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2569,9 +2569,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2581,9 +2581,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2593,9 +2593,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2605,9 +2605,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2617,9 +2617,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2629,9 +2629,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2641,9 +2641,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2653,9 +2653,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2665,9 +2665,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2677,9 +2677,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2689,9 +2689,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2701,9 +2701,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2713,9 +2713,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2725,9 +2725,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2737,9 +2737,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2749,9 +2749,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2761,9 +2761,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2773,9 +2773,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2785,9 +2785,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2797,9 +2797,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2809,9 +2809,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2821,9 +2821,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2833,9 +2833,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2845,9 +2845,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2857,9 +2857,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2869,9 +2869,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2881,9 +2881,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 17:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2893,9 +2893,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2905,9 +2905,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2917,9 +2917,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2929,9 +2929,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2941,9 +2941,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -2953,9 +2953,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2965,9 +2965,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2977,9 +2977,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -2989,9 +2989,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3001,9 +3001,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3013,9 +3013,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3025,9 +3025,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3037,9 +3037,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3049,9 +3049,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3061,9 +3061,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3073,9 +3073,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3085,9 +3085,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3097,9 +3097,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3109,9 +3109,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3121,9 +3121,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3133,9 +3133,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3145,9 +3145,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3157,9 +3157,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3169,9 +3169,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3181,9 +3181,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3193,9 +3193,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3205,9 +3205,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3217,9 +3217,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3229,9 +3229,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3241,9 +3241,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2015-01-10 20:46+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3253,9 +3253,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.7.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3265,9 +3265,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3277,9 +3277,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3289,9 +3289,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3301,9 +3301,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3313,9 +3313,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3325,9 +3325,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3337,9 +3337,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3349,9 +3349,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3361,9 +3361,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3373,9 +3373,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3385,9 +3385,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3397,9 +3397,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3409,9 +3409,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3421,9 +3421,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3433,9 +3433,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3445,9 +3445,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3457,9 +3457,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3469,9 +3469,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3481,9 +3481,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3493,9 +3493,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3505,9 +3505,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3517,9 +3517,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3529,9 +3529,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3541,9 +3541,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3553,9 +3553,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3565,9 +3565,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3577,9 +3577,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3589,9 +3589,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3601,9 +3601,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-12-27 18:52+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3613,9 +3613,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.7.1\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3625,9 +3625,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3637,9 +3637,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3649,9 +3649,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3661,9 +3661,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3673,9 +3673,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3685,9 +3685,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3697,9 +3697,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3709,9 +3709,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3721,9 +3721,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3733,9 +3733,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3745,9 +3745,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3757,9 +3757,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3769,9 +3769,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3781,9 +3781,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3793,9 +3793,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3805,9 +3805,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3817,9 +3817,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3829,9 +3829,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3841,9 +3841,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3853,9 +3853,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3865,9 +3865,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3877,9 +3877,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3889,9 +3889,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3901,9 +3901,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3913,9 +3913,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3925,9 +3925,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3937,9 +3937,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3949,9 +3949,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3961,9 +3961,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 17:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -3973,9 +3973,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3985,9 +3985,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -3997,9 +3997,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4009,9 +4009,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4021,9 +4021,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -4033,9 +4033,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4045,9 +4045,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4057,9 +4057,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4069,9 +4069,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4081,9 +4081,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -4093,9 +4093,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4105,9 +4105,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4117,9 +4117,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4129,9 +4129,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4141,9 +4141,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-11-05 16:47+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -4153,9 +4153,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.10\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4165,9 +4165,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4177,9 +4177,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4189,9 +4189,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4201,9 +4201,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-09-08 18:25+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -4213,9 +4213,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.9\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4225,9 +4225,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4237,9 +4237,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4249,9 +4249,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4261,9 +4261,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2014-02-06 23:05+0100\n" "Last-Translator: Pomsár Miklós \n" "Language-Team: MagyarBlender \n" @@ -4273,9 +4273,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.6.3\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:27+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4285,9 +4285,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-03 20:47+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4297,9 +4297,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-09 21:29+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" @@ -4309,9 +4309,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 1.5.5\n" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-08-19 16:10+0100\n" "Last-Translator: Pomsár András \n" "Language-Team: MagyarBlender \n" diff --git a/locale/po/id.po b/locale/po/id.po index a73aa43394b..6ae306d4e38 100644 --- a/locale/po/id.po +++ b/locale/po/id.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2021-12-25 23:57-0800\n" "Last-Translator: Adriel Tristanputra \n" "Language-Team: Indonesian <>\n" @@ -11629,6 +11629,10 @@ msgid "Weight of feather point" msgstr "Kamera" +msgid "Active Point" +msgstr "Titik Aktif" + + msgid "Grease Pencil Color" msgstr "Warna Pensil Grease" @@ -20109,10 +20113,6 @@ msgid "Camera Presets" msgstr "Preset Kamera" -msgid "Active Point" -msgstr "Titik Aktif" - - msgid "Clip Display" msgstr "Tampilan Klip" diff --git a/locale/po/it.po b/locale/po/it.po index 268d6543e15..bf5b6d0cc32 100644 --- a/locale/po/it.po +++ b/locale/po/it.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2022-01-21 16:08+0100\n" "Last-Translator: MT\n" "Language-Team: blend-it \n" @@ -18365,6 +18365,10 @@ msgid "Weight of feather point" msgstr "Peso del punto sfumatura" +msgid "Active Point" +msgstr "Punto Attivo" + + msgid "Alignment" msgstr "Allineamento" @@ -30999,19 +31003,11 @@ msgid "Clear Restrict View" msgstr "Pulisci Vista con Restrizioni" -msgid "Reveal the layer by setting the hide flag" -msgstr "Rivela il livello impostando il flag hide" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Imposta Vista con Restrizioni" -msgid "Hide the layer by setting the hide flag" -msgstr "Nasconde il livello impostando il flag hide" - - msgctxt "Operator" msgid "Move Layer" msgstr "Sposta Livello" @@ -42411,10 +42407,6 @@ msgid "2D Cursor" msgstr "Cursore 2D" -msgid "Active Point" -msgstr "Punto Attivo" - - msgid "Footage Settings" msgstr "Impostazioni Filmato Originale" @@ -54591,10 +54583,6 @@ msgid "View Name" msgstr "Nome Vista" -msgid "3D Viewport Axis" -msgstr "Assi Vista 3D" - - msgid "Limit Size" msgstr "Limita Dimensioni" diff --git a/locale/po/ja.po b/locale/po/ja.po index 59b7801f46b..9de6d4dbe8b 100644 --- a/locale/po/ja.po +++ b/locale/po/ja.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2016-10-13 03:05+0900\n" "Last-Translator: \n" "Language-Team: Japanese Translation Team (https://sites.google.com/site/blugjp/blender-translators)\n" @@ -1115,6 +1115,10 @@ msgid "Copyright" msgstr "コピーライト" +msgid "Copyright notice for this asset. An empty copyright notice does not necessarily indicate that this is copyright-free. Contact the author if any clarification is needed" +msgstr "このアセットの著作権情報。著作権情報が空の場合でも著作権フリーとは限りません。明確にする必要がある場合は作者に連絡してください" + + msgid "Description" msgstr "詳細" @@ -1123,6 +1127,14 @@ msgid "A description of the asset to be displayed for the user" msgstr "ユーザー用に表示されるアセットの解説" +msgid "License" +msgstr "ライセンス" + + +msgid "The type of license this asset is distributed under. An empty license name does not necessarily indicate that this is free of licensing terms. Contact the author if any clarification is needed" +msgstr "このアセットのライセンスタイプ。" + + msgid "Tags" msgstr "タグ" @@ -13873,8 +13885,13 @@ msgstr "" "(各セルは少なくともこのパーティクル数を持つようになります)" +msgctxt "Amount" +msgid "Number" +msgstr "数" + + msgid "Particle number factor (higher value results in more particles)" -msgstr "パーティクル係数(大きな値でパーティクルが増加)" +msgstr "パーティクル数の係数(大きな値でパーティクルが増加)" msgid "Particle radius factor. Increase this value if the simulation appears to leak volume, decrease it if the simulation seems to gain volume" @@ -19794,6 +19811,61 @@ msgid "Editable falloff curve" msgstr "減衰曲線を有効化します" +msgctxt "Curves" +msgid "Curve Preset" +msgstr "カーブプリセット" + + +msgctxt "Curves" +msgid "Custom" +msgstr "カスタム" + + +msgctxt "Curves" +msgid "Smooth" +msgstr "スムーズ" + + +msgctxt "Curves" +msgid "Smoother" +msgstr "強スムーズ" + + +msgctxt "Curves" +msgid "Sphere" +msgstr "球状" + + +msgctxt "Curves" +msgid "Root" +msgstr "ルート" + + +msgctxt "Curves" +msgid "Sharp" +msgstr "シャープ" + + +msgctxt "Curves" +msgid "Linear" +msgstr "リニア" + + +msgctxt "Curves" +msgid "Sharper" +msgstr "強シャープ" + + +msgctxt "Curves" +msgid "Inverse Square" +msgstr "逆二乗式" + + +msgctxt "Curves" +msgid "Constant" +msgstr "一定" + + msgid "Curves Sculpt Settings" msgstr "ヘアーカーブスカルプト設定" @@ -21263,6 +21335,11 @@ msgid "Name of the Alembic attribute used for generating motion blur data" msgstr "モーションブラーデータの生成に使用される Alembic の属性の名前" +msgctxt "Unit" +msgid "Velocity Unit" +msgstr "速度の単位" + + msgid "Define how the velocity vectors are interpreted with regard to time, 'frame' means the delta time is 1 frame, 'second' means the delta time is 1 / FPS" msgstr "" "時間に対する速度ベクトルの解釈方法\n" @@ -21270,6 +21347,16 @@ msgstr "" "「秒数」はデルタタイムが 1/FPS" +msgctxt "Unit" +msgid "Second" +msgstr "秒数" + + +msgctxt "Unit" +msgid "Frame" +msgstr "フレーム" + + msgid "Camera data-block for storing camera settings" msgstr "カメラ設定を格納するカメラデータブロック" @@ -28351,8 +28438,13 @@ msgid "Text file on disk is different than the one in memory" msgstr "ディスク上のテキストファイルはメモリ内のものと異なります" +msgctxt "Text" +msgid "Lines" +msgstr "行数" + + msgid "Lines of text" -msgstr "テキストの行" +msgstr "テキストの行数" msgid "Selection End Character" @@ -29033,7 +29125,7 @@ msgstr "よりクリアに設定されたマーブルを使用" msgid "Sharper" -msgstr "よりシャープ" +msgstr "強シャープ" msgid "Use very clearly defined marble" @@ -33879,6 +33971,10 @@ msgid "Active spline of masking layer" msgstr "マスキングレイヤーのアクティブスプライン" +msgid "Active Point" +msgstr "アクティブポイント" + + msgid "Grease Pencil Color" msgstr "グリースペンシルカラー" @@ -34416,6 +34512,11 @@ msgid "Write" msgstr "書込" +msgctxt "NodeTree" +msgid "Constant" +msgstr "定数" + + msgid "Instances" msgstr "インスタンス" @@ -45081,10 +45182,6 @@ msgid "Is Face Planar" msgstr "平面判定" -msgid "Retrieve whether all triangles in a face are on the same plane, i.e. whether have the same normal" -msgstr "1つの面内の全三角形が同一平面上にあるかどうか(同じ法線かどうか)を計算します" - - msgid "Face Neighbors" msgstr "面情報" @@ -60483,19 +60580,11 @@ msgid "Clear Restrict View" msgstr "ビューの制限を解除" -msgid "Reveal the layer by setting the hide flag" -msgstr "非表示フラグを解除しオブジェクトを再表示します" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "ビューの制限を設定" -msgid "Hide the layer by setting the hide flag" -msgstr "非表示フラグを設定し、レイヤーを隠します" - - msgctxt "Operator" msgid "Move Layer" msgstr "レイヤー移動" @@ -82685,10 +82774,6 @@ msgid "2D Cursor" msgstr "2Dカーソル" -msgid "Active Point" -msgstr "アクティブポイント" - - msgid "Predefined tracking camera intrinsics" msgstr "定義済トラッキングカメラ固有値" @@ -87791,14 +87876,6 @@ msgid "Mini Axes Type" msgstr "ミニ軸のタイプ" -msgid "Show a small rotating 3D axes in the top right corner of the 3D viewport" -msgstr "3Dビューポートの右上隅に、回転する小さな3D座標軸を表示します" - - -msgid "Simple Axis" -msgstr "シンプルな軸" - - msgid "Interactive Navigation" msgstr "インタラクティブナビゲーション" @@ -90872,10 +90949,25 @@ msgid "Additional subdivision along the curves" msgstr "カーブに沿ってさらに細分化します" +msgctxt "Curves" +msgid "Curves Shape Type" +msgstr "カーブの形状タイプ" + + msgid "Curves shape type" msgstr "カーブの形状タイプ" +msgctxt "Curves" +msgid "Strand" +msgstr "ストランド" + + +msgctxt "Curves" +msgid "Strip" +msgstr "ストリップ" + + msgid "Multiple Engines" msgstr "複数のエンジン" @@ -107222,6 +107314,10 @@ msgid "Previews clear process failed for file '%s'!" msgstr "ファイル「%s」のプレビュークリアプロセスに失敗しました" +msgid "No active camera in the scene" +msgstr "シーンにアクティブカメラがありません" + + msgid "Unexpected modifier type: " msgstr "未知のモディファイアータイプ:" @@ -109574,7 +109670,7 @@ msgstr "このオブジェクトは複合形状の一部です" msgid "Second" -msgstr "秒数" +msgstr "2つめ" msgid "X Stiffness" @@ -112298,10 +112394,6 @@ msgid "Playback Frame Rate (FPS)" msgstr "再生フレームレート(FPS)" -msgid "3D Viewport Axis" -msgstr "3Dビューポートの軸" - - msgid "Smooth Wires" msgstr "スムーズワイヤ" @@ -117296,6 +117388,10 @@ msgid "Error evaluating number, see Info editor for details" msgstr "数値の評価エラー。詳細は情報エディターを参照してください" +msgid "Press a key" +msgstr "キーを押下" + + msgid "Missing Panel: %s" msgstr "欠けているパネル:%s" @@ -124590,6 +124686,31 @@ msgid "UNDEFINED" msgstr "未定義" +msgctxt "NodeTree" +msgid "Functions" +msgstr "関数" + + +msgctxt "NodeTree" +msgid "Comparison" +msgstr "比較" + + +msgctxt "NodeTree" +msgid "Rounding" +msgstr "丸め" + + +msgctxt "NodeTree" +msgid "Trigonometric" +msgstr "三角関数" + + +msgctxt "NodeTree" +msgid "Conversion" +msgstr "変換" + + msgid "Same input/output direction of sockets" msgstr "ソケットの入出力方向が同じです" diff --git a/locale/po/ka.po b/locale/po/ka.po index 513287cf0e8..0376b912d9d 100644 --- a/locale/po/ka.po +++ b/locale/po/ka.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Tamar Mebonia , 2023\n" "Language-Team: LANGUAGE \n" diff --git a/locale/po/ko.po b/locale/po/ko.po index da733b10f66..63849170572 100644 --- a/locale/po/ko.po +++ b/locale/po/ko.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2020-01-04 05:04+0900\n" "Last-Translator: Geuntak Jeong \n" "Language-Team: Korean (http://www.transifex.com/lxlalexlxl/blender/language/ko/)\n" @@ -26193,6 +26193,10 @@ msgid "Active spline of masking layer" msgstr "마스킹 레이어의 활성 스플라인" +msgid "Active Point" +msgstr "활성 포인트" + + msgid "Grease Pencil Color" msgstr "그리스 펜슬 컬러" @@ -44683,19 +44687,11 @@ msgid "Clear Restrict View" msgstr "제한 뷰를 지우기" -msgid "Reveal the layer by setting the hide flag" -msgstr "숨기기 플레그를 설정하여 레이어를 보이기" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "제한 뷰를 설정" -msgid "Hide the layer by setting the hide flag" -msgstr "숨기기 플레그를 설정하여 레이어를 숨기기" - - msgctxt "Operator" msgid "Move Layer" msgstr "레이어 이동" @@ -60696,10 +60692,6 @@ msgid "2D Cursor" msgstr "2D 커서" -msgid "Active Point" -msgstr "활성 포인트" - - msgid "Predefined tracking camera intrinsics" msgstr "미리 정의된 트래킹 카메라 내장" @@ -64649,10 +64641,6 @@ msgid "Mini Axes Type" msgstr "미니 축 유형" -msgid "Simple Axis" -msgstr "심플 축" - - msgid "Interactive Navigation" msgstr "대화형 네비게이션" @@ -80660,10 +80648,6 @@ msgid "View Name" msgstr "뷰 이름" -msgid "3D Viewport Axis" -msgstr "3D 뷰포트 축" - - msgid "Limit Size" msgstr "크기를 제한" diff --git a/locale/po/ky.po b/locale/po/ky.po index 0b99af31954..321d8378853 100644 --- a/locale/po/ky.po +++ b/locale/po/ky.po @@ -1,10 +1,10 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "(b'0000000000000000000000000000000000000000')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2013-11-05 13:47+0600\n" "Last-Translator: Chyngyz Dzhumaliev \n" "Language-Team: Kirghiz \n" diff --git a/locale/po/nl.po b/locale/po/nl.po index 5faa45f6950..070a8c17cf4 100644 --- a/locale/po/nl.po +++ b/locale/po/nl.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2021-12-05 20:05+0100\n" "Language: nl\n" "MIME-Version: 1.0\n" @@ -2699,6 +2699,10 @@ msgid "Calculate Holes" msgstr "Bereken Gaten" +msgid "Active Point" +msgstr "Actieve Punt" + + msgctxt "MovieClip" msgid "Clip" msgstr "Clip" @@ -6443,10 +6447,6 @@ msgid "Custom Shape" msgstr "Aangepaste Vorm" -msgid "Active Point" -msgstr "Actieve Punt" - - msgctxt "MovieClip" msgid "Scene Setup" msgstr "Scene Opstelling" diff --git a/locale/po/pl.po b/locale/po/pl.po index d3b4787a68d..c7a11d8fcc2 100644 --- a/locale/po/pl.po +++ b/locale/po/pl.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2017-08-26 11:13+0200\n" "Last-Translator: Mikołaj Juda \n" "Language: pl\n" diff --git a/locale/po/pt.po b/locale/po/pt.po index a25d618a3e0..5179362d4fe 100644 --- a/locale/po/pt.po +++ b/locale/po/pt.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: Ivan Paulos Tomé \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2017-09-08 21:24-0300\n" "Last-Translator: Ivan Paulos Tomé \n" "Language-Team: Ivan Paulos Tomé, Inês Almeida, João Brandão (ULISBOA), Paulo Martins \n" @@ -20652,6 +20652,10 @@ msgid "Active spline of masking layer" msgstr "Spline ativa da camada de máscara." +msgid "Active Point" +msgstr "Ponto ativo" + + msgid "Alignment" msgstr "Alinhamento" @@ -35586,19 +35590,11 @@ msgid "Clear Restrict View" msgstr "Limpar visualização restrita" -msgid "Reveal the layer by setting the hide flag" -msgstr "Revela a camada pela definição da bandeira de ocultação." - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Definir restrição de visualização" -msgid "Hide the layer by setting the hide flag" -msgstr "Oculta a camada definindo a bandeira de ocultação." - - msgctxt "Operator" msgid "Move Layer" msgstr "Mover camada" @@ -48266,10 +48262,6 @@ msgid "2D Cursor" msgstr "Cursor 2D" -msgid "Active Point" -msgstr "Ponto ativo" - - msgid "Predefined tracking camera intrinsics" msgstr "Intrínsecos de câmara de rastreamento predefinidos." diff --git a/locale/po/pt_BR.po b/locale/po/pt_BR.po index 194221dcdb1..49fc5e4fe2e 100644 --- a/locale/po/pt_BR.po +++ b/locale/po/pt_BR.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: Leandro Paganelli \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2022-03-21 19:03-0300\n" "Last-Translator: Leandro Paganelli \n" "Language-Team: Leandro Paganelli, Ivan Paulos Tomé, Dalai Felinto, Bruno Gonçalves Pirajá, Samuel Arataca, Daniel Tavares, Moraes Junior \n" @@ -22130,6 +22130,10 @@ msgid "Active spline of masking layer" msgstr "Spline ativa da camada de máscara." +msgid "Active Point" +msgstr "Ponto ativo" + + msgid "Alignment" msgstr "Alinhamento" @@ -38735,19 +38739,11 @@ msgid "Clear Restrict View" msgstr "Limpar visualização restrita" -msgid "Reveal the layer by setting the hide flag" -msgstr "Revela a camada pela configuração da bandeira de ocultação." - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Configurar restrição de visualização" -msgid "Hide the layer by setting the hide flag" -msgstr "Oculta a camada configurando a bandeira de ocultação." - - msgctxt "Operator" msgid "Move Layer" msgstr "Mover camada" @@ -53035,10 +53031,6 @@ msgid "2D Cursor" msgstr "Cursor 2D" -msgid "Active Point" -msgstr "Ponto ativo" - - msgid "Predefined tracking camera intrinsics" msgstr "Intrínsecos de câmera de rastreamento predefinidos." @@ -68762,10 +68754,6 @@ msgid "View Name" msgstr "Visualizar nomes" -msgid "3D Viewport Axis" -msgstr "Eixo da Janela de Exibição 3D" - - msgid "Limit Size" msgstr "Limitar texturas" diff --git a/locale/po/ru.po b/locale/po/ru.po index 8a80ae67955..14161e2dd28 100644 --- a/locale/po/ru.po +++ b/locale/po/ru.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2018-01-03 14:47+0000\n" "Last-Translator: Lockal , 2023\n" "Language-Team: Russian (https://www.transifex.com/translateblender/teams/82039/ru/)\n" @@ -29060,6 +29060,10 @@ msgid "Active spline of masking layer" msgstr "Активный сплайн слоя маски" +msgid "Active Point" +msgstr "Активная точка" + + msgid "Grease Pencil Color" msgstr "Цвет Grease Pencil" @@ -47215,19 +47219,11 @@ msgid "Clear Restrict View" msgstr "Очистить ограничение просмотра" -msgid "Reveal the layer by setting the hide flag" -msgstr "Отобразить слой, установив переключатель скрытия" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Установить ограничение просмотра" -msgid "Hide the layer by setting the hide flag" -msgstr "Скрыть слой, установив переключатель скрытия" - - msgctxt "Operator" msgid "Move Layer" msgstr "Переместить слой" @@ -63202,10 +63198,6 @@ msgid "2D Cursor" msgstr "2D-курсор" -msgid "Active Point" -msgstr "Активная точка" - - msgid "Predefined tracking camera intrinsics" msgstr "Предопределённые характеристики отслеживаемой камеры" @@ -67168,10 +67160,6 @@ msgid "Mini Axes Type" msgstr "Тип миниосей" -msgid "Simple Axis" -msgstr "Простые оси" - - msgid "Interactive Navigation" msgstr "Интерактивная навигация" @@ -83315,10 +83303,6 @@ msgid "View Name" msgstr "Имена видов" -msgid "3D Viewport Axis" -msgstr "Оси 3D-вьюпорта" - - msgid "Limit Size" msgstr "Максимальный размер" diff --git a/locale/po/sk.po b/locale/po/sk.po index c7f864feba8..f6abe62ec97 100644 --- a/locale/po/sk.po +++ b/locale/po/sk.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2023-03-08 07:56+0100\n" "Last-Translator: Jozef Matta \n" "Language-Team: Jozef Matta\n" @@ -33509,6 +33509,10 @@ msgid "Active spline of masking layer" msgstr "Aktívna drážka vrstvy maskovania" +msgid "Active Point" +msgstr "Aktívny bod" + + msgid "Grease Pencil Color" msgstr "Farba pastelky" @@ -44660,10 +44664,6 @@ msgid "Is Face Planar" msgstr "Je plôška rovinná" -msgid "Retrieve whether all triangles in a face are on the same plane, i.e. whether have the same normal" -msgstr "Zisťuje, či sú všetky trojuholníky na plôške v rovnakej rovine, t. j. či majú rovnaký normál" - - msgid "Face Neighbors" msgstr "Susedné plôšky" @@ -59919,19 +59919,11 @@ msgid "Clear Restrict View" msgstr "Zmazať obmedzené zobrazenie" -msgid "Reveal the layer by setting the hide flag" -msgstr "Odhalí vrstvu nastavením príznaku skrytia" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Nastaviť obmedzenie zobrazenia" -msgid "Hide the layer by setting the hide flag" -msgstr "Skryje vrstvu nastavením príznaku skrytia" - - msgctxt "Operator" msgid "Move Layer" msgstr "Presunúť vrstvu" @@ -81988,10 +81980,6 @@ msgid "2D Cursor" msgstr "2D kurzor" -msgid "Active Point" -msgstr "Aktívny bod" - - msgid "Predefined tracking camera intrinsics" msgstr "Preddefinované snímanie vnútornej kamery" @@ -87052,14 +87040,6 @@ msgid "Mini Axes Type" msgstr "Typ mini osí" -msgid "Show a small rotating 3D axes in the top right corner of the 3D viewport" -msgstr "Zobrazí malé rotujúce 3D osi v pravom hornom rohu 3D záberu" - - -msgid "Simple Axis" -msgstr "Jednoduchá os" - - msgid "Interactive Navigation" msgstr "Interaktívna navigácia" @@ -111428,10 +111408,6 @@ msgid "Playback Frame Rate (FPS)" msgstr "Frekvencia prehrávania (sním/s)" -msgid "3D Viewport Axis" -msgstr "Osi 3D záberu" - - msgid "Smooth Wires" msgstr "Vyhladiť drôty" diff --git a/locale/po/sr.po b/locale/po/sr.po index afe8983e3ac..ad5124fef6b 100644 --- a/locale/po/sr.po +++ b/locale/po/sr.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2012-09-07 22:32+0100\n" "Last-Translator: Nikola Radovanovic \n" "Language-Team: Nikola Radovanovic\n" @@ -9229,6 +9229,10 @@ msgid "Weight of the point" msgstr "Тежина тачке" +msgid "Active Point" +msgstr "Активна тачка" + + msgid "Alignment" msgstr "Поравнање" @@ -20914,10 +20918,6 @@ msgid "2D Cursor" msgstr "2D курсор" -msgid "Active Point" -msgstr "Активна тачка" - - msgid "Footage Settings" msgstr "Подешавање видеа" diff --git a/locale/po/sr@latin.po b/locale/po/sr@latin.po index 395d90f2612..963bd79f628 100644 --- a/locale/po/sr@latin.po +++ b/locale/po/sr@latin.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2012-09-07 22:32+0100\n" "Last-Translator: Nikola Radovanovic \n" "Language-Team: Nikola Radovanovic\n" @@ -9229,6 +9229,10 @@ msgid "Weight of the point" msgstr "Težina tačke" +msgid "Active Point" +msgstr "Aktivna tačka" + + msgid "Alignment" msgstr "Poravnanje" @@ -20914,10 +20918,6 @@ msgid "2D Cursor" msgstr "2D kursor" -msgid "Active Point" -msgstr "Aktivna tačka" - - msgid "Footage Settings" msgstr "Podešavanje videa" diff --git a/locale/po/sv.po b/locale/po/sv.po index 82e6aa12406..77deec7cd6b 100644 --- a/locale/po/sv.po +++ b/locale/po/sv.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: \n" "Last-Translator: Arvid Rudling \n" "Language-Team: \n" diff --git a/locale/po/th.po b/locale/po/th.po index be2163e9713..f8d31660954 100644 --- a/locale/po/th.po +++ b/locale/po/th.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2019-12-08 17:40+0700\n" "Last-Translator: gongpha \n" "Language-Team: Thai Translation Team \n" diff --git a/locale/po/tr.po b/locale/po/tr.po index 6b123b8d008..1dc5ee9d41c 100644 --- a/locale/po/tr.po +++ b/locale/po/tr.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2023-02-05 22:00+0300\n" "Last-Translator: Emir SARI \n" "Language-Team: Turkish <>\n" diff --git a/locale/po/uk.po b/locale/po/uk.po index 02ba446711a..61a0230e063 100644 --- a/locale/po/uk.po +++ b/locale/po/uk.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2021-03-01 19:15+0000\n" "Last-Translator: lxlalexlxl \n" "Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/lxlalexlxl/blender/language/uk_UA/)\n" @@ -29651,6 +29651,10 @@ msgid "Active spline of masking layer" msgstr "Активний сплайн шару маскування" +msgid "Active Point" +msgstr "Активна Точка" + + msgid "Grease Pencil Color" msgstr "Колір Нарисного Олівця" @@ -51158,19 +51162,11 @@ msgid "Clear Restrict View" msgstr "Зчистити обмеження видимості" -msgid "Reveal the layer by setting the hide flag" -msgstr "Виявити шар, знявши прапорець приховування" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Встановити обмеження видимості" -msgid "Hide the layer by setting the hide flag" -msgstr "Приховати шар, встановивши прапорець приховування" - - msgctxt "Operator" msgid "Move Layer" msgstr "Пересунути шар" @@ -69963,10 +69959,6 @@ msgid "2D Cursor" msgstr "2D-курсор" -msgid "Active Point" -msgstr "Активна Точка" - - msgid "Predefined tracking camera intrinsics" msgstr "Передустави простеження камери" @@ -74387,10 +74379,6 @@ msgid "Mini Axes Type" msgstr "Тип мініосей" -msgid "Simple Axis" -msgstr "Проста Вісь" - - msgid "Interactive Navigation" msgstr "Інтерактивна навігація" @@ -93457,10 +93445,6 @@ msgid "View Name" msgstr "Назва огляду" -msgid "3D Viewport Axis" -msgstr "Вісь 3D Оглядвікна" - - msgid "Smooth Wires" msgstr "Згладження Дротів" diff --git a/locale/po/vi.po b/locale/po/vi.po index 5ea65674b48..6dbb0745228 100644 --- a/locale/po/vi.po +++ b/locale/po/vi.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2022-08-19 12:33+0700\n" "Last-Translator: HỒ NHỰT CHÂU \n" "Language-Team: Tỉnh An Giang, Đình Bình Phú\n" @@ -32828,6 +32828,10 @@ msgid "Active spline of masking layer" msgstr "Mẫu cong hoạt động của lớp mặt nạ" +msgid "Active Point" +msgstr "Điểm Hoạt Động" + + msgid "Grease Pencil Color" msgstr "Màu Bút Sáp" @@ -43645,10 +43649,6 @@ msgid "Is Face Planar" msgstr "Mặt Là Mặt Phẳng" -msgid "Retrieve whether all triangles in a face are on the same plane, i.e. whether have the same normal" -msgstr "Rút thông tin về tất cả tam giác nằm trên cùng mặt phẳng, ví dụ: có cùnh pháp tuyến" - - msgid "Face Neighbors" msgstr "Kề Mặt" @@ -58326,19 +58326,11 @@ msgid "Clear Restrict View" msgstr "Xóa Hạn Chế Hiển Thị" -msgid "Reveal the layer by setting the hide flag" -msgstr "Hiện lớp bằng đặt cờ ẩn" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "Đặt Hạn Chế Hiển Thị" -msgid "Hide the layer by setting the hide flag" -msgstr "Ẩn lớp bằng đặt cờ ẩn" - - msgctxt "Operator" msgid "Move Layer" msgstr "Di Chuyển Lớp" @@ -79542,10 +79534,6 @@ msgid "2D Cursor" msgstr "Con Trỏ 2D" -msgid "Active Point" -msgstr "Điểm Hoạt Động" - - msgid "Predefined tracking camera intrinsics" msgstr "Bản chất theo dõi máy quay phim được đặt sẵn" @@ -84476,14 +84464,6 @@ msgid "Mini Axes Type" msgstr "Loại Tiểu Trục" -msgid "Show a small rotating 3D axes in the top right corner of the 3D viewport" -msgstr "Cho xem một bộ trục 3D xoay trong góc trên phải của màn chiếu 3D" - - -msgid "Simple Axis" -msgstr "Trục Đơn Giản" - - msgid "Interactive Navigation" msgstr "Chuyển Hướng Tương Tác" @@ -107456,10 +107436,6 @@ msgid "Playback Frame Rate (FPS)" msgstr "Tốc Độ Hát Lại (Bức Ảnh/Giây)" -msgid "3D Viewport Axis" -msgstr "Trục Màn Chiếu 3D" - - msgid "Smooth Wires" msgstr "Sợi Dây Mịn" diff --git a/locale/po/zh_CN.po b/locale/po/zh_CN.po index 44aa8b68018..d3c711694ae 100644 --- a/locale/po/zh_CN.po +++ b/locale/po/zh_CN.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: \n" "Last-Translator: DeathBlood\n" "Language-Team: \n" @@ -33498,6 +33498,10 @@ msgid "Active spline of masking layer" msgstr "遮罩层活动样条" +msgid "Active Point" +msgstr "活动点" + + msgid "Grease Pencil Color" msgstr "蜡笔颜色" @@ -44640,10 +44644,6 @@ msgid "Is Face Planar" msgstr "面是否平直" -msgid "Retrieve whether all triangles in a face are on the same plane, i.e. whether have the same normal" -msgstr "检索面中的所有三角形是否在同一平面上,即是否具有相同的法向" - - msgid "Face Neighbors" msgstr "面的邻项" @@ -59879,19 +59879,11 @@ msgid "Clear Restrict View" msgstr "清除显示限制" -msgid "Reveal the layer by setting the hide flag" -msgstr "通过对隐藏标记进行设置, 恢复层的可见性" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "设置显示限制" -msgid "Hide the layer by setting the hide flag" -msgstr "通过设置隐藏标识来隐藏图层" - - msgctxt "Operator" msgid "Move Layer" msgstr "移动层" @@ -81867,10 +81859,6 @@ msgid "2D Cursor" msgstr "2D 游标" -msgid "Active Point" -msgstr "活动点" - - msgid "Predefined tracking camera intrinsics" msgstr "预定义的轨迹摄像机内部参数" @@ -86919,14 +86907,6 @@ msgid "Mini Axes Type" msgstr "迷你坐标轴类型" -msgid "Show a small rotating 3D axes in the top right corner of the 3D viewport" -msgstr "在3D视图的左下角显示一个可旋转的小3D坐标轴" - - -msgid "Simple Axis" -msgstr "单一轴向" - - msgid "Interactive Navigation" msgstr "交互漫游" @@ -111166,10 +111146,6 @@ msgid "Playback Frame Rate (FPS)" msgstr "播放帧率(FPS)" -msgid "3D Viewport Axis" -msgstr "3D 视图轴向" - - msgid "Smooth Wires" msgstr "平滑线框" diff --git a/locale/po/zh_TW.po b/locale/po/zh_TW.po index 44cb063b309..84b0e9ed193 100644 --- a/locale/po/zh_TW.po +++ b/locale/po/zh_TW.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Blender 3.5.0 Beta (b'4096bcfb25f6')\n" +"Project-Id-Version: Blender 3.5.0 Beta (b'3962d9b931f1')\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-13 11:29:34\n" +"POT-Creation-Date: 2023-03-20 13:37:56\n" "PO-Revision-Date: 2023-01-28 11:09+0800\n" "Last-Translator: Cheng-Chia Tseng \n" "Language-Team: Chinese (Traditional) \n" @@ -19148,6 +19148,10 @@ msgid "Weight of feather point" msgstr "羽毛點的權重" +msgid "Active Point" +msgstr "作用中的點" + + msgid "Alignment" msgstr "對齊" @@ -32215,19 +32219,11 @@ msgid "Clear Restrict View" msgstr "清除限制視圖" -msgid "Reveal the layer by setting the hide flag" -msgstr "揭開設有隱藏旗幟的層" - - msgctxt "Operator" msgid "Set Restrict View" msgstr "設定限制視圖" -msgid "Hide the layer by setting the hide flag" -msgstr "隱藏設有隱藏旗幟的層" - - msgctxt "Operator" msgid "Move Layer" msgstr "移動層" @@ -43722,10 +43718,6 @@ msgid "2D Cursor" msgstr "2D 游標" -msgid "Active Point" -msgstr "作用中的點" - - msgid "Predefined tracking camera intrinsics" msgstr "預先定義的追蹤攝影機內在本質" @@ -55612,10 +55604,6 @@ msgid "View Name" msgstr "視圖名稱" -msgid "3D Viewport Axis" -msgstr "3D 視接口座標軸" - - msgid "Limit Size" msgstr "限制大小" diff --git a/make.bat b/make.bat index 239be60ebf0..b81f679654b 100644 --- a/make.bat +++ b/make.bat @@ -113,9 +113,6 @@ if "%TEST%" == "1" ( goto EOF ) -call "%BLENDER_DIR%\build_files\windows\check_submodules.cmd" -if errorlevel 1 goto EOF - if "%BUILD_WITH_NINJA%" == "" ( call "%BLENDER_DIR%\build_files\windows\configure_msbuild.cmd" if errorlevel 1 goto EOF diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c index ce6f0b0a072..d62f95d83f6 100644 --- a/release/datafiles/userdef/userdef_default.c +++ b/release/datafiles/userdef/userdef_default.c @@ -66,8 +66,8 @@ const UserDef U_default = { /** Default so DPI is detected automatically. */ .dpi = 0, - .dpi_fac = 0.0, - .inv_dpi_fac = 0.0, /* run-time. */ + .scale_factor = 0.0, + .inv_scale_factor = 0.0, /* run-time. */ .pixelsize = 1, .virtual_pixel = 0, diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index 108015996a1..4465577305f 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -389,6 +389,8 @@ class NODE_MT_geometry_node_GEO_MESH_OPERATIONS(Menu): node_add_menu.add_node_type(layout, "GeometryNodeMeshBoolean") node_add_menu.add_node_type(layout, "GeometryNodeMeshToCurve") node_add_menu.add_node_type(layout, "GeometryNodeMeshToPoints") + if _context.preferences.experimental.use_new_volume_nodes: + node_add_menu.add_node_type(layout, "GeometryNodeMeshToSDFVolume") node_add_menu.add_node_type(layout, "GeometryNodeMeshToVolume") node_add_menu.add_node_type(layout, "GeometryNodeScaleElements") node_add_menu.add_node_type(layout, "GeometryNodeSplitEdges") @@ -453,6 +455,8 @@ class NODE_MT_category_GEO_POINT(Menu): layout.separator() node_add_menu.add_node_type(layout, "GeometryNodePoints") node_add_menu.add_node_type(layout, "GeometryNodePointsToVertices") + if _context.preferences.experimental.use_new_volume_nodes: + node_add_menu.add_node_type(layout, "GeometryNodePointsToSDFVolume") node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume") layout.separator() node_add_menu.add_node_type(layout, "GeometryNodeSetPointRadius") @@ -604,6 +608,11 @@ class NODE_MT_category_GEO_VOLUME(Menu): layout = self.layout node_add_menu.add_node_type(layout, "GeometryNodeVolumeCube") node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh") + if _context.preferences.experimental.use_new_volume_nodes: + layout.separator() + node_add_menu.add_node_type(layout, "GeometryNodeMeanFilterSDFVolume") + node_add_menu.add_node_type(layout, "GeometryNodeOffsetSDFVolume") + node_add_menu.add_node_type(layout, "GeometryNodeSDFVolumeSphere") node_add_menu.draw_assets_for_catalog(layout, self.bl_label) diff --git a/source/blender/asset_system/AS_asset_identifier.hh b/source/blender/asset_system/AS_asset_identifier.hh index 33b7f71becc..5c5e4f26a00 100644 --- a/source/blender/asset_system/AS_asset_identifier.hh +++ b/source/blender/asset_system/AS_asset_identifier.hh @@ -25,6 +25,7 @@ class AssetIdentifier { AssetIdentifier(const AssetIdentifier &) = default; std::string full_path() const; + std::string full_library_path() const; }; } // namespace blender::asset_system diff --git a/source/blender/asset_system/AS_asset_representation.h b/source/blender/asset_system/AS_asset_representation.h index 359567cbf0b..366c1a1f16e 100644 --- a/source/blender/asset_system/AS_asset_representation.h +++ b/source/blender/asset_system/AS_asset_representation.h @@ -21,6 +21,8 @@ const char *AS_asset_representation_name_get(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT; AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT; +struct ID *AS_asset_representation_local_id_get(const AssetRepresentation *asset) + ATTR_WARN_UNUSED_RESULT; bool AS_asset_representation_is_local_id(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT; bool AS_asset_representation_is_never_link(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/asset_system/AS_asset_representation.hh b/source/blender/asset_system/AS_asset_representation.hh index 99fde7d3dc2..6e84fa2aa20 100644 --- a/source/blender/asset_system/AS_asset_representation.hh +++ b/source/blender/asset_system/AS_asset_representation.hh @@ -82,6 +82,9 @@ class AssetRepresentation { * #get_import_method(). Also returns true if there is no predefined import method * (when #get_import_method() returns no value). */ bool may_override_import_method() const; + /** If this asset is stored inside this current file (#is_local_id() is true), this returns the + * ID's pointer, otherwise null. */ + ID *local_id() const; /** Returns if this asset is stored inside this current file, and as such fully editable. */ bool is_local_id() const; const AssetLibrary &owner_asset_library() const; @@ -92,7 +95,11 @@ class AssetRepresentation { /* C-Handle */ struct AssetRepresentation; -const std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset); +std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset); +/** Get the absolute path to the .blend file containing the given asset. String will be empty if + * the asset could not be mapped to a valid .blend file path. Valid in this case also means that + * the file needs to exist on disk. */ +std::string AS_asset_representation_full_library_path_get(const ::AssetRepresentation *asset); std::optional AS_asset_representation_import_method_get( const ::AssetRepresentation *asset_handle); bool AS_asset_representation_may_override_import_method(const ::AssetRepresentation *asset_handle); diff --git a/source/blender/asset_system/intern/asset_identifier.cc b/source/blender/asset_system/intern/asset_identifier.cc index 94a15103b52..3509eb1e4aa 100644 --- a/source/blender/asset_system/intern/asset_identifier.cc +++ b/source/blender/asset_system/intern/asset_identifier.cc @@ -4,8 +4,11 @@ * \ingroup asset_system */ +#include + +#include "BKE_blendfile.h" + #include "BLI_path_util.h" -#include #include "AS_asset_identifier.hh" @@ -24,4 +27,16 @@ std::string AssetIdentifier::full_path() const return path; } +std::string AssetIdentifier::full_library_path() const +{ + std::string asset_path = full_path(); + + char blend_path[1090 /*FILE_MAX_LIBEXTRA*/]; + if (!BKE_blendfile_library_path_explode(asset_path.c_str(), blend_path, nullptr, nullptr)) { + return {}; + } + + return blend_path; +} + } // namespace blender::asset_system diff --git a/source/blender/asset_system/intern/asset_representation.cc b/source/blender/asset_system/intern/asset_representation.cc index daaa7bdff0f..6ebd6dd4c6c 100644 --- a/source/blender/asset_system/intern/asset_representation.cc +++ b/source/blender/asset_system/intern/asset_representation.cc @@ -97,6 +97,11 @@ bool AssetRepresentation::may_override_import_method() const return owner_asset_library_->may_override_import_method_; } +ID *AssetRepresentation::local_id() const +{ + return is_local_id_ ? local_asset_id_ : nullptr; +} + bool AssetRepresentation::is_local_id() const { return is_local_id_; @@ -111,7 +116,7 @@ const AssetLibrary &AssetRepresentation::owner_asset_library() const using namespace blender; -const std::string AS_asset_representation_full_path_get(const AssetRepresentation *asset_handle) +std::string AS_asset_representation_full_path_get(const AssetRepresentation *asset_handle) { const asset_system::AssetRepresentation *asset = reinterpret_cast(asset_handle); @@ -119,6 +124,13 @@ const std::string AS_asset_representation_full_path_get(const AssetRepresentatio return identifier.full_path(); } +std::string AS_asset_representation_full_library_path_get(const AssetRepresentation *asset_handle) +{ + const asset_system::AssetRepresentation *asset = + reinterpret_cast(asset_handle); + return asset->get_identifier().full_library_path(); +} + std::optional AS_asset_representation_import_method_get( const AssetRepresentation *asset_handle) { @@ -152,6 +164,13 @@ AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *a return &asset->get_metadata(); } +ID *AS_asset_representation_local_id_get(const AssetRepresentation *asset_handle) +{ + const asset_system::AssetRepresentation *asset = + reinterpret_cast(asset_handle); + return asset->local_id(); +} + bool AS_asset_representation_is_local_id(const AssetRepresentation *asset_handle) { const asset_system::AssetRepresentation *asset = diff --git a/source/blender/blenfont/intern/blf_default.c b/source/blender/blenfont/intern/blf_default.c index 738683284e3..58b4f3c8906 100644 --- a/source/blender/blenfont/intern/blf_default.c +++ b/source/blender/blenfont/intern/blf_default.c @@ -45,7 +45,7 @@ int BLF_set_default(void) { ASSERT_DEFAULT_SET; - BLF_size(global_font_default, global_font_size * U.dpi_fac); + BLF_size(global_font_default, global_font_size * UI_SCALE_FAC); return global_font_default; } @@ -53,7 +53,7 @@ int BLF_set_default(void) void BLF_draw_default(float x, float y, float z, const char *str, const size_t str_len) { ASSERT_DEFAULT_SET; - BLF_size(global_font_default, global_font_size * U.dpi_fac); + BLF_size(global_font_default, global_font_size * UI_SCALE_FAC); BLF_position(global_font_default, x, y, z); BLF_draw(global_font_default, str, str_len); } diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index d0a894389f4..72f1171fe08 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -29,7 +29,7 @@ * It's mostly used for modifiers, and has the advantages of not taking much * resources. * - * BMesh is a full-on brep, used for editmode, some modifiers, etc. It's much + * BMesh is a full-on BREP, used for edit-mode, some modifiers, etc. It's much * more capable (if memory-intensive) then CDDM. * * DerivedMesh is somewhat hackish. Many places assumes that a DerivedMesh is @@ -129,7 +129,8 @@ struct DerivedMesh { */ float *(*getVertArray)(DerivedMesh *dm); struct MEdge *(*getEdgeArray)(DerivedMesh *dm); - struct MLoop *(*getLoopArray)(DerivedMesh *dm); + int *(*getCornerVertArray)(DerivedMesh *dm); + int *(*getCornerEdgeArray)(DerivedMesh *dm); struct MPoly *(*getPolyArray)(DerivedMesh *dm); /** Copy all verts/edges/faces from the derived mesh into @@ -137,7 +138,8 @@ struct DerivedMesh { */ void (*copyVertArray)(DerivedMesh *dm, float (*r_positions)[3]); void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *r_edge); - void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *r_loop); + void (*copyCornerVertArray)(DerivedMesh *dm, int *r_corner_verts); + void (*copyCornerEdgeArray)(DerivedMesh *dm, int *r_corner_edges); void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly); /** Return a pointer to the entire array of vert/edge/face custom data diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index feee80b4edc..f216ff58ab3 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -19,6 +19,32 @@ struct ReportList; struct UserDef; struct bContext; +/** + * Check whether given path ends with a blend file compatible extension + * (`.blend`, `.ble` or `.blend.gz`). + * + * \param str: The path to check. + * \return true is this path ends with a blender file extension. + */ +bool BKE_blendfile_extension_check(const char *str); +/** + * Try to explode given path into its 'library components' + * (i.e. a .blend file, id type/group, and data-block itself). + * + * \param path: the full path to explode. + * \param r_dir: the string that'll contain path up to blend file itself ('library' path). + * WARNING! Must be at least #FILE_MAX_LIBEXTRA long (it also stores group and name strings)! + * \param r_group: a pointer within `r_dir` to the 'group' part of the path, if any ('\0' + * terminated). May be NULL. + * \param r_name: a pointer within `r_dir` to the data-block name, if any ('\0' terminated). May be + * NULL. + * \return true if path contains a blend file. + */ +bool BKE_blendfile_library_path_explode(const char *path, + char *r_dir, + char **r_group, + char **r_name); + /** * Shared setup function that makes the data from `bfd` into the current blend file, * replacing the contents of #G.main. diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index ba13d9d6a6c..53620561ea7 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -61,7 +61,7 @@ typedef struct BVHTreeFromMesh { const float (*vert_positions)[3]; const struct MEdge *edge; const struct MFace *face; - const struct MLoop *loop; + const int *corner_verts; const struct MLoopTri *looptri; /* Private data */ @@ -181,7 +181,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, */ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data, const float (*vert_positions)[3], - const struct MLoop *mloop, + const int *corner_verts, const struct MLoopTri *looptri, int looptri_num, blender::BitSpan mask, diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index f836b98f3b2..0b58adf7ca7 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -381,6 +381,8 @@ bool CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list); const struct AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C); struct AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid); +struct AssetRepresentation *CTX_wm_asset(const bContext *C); + bool CTX_wm_interface_locked(const bContext *C); /** diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index d7adfb17c88..ddfe0f9c158 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -486,6 +486,8 @@ const char *CustomData_get_active_layer_name(const struct CustomData *data, int */ const char *CustomData_get_render_layer_name(const struct CustomData *data, int type); +bool CustomData_layer_is_anonymous(const struct CustomData *data, int type, int n); + void CustomData_bmesh_set(const struct CustomData *data, void *block, int type, diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index a1ab2e47a55..0fae5823209 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -18,7 +18,6 @@ struct ID; struct ListBase; struct MDeformVert; struct MEdge; -struct MLoop; struct MPoly; struct Object; struct bDeformGroup; @@ -270,14 +269,14 @@ void BKE_defvert_extract_vgroup_to_edgeweights(const struct MDeformVert *dvert, void BKE_defvert_extract_vgroup_to_loopweights(const struct MDeformVert *dvert, int defgroup, int verts_num, - const struct MLoop *loops, + const int *corner_verts, int loops_num, bool invert_vgroup, float *r_weights); void BKE_defvert_extract_vgroup_to_polyweights(const struct MDeformVert *dvert, int defgroup, int verts_num, - const struct MLoop *loops, + const int *corner_verts, int loops_num, const struct MPoly *polys, int polys_num, diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 49c4369aa89..2f18eef7850 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -44,7 +44,7 @@ typedef struct CfraElem { /* ************** F-Curve Modifiers *************** */ /** - * F-Curve Modifier Type-Info (fmi): + * F-Curve Modifier Type-Info (`fmi`): * This struct provides function pointers for runtime, so that functions can be * written more generally (with fewer/no special exceptions for various modifiers). * diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 70d6f1a0383..2b28b28d68a 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -33,7 +33,6 @@ struct MDeformVert; struct MDisps; struct MEdge; struct MFace; -struct MLoop; struct MLoopTri; struct MPoly; struct Main; @@ -109,14 +108,14 @@ void BKE_mesh_ensure_default_orig_index_customdata_no_check(struct Mesh *mesh); * Find the index of the loop in 'poly' which references vertex, * returns -1 if not found */ -int poly_find_loop_from_vert(const struct MPoly *poly, const struct MLoop *loopstart, int vert); +int poly_find_loop_from_vert(const struct MPoly *poly, const int *poly_verts, int vert); /** * Fill \a r_adj with the loop indices in \a poly adjacent to the * vertex. Returns the index of the loop matching vertex, or -1 if the * vertex is not in \a poly */ int poly_get_adj_loops_from_vert(const struct MPoly *poly, - const struct MLoop *mloop, + const int *corner_verts, int vert, int r_adj[2]); @@ -129,8 +128,9 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v); * Sets each output array element to the edge index if it is a real edge, or -1. */ void BKE_mesh_looptri_get_real_edges(const struct MEdge *edges, - const struct MLoop *loops, - const struct MLoopTri *looptri, + const int *corner_verts, + const int *corner_edges, + const struct MLoopTri *tri, int r_edges[3]); /** @@ -312,7 +312,7 @@ void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3] /** * Calculate tessellation into #MLoopTri which exist only for this purpose. */ -void BKE_mesh_recalc_looptri(const struct MLoop *mloop, +void BKE_mesh_recalc_looptri(const int *corner_verts, const struct MPoly *polys, const float (*vert_positions)[3], int totvert, @@ -384,7 +384,7 @@ bool BKE_mesh_vert_normals_are_dirty(const struct Mesh *mesh); */ bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh); -void BKE_mesh_calc_poly_normal(const struct MLoop *poly_loops, +void BKE_mesh_calc_poly_normal(const int *poly_verts, int poly_size, const float (*vert_positions)[3], int verts_num, @@ -430,7 +430,7 @@ enum { * Collection of #MLoopNorSpace basic storage & pre-allocation. */ typedef struct MLoopNorSpaceArray { - MLoopNorSpace **lspacearr; /* MLoop aligned array */ + MLoopNorSpace **lspacearr; /* Face corner aligned array */ struct LinkNode *loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */ char data_type; /* Whether we store loop indices, or pointers to BMLoop. */ @@ -505,7 +505,7 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space, * \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals. */ void BKE_mesh_normals_loop_to_vertex(int numVerts, - const struct MLoop *mloops, + const int *corner_verts, int numLoops, const float (*clnors)[3], float (*r_vert_clnors)[3]); @@ -546,12 +546,12 @@ void BKE_mesh_set_custom_normals_from_verts(struct Mesh *mesh, float (*r_custom_ /* *** mesh_evaluate.cc *** */ -void BKE_mesh_calc_poly_center(const struct MLoop *poly_loops, +void BKE_mesh_calc_poly_center(const int *poly_verts, int poly_size, const float (*vert_positions)[3], int verts_num, float r_cent[3]); -float BKE_mesh_calc_poly_area(const struct MLoop *poly_loops, +float BKE_mesh_calc_poly_area(const int *poly_verts, int poly_size, const float (*vert_positions)[3], int verts_num); @@ -581,12 +581,12 @@ void BKE_mesh_calc_volume(const float (*vert_positions)[3], int mverts_num, const struct MLoopTri *mlooptri, int looptri_num, - const struct MLoop *mloop, + const int *corner_verts, float *r_volume, float r_center[3]); /** - * Flip a single MLoop's #MDisps structure, + * Flip a single corner's #MDisps structure, * low level function to be called from face-flipping code which re-arranged the mdisps themselves. */ void BKE_mesh_mdisp_flip(struct MDisps *md, bool use_loop_mdisp_flip); @@ -600,13 +600,15 @@ void BKE_mesh_mdisp_flip(struct MDisps *md, bool use_loop_mdisp_flip); * \param ldata: the loops custom data. */ void BKE_mesh_polygon_flip_ex(const struct MPoly *poly, - struct MLoop *mloop, + int *corner_verts, + int *corner_edges, struct CustomData *ldata, float (*lnors)[3], struct MDisps *mdisp, bool use_loop_mdisp_flip); void BKE_mesh_polygon_flip(const struct MPoly *poly, - struct MLoop *mloop, + int *corner_verts, + int *corner_edges, struct CustomData *ldata, int totloop); /** @@ -615,7 +617,8 @@ void BKE_mesh_polygon_flip(const struct MPoly *poly, * \note Invalidates tessellation, caller must handle that. */ void BKE_mesh_polys_flip(const struct MPoly *polys, - struct MLoop *mloop, + int *corner_verts, + int *corner_edges, struct CustomData *ldata, int totpoly); @@ -652,7 +655,7 @@ void BKE_mesh_flush_select_from_verts(struct Mesh *me); */ void BKE_mesh_calc_relative_deform(const struct MPoly *polys, int totpoly, - const struct MLoop *mloop, + const int *corner_verts, int totvert, const float (*vert_cos_src)[3], @@ -702,7 +705,8 @@ bool BKE_mesh_validate_arrays(struct Mesh *me, unsigned int totedge, struct MFace *mfaces, unsigned int totface, - struct MLoop *mloops, + int *corner_verts, + int *corner_edges, unsigned int totloop, struct MPoly *polys, unsigned int totpoly, @@ -819,13 +823,24 @@ BLI_INLINE MPoly *BKE_mesh_polys_for_write(Mesh *mesh) return (MPoly *)CustomData_get_layer_for_write(&mesh->pdata, CD_MPOLY, mesh->totpoly); } -BLI_INLINE const MLoop *BKE_mesh_loops(const Mesh *mesh) +BLI_INLINE const int *BKE_mesh_corner_verts(const Mesh *mesh) { - return (const MLoop *)CustomData_get_layer(&mesh->ldata, CD_MLOOP); + return (const int *)CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_vert"); } -BLI_INLINE MLoop *BKE_mesh_loops_for_write(Mesh *mesh) +BLI_INLINE int *BKE_mesh_corner_verts_for_write(Mesh *mesh) { - return (MLoop *)CustomData_get_layer_for_write(&mesh->ldata, CD_MLOOP, mesh->totloop); + return (int *)CustomData_get_layer_named_for_write( + &mesh->ldata, CD_PROP_INT32, ".corner_vert", mesh->totloop); +} + +BLI_INLINE const int *BKE_mesh_corner_edges(const Mesh *mesh) +{ + return (const int *)CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge"); +} +BLI_INLINE int *BKE_mesh_corner_edges_for_write(Mesh *mesh) +{ + return (int *)CustomData_get_layer_named_for_write( + &mesh->ldata, CD_PROP_INT32, ".corner_edge", mesh->totloop); } BLI_INLINE const MDeformVert *BKE_mesh_deform_verts(const Mesh *mesh) diff --git a/source/blender/blenkernel/BKE_mesh.hh b/source/blender/blenkernel/BKE_mesh.hh index 7035b80dfd6..1ed858cf1aa 100644 --- a/source/blender/blenkernel/BKE_mesh.hh +++ b/source/blender/blenkernel/BKE_mesh.hh @@ -15,14 +15,14 @@ namespace blender::bke::mesh { * \{ */ /** Calculate the up direction for the polygon, depending on its winding direction. */ -float3 poly_normal_calc(Span vert_positions, Span poly_loops); +float3 poly_normal_calc(Span vert_positions, Span poly_verts); /** * Calculate tessellation into #MLoopTri which exist only for this purpose. */ void looptris_calc(Span vert_positions, Span polys, - Span loops, + Span corner_verts, MutableSpan looptris); /** * A version of #looptris_calc which takes pre-calculated polygon normals @@ -33,19 +33,19 @@ void looptris_calc(Span vert_positions, */ void looptris_calc_with_normals(Span vert_positions, Span polys, - Span loops, + Span corner_verts, Span poly_normals, MutableSpan looptris); /** Calculate the average position of the vertices in the polygon. */ -float3 poly_center_calc(Span vert_positions, Span poly_loops); +float3 poly_center_calc(Span vert_positions, Span poly_verts); /** Calculate the surface area of the polygon described by the indexed vertices. */ -float poly_area_calc(Span vert_positions, Span poly_loops); +float poly_area_calc(Span vert_positions, Span poly_verts); /** Calculate the angles at each of the polygons corners. */ void poly_angles_calc(Span vert_positions, - Span poly_loops, + Span poly_verts, MutableSpan angles); /** \} */ @@ -62,7 +62,7 @@ void poly_angles_calc(Span vert_positions, */ void normals_calc_polys(Span vert_positions, Span polys, - Span loops, + Span corner_verts, MutableSpan poly_normals); /** @@ -73,7 +73,7 @@ void normals_calc_polys(Span vert_positions, */ void normals_calc_poly_vert(Span vert_positions, Span polys, - Span loops, + Span corner_verts, MutableSpan poly_normals, MutableSpan vert_normals); @@ -82,14 +82,15 @@ void normals_calc_poly_vert(Span vert_positions, * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry * (splitting edges). * - * \param loop_to_poly_map: Optional pre-created map from loops to their polygon. + * \param loop_to_poly_map: Optional pre-created map from corners to their polygon. * \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on * each side of the edge. */ void normals_calc_loop(Span vert_positions, Span edges, Span polys, - Span loops, + Span corner_verts, + Span corner_edges, Span loop_to_poly_map, Span vert_normals, Span poly_normals, @@ -104,7 +105,8 @@ void normals_calc_loop(Span vert_positions, void normals_loop_custom_set(Span vert_positions, Span edges, Span polys, - Span loops, + Span corner_verts, + Span corner_edges, Span vert_normals, Span poly_normals, const bool *sharp_faces, @@ -115,7 +117,8 @@ void normals_loop_custom_set(Span vert_positions, void normals_loop_custom_set_from_verts(Span vert_positions, Span edges, Span polys, - Span loops, + Span corner_verts, + Span corner_edges, Span vert_normals, Span poly_normals, const bool *sharp_faces, @@ -132,7 +135,8 @@ void normals_loop_custom_set_from_verts(Span vert_positions, * \param sharp_faces: Optional array used to mark specific faces for sharp shading. */ void edges_sharp_from_angle_set(Span polys, - Span loops, + Span corner_verts, + Span corner_edges, Span poly_normals, const bool *sharp_faces, const float split_angle, @@ -174,13 +178,22 @@ inline blender::MutableSpan Mesh::polys_for_write() return {BKE_mesh_polys_for_write(this), this->totpoly}; } -inline blender::Span Mesh::loops() const +inline blender::Span Mesh::corner_verts() const { - return {BKE_mesh_loops(this), this->totloop}; + return {BKE_mesh_corner_verts(this), this->totloop}; } -inline blender::MutableSpan Mesh::loops_for_write() +inline blender::MutableSpan Mesh::corner_verts_for_write() { - return {BKE_mesh_loops_for_write(this), this->totloop}; + return {BKE_mesh_corner_verts_for_write(this), this->totloop}; +} + +inline blender::Span Mesh::corner_edges() const +{ + return {BKE_mesh_corner_edges(this), this->totloop}; +} +inline blender::MutableSpan Mesh::corner_edges_for_write() +{ + return {BKE_mesh_corner_edges_for_write(this), this->totloop}; } inline blender::Span Mesh::deform_verts() const diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.h b/source/blender/blenkernel/BKE_mesh_legacy_convert.h index 950cf76174c..8a0ae63ce72 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.h +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.h @@ -112,8 +112,15 @@ struct MVert *BKE_mesh_legacy_convert_positions_to_verts( void BKE_mesh_legacy_convert_verts_to_positions(Mesh *mesh); +struct MLoop *BKE_mesh_legacy_convert_corners_to_loops( + Mesh *mesh, + blender::ResourceScope &temp_arrays_for_convert, + blender::Vector &loop_layers_to_write); + #endif +void BKE_mesh_legacy_convert_loops_to_corners(struct Mesh *mesh); + /** * Recreate #MFace Tessellation. * diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index 6f14b25588f..839f9345aa7 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -15,7 +15,6 @@ extern "C" { #endif struct MEdge; -struct MLoop; struct MLoopTri; struct MPoly; @@ -104,7 +103,7 @@ typedef struct MeshElemMap { UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *polys, const bool *hide_poly, const bool *select_poly, - const struct MLoop *mloop, + const int *corner_verts, const float (*mloopuv)[2], unsigned int totpoly, unsigned int totvert, @@ -122,7 +121,7 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap); void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem, const struct MPoly *polys, - const struct MLoop *mloop, + const int *corner_verts, int totvert, int totpoly, int totloop); @@ -134,7 +133,7 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem, const struct MPoly *polys, - const struct MLoop *mloop, + const int *corner_verts, int totvert, int totpoly, int totloop); @@ -148,7 +147,7 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, int totvert, const struct MLoopTri *mlooptri, int totlooptri, - const struct MLoop *mloop, + const int *corner_verts, int totloop); /** * Generates a map where the key is the vertex and the value @@ -173,7 +172,7 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, int totedge, const struct MPoly *polys, int totpoly, - const struct MLoop *mloop, + const int *corner_edges, int totloop); /** * Generates a map where the key is the edge and the value @@ -185,7 +184,7 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int totedge, const struct MPoly *polys, int totpoly, - const struct MLoop *mloop, + const int *corner_edges, int totloop); /** * This function creates a map so the source-data (vert/edge/loop/poly) @@ -263,7 +262,8 @@ typedef bool (*MeshRemapIslandsCalc)(const float (*vert_positions)[3], const bool *uv_seams, const struct MPoly *polys, int totpoly, - const struct MLoop *loops, + const int *corner_verts, + const int *corner_edges, int totloop, struct MeshIslandStore *r_island_store); @@ -281,7 +281,8 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3], const bool *uv_seams, const struct MPoly *polys, int totpoly, - const struct MLoop *loops, + const int *corner_verts, + const int *corner_edges, int totloop, MeshIslandStore *r_island_store); @@ -305,7 +306,8 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], const bool *uv_seams, struct MPoly *polys, int totpoly, - struct MLoop *loops, + const int *corner_verts, + const int *corner_edges, int totloop, const float (*luvs)[2], MeshIslandStore *r_island_store); @@ -321,7 +323,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], int *BKE_mesh_calc_smoothgroups(int totedge, const struct MPoly *polys, int totpoly, - const struct MLoop *mloop, + const int *corner_edges, int totloop, const bool *sharp_edges, const bool *sharp_faces, @@ -351,11 +353,15 @@ namespace blender::bke::mesh_topology { Array build_loop_to_poly_map(Span polys, int loops_num); Array> build_vert_to_edge_map(Span edges, int verts_num); -Array> build_vert_to_poly_map(Span polys, Span loops, int verts_num); -Array> build_vert_to_loop_map(Span loops, int verts_num); -Array> build_edge_to_loop_map(Span loops, int edges_num); -Array> build_edge_to_poly_map(Span polys, Span loops, int edges_num); -Vector> build_edge_to_loop_map_resizable(Span loops, int edges_num); +Array> build_vert_to_poly_map(Span polys, + Span corner_verts, + int verts_num); +Array> build_vert_to_loop_map(Span corner_verts, int verts_num); +Array> build_edge_to_loop_map(Span corner_edges, int edges_num); +Array> build_edge_to_poly_map(Span polys, + Span corner_edges, + int edges_num); +Vector> build_edge_to_loop_map_resizable(Span corner_edges, int edges_num); inline int poly_loop_prev(const MPoly &poly, int loop_i) { diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h index d08c6cbbcee..81407732a20 100644 --- a/source/blender/blenkernel/BKE_mesh_remap.h +++ b/source/blender/blenkernel/BKE_mesh_remap.h @@ -202,7 +202,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode, int numverts_dst, const struct MEdge *edges_dst, int numedges_dst, - const struct MLoop *loops_dst, + const int *corner_verts_dst, + const int *corner_edges_dst, int numloops_dst, const struct MPoly *polys_dst, int numpolys_dst, @@ -222,7 +223,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(int mode, const struct Mesh *mesh_dst, const float (*vert_positions_dst)[3], int numverts_dst, - const struct MLoop *loops_dst, + const int *corner_verts, const struct MPoly *polys_dst, int numpolys_dst, struct Mesh *me_src, diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 1d96da5fb69..48907c21bc8 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -17,7 +17,6 @@ extern "C" { struct CustomData_MeshMasks; struct Depsgraph; struct KeyBlock; -struct MLoop; struct MLoopTri; struct MVertTri; struct Mesh; @@ -63,7 +62,7 @@ void BKE_mesh_runtime_clear_cache(struct Mesh *mesh); * Convert triangles encoded as face corner indices to triangles encoded as vertex indices. */ void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri, - const struct MLoop *mloop, + const int *corner_verts, const struct MLoopTri *looptri, int looptri_num); diff --git a/source/blender/blenkernel/BKE_mesh_sample.hh b/source/blender/blenkernel/BKE_mesh_sample.hh index 191c5c57ee9..3f181d0ae28 100644 --- a/source/blender/blenkernel/BKE_mesh_sample.hh +++ b/source/blender/blenkernel/BKE_mesh_sample.hh @@ -128,7 +128,7 @@ int sample_surface_points_projected( Vector &r_positions); float3 compute_bary_coord_in_triangle(Span vert_positions, - Span loops, + Span corner_verts, const MLoopTri &looptri, const float3 &position); diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h index 085096c77f1..47d43e984be 100644 --- a/source/blender/blenkernel/BKE_mesh_tangent.h +++ b/source/blender/blenkernel/BKE_mesh_tangent.h @@ -20,7 +20,7 @@ struct ReportList; */ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3], int numVerts, - const struct MLoop *mloops, + const int *corner_verts, float (*r_looptangent)[4], const float (*loop_normals)[3], const float (*loopuv)[2], @@ -45,7 +45,7 @@ void BKE_mesh_calc_loop_tangent_single(struct Mesh *mesh, void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], const struct MPoly *polys, uint polys_len, - const struct MLoop *mloop, + const int *corner_verts, const struct MLoopTri *looptri, uint looptri_len, const bool *sharp_faces, diff --git a/source/blender/blenkernel/BKE_mesh_types.h b/source/blender/blenkernel/BKE_mesh_types.h index 9b9efeeb761..9436ba971ca 100644 --- a/source/blender/blenkernel/BKE_mesh_types.h +++ b/source/blender/blenkernel/BKE_mesh_types.h @@ -49,7 +49,7 @@ typedef enum eMeshBatchDirtyMode { /** #MeshRuntime.wrapper_type */ typedef enum eMeshWrapperType { - /** Use mesh data (#Mesh.vert_positions(), #Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */ + /** Use mesh data (#Mesh.vert_positions(), #Mesh.medge, #Mesh.corner_verts(), #Mesh.mpoly). */ ME_WRAPPER_TYPE_MDATA = 0, /** Use edit-mesh data (#Mesh.edit_mesh, #MeshRuntime.edit_data). */ ME_WRAPPER_TYPE_BMESH = 1, diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 02a0e184087..ffe1d75f052 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -24,6 +24,7 @@ struct Object; struct Scene; struct SubdivCCG; +struct MLoopTri; struct MPoly; /** diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index c954b341b2e..82e601b3b96 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1558,6 +1558,11 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define GEO_NODE_IMAGE 1191 #define GEO_NODE_INTERPOLATE_CURVES 1192 #define GEO_NODE_EDGES_TO_FACE_GROUPS 1193 +#define GEO_NODE_POINTS_TO_SDF_VOLUME 1194 +#define GEO_NODE_MESH_TO_SDF_VOLUME 1195 +#define GEO_NODE_SDF_VOLUME_SPHERE 1196 +#define GEO_NODE_MEAN_FILTER_SDF_VOLUME 1197 +#define GEO_NODE_OFFSET_SDF_VOLUME 1198 /** \} */ diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh index 2355fd9ec6e..5da9cb7072a 100644 --- a/source/blender/blenkernel/BKE_node_runtime.hh +++ b/source/blender/blenkernel/BKE_node_runtime.hh @@ -153,13 +153,6 @@ class bNodeTreeRuntime : NonCopyable, NonMovable { Vector root_frames; Vector interface_inputs; Vector interface_outputs; - - /** - * The location of all sockets in the tree, calculated while drawing the nodes. - * Indexed with #bNodeSocket::index_in_tree(). In the node tree's "world space" - * (the same as #bNode::runtime::totr). - */ - Vector all_socket_locations; }; /** @@ -185,6 +178,13 @@ class bNodeSocketRuntime : NonCopyable, NonMovable { */ short total_inputs = 0; + /** + * The location of the socket in the tree, calculated while drawing the nodes and invalid if the + * node tree hasn't been drawn yet. In the node tree's "world space" (the same as + * #bNode::runtime::totr). + */ + float2 location; + /** Only valid when #topology_cache_is_dirty is false. */ Vector directly_linked_links; Vector directly_linked_sockets; diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index a9ac01c9f73..01a6b549923 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -37,7 +37,6 @@ struct Image; struct ImagePool; struct ImageUser; struct ListBase; -struct MLoop; struct MLoopTri; struct Main; struct Mesh; @@ -578,7 +577,7 @@ typedef struct SculptSession { /* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */ float (*vert_positions)[3]; const struct MPoly *polys; - const struct MLoop *mloop; + const int *corner_verts; /* These contain the vertex and poly counts of the final mesh. */ int totvert, totpoly; diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 833cb425987..719ffb9075e 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -29,7 +29,6 @@ struct CCGKey; struct CustomData; struct DMFlagMat; struct IsectRayPrecalc; -struct MLoop; struct MLoopTri; struct MPoly; struct Mesh; @@ -283,13 +282,13 @@ PBVH *BKE_pbvh_new(PBVHType type); /** * Do a full rebuild with on Mesh data structure. * - * \note Unlike mpoly/mloop/verts, looptri is *totally owned* by PBVH + * \note Unlike mpoly/corner_verts/verts, looptri is *totally owned* by PBVH * (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply(). */ void BKE_pbvh_build_mesh(PBVH *pbvh, struct Mesh *mesh, const struct MPoly *polys, - const struct MLoop *mloop, + const int *corner_verts, float (*vert_positions)[3], int totvert, struct CustomData *vdata, @@ -510,7 +509,7 @@ const int *BKE_pbvh_node_get_vert_indices(PBVHNode *node); void BKE_pbvh_node_get_loops(PBVH *pbvh, PBVHNode *node, const int **r_loop_indices, - const struct MLoop **r_loops); + const int **r_corner_verts); /* Get number of faces in the mesh; for PBVH_GRIDS the * number of base mesh faces is returned. @@ -737,7 +736,7 @@ typedef struct PBVHFaceIter { int *face_sets_; const struct MPoly *polys_; const struct MLoopTri *looptri_; - const struct MLoop *mloop_; + const int *corner_verts_; int prim_index_; const struct SubdivCCG *subdiv_ccg_; const struct BMesh *bm; diff --git a/source/blender/blenkernel/BKE_pbvh_pixels.hh b/source/blender/blenkernel/BKE_pbvh_pixels.hh index f8f71c2a602..9110ba4f8f9 100644 --- a/source/blender/blenkernel/BKE_pbvh_pixels.hh +++ b/source/blender/blenkernel/BKE_pbvh_pixels.hh @@ -256,8 +256,8 @@ struct NodeData { MEM_delete(node_data); } }; -/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ /** \name Fix non-manifold edge bleeding. * \{ */ diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 79a3bdf7c3c..dc05646884c 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -122,11 +122,11 @@ typedef struct PTCacheID { /* flags defined in DNA_object_force_types.h */ unsigned int data_types, info_types; - /* copies point data to cache data */ + /* Copies point data to cache data. */ int (*write_point)(int index, void *calldata, void **data, int cfra); - /* copies cache cata to point data */ + /* Copies cache data to point data. */ void (*read_point)(int index, void *calldata, void **data, float cfra, const float *old_data); - /* interpolated between previously read point data and cache data */ + /* Interpolated between previously read point data and cache data. */ void (*interpolate_point)(int index, void *calldata, void **data, diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 707dbc0ada6..40e45b58b52 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -75,6 +75,7 @@ typedef struct ShrinkwrapTreeData { const struct MPoly *polys; const float (*vert_normals)[3]; + const int *corner_edges; const float (*poly_normals)[3]; const bool *sharp_faces; const float (*clnors)[3]; diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index 582e0774a58..bc35aae1ff6 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -21,7 +21,6 @@ struct CCGKey; struct DMFlagMat; struct Mesh; struct MPoly; -struct MLoop; struct Subdiv; /* -------------------------------------------------------------------- @@ -310,8 +309,8 @@ typedef enum SubdivCCGAdjacencyType { * adjacent to a vertex, r_v1 and r_v2 will be the index of that vertex. */ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, - const struct MLoop *mloop, - const struct MPoly *polys, + const int *corner_verts, + const struct MPoly *mpoly, int *r_v1, int *r_v2); diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h index 9273ea14127..42af44a299e 100644 --- a/source/blender/blenkernel/BKE_volume.h +++ b/source/blender/blenkernel/BKE_volume.h @@ -76,6 +76,7 @@ VolumeGrid *BKE_volume_grid_get_for_write(struct Volume *volume, int grid_index) const VolumeGrid *BKE_volume_grid_active_get_for_read(const struct Volume *volume); /* Tries to find a grid with the given name. Make sure that the volume has been loaded. */ const VolumeGrid *BKE_volume_grid_find_for_read(const struct Volume *volume, const char *name); +VolumeGrid *BKE_volume_grid_find_for_write(struct Volume *volume, const char *name); /* Tries to set the name of the velocity field. If no such grid exists with the given base name, * this will try common post-fixes in order to detect velocity fields split into multiple grids. diff --git a/source/blender/blenkernel/BKE_volume_to_mesh.hh b/source/blender/blenkernel/BKE_volume_to_mesh.hh index 15e405a103d..33ff97b0fe9 100644 --- a/source/blender/blenkernel/BKE_volume_to_mesh.hh +++ b/source/blender/blenkernel/BKE_volume_to_mesh.hh @@ -64,7 +64,7 @@ void fill_mesh_from_openvdb_data(const Span vdb_verts, int loop_offset, MutableSpan vert_positions, MutableSpan polys, - MutableSpan loops); + MutableSpan corner_verts); #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index e42892ea937..f6fcd4278a0 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -122,19 +122,32 @@ static MEdge *dm_getEdgeArray(DerivedMesh *dm) return edge; } -static MLoop *dm_getLoopArray(DerivedMesh *dm) +static int *dm_getCornerVertArray(DerivedMesh *dm) { - MLoop *mloop = (MLoop *)CustomData_get_layer_for_write( - &dm->loopData, CD_MLOOP, dm->getNumLoops(dm)); + int *corner_verts = (int *)CustomData_get_layer_named_for_write( + &dm->loopData, CD_PROP_INT32, ".corner_vert", dm->getNumLoops(dm)); - if (!mloop) { - mloop = (MLoop *)CustomData_add_layer( - &dm->loopData, CD_MLOOP, CD_SET_DEFAULT, dm->getNumLoops(dm)); - CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY); - dm->copyLoopArray(dm, mloop); + if (!corner_verts) { + corner_verts = (int *)CustomData_add_layer_named( + &dm->loopData, CD_PROP_INT32, CD_SET_DEFAULT, dm->getNumLoops(dm), ".corner_vert"); + dm->copyCornerVertArray(dm, corner_verts); } - return mloop; + return corner_verts; +} + +static int *dm_getCornerEdgeArray(DerivedMesh *dm) +{ + int *corner_edges = (int *)CustomData_get_layer_named( + &dm->loopData, CD_PROP_INT32, ".corner_edge"); + + if (!corner_edges) { + corner_edges = (int *)CustomData_add_layer_named( + &dm->loopData, CD_PROP_INT32, CD_SET_DEFAULT, dm->getNumLoops(dm), ".corner_edge"); + dm->copyCornerEdgeArray(dm, corner_edges); + } + + return corner_edges; } static MPoly *dm_getPolyArray(DerivedMesh *dm) @@ -188,7 +201,8 @@ void DM_init_funcs(DerivedMesh *dm) /* default function implementations */ dm->getVertArray = dm_getVertArray; dm->getEdgeArray = dm_getEdgeArray; - dm->getLoopArray = dm_getLoopArray; + dm->getCornerVertArray = dm_getCornerVertArray; + dm->getCornerEdgeArray = dm_getCornerEdgeArray; dm->getPolyArray = dm_getPolyArray; dm->getLoopTriArray = dm_getLoopTriArray; @@ -1891,7 +1905,7 @@ static void mesh_init_origspace(Mesh *mesh) &mesh->ldata, CD_ORIGSPACE_MLOOP, mesh->totloop); const Span positions = mesh->vert_positions(); const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); int j, k; @@ -1907,7 +1921,6 @@ static void mesh_init_origspace(Mesh *mesh) } } else { - const MLoop *l = &loops[poly.loopstart]; float co[3]; float mat[3][3]; @@ -1915,13 +1928,13 @@ static void mesh_init_origspace(Mesh *mesh) float translate[2], scale[2]; const float3 p_nor = blender::bke::mesh::poly_normal_calc( - positions, loops.slice(poly.loopstart, poly.totloop)); + positions, corner_verts.slice(poly.loopstart, poly.totloop)); axis_dominant_v3_to_m3(mat, p_nor); vcos_2d.resize(poly.totloop); - for (j = 0; j < poly.totloop; j++, l++) { - mul_v3_m3v3(co, mat, positions[l->v]); + for (j = 0; j < poly.totloop; j++) { + mul_v3_m3v3(co, mat, positions[corner_verts[poly.loopstart + j]]); copy_v2_v2(vcos_2d[j], co); for (k = 0; k < 2; k++) { diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index b8235176502..e81fa183e4b 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -3767,12 +3767,12 @@ void BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context, NlaEvalChannelSnapshot *blended_necs = nlaeval_snapshot_ensure_channel(&blended_snapshot, nec); memcpy(blended_necs->values, values, sizeof(float) * count); - /* Force all channels to be remapped for quaternions in a Combine strip, otherwise it will - * always fail. See nlaevalchan_combine_quaternion_handle_undefined_blend_values(). + /* Force all channels to be remapped for quaternions in a Combine or Replace strip, otherwise it + * will always fail. See nlaevalchan_combine_quaternion_handle_undefined_blend_values(). */ const bool can_force_all = r_force_all != NULL; if (blended_necs->channel->mix_mode == NEC_MIX_QUATERNION && - blend_mode == NLASTRIP_MODE_COMBINE && can_force_all) { + ELEM(blend_mode, NLASTRIP_MODE_COMBINE, NLASTRIP_MODE_REPLACE) && can_force_all) { *r_force_all = true; index = -1; diff --git a/source/blender/blenkernel/intern/attribute.cc b/source/blender/blenkernel/intern/attribute.cc index 3922d5b5238..bb993156eae 100644 --- a/source/blender/blenkernel/intern/attribute.cc +++ b/source/blender/blenkernel/intern/attribute.cc @@ -370,6 +370,26 @@ CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList return BKE_id_attribute_search(id, uniquename, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL); } +static int color_name_to_index(ID *id, const char *name) +{ + const CustomDataLayer *layer = BKE_id_attribute_search( + id, name, CD_MASK_COLOR_ALL, ATTR_DOMAIN_MASK_COLOR); + return BKE_id_attribute_to_index(id, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); +} + +static int color_clamp_index(ID *id, int index) +{ + const int length = BKE_id_attributes_length(id, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); + return min_ii(index, length - 1); +} + +static const char *color_name_from_index(ID *id, int index) +{ + const CustomDataLayer *layer = BKE_id_attribute_from_index( + id, index, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); + return layer ? layer->name : nullptr; +} + bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports) { using namespace blender; @@ -391,31 +411,43 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports) if (BMEditMesh *em = mesh->edit_mesh) { for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) { if (CustomData *data = info[domain].customdata) { - int layer_index = CustomData_get_named_layer_index_notype(data, name); - if (layer_index >= 0) { - if (data->layers[layer_index].type == CD_PROP_FLOAT2) { - /* free associated UV map bool layers */ - char buffer_src[MAX_CUSTOMDATA_LAYER_NAME]; - BM_data_layer_free_named( - em->bm, data, BKE_uv_map_vert_select_name_get(name, buffer_src)); - BM_data_layer_free_named( - em->bm, data, BKE_uv_map_edge_select_name_get(name, buffer_src)); - BM_data_layer_free_named(em->bm, data, BKE_uv_map_pin_name_get(name, buffer_src)); - } + const std::string name_copy = name; + const int layer_index = CustomData_get_named_layer_index_notype(data, name_copy.c_str()); + if (layer_index == -1) { + continue; } - /* Because it's possible that name is owned by the layer and will be freed - * when freeing the layer, do these checks before freeing. */ - const bool is_active_color_attribute = name == StringRef(mesh->active_color_attribute); - const bool is_default_color_attribute = name == StringRef(mesh->default_color_attribute); - if (BM_data_layer_free_named(em->bm, data, name)) { - if (is_active_color_attribute) { - MEM_SAFE_FREE(mesh->active_color_attribute); - } - else if (is_default_color_attribute) { - MEM_SAFE_FREE(mesh->default_color_attribute); - } - return true; + + const eCustomDataType type = eCustomDataType(data->layers[layer_index].type); + const bool is_active_color_attribute = name_copy.c_str() == + StringRef(mesh->active_color_attribute); + const bool is_default_color_attribute = name_copy.c_str() == + StringRef(mesh->default_color_attribute); + const int active_color_index = color_name_to_index(id, mesh->active_color_attribute); + const int default_color_index = color_name_to_index(id, mesh->default_color_attribute); + + if (!BM_data_layer_free_named(em->bm, data, name_copy.c_str())) { + BLI_assert_unreachable(); } + + if (is_active_color_attribute) { + BKE_id_attributes_active_color_set( + id, color_name_from_index(id, color_clamp_index(id, active_color_index))); + } + if (is_default_color_attribute) { + BKE_id_attributes_default_color_set( + id, color_name_from_index(id, color_clamp_index(id, default_color_index))); + } + + if (type == CD_PROP_FLOAT2 && domain == ATTR_DOMAIN_CORNER) { + char buffer[MAX_CUSTOMDATA_LAYER_NAME]; + BM_data_layer_free_named( + em->bm, data, BKE_uv_map_vert_select_name_get(name_copy.c_str(), buffer)); + BM_data_layer_free_named( + em->bm, data, BKE_uv_map_edge_select_name_get(name_copy.c_str(), buffer)); + BM_data_layer_free_named( + em->bm, data, BKE_uv_map_pin_name_get(name_copy.c_str(), buffer)); + } + return true; } } return false; @@ -423,21 +455,44 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports) } std::optional attributes = get_attribute_accessor_for_write(*id); - if (!attributes) { return false; } if (GS(id->name) == ID_ME) { - - std::optional metadata = attributes->lookup_meta_data(name); - if (metadata->data_type == CD_PROP_FLOAT2) { - /* remove UV sub-attributes. */ - char buffer_src[MAX_CUSTOMDATA_LAYER_NAME]; - BKE_id_attribute_remove(id, BKE_uv_map_vert_select_name_get(name, buffer_src), reports); - BKE_id_attribute_remove(id, BKE_uv_map_edge_select_name_get(name, buffer_src), reports); - BKE_id_attribute_remove(id, BKE_uv_map_pin_name_get(name, buffer_src), reports); + const std::string name_copy = name; + std::optional metadata = attributes->lookup_meta_data( + name_copy); + if (!metadata) { + return false; } + /* Update active and default color attributes. */ + Mesh *mesh = reinterpret_cast(id); + const bool is_active_color_attribute = name_copy == StringRef(mesh->active_color_attribute); + const bool is_default_color_attribute = name_copy == StringRef(mesh->default_color_attribute); + const int active_color_index = color_name_to_index(id, mesh->active_color_attribute); + const int default_color_index = color_name_to_index(id, mesh->default_color_attribute); + + if (!attributes->remove(name_copy)) { + BLI_assert_unreachable(); + } + + if (is_active_color_attribute) { + BKE_id_attributes_active_color_set( + id, color_name_from_index(id, color_clamp_index(id, active_color_index))); + } + if (is_default_color_attribute) { + BKE_id_attributes_default_color_set( + id, color_name_from_index(id, color_clamp_index(id, default_color_index))); + } + + if (metadata->data_type == CD_PROP_FLOAT2 && metadata->domain == ATTR_DOMAIN_CORNER) { + char buffer[MAX_CUSTOMDATA_LAYER_NAME]; + attributes->remove(BKE_uv_map_vert_select_name_get(name_copy.c_str(), buffer)); + attributes->remove(BKE_uv_map_edge_select_name_get(name_copy.c_str(), buffer)); + attributes->remove(BKE_uv_map_pin_name_get(name_copy.c_str(), buffer)); + } + return true; } return attributes->remove(name); diff --git a/source/blender/blenkernel/intern/blendfile.cc b/source/blender/blenkernel/intern/blendfile.cc index be6c3f96dce..0d12ddf152e 100644 --- a/source/blender/blenkernel/intern/blendfile.cc +++ b/source/blender/blenkernel/intern/blendfile.cc @@ -14,6 +14,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "DNA_workspace_types.h" #include "BLI_fileops.h" @@ -62,6 +63,81 @@ # include "BPY_extern.h" #endif +/* -------------------------------------------------------------------- */ +/** \name Blend/Library Paths + * \{ */ + +bool BKE_blendfile_extension_check(const char *str) +{ + const char *ext_test[4] = {".blend", ".ble", ".blend.gz", nullptr}; + return BLI_path_extension_check_array(str, ext_test); +} + +bool BKE_blendfile_library_path_explode(const char *path, + char *r_dir, + char **r_group, + char **r_name) +{ + /* We might get some data names with slashes, + * so we have to go up in path until we find blend file itself, + * then we know next path item is group, and everything else is data name. */ + char *slash = nullptr, *prev_slash = nullptr, c = '\0'; + + r_dir[0] = '\0'; + if (r_group) { + *r_group = nullptr; + } + if (r_name) { + *r_name = nullptr; + } + + /* if path leads to an existing directory, we can be sure we're not (in) a library */ + if (BLI_is_dir(path)) { + return false; + } + + BLI_strncpy(r_dir, path, FILE_MAX_LIBEXTRA); + + while ((slash = (char *)BLI_path_slash_rfind(r_dir))) { + char tc = *slash; + *slash = '\0'; + if (BKE_blendfile_extension_check(r_dir) && BLI_is_file(r_dir)) { + break; + } + if (STREQ(r_dir, BLO_EMBEDDED_STARTUP_BLEND)) { + break; + } + + if (prev_slash) { + *prev_slash = c; + } + prev_slash = slash; + c = tc; + } + + if (!slash) { + return false; + } + + if (slash[1] != '\0') { + BLI_assert(strlen(slash + 1) < BLO_GROUP_MAX); + if (r_group) { + *r_group = slash + 1; + } + } + + if (prev_slash && (prev_slash[1] != '\0')) { + BLI_assert(strlen(prev_slash + 1) < MAX_ID_NAME - 2); + if (r_name) { + *r_name = prev_slash + 1; + } + } + + return true; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Blend File IO (High Level) * \{ */ diff --git a/source/blender/blenkernel/intern/bvhutils.cc b/source/blender/blenkernel/intern/bvhutils.cc index feb2577e09f..8d032d07043 100644 --- a/source/blender/blenkernel/intern/bvhutils.cc +++ b/source/blender/blenkernel/intern/bvhutils.cc @@ -276,9 +276,9 @@ static void mesh_looptri_nearest_point(void *userdata, const float(*positions)[3] = data->vert_positions; const MLoopTri *lt = &data->looptri[index]; const float *vtri_co[3] = { - positions[data->loop[lt->tri[0]].v], - positions[data->loop[lt->tri[1]].v], - positions[data->loop[lt->tri[2]].v], + positions[data->corner_verts[lt->tri[0]]], + positions[data->corner_verts[lt->tri[1]]], + positions[data->corner_verts[lt->tri[2]]], }; float nearest_tmp[3], dist_sq; @@ -376,9 +376,9 @@ static void mesh_looptri_spherecast(void *userdata, const float(*positions)[3] = data->vert_positions; const MLoopTri *lt = &data->looptri[index]; const float *vtri_co[3] = { - positions[data->loop[lt->tri[0]].v], - positions[data->loop[lt->tri[1]].v], - positions[data->loop[lt->tri[2]].v], + positions[data->corner_verts[lt->tri[0]]], + positions[data->corner_verts[lt->tri[1]]], + positions[data->corner_verts[lt->tri[2]]], }; float dist; @@ -579,7 +579,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree, const float (*positions)[3], const MEdge *edge, const MFace *face, - const MLoop *loop, + const int *corner_verts, const Span looptris, BVHTreeFromMesh *r_data) { @@ -590,7 +590,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree, r_data->vert_positions = positions; r_data->edge = edge; r_data->face = face; - r_data->loop = loop; + r_data->corner_verts = corner_verts; r_data->looptri = looptris.data(); switch (bvh_cache_type) { @@ -1036,7 +1036,7 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon, int tree_type, int axis, const float (*positions)[3], - const MLoop *mloop, + const int *corner_verts, const Span looptris, const BitSpan looptri_mask, int looptri_num_active) @@ -1065,9 +1065,9 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon, continue; } - copy_v3_v3(co[0], positions[mloop[looptris[i].tri[0]].v]); - copy_v3_v3(co[1], positions[mloop[looptris[i].tri[1]].v]); - copy_v3_v3(co[2], positions[mloop[looptris[i].tri[2]].v]); + copy_v3_v3(co[0], positions[corner_verts[looptris[i].tri[0]]]); + copy_v3_v3(co[1], positions[corner_verts[looptris[i].tri[1]]]); + copy_v3_v3(co[2], positions[corner_verts[looptris[i].tri[2]]]); BLI_bvhtree_insert(tree, i, co[0], 3); } @@ -1106,7 +1106,7 @@ BVHTree *bvhtree_from_editmesh_looptri( BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, const float (*vert_positions)[3], - const struct MLoop *mloop, + const int *corner_verts, const struct MLoopTri *looptri, const int looptri_num, const BitSpan looptri_mask, @@ -1119,7 +1119,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, tree_type, axis, vert_positions, - mloop, + corner_verts, {looptri, looptri_num}, looptri_mask, looptri_num_active); @@ -1133,7 +1133,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, vert_positions, nullptr, nullptr, - mloop, + corner_verts, {looptri, looptri_num}, data); } @@ -1218,7 +1218,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, } const float(*positions)[3] = reinterpret_cast(mesh->vert_positions().data()); const Span edges = mesh->edges(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_setup_data(nullptr, @@ -1226,7 +1226,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, positions, edges.data(), (const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE), - loops.data(), + corner_verts.data(), looptris, data); @@ -1286,7 +1286,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, } case BVHTREE_FROM_LOOPTRI: data->tree = bvhtree_from_mesh_looptri_create_tree( - 0.0f, tree_type, 6, positions, loops.data(), looptris, mask, mask_bits_act_len); + 0.0f, tree_type, 6, positions, corner_verts.data(), looptris, mask, mask_bits_act_len); break; case BVHTREE_FROM_EM_VERTS: case BVHTREE_FROM_EM_EDGES: diff --git a/source/blender/blenkernel/intern/cdderivedmesh.cc b/source/blender/blenkernel/intern/cdderivedmesh.cc index 9d244f1b441..fa7273314a2 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.cc +++ b/source/blender/blenkernel/intern/cdderivedmesh.cc @@ -42,7 +42,8 @@ struct CDDerivedMesh { const blender::float3 *vert_normals; MEdge *medge; MFace *mface; - MLoop *mloop; + int *corner_verts; + int *corner_edges; MPoly *mpoly; /* Cached */ @@ -87,10 +88,16 @@ static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge) memcpy(r_edge, cddm->medge, sizeof(*r_edge) * dm->numEdgeData); } -static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop) +static void cdDM_copyCornerVertArray(DerivedMesh *dm, int *r_corner_verts) { CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - memcpy(r_loop, cddm->mloop, sizeof(*r_loop) * dm->numLoopData); + memcpy(r_corner_verts, cddm->corner_verts, sizeof(*r_corner_verts) * dm->numLoopData); +} + +static void cdDM_copyCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges) +{ + CDDerivedMesh *cddm = (CDDerivedMesh *)dm; + memcpy(r_corner_edges, cddm->corner_edges, sizeof(*r_corner_edges) * dm->numLoopData); } static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly) @@ -124,7 +131,7 @@ static void cdDM_recalc_looptri(DerivedMesh *dm) blender::bke::mesh::looptris_calc( {reinterpret_cast(cddm->vert_positions), dm->numVertData}, {cddm->mpoly, totpoly}, - {cddm->mloop, totloop}, + {cddm->corner_verts, totloop}, {dm->looptris.array_wip, dm->looptris.num}); BLI_assert(cddm->dm.looptris.array == NULL); @@ -166,7 +173,8 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->copyVertArray = cdDM_copyVertArray; dm->copyEdgeArray = cdDM_copyEdgeArray; - dm->copyLoopArray = cdDM_copyLoopArray; + dm->copyCornerVertArray = cdDM_copyCornerVertArray; + dm->copyCornerEdgeArray = cdDM_copyCornerEdgeArray; dm->copyPolyArray = cdDM_copyPolyArray; dm->getVertDataArray = DM_get_vert_data_layer; @@ -224,8 +232,10 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh, cddm->vert_normals = mesh->vert_normals().data(); cddm->medge = static_cast( CustomData_get_layer_for_write(&dm->edgeData, CD_MEDGE, mesh->totedge)); - cddm->mloop = static_cast( - CustomData_get_layer_for_write(&dm->loopData, CD_MLOOP, mesh->totloop)); + cddm->corner_verts = static_cast(CustomData_get_layer_named_for_write( + &dm->loopData, CD_PROP_INT32, ".corner_vert", mesh->totloop)); + cddm->corner_edges = static_cast(CustomData_get_layer_named_for_write( + &dm->loopData, CD_PROP_INT32, ".corner_edge", mesh->totloop)); cddm->mpoly = static_cast( CustomData_get_layer_for_write(&dm->polyData, CD_MPOLY, mesh->totpoly)); #if 0 diff --git a/source/blender/blenkernel/intern/cloth.cc b/source/blender/blenkernel/intern/cloth.cc index f83e8056109..bd85b0f3f33 100644 --- a/source/blender/blenkernel/intern/cloth.cc +++ b/source/blender/blenkernel/intern/cloth.cc @@ -835,7 +835,7 @@ static bool cloth_from_object( static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh) { - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); const blender::Span looptris = mesh->looptris(); const uint mvert_num = mesh->totvert; @@ -868,7 +868,7 @@ static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mes return; } BKE_mesh_runtime_verttri_from_looptri( - clmd->clothObject->tri, loops.data(), looptris.data(), looptris.size()); + clmd->clothObject->tri, corner_verts.data(), looptris.data(), looptris.size()); clmd->clothObject->edges = mesh->edges().data(); @@ -1288,7 +1288,7 @@ void cloth_parallel_transport_hair_frame(float mat[3][3], /* Add a shear and a bend spring between two verts within a poly. */ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, LinkNodePair *edgelist, - const blender::Span loops, + const blender::Span corner_verts, const blender::Span polys, int i, int j, @@ -1296,7 +1296,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, { Cloth *cloth = clmd->clothObject; ClothSpring *spring; - const MLoop *tmp_loop; + const int *tmp_corner; float shrink_factor; int x, y; @@ -1308,7 +1308,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, } spring_verts_ordered_set( - spring, loops[polys[i].loopstart + j].v, loops[polys[i].loopstart + k].v); + spring, corner_verts[polys[i].loopstart + j], corner_verts[polys[i].loopstart + k]); shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * @@ -1340,18 +1340,18 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, return false; } - tmp_loop = &loops[polys[i].loopstart]; + tmp_corner = &corner_verts[polys[i].loopstart]; for (x = 0; x < spring->la; x++) { - spring->pa[x] = tmp_loop[j + x].v; + spring->pa[x] = tmp_corner[j + x]; } for (x = 0; x <= j; x++) { - spring->pb[x] = tmp_loop[x].v; + spring->pb[x] = tmp_corner[x]; } for (y = k; y < polys[i].totloop; x++, y++) { - spring->pb[x] = tmp_loop[y].v; + spring->pb[x] = tmp_corner[y]; } spring->mn = -1; @@ -1369,7 +1369,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, return true; } -BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop *mloop) +BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const int *corner_verts) { int *p = static_cast(MEM_mallocN(sizeof(int) * len, "spring poly")); @@ -1377,8 +1377,8 @@ BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop return false; } - for (int i = 0; i < len; i++, mloop++) { - p[i] = mloop->v; + for (int i = 0; i < len; i++) { + p[i] = corner_verts[i]; } *poly = p; @@ -1431,7 +1431,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata); uint vert_idx = -1; - const MLoop *mloop = treedata->loop; + const int *corner_verts = treedata->corner_verts; const MLoopTri *lt = nullptr; if (rayhit.index != -1 && rayhit.dist <= max_length) { @@ -1444,7 +1444,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, lt = &treedata->looptri[rayhit.index]; for (int i = 0; i < 3; i++) { - uint tmp_vert_idx = mloop[lt->tri[i]].v; + uint tmp_vert_idx = corner_verts[lt->tri[i]]; if (tmp_vert_idx == v_idx) { /* We managed to hit ourselves. */ return false; @@ -1466,6 +1466,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) { + using namespace blender; using namespace blender::bke; Cloth *cloth = clmd->clothObject; ClothSpring *spring = nullptr, *tspring = nullptr, *tspring2 = nullptr; @@ -1476,7 +1477,8 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) float shrink_factor; const blender::Span edges = mesh->edges(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); + const Span corner_edges = mesh->corner_edges(); int index2 = 0; /* our second vertex index */ LinkNodePair *edgelist = nullptr; EdgeSet *edgeset = nullptr; @@ -1672,7 +1674,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) if (polys[i].totloop > 3) { for (int j = 1; j < polys[i].totloop - 1; j++) { if (j > 1) { - if (cloth_add_shear_bend_spring(clmd, edgelist, loops, polys, i, 0, j)) { + if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, polys, i, 0, j)) { shear_springs++; if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { @@ -1686,7 +1688,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) } for (int k = j + 2; k < polys[i].totloop; k++) { - if (cloth_add_shear_bend_spring(clmd, edgelist, loops, polys, i, j, k)) { + if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, polys, i, j, k)) { shear_springs++; if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { @@ -1703,10 +1705,9 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) /* Angular bending springs along struct springs. */ if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { - const MLoop *ml = &loops[polys[i].loopstart]; - - for (int j = 0; j < polys[i].totloop; j++, ml++) { - BendSpringRef *curr_ref = &spring_ref[ml->e]; + for (int j = 0; j < polys[i].totloop; j++) { + const int edge_i = corner_edges[polys[i].loopstart + j]; + BendSpringRef *curr_ref = &spring_ref[edge_i]; curr_ref->polys++; /* First poly found for this edge, store poly index. */ @@ -1723,14 +1724,14 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) spring->lb = polys[i].totloop; if (!cloth_bend_set_poly_vert_array( - &spring->pa, spring->la, &loops[polys[curr_ref->index].loopstart]) || + &spring->pa, spring->la, &corner_verts[polys[curr_ref->index].loopstart]) || !cloth_bend_set_poly_vert_array( - &spring->pb, spring->lb, &loops[polys[i].loopstart])) { + &spring->pb, spring->lb, &corner_verts[polys[i].loopstart])) { cloth_free_errorsprings(cloth, edgelist, spring_ref); return false; } - spring->mn = ml->e; + spring->mn = edge_i; spring->restang = cloth_spring_angle(cloth->verts, spring->ij, @@ -1897,8 +1898,10 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) for (int i = 0; i < numpolys; i++) { /* edge springs */ if (polys[i].totloop == 4) { - BLI_edgeset_add(edgeset, loops[polys[i].loopstart + 0].v, loops[polys[i].loopstart + 2].v); - BLI_edgeset_add(edgeset, loops[polys[i].loopstart + 1].v, loops[polys[i].loopstart + 3].v); + BLI_edgeset_add( + edgeset, corner_verts[polys[i].loopstart + 0], corner_verts[polys[i].loopstart + 2]); + BLI_edgeset_add( + edgeset, corner_verts[polys[i].loopstart + 1], corner_verts[polys[i].loopstart + 3]); } } diff --git a/source/blender/blenkernel/intern/context.cc b/source/blender/blenkernel/intern/context.cc index 1ff84bebc62..36eec388622 100644 --- a/source/blender/blenkernel/intern/context.cc +++ b/source/blender/blenkernel/intern/context.cc @@ -1493,6 +1493,11 @@ AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid) return AssetHandle{nullptr}; } +AssetRepresentation *CTX_wm_asset(const bContext *C) +{ + return static_cast(ctx_data_pointer_get(C, "asset")); +} + Depsgraph *CTX_data_depsgraph_pointer(const bContext *C) { Main *bmain = CTX_data_main(C); diff --git a/source/blender/blenkernel/intern/crazyspace.cc b/source/blender/blenkernel/intern/crazyspace.cc index 0f1cd0a2f06..0557921e699 100644 --- a/source/blender/blenkernel/intern/crazyspace.cc +++ b/source/blender/blenkernel/intern/crazyspace.cc @@ -190,44 +190,44 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me, /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */ const Span positions = me->vert_positions(); const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); for (int i = 0; i < me->totpoly; i++) { const MPoly &poly = polys[i]; - const MLoop *ml_next = &loops[poly.loopstart]; - const MLoop *ml_curr = &ml_next[poly.totloop - 1]; - const MLoop *ml_prev = &ml_next[poly.totloop - 2]; + const int *corner_vert_next = &corner_verts[poly.loopstart]; + const int *corner_vert_curr = &corner_vert_next[poly.totloop - 1]; + const int *corner_vert_prev = &corner_vert_next[poly.totloop - 2]; for (int j = 0; j < poly.totloop; j++) { - if (!BLI_BITMAP_TEST(vert_tag, ml_curr->v)) { + if (!BLI_BITMAP_TEST(vert_tag, *corner_vert_curr)) { const float *co_prev, *co_curr, *co_next; /* orig */ const float *vd_prev, *vd_curr, *vd_next; /* deform */ /* retrieve mapped coordinates */ - vd_prev = mappedcos[ml_prev->v]; - vd_curr = mappedcos[ml_curr->v]; - vd_next = mappedcos[ml_next->v]; + vd_prev = mappedcos[*corner_vert_prev]; + vd_curr = mappedcos[*corner_vert_curr]; + vd_next = mappedcos[*corner_vert_next]; if (origcos) { - co_prev = origcos[ml_prev->v]; - co_curr = origcos[ml_curr->v]; - co_next = origcos[ml_next->v]; + co_prev = origcos[*corner_vert_prev]; + co_curr = origcos[*corner_vert_curr]; + co_next = origcos[*corner_vert_next]; } else { - co_prev = positions[ml_prev->v]; - co_curr = positions[ml_curr->v]; - co_next = positions[ml_next->v]; + co_prev = positions[*corner_vert_prev]; + co_curr = positions[*corner_vert_curr]; + co_next = positions[*corner_vert_next]; } set_crazy_vertex_quat( - quats[ml_curr->v], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev); + quats[*corner_vert_curr], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev); - BLI_BITMAP_ENABLE(vert_tag, ml_curr->v); + BLI_BITMAP_ENABLE(vert_tag, *corner_vert_curr); } - ml_prev = ml_curr; - ml_curr = ml_next; - ml_next++; + corner_vert_prev = corner_vert_curr; + corner_vert_curr = corner_vert_next; + corner_vert_next++; } } diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index d90da24f2b2..8d893645f74 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -28,7 +28,8 @@ static void fill_mesh_topology(const int vert_offset, const bool profile_cyclic, const bool fill_caps, MutableSpan edges, - MutableSpan loops, + MutableSpan corner_verts, + MutableSpan corner_edges, MutableSpan polys) { const int main_segment_num = curves::segments_num(main_point_num, main_cyclic); @@ -104,18 +105,17 @@ static void fill_mesh_topology(const int vert_offset, poly.loopstart = ring_segment_loop_offset; poly.totloop = 4; - MLoop &loop_a = loops[ring_segment_loop_offset]; - loop_a.v = ring_vert_offset + i_profile; - loop_a.e = ring_edge_start + i_profile; - MLoop &loop_b = loops[ring_segment_loop_offset + 1]; - loop_b.v = ring_vert_offset + i_next_profile; - loop_b.e = next_main_edge_start + i_ring; - MLoop &loop_c = loops[ring_segment_loop_offset + 2]; - loop_c.v = next_ring_vert_offset + i_next_profile; - loop_c.e = next_ring_edge_offset + i_profile; - MLoop &loop_d = loops[ring_segment_loop_offset + 3]; - loop_d.v = next_ring_vert_offset + i_profile; - loop_d.e = main_edge_start + i_ring; + corner_verts[ring_segment_loop_offset] = ring_vert_offset + i_profile; + corner_edges[ring_segment_loop_offset] = ring_edge_start + i_profile; + + corner_verts[ring_segment_loop_offset + 1] = ring_vert_offset + i_next_profile; + corner_edges[ring_segment_loop_offset + 1] = next_main_edge_start + i_ring; + + corner_verts[ring_segment_loop_offset + 2] = next_ring_vert_offset + i_next_profile; + corner_edges[ring_segment_loop_offset + 2] = next_ring_edge_offset + i_profile; + + corner_verts[ring_segment_loop_offset + 3] = next_ring_vert_offset + i_profile; + corner_edges[ring_segment_loop_offset + 3] = main_edge_start + i_ring; } } @@ -138,13 +138,12 @@ static void fill_mesh_topology(const int vert_offset, for (const int i : IndexRange(profile_segment_num)) { const int i_inv = profile_segment_num - i - 1; - MLoop &loop_start = loops[cap_loop_offset + i]; - loop_start.v = vert_offset + i_inv; - loop_start.e = profile_edges_start + - ((i == (profile_segment_num - 1)) ? (profile_segment_num - 1) : (i_inv - 1)); - MLoop &loop_end = loops[cap_loop_offset + profile_segment_num + i]; - loop_end.v = last_ring_vert_offset + i; - loop_end.e = last_ring_edge_offset + i; + corner_verts[cap_loop_offset + i] = vert_offset + i_inv; + corner_edges[cap_loop_offset + i] = profile_edges_start + ((i == (profile_segment_num - 1)) ? + (profile_segment_num - 1) : + (i_inv - 1)); + corner_verts[cap_loop_offset + profile_segment_num + i] = last_ring_vert_offset + i; + corner_edges[cap_loop_offset + profile_segment_num + i] = last_ring_edge_offset + i; } } } @@ -672,7 +671,8 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main, MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); + MutableSpan corner_edges = mesh->corner_edges_for_write(); MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write(); foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) { @@ -686,7 +686,8 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main, info.profile_cyclic, fill_caps, edges, - loops, + corner_verts, + corner_edges, polys); }); diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 8bc57f8995b..0d7f55a6f26 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -1770,7 +1770,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MRecast), "MRecast", 1, N_("Recast"), nullptr, nullptr, nullptr, nullptr}, /* 25: CD_MPOLY */ {sizeof(MPoly), "MPoly", 1, N_("NGon Face"), nullptr, nullptr, nullptr, nullptr, nullptr}, - /* 26: CD_MLOOP */ + /* 26: CD_MLOOP */ /* DEPRECATED*/ {sizeof(MLoop), "MLoop", 1, @@ -2030,14 +2030,14 @@ const CustomData_MeshMasks CD_MASK_BAREMESH = { /*emask*/ CD_MASK_MEDGE, /*fmask*/ 0, /*pmask*/ CD_MASK_MPOLY | CD_MASK_FACEMAP, - /*lmask*/ CD_MASK_MLOOP, + /*lmask*/ CD_MASK_PROP_INT32, }; const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = { /*vmask*/ CD_MASK_PROP_FLOAT3 | CD_MASK_ORIGINDEX, /*emask*/ CD_MASK_MEDGE | CD_MASK_ORIGINDEX, /*fmask*/ 0, /*pmask*/ CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX, - /*lmask*/ CD_MASK_MLOOP, + /*lmask*/ CD_MASK_PROP_INT32, }; const CustomData_MeshMasks CD_MASK_MESH = { /*vmask*/ (CD_MASK_PROP_FLOAT3 | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | @@ -2048,8 +2048,7 @@ const CustomData_MeshMasks CD_MASK_MESH = { /*pmask*/ (CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL), /*lmask*/ - (CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | - CD_MASK_PROP_ALL), + (CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL), }; const CustomData_MeshMasks CD_MASK_DERIVEDMESH = { /*vmask*/ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN | @@ -2090,9 +2089,9 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = { (CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL), /*lmask*/ - (CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | - CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | - CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL), + (CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL | + CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP | + CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL), }; static const LayerTypeInfo *layerType_getInfo(int type) @@ -2686,6 +2685,15 @@ void CustomData_clear_layer_flag(CustomData *data, const int type, const int fla } } +bool CustomData_layer_is_anonymous(const struct CustomData *data, int type, int n) +{ + const int layer_index = CustomData_get_layer_index_n(data, type, n); + + BLI_assert(layer_index >= 0); + + return data->layers[layer_index].anonymous_id != nullptr; +} + static bool customData_resize(CustomData *data, const int amount) { CustomDataLayer *tmp = static_cast( diff --git a/source/blender/blenkernel/intern/data_transfer.cc b/source/blender/blenkernel/intern/data_transfer.cc index 552de64cf26..0265b2eb54e 100644 --- a/source/blender/blenkernel/intern/data_transfer.cc +++ b/source/blender/blenkernel/intern/data_transfer.cc @@ -380,7 +380,8 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src, blender::bke::mesh::normals_calc_loop(me_dst->vert_positions(), me_dst->edges(), me_dst->polys(), - me_dst->loops(), + me_dst->corner_verts(), + me_dst->corner_edges(), {}, me_dst->vert_normals(), me_dst->poly_normals(), @@ -429,7 +430,8 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/, blender::bke::mesh::normals_loop_custom_set(me_dst->vert_positions(), me_dst->edges(), me_dst->polys(), - me_dst->loops(), + me_dst->corner_verts(), + me_dst->corner_edges(), me_dst->vert_normals(), me_dst->poly_normals(), sharp_faces, @@ -1563,7 +1565,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, const int num_verts_dst = me_dst->totvert; const blender::Span edges_dst = me_dst->edges(); const blender::Span polys_dst = me_dst->polys(); - const blender::Span loops_dst = me_dst->loops(); + const blender::Span corner_verts_dst = me_dst->corner_verts(); + const blender::Span corner_edges_dst = me_dst->corner_edges(); CustomData *ldata_dst = &me_dst->ldata; MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type); @@ -1571,7 +1574,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, if (!geom_map_init[LDATA]) { const int num_loops_src = me_src->totloop; - if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (loops_dst.size() != num_loops_src)) { + if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && + (corner_verts_dst.size() != num_loops_src)) { BKE_report(reports, RPT_ERROR, "Source and destination meshes do not have the same amount of face corners, " @@ -1585,7 +1589,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, "None of the 'Edge' mappings can be used in this case"); continue; } - if (ELEM(0, loops_dst.size(), num_loops_src)) { + if (ELEM(0, corner_verts_dst.size(), num_loops_src)) { BKE_report( reports, RPT_ERROR, @@ -1602,8 +1606,9 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, num_verts_dst, edges_dst.data(), edges_dst.size(), - loops_dst.data(), - loops_dst.size(), + corner_verts_dst.data(), + corner_edges_dst.data(), + corner_verts_dst.size(), polys_dst.data(), polys_dst.size(), ldata_dst, @@ -1619,12 +1624,12 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, if (mdef && vg_idx != -1 && !weights[LDATA]) { weights[LDATA] = static_cast( - MEM_mallocN(sizeof(*weights[LDATA]) * size_t(loops_dst.size()), __func__)); + MEM_mallocN(sizeof(*weights[LDATA]) * size_t(corner_verts_dst.size()), __func__)); BKE_defvert_extract_vgroup_to_loopweights(mdef, vg_idx, num_verts_dst, - loops_dst.data(), - loops_dst.size(), + corner_verts_dst.data(), + corner_verts_dst.size(), invert_vgroup, weights[LDATA]); } @@ -1639,7 +1644,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, mix_mode, mix_factor, weights[LDATA], - loops_dst.size(), + corner_verts_dst.size(), use_create, use_delete, fromlayers, @@ -1661,7 +1666,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, const float(*positions_dst)[3] = BKE_mesh_vert_positions(me_dst); const int num_verts_dst = me_dst->totvert; const blender::Span polys_dst = me_dst->polys(); - const blender::Span loops_dst = me_dst->loops(); + const blender::Span corner_verts_dst = me_dst->corner_verts(); if (!geom_map_init[PDATA]) { const int num_polys_src = me_src->totpoly; @@ -1695,7 +1700,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, me_dst, positions_dst, num_verts_dst, - loops_dst.data(), + corner_verts_dst.data(), polys_dst.data(), polys_dst.size(), me_src, @@ -1709,8 +1714,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, BKE_defvert_extract_vgroup_to_polyweights(mdef, vg_idx, num_verts_dst, - loops_dst.data(), - loops_dst.size(), + corner_verts_dst.data(), + corner_verts_dst.size(), polys_dst.data(), polys_dst.size(), invert_vgroup, diff --git a/source/blender/blenkernel/intern/deform.cc b/source/blender/blenkernel/intern/deform.cc index e759d012e58..4c7ddfe5877 100644 --- a/source/blender/blenkernel/intern/deform.cc +++ b/source/blender/blenkernel/intern/deform.cc @@ -1074,7 +1074,7 @@ void BKE_defvert_extract_vgroup_to_edgeweights(const MDeformVert *dvert, void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert, const int defgroup, const int verts_num, - const MLoop *loops, + const int *corner_verts, const int loops_num, const bool invert_vgroup, float *r_weights) @@ -1088,9 +1088,7 @@ void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert, dvert, defgroup, verts_num, invert_vgroup, tmp_weights); while (i--) { - const MLoop *ml = &loops[i]; - - r_weights[i] = tmp_weights[ml->v]; + r_weights[i] = tmp_weights[corner_verts[i]]; } MEM_freeN(tmp_weights); @@ -1103,7 +1101,7 @@ void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert, void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert, const int defgroup, const int verts_num, - const MLoop *loops, + const int *corner_verts, const int /*loops_num*/, const MPoly *polys, const int polys_num, @@ -1120,12 +1118,12 @@ void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert, while (i--) { const MPoly &poly = polys[i]; - const MLoop *ml = &loops[poly.loopstart]; + const int *corner_vert = &corner_verts[poly.loopstart]; int j = poly.totloop; float w = 0.0f; - for (; j--; ml++) { - w += tmp_weights[ml->v]; + for (; j--; corner_vert++) { + w += tmp_weights[*corner_vert]; } r_weights[i] = w / float(poly.totloop); } diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc index 738e657ecfa..45e8abe2a53 100644 --- a/source/blender/blenkernel/intern/displist.cc +++ b/source/blender/blenkernel/intern/displist.cc @@ -743,11 +743,9 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph, Mesh *mesh = geometry_set.get_mesh_for_write(); if (mti->type == eModifierTypeType_OnlyDeform) { - int totvert; - float(*vertex_coords)[3] = BKE_mesh_vert_coords_alloc(mesh, &totvert); - mti->deformVerts(md, &mectx_deform, mesh, vertex_coords, totvert); - BKE_mesh_vert_coords_apply(mesh, vertex_coords); - MEM_freeN(vertex_coords); + mti->deformVerts( + md, &mectx_deform, mesh, BKE_mesh_vert_positions_for_write(mesh), mesh->totvert); + BKE_mesh_tag_positions_changed(mesh); } else { Mesh *output_mesh = mti->modifyMesh(md, &mectx_apply, mesh); diff --git a/source/blender/blenkernel/intern/dynamicpaint.cc b/source/blender/blenkernel/intern/dynamicpaint.cc index 82ea253a27a..4388f1d2535 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.cc +++ b/source/blender/blenkernel/intern/dynamicpaint.cc @@ -1416,7 +1416,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b int numOfPolys = mesh->totpoly; const blender::Span edges = mesh->edges(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); /* count number of edges per vertex */ for (int i = 0; i < numOfEdges; i++) { @@ -1431,7 +1431,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b * to locate points on "mesh edge" */ for (int i = 0; i < numOfPolys; i++) { for (int j = 0; j < polys[i].totloop; j++) { - temp_data[loops[polys[i].loopstart + j].v]++; + temp_data[corner_verts[polys[i].loopstart + j]]++; } } @@ -1479,7 +1479,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b struct DynamicPaintSetInitColorData { const DynamicPaintSurface *surface; - blender::Span loops; + blender::Span corner_verts; const float (*mloopuv)[2]; blender::Span looptris; const MLoopCol *mloopcol; @@ -1497,7 +1497,7 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat const PaintSurfaceData *sData = data->surface->data; PaintPoint *pPoint = (PaintPoint *)sData->type_data; - const blender::Span loops = data->loops; + const blender::Span corner_verts = data->corner_verts; const blender::Span looptris = data->looptris; const float(*mloopuv)[2] = data->mloopuv; ImagePool *pool = data->pool; @@ -1509,7 +1509,7 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat for (int j = 3; j--;) { TexResult texres = {0}; - const uint vert = loops[looptris[i].tri[j]].v; + const int vert = corner_verts[looptris[i].tri[j]]; /* remap to [-1.0, 1.0] */ uv[0] = mloopuv[looptris[i].tri[j]][0] * 2.0f - 1.0f; @@ -1618,7 +1618,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) { Tex *tex = surface->init_texture; - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); const blender::Span looptris = mesh->looptris(); char uvname[MAX_CUSTOMDATA_LAYER_NAME]; @@ -1643,7 +1643,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface DynamicPaintSetInitColorData data{}; data.surface = surface; - data.loops = loops; + data.corner_verts = corner_verts; data.looptris = looptris; data.mloopuv = mloopuv; data.pool = pool; @@ -1675,15 +1675,15 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface /* For vertex surface, just copy colors from #MLoopCol. */ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); const MLoopCol *col = static_cast( CustomData_get_layer_named(&mesh->ldata, CD_PROP_BYTE_COLOR, surface->init_layername)); if (!col) { return; } - for (const int i : loops.index_range()) { - rgba_uchar_to_float(pPoint[loops[i].v].color, (const uchar *)&col[i].r); + for (const int i : corner_verts.index_range()) { + rgba_uchar_to_float(pPoint[corner_verts[i]].color, (const uchar *)&col[i].r); } } else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { @@ -1791,7 +1791,7 @@ struct DynamicPaintModifierApplyData { float (*vert_positions)[3]; blender::Span vert_normals; blender::Span polys; - blender::Span loops; + blender::Span corner_verts; float (*fcolor)[4]; MLoopCol *mloopcol; @@ -1860,7 +1860,7 @@ static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata, userdata); const blender::Span polys = data->polys; - const blender::Span loops = data->loops; + const blender::Span corner_verts = data->corner_verts; const DynamicPaintSurface *surface = data->surface; PaintPoint *pPoint = (PaintPoint *)surface->data->type_data; @@ -1871,7 +1871,7 @@ static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata, for (int j = 0; j < polys[p_index].totloop; j++) { const int l_index = polys[p_index].loopstart + j; - const int v_index = loops[l_index].v; + const int v_index = corner_verts[l_index]; /* save layer data to output layer */ /* apply color */ @@ -1929,7 +1929,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * /* vertex color paint */ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { const blender::Span polys = result->polys(); - const blender::Span loops = result->loops(); + const blender::Span corner_verts = result->corner_verts(); /* paint is stored on dry and wet layers, so mix final color first */ float(*fcolor)[4] = static_cast( @@ -1958,7 +1958,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * mloopcol = static_cast(CustomData_add_layer_named(&result->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, - loops.size(), + corner_verts.size(), surface->output_name)); } @@ -1971,12 +1971,12 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * CustomData_add_layer_named(&result->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, - loops.size(), + corner_verts.size(), surface->output_name2)); } data.ob = ob; - data.loops = loops; + data.corner_verts = corner_verts; data.polys = polys; data.mloopcol = mloopcol; data.mloopcol_wet = mloopcol_wet; @@ -2191,7 +2191,7 @@ struct DynamicPaintCreateUVSurfaceData { blender::Span looptris; const float (*mloopuv)[2]; - blender::Span loops; + blender::Span corner_verts; const Bounds2D *faceBB; uint32_t *active_points; @@ -2210,7 +2210,7 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata, const blender::Span looptris = data->looptris; const float(*mloopuv)[2] = data->mloopuv; - const blender::Span loops = data->loops; + const blender::Span corner_verts = data->corner_verts; const Bounds2D *faceBB = data->faceBB; @@ -2281,9 +2281,9 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata, tPoint->tri_index = i; /* save vertex indexes */ - tPoint->v1 = loops[looptris[i].tri[0]].v; - tPoint->v2 = loops[looptris[i].tri[1]].v; - tPoint->v3 = loops[looptris[i].tri[2]].v; + tPoint->v1 = corner_verts[looptris[i].tri[0]]; + tPoint->v2 = corner_verts[looptris[i].tri[1]]; + tPoint->v3 = corner_verts[looptris[i].tri[2]]; sample = 5; /* make sure we exit sample loop as well */ break; @@ -2306,7 +2306,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat const blender::Span looptris = data->looptris; const float(*mloopuv)[2] = data->mloopuv; - const blender::Span loops = data->loops; + const blender::Span corner_verts = data->corner_verts; uint32_t *active_points = data->active_points; @@ -2371,9 +2371,9 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat } /* save vertex indexes */ - tPoint->v1 = loops[looptris[i].tri[0]].v; - tPoint->v2 = loops[looptris[i].tri[1]].v; - tPoint->v3 = loops[looptris[i].tri[2]].v; + tPoint->v1 = corner_verts[looptris[i].tri[0]]; + tPoint->v2 = corner_verts[looptris[i].tri[1]]; + tPoint->v3 = corner_verts[looptris[i].tri[2]]; break; } @@ -2514,7 +2514,7 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa int in_edge, int depth) { - const blender::Span loops = data->loops; + const blender::Span corner_verts = data->corner_verts; const blender::Span looptris = data->looptris; const float(*mloopuv)[2] = data->mloopuv; @@ -2552,8 +2552,8 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa } /* Now find another face that is linked to that edge. */ - const int vert0 = loops[loop_idx[(edge_idx + 0)]].v; - const int vert1 = loops[loop_idx[(edge_idx + 1) % 3]].v; + const int vert0 = corner_verts[loop_idx[(edge_idx + 0)]]; + const int vert1 = corner_verts[loop_idx[(edge_idx + 1) % 3]]; /* Use a pre-computed vert-to-looptri mapping, * speeds up things a lot compared to looping over all looptri. */ @@ -2576,8 +2576,8 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa /* Check edges for match, looping in the same order as the outer loop. */ for (int j = 0; j < 3; j++) { - const int overt0 = loops[other_loop_idx[(j + 0)]].v; - const int overt1 = loops[other_loop_idx[(j + 1) % 3]].v; + const int overt0 = corner_verts[other_loop_idx[(j + 0)]]; + const int overt1 = corner_verts[other_loop_idx[(j + 1) % 3]]; /* Allow for swapped vertex order */ if (overt0 == vert0 && overt1 == vert1) { @@ -2828,7 +2828,7 @@ int dynamicPaint_createUVSurface(Scene *scene, return setError(canvas, N_("Cannot bake non-'image sequence' formats")); } - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); const blender::Span looptris = mesh->looptris(); /* get uv map */ @@ -2917,7 +2917,7 @@ int dynamicPaint_createUVSurface(Scene *scene, data.tempWeights = tempWeights; data.looptris = looptris; data.mloopuv = mloopuv; - data.loops = loops; + data.corner_verts = corner_verts; data.faceBB = faceBB; { @@ -2975,7 +2975,7 @@ int dynamicPaint_createUVSurface(Scene *scene, mesh->totvert, looptris.data(), looptris.size(), - loops.data(), + corner_verts.data(), mesh->totloop); int total_border = 0; @@ -3434,14 +3434,14 @@ static void mesh_tris_spherecast_dp(void *userdata, const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata; const float(*positions)[3] = data->vert_positions; const MLoopTri *looptris = data->looptri; - const MLoop *loops = data->loop; + const int *corner_verts = data->corner_verts; const float *t0, *t1, *t2; float dist; - t0 = positions[loops[looptris[index].tri[0]].v]; - t1 = positions[loops[looptris[index].tri[1]].v]; - t2 = positions[loops[looptris[index].tri[2]].v]; + t0 = positions[corner_verts[looptris[index].tri[0]]]; + t1 = positions[corner_verts[looptris[index].tri[1]]]; + t2 = positions[corner_verts[looptris[index].tri[2]]]; dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2); @@ -3466,13 +3466,13 @@ static void mesh_tris_nearest_point_dp(void *userdata, const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata; const float(*positions)[3] = data->vert_positions; const MLoopTri *looptris = data->looptri; - const MLoop *loops = data->loop; + const int *corner_verts = data->corner_verts; float nearest_tmp[3], dist_sq; const float *t0, *t1, *t2; - t0 = positions[loops[looptris[index].tri[0]].v]; - t1 = positions[loops[looptris[index].tri[1]].v]; - t2 = positions[loops[looptris[index].tri[2]].v]; + t0 = positions[corner_verts[looptris[index].tri[0]]]; + t1 = positions[corner_verts[looptris[index].tri[1]]]; + t2 = positions[corner_verts[looptris[index].tri[2]]]; closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2); dist_sq = len_squared_v3v3(co, nearest_tmp); @@ -3905,7 +3905,7 @@ struct DynamicPaintPaintData { Mesh *mesh; const float (*positions)[3]; - blender::Span loops; + blender::Span corner_verts; blender::Span looptris; float brush_radius; const float *avg_brushNor; @@ -3939,7 +3939,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata, const int c_index = data->c_index; const float(*positions)[3] = data->positions; - const blender::Span loops = data->loops; + const blender::Span corner_verts = data->corner_verts; const blender::Span looptris = data->looptris; const float brush_radius = data->brush_radius; const float *avg_brushNor = data->avg_brushNor; @@ -4013,9 +4013,9 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata, /* For optimization sake, hit point normal isn't calculated in ray cast loop */ const int vtri[3] = { - int(loops[looptris[hit.index].tri[0]].v), - int(loops[looptris[hit.index].tri[1]].v), - int(loops[looptris[hit.index].tri[2]].v), + corner_verts[looptris[hit.index].tri[0]], + corner_verts[looptris[hit.index].tri[1]], + corner_verts[looptris[hit.index].tri[2]], }; float dot; @@ -4163,9 +4163,9 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata, float brushPointVelocity[3]; float velocity[3]; - const int v1 = loops[looptris[hitTri].tri[0]].v; - const int v2 = loops[looptris[hitTri].tri[1]].v; - const int v3 = loops[looptris[hitTri].tri[2]].v; + const int v1 = corner_verts[looptris[hitTri].tri[0]]; + const int v2 = corner_verts[looptris[hitTri].tri[1]]; + const int v3 = corner_verts[looptris[hitTri].tri[2]]; /* calculate barycentric weights for hit point */ interp_weights_tri_v3(weights, positions[v1], positions[v2], positions[v3], hitCoord); @@ -4287,8 +4287,8 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph, mesh = BKE_mesh_copy_for_eval(brush_mesh, false); float(*positions)[3] = BKE_mesh_vert_positions_for_write(mesh); const blender::Span vert_normals = mesh->vert_normals(); + const blender::Span corner_verts = mesh->corner_verts(); const blender::Span looptris = mesh->looptris(); - const blender::Span loops = mesh->loops(); numOfVerts = mesh->totvert; /* Transform collider vertices to global space @@ -4342,7 +4342,7 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph, data.c_index = c_index; data.mesh = mesh; data.positions = positions; - data.loops = loops; + data.corner_verts = corner_verts; data.looptris = looptris; data.brush_radius = brush_radius; data.avg_brushNor = avg_brushNor; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e06c428349f..64b305accdd 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -660,12 +660,12 @@ bool closest_point_on_surface(SurfaceModifierData *surmd, } if (surface_vel) { - const MLoop *mloop = bvhtree->loop; + const int *corner_verts = bvhtree->corner_verts; const MLoopTri *lt = &bvhtree->looptri[nearest.index]; - copy_v3_v3(surface_vel, surmd->runtime.vert_velocities[mloop[lt->tri[0]].v]); - add_v3_v3(surface_vel, surmd->runtime.vert_velocities[mloop[lt->tri[1]].v]); - add_v3_v3(surface_vel, surmd->runtime.vert_velocities[mloop[lt->tri[2]].v]); + copy_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[0]]]); + add_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[1]]]); + add_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[2]]]); mul_v3_fl(surface_vel, (1.0f / 3.0f)); } diff --git a/source/blender/blenkernel/intern/fcurve_test.cc b/source/blender/blenkernel/intern/fcurve_test.cc index 55b11c61c20..45faa44ff27 100644 --- a/source/blender/blenkernel/intern/fcurve_test.cc +++ b/source/blender/blenkernel/intern/fcurve_test.cc @@ -387,7 +387,7 @@ TEST(BKE_fcurve, BKE_fcurve_calc_range) /* Curve samples. */ const int sample_start = 1; const int sample_end = 20; - fcurve_store_samples(fcu, NULL, sample_start, sample_end, fcurve_samplingcb_evalcurve); + fcurve_store_samples(fcu, nullptr, sample_start, sample_end, fcurve_samplingcb_evalcurve); success = BKE_fcurve_calc_range(fcu, &min, &max, true); EXPECT_TRUE(success) << "FCurve samples should have a range."; @@ -421,8 +421,11 @@ TEST(BKE_fcurve, BKE_fcurve_calc_bounds) bool success; /* All keys. */ - success = BKE_fcurve_calc_bounds( - fcu, false /* select only */, false /* include handles */, NULL /* frame range */, &bounds); + success = BKE_fcurve_calc_bounds(fcu, + false /* select only */, + false /* include handles */, + nullptr /* frame range */, + &bounds); EXPECT_TRUE(success) << "A non-empty FCurve should have bounds."; EXPECT_FLOAT_EQ(fcu->bezt[0].vec[1][0], bounds.xmin); EXPECT_FLOAT_EQ(fcu->bezt[4].vec[1][0], bounds.xmax); @@ -430,16 +433,22 @@ TEST(BKE_fcurve, BKE_fcurve_calc_bounds) EXPECT_FLOAT_EQ(fcu->bezt[2].vec[1][1], bounds.ymax); /* Only selected. */ - success = BKE_fcurve_calc_bounds( - fcu, true /* select only */, false /* include handles */, NULL /* frame range */, &bounds); + success = BKE_fcurve_calc_bounds(fcu, + true /* select only */, + false /* include handles */, + nullptr /* frame range */, + &bounds); EXPECT_FALSE(success) << "Using selected keyframes only should not find bounds if nothing is selected."; fcu->bezt[1].f2 |= SELECT; fcu->bezt[3].f2 |= SELECT; - success = BKE_fcurve_calc_bounds( - fcu, true /* select only */, false /* include handles */, NULL /* frame range */, &bounds); + success = BKE_fcurve_calc_bounds(fcu, + true /* select only */, + false /* include handles */, + nullptr /* frame range */, + &bounds); EXPECT_TRUE(success) << "Selected keys should have been found."; EXPECT_FLOAT_EQ(fcu->bezt[1].vec[1][0], bounds.xmin); EXPECT_FLOAT_EQ(fcu->bezt[3].vec[1][0], bounds.xmax); @@ -447,8 +456,11 @@ TEST(BKE_fcurve, BKE_fcurve_calc_bounds) EXPECT_FLOAT_EQ(fcu->bezt[3].vec[1][1], bounds.ymax); /* Including handles. */ - success = BKE_fcurve_calc_bounds( - fcu, false /* select only */, true /* include handles */, NULL /* frame range */, &bounds); + success = BKE_fcurve_calc_bounds(fcu, + false /* select only */, + true /* include handles */, + nullptr /* frame range */, + &bounds); EXPECT_TRUE(success) << "A non-empty FCurve should have bounds including handles."; EXPECT_FLOAT_EQ(fcu->bezt[0].vec[0][0], bounds.xmin); EXPECT_FLOAT_EQ(fcu->bezt[4].vec[2][0], bounds.xmax); @@ -499,10 +511,13 @@ TEST(BKE_fcurve, BKE_fcurve_calc_bounds) /* Curve samples. */ const int sample_start = 1; const int sample_end = 20; - fcurve_store_samples(fcu, NULL, sample_start, sample_end, fcurve_samplingcb_evalcurve); + fcurve_store_samples(fcu, nullptr, sample_start, sample_end, fcurve_samplingcb_evalcurve); - success = BKE_fcurve_calc_bounds( - fcu, false /* select only */, false /* include handles */, NULL /* frame range */, &bounds); + success = BKE_fcurve_calc_bounds(fcu, + false /* select only */, + false /* include handles */, + nullptr /* frame range */, + &bounds); EXPECT_TRUE(success) << "FCurve samples should have a range."; EXPECT_FLOAT_EQ(sample_start, bounds.xmin); diff --git a/source/blender/blenkernel/intern/fluid.cc b/source/blender/blenkernel/intern/fluid.cc index af723bdd5e1..e3a00690b2a 100644 --- a/source/blender/blenkernel/intern/fluid.cc +++ b/source/blender/blenkernel/intern/fluid.cc @@ -840,7 +840,7 @@ BLI_INLINE void apply_effector_fields(FluidEffectorSettings * /*fes*/, static void update_velocities(FluidEffectorSettings *fes, const float (*vert_positions)[3], - const MLoop *mloop, + const int *corner_verts, const MLoopTri *mlooptri, float *velocity_map, int index, @@ -866,9 +866,9 @@ static void update_velocities(FluidEffectorSettings *fes, int v1, v2, v3, f_index = nearest.index; /* Calculate barycentric weights for nearest point. */ - v1 = mloop[mlooptri[f_index].tri[0]].v; - v2 = mloop[mlooptri[f_index].tri[1]].v; - v3 = mloop[mlooptri[f_index].tri[2]].v; + v1 = corner_verts[mlooptri[f_index].tri[0]]; + v2 = corner_verts[mlooptri[f_index].tri[1]]; + v3 = corner_verts[mlooptri[f_index].tri[2]]; interp_weights_tri_v3( weights, vert_positions[v1], vert_positions[v2], vert_positions[v3], nearest.co); @@ -938,7 +938,7 @@ struct ObstaclesFromDMData { FluidEffectorSettings *fes; const float (*vert_positions)[3]; - blender::Span loops; + blender::Span corner_verts; blender::Span looptris; BVHTreeFromMesh *tree; @@ -973,7 +973,7 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata, /* Calculate object velocities. Result in bb->velocity. */ update_velocities(data->fes, data->vert_positions, - data->loops.data(), + data->corner_verts.data(), data->looptris.data(), bb->velocity, index, @@ -1008,7 +1008,7 @@ static void obstacles_from_mesh(Object *coll_ob, int min[3], max[3], res[3]; - const blender::Span loops = me->loops(); + const blender::Span corner_verts = me->corner_verts(); const blender::Span looptris = me->looptris(); numverts = me->totvert; @@ -1072,7 +1072,7 @@ static void obstacles_from_mesh(Object *coll_ob, ObstaclesFromDMData data{}; data.fes = fes; data.vert_positions = positions; - data.loops = loops; + data.corner_verts = corner_verts; data.looptris = looptris; data.tree = &tree_data; data.bb = bb; @@ -1786,7 +1786,7 @@ static void update_distances(int index, static void sample_mesh(FluidFlowSettings *ffs, const float (*vert_positions)[3], const blender::Span vert_normals, - const MLoop *mloop, + const int *corner_verts, const MLoopTri *mlooptri, const float (*mloopuv)[2], float *influence_map, @@ -1869,9 +1869,9 @@ static void sample_mesh(FluidFlowSettings *ffs, float hit_normal[3]; /* Calculate barycentric weights for nearest point. */ - v1 = mloop[mlooptri[f_index].tri[0]].v; - v2 = mloop[mlooptri[f_index].tri[1]].v; - v3 = mloop[mlooptri[f_index].tri[2]].v; + v1 = corner_verts[mlooptri[f_index].tri[0]]; + v2 = corner_verts[mlooptri[f_index].tri[1]]; + v3 = corner_verts[mlooptri[f_index].tri[2]]; interp_weights_tri_v3( weights, vert_positions[v1], vert_positions[v2], vert_positions[v3], nearest.co); @@ -1981,7 +1981,7 @@ struct EmitFromDMData { const float (*vert_positions)[3]; blender::Span vert_normals; - blender::Span loops; + blender::Span corner_verts; blender::Span looptris; const float (*mloopuv)[2]; const MDeformVert *dvert; @@ -2015,7 +2015,7 @@ static void emit_from_mesh_task_cb(void *__restrict userdata, sample_mesh(data->ffs, data->vert_positions, data->vert_normals, - data->loops.data(), + data->corner_verts.data(), data->looptris.data(), data->mloopuv, bb->influence, @@ -2065,7 +2065,7 @@ static void emit_from_mesh( Mesh *me = BKE_mesh_copy_for_eval(ffs->mesh, false); float(*positions)[3] = BKE_mesh_vert_positions_for_write(me); - const blender::Span loops = me->loops(); + const blender::Span corner_verts = me->corner_verts(); const blender::Span looptris = me->looptris(); const int numverts = me->totvert; const MDeformVert *dvert = BKE_mesh_deform_verts(me); @@ -2136,7 +2136,7 @@ static void emit_from_mesh( data.ffs = ffs; data.vert_positions = positions; data.vert_normals = me->vert_normals(); - data.loops = loops; + data.corner_verts = corner_verts; data.looptris = looptris; data.mloopuv = mloopuv; data.dvert = dvert; @@ -3235,7 +3235,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, } float(*positions)[3] = BKE_mesh_vert_positions_for_write(me); blender::MutableSpan polys = me->polys_for_write(); - blender::MutableSpan loops = me->loops_for_write(); + blender::MutableSpan corner_verts = me->corner_verts_for_write(); const bool is_sharp = orgmesh->attributes().lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false)[0]; @@ -3332,9 +3332,9 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, polys[i].loopstart = i * 3; polys[i].totloop = 3; - loops[i * 3 + 0].v = manta_liquid_get_triangle_x_at(fds->fluid, i); - loops[i * 3 + 1].v = manta_liquid_get_triangle_y_at(fds->fluid, i); - loops[i * 3 + 2].v = manta_liquid_get_triangle_z_at(fds->fluid, i); + corner_verts[i * 3 + 0] = manta_liquid_get_triangle_x_at(fds->fluid, i); + corner_verts[i * 3 + 1] = manta_liquid_get_triangle_y_at(fds->fluid, i); + corner_verts[i * 3 + 2] = manta_liquid_get_triangle_z_at(fds->fluid, i); # ifdef DEBUG_PRINT /* Debugging: Print mesh faces. */ printf("mloops[0].v: %d, mloops[1].v: %d, mloops[2].v: %d\n", @@ -3356,7 +3356,7 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje float max[3]; float *co; MPoly *poly; - MLoop *ml; + int *corner_vert; int num_verts = 8; int num_faces = 6; @@ -3371,7 +3371,7 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje result = BKE_mesh_new_nomain(num_verts, 0, num_faces * 4, num_faces); float(*positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan polys = result->polys_for_write(); - blender::MutableSpan loops = result->loops_for_write(); + blender::MutableSpan corner_verts = result->corner_verts_for_write(); if (num_verts) { /* Volume bounds. */ @@ -3417,58 +3417,58 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje /* Create faces. */ /* Top side. */ poly = &polys[0]; - ml = &loops[0 * 4]; + corner_vert = &corner_verts[0 * 4]; poly->loopstart = 0 * 4; poly->totloop = 4; - ml[0].v = 0; - ml[1].v = 1; - ml[2].v = 2; - ml[3].v = 3; + corner_vert[0] = 0; + corner_vert[1] = 1; + corner_vert[2] = 2; + corner_vert[3] = 3; /* Right side. */ poly = &polys[1]; - ml = &loops[1 * 4]; + corner_vert = &corner_verts[1 * 4]; poly->loopstart = 1 * 4; poly->totloop = 4; - ml[0].v = 2; - ml[1].v = 1; - ml[2].v = 5; - ml[3].v = 6; + corner_vert[0] = 2; + corner_vert[1] = 1; + corner_vert[2] = 5; + corner_vert[3] = 6; /* Bottom side. */ poly = &polys[2]; - ml = &loops[2 * 4]; + corner_vert = &corner_verts[2 * 4]; poly->loopstart = 2 * 4; poly->totloop = 4; - ml[0].v = 7; - ml[1].v = 6; - ml[2].v = 5; - ml[3].v = 4; + corner_vert[0] = 7; + corner_vert[1] = 6; + corner_vert[2] = 5; + corner_vert[3] = 4; /* Left side. */ poly = &polys[3]; - ml = &loops[3 * 4]; + corner_vert = &corner_verts[3 * 4]; poly->loopstart = 3 * 4; poly->totloop = 4; - ml[0].v = 0; - ml[1].v = 3; - ml[2].v = 7; - ml[3].v = 4; + corner_vert[0] = 0; + corner_vert[1] = 3; + corner_vert[2] = 7; + corner_vert[3] = 4; /* Front side. */ poly = &polys[4]; - ml = &loops[4 * 4]; + corner_vert = &corner_verts[4 * 4]; poly->loopstart = 4 * 4; poly->totloop = 4; - ml[0].v = 3; - ml[1].v = 2; - ml[2].v = 6; - ml[3].v = 7; + corner_vert[0] = 3; + corner_vert[1] = 2; + corner_vert[2] = 6; + corner_vert[3] = 7; /* Back side. */ poly = &polys[5]; - ml = &loops[5 * 4]; + corner_vert = &corner_verts[5 * 4]; poly->loopstart = 5 * 4; poly->totloop = 4; - ml[0].v = 1; - ml[1].v = 0; - ml[2].v = 4; - ml[3].v = 5; + corner_vert[0] = 1; + corner_vert[1] = 0; + corner_vert[2] = 4; + corner_vert[3] = 5; /* Calculate required shift to match domain's global position * it was originally simulated at (if object moves without manta step). */ diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index b5bc08039b2..b5337ec59b0 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -174,15 +174,11 @@ static void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totvert); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); attribute_math::DefaultMixer mixer(r_values); - - for (const int loop_index : IndexRange(mesh.totloop)) { - const T value = old_values[loop_index]; - const MLoop &loop = loops[loop_index]; - const int point_index = loop.v; - mixer.mix_in(point_index, value); + for (const int corner : IndexRange(mesh.totloop)) { + mixer.mix_in(corner_verts[corner], old_values[corner]); } mixer.finalize(); } @@ -194,17 +190,16 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh, MutableSpan r_values) { BLI_assert(r_values.size() == mesh.totvert); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); Array loose_verts(mesh.totvert, true); r_values.fill(true); - for (const int loop_index : IndexRange(mesh.totloop)) { - const MLoop &loop = loops[loop_index]; - const int point_index = loop.v; + for (const int corner : IndexRange(mesh.totloop)) { + const int point_index = corner_verts[corner]; loose_verts[point_index] = false; - if (!old_values[loop_index]) { + if (!old_values[corner]) { r_values[point_index] = false; } } @@ -242,16 +237,15 @@ static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray */ static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray) { - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); GVArray new_varray; attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); - new_varray = VArray::ForFunc(mesh.totloop, - [loops, varray = varray.typed()](const int64_t loop_index) { - const int vertex_index = loops[loop_index].v; - return varray[vertex_index]; - }); + new_varray = VArray::ForFunc( + mesh.totloop, [corner_verts, varray = varray.typed()](const int64_t corner) { + return varray[corner_verts[corner]]; + }); }); return new_varray; } @@ -303,7 +297,7 @@ static void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, { BLI_assert(r_values.size() == mesh.totedge); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); attribute_math::DefaultMixer mixer(r_values); @@ -315,8 +309,7 @@ static void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, const int next_i = (i + 1) % poly.totloop; const int loop_i = poly.loopstart + i; const int next_loop_i = poly.loopstart + next_i; - const MLoop &loop = loops[loop_i]; - const int edge_index = loop.e; + const int edge_index = corner_edges[loop_i]; mixer.mix_in(edge_index, old_values[loop_i]); mixer.mix_in(edge_index, old_values[next_loop_i]); } @@ -333,7 +326,7 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, { BLI_assert(r_values.size() == mesh.totedge); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); r_values.fill(true); for (const int poly_index : polys.index_range()) { @@ -343,8 +336,7 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, const int next_i = (i + 1) % poly.totloop; const int loop_i = poly.loopstart + i; const int next_loop_i = poly.loopstart + next_i; - const MLoop &loop = loops[loop_i]; - const int edge_index = loop.e; + const int edge_index = corner_edges[loop_i]; if (!old_values[loop_i] || !old_values[next_loop_i]) { r_values[edge_index] = false; @@ -385,17 +377,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, { BLI_assert(r_values.size() == mesh.totvert); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); attribute_math::DefaultMixer mixer(r_values); for (const int poly_index : polys.index_range()) { const MPoly &poly = polys[poly_index]; const T value = old_values[poly_index]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = loops[loop_index]; - const int point_index = loop.v; - mixer.mix_in(point_index, value); + for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + mixer.mix_in(vert, value); } } @@ -410,15 +400,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, { BLI_assert(r_values.size() == mesh.totvert); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); r_values.fill(false); threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) { for (const int poly_index : range) { if (old_values[poly_index]) { const MPoly &poly = polys[poly_index]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - r_values[loop.v] = true; + for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + r_values[vert] = true; } } } @@ -476,16 +466,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, { BLI_assert(r_values.size() == mesh.totedge); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); attribute_math::DefaultMixer mixer(r_values); for (const int poly_index : polys.index_range()) { const MPoly &poly = polys[poly_index]; const T value = old_values[poly_index]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = loops[loop_index]; - mixer.mix_in(loop.e, value); + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + mixer.mix_in(edge, value); } } mixer.finalize(); @@ -499,15 +488,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, { BLI_assert(r_values.size() == mesh.totedge); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); r_values.fill(false); threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) { for (const int poly_index : range) { if (old_values[poly_index]) { const MPoly &poly = polys[poly_index]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - r_values[loop.e] = true; + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + r_values[edge] = true; } } } @@ -530,7 +519,7 @@ static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &v static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray) { const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); GVArray new_varray; attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { @@ -538,12 +527,12 @@ static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray & if constexpr (!std::is_void_v>) { if constexpr (std::is_same_v) { new_varray = VArray::ForFunc( - mesh.totpoly, [loops, polys, varray = varray.typed()](const int face_index) { + mesh.totpoly, + [corner_verts, polys, varray = varray.typed()](const int face_index) { /* A face is selected if all of its vertices were selected. */ const MPoly &poly = polys[face_index]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = loops[loop_index]; - if (!varray[loop.v]) { + for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + if (!varray[vert]) { return false; } } @@ -552,14 +541,12 @@ static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray & } else { new_varray = VArray::ForFunc( - mesh.totpoly, [loops, polys, varray = varray.typed()](const int face_index) { + mesh.totpoly, [corner_verts, polys, varray = varray.typed()](const int face_index) { T return_value; attribute_math::DefaultMixer mixer({&return_value, 1}); const MPoly &poly = polys[face_index]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = loops[loop_index]; - const T value = varray[loop.v]; - mixer.mix_in(0, value); + for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + mixer.mix_in(0, varray[vert]); } mixer.finalize(); return return_value; @@ -610,7 +597,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, { BLI_assert(r_values.size() == mesh.totloop); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); attribute_math::DefaultMixer mixer(r_values); @@ -620,10 +607,10 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, /* For every corner, mix the values from the adjacent edges on the face. */ for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { const int loop_index_prev = mesh_topology::poly_loop_prev(poly, loop_index); - const MLoop &loop = loops[loop_index]; - const MLoop &loop_prev = loops[loop_index_prev]; - mixer.mix_in(loop_index, old_values[loop.e]); - mixer.mix_in(loop_index, old_values[loop_prev.e]); + const int edge = corner_edges[loop_index]; + const int edge_prev = corner_edges[loop_index_prev]; + mixer.mix_in(loop_index, old_values[edge]); + mixer.mix_in(loop_index, old_values[edge_prev]); } } @@ -638,7 +625,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, { BLI_assert(r_values.size() == mesh.totloop); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); r_values.fill(false); @@ -647,9 +634,9 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, const MPoly &poly = polys[poly_index]; for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { const int loop_index_prev = mesh_topology::poly_loop_prev(poly, loop_index); - const MLoop &loop = loops[loop_index]; - const MLoop &loop_prev = loops[loop_index_prev]; - if (old_values[loop.e] && old_values[loop_prev.e]) { + const int edge = corner_edges[loop_index]; + const int edge_prev = corner_edges[loop_index_prev]; + if (old_values[edge] && old_values[edge_prev]) { r_values[loop_index] = true; } } @@ -729,7 +716,7 @@ static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray & static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray) { const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); GVArray new_varray; attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { @@ -738,11 +725,10 @@ static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &v if constexpr (std::is_same_v) { /* A face is selected if all of its edges are selected. */ new_varray = VArray::ForFunc( - polys.size(), [loops, polys, varray = varray.typed()](const int face_index) { + polys.size(), [corner_edges, polys, varray = varray.typed()](const int face_index) { const MPoly &poly = polys[face_index]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = loops[loop_index]; - if (!varray[loop.e]) { + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + if (!varray[edge]) { return false; } } @@ -751,14 +737,12 @@ static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &v } else { new_varray = VArray::ForFunc( - polys.size(), [loops, polys, varray = varray.typed()](const int face_index) { + polys.size(), [corner_edges, polys, varray = varray.typed()](const int face_index) { T return_value; attribute_math::DefaultMixer mixer({&return_value, 1}); const MPoly &poly = polys[face_index]; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = loops[loop_index]; - const T value = varray[loop.e]; - mixer.mix_in(0, value); + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + mixer.mix_in(0, varray[edge]); } mixer.finalize(); return return_value; @@ -1207,6 +1191,35 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() nullptr, AttributeValidator{&material_index_clamp}); + /* Note: This clamping is more of a last resort, since it's quite easy to make an + * invalid mesh that will crash Blender by arbitrarily editing this attribute. */ + static const auto int_index_clamp = mf::build::SI1_SO( + "Index Validate", + [](int value) { return std::max(value, 0); }, + mf::build::exec_presets::AllSpanOrSingle()); + static BuiltinCustomDataLayerProvider corner_vert(".corner_vert", + ATTR_DOMAIN_CORNER, + CD_PROP_INT32, + CD_PROP_INT32, + BuiltinAttributeProvider::NonCreatable, + BuiltinAttributeProvider::NonDeletable, + corner_access, + make_array_read_attribute, + make_array_write_attribute, + nullptr, + AttributeValidator{&int_index_clamp}); + static BuiltinCustomDataLayerProvider corner_edge(".corner_edge", + ATTR_DOMAIN_CORNER, + CD_PROP_INT32, + CD_PROP_INT32, + BuiltinAttributeProvider::NonCreatable, + BuiltinAttributeProvider::NonDeletable, + corner_access, + make_array_read_attribute, + make_array_write_attribute, + nullptr, + AttributeValidator{&int_index_clamp}); + static BuiltinCustomDataLayerProvider sharp_face("sharp_face", ATTR_DOMAIN_FACE, CD_PROP_BOOL, @@ -1247,13 +1260,19 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() static CustomDataAttributeProvider edge_custom_data(ATTR_DOMAIN_EDGE, edge_access); static CustomDataAttributeProvider face_custom_data(ATTR_DOMAIN_FACE, face_access); - return ComponentAttributeProviders( - {&position, &id, &material_index, &sharp_face, &sharp_edge, &crease}, - {&corner_custom_data, - &vertex_groups, - &point_custom_data, - &edge_custom_data, - &face_custom_data}); + return ComponentAttributeProviders({&position, + &corner_vert, + &corner_edge, + &id, + &material_index, + &sharp_face, + &sharp_edge, + &crease}, + {&corner_custom_data, + &vertex_groups, + &point_custom_data, + &edge_custom_data, + &face_custom_data}); } static AttributeAccessorFunctions get_mesh_accessor_functions() diff --git a/source/blender/blenkernel/intern/gpencil_curve_legacy.c b/source/blender/blenkernel/intern/gpencil_curve_legacy.c index c7409bdebf0..c6a1cb1474a 100644 --- a/source/blender/blenkernel/intern/gpencil_curve_legacy.c +++ b/source/blender/blenkernel/intern/gpencil_curve_legacy.c @@ -983,7 +983,7 @@ static float *gpencil_stroke_points_from_editcurve_fixed_resolu(bGPDcurve_point bool is_cyclic, int *r_points_len) { - /* One stride contains: x, y, z, pressure, strength, Vr, Vg, Vb, Vmix_factor */ + /* One stride contains: `x, y, z, pressure, strength, Vr, Vg, Vb, Vmix_factor`. */ const uint stride = sizeof(float[9]); const uint array_last = curve_point_array_len - 1; const uint resolu_stride = resolution * stride; diff --git a/source/blender/blenkernel/intern/gpencil_geom_legacy.cc b/source/blender/blenkernel/intern/gpencil_geom_legacy.cc index ba0aac22385..4a2fd8ec6ce 100644 --- a/source/blender/blenkernel/intern/gpencil_geom_legacy.cc +++ b/source/blender/blenkernel/intern/gpencil_geom_legacy.cc @@ -2715,7 +2715,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); const Span positions = me_eval->vert_positions(); const Span polys = me_eval->polys(); - const Span loops = me_eval->loops(); + const Span corner_verts = me_eval->corner_verts(); int polys_len = me_eval->totpoly; char element_name[200]; @@ -2787,10 +2787,10 @@ bool BKE_gpencil_convert_mesh(Main *bmain, /* Add points to strokes. */ for (int j = 0; j < poly.totloop; j++) { - const MLoop *ml = &loops[poly.loopstart + j]; + const int vert = corner_verts[poly.loopstart + j]; bGPDspoint *pt = &gps_fill->points[j]; - copy_v3_v3(&pt->x, positions[ml->v]); + copy_v3_v3(&pt->x, positions[vert]); mul_m4_v3(matrix, &pt->x); pt->pressure = 1.0f; pt->strength = 1.0f; @@ -2798,7 +2798,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain, /* Copy vertex groups from mesh. Assuming they already exist in the same order. */ if (use_vgroups && !dverts.is_empty()) { MDeformVert *dv = &gps_fill->dvert[j]; - const MDeformVert *src_dv = &dverts[ml->v]; + const MDeformVert *src_dv = &dverts[vert]; dv->totweight = src_dv->totweight; dv->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight, "gp_fill_dverts_dw"); diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc index ae29e681d50..60fa4cfc474 100644 --- a/source/blender/blenkernel/intern/key.cc +++ b/source/blender/blenkernel/intern/key.cc @@ -2235,7 +2235,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, BKE_keyblock_convert_to_mesh(kb, positions, mesh->totvert); const blender::Span edges = mesh->edges(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); + const blender::Span corner_edges = mesh->corner_edges(); const bool loop_normals_needed = r_loop_normals != nullptr; const bool vert_normals_needed = r_vert_normals != nullptr || loop_normals_needed; @@ -2261,20 +2262,20 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, blender::bke::mesh::normals_calc_polys( {reinterpret_cast(positions), mesh->totvert}, polys, - loops, + corner_verts, {reinterpret_cast(poly_normals), polys.size()}); } if (vert_normals_needed) { blender::bke::mesh::normals_calc_poly_vert( {reinterpret_cast(positions), mesh->totvert}, polys, - loops, + corner_verts, {reinterpret_cast(poly_normals), polys.size()}, {reinterpret_cast(vert_normals), mesh->totvert}); } if (loop_normals_needed) { short(*clnors)[2] = static_cast(CustomData_get_layer_for_write( - &mesh->ldata, CD_CUSTOMLOOPNORMAL, loops.size())); /* May be nullptr. */ + &mesh->ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); /* May be nullptr. */ const bool *sharp_edges = static_cast( CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge")); const bool *sharp_faces = static_cast( @@ -2283,7 +2284,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, {reinterpret_cast(positions), mesh->totvert}, edges, polys, - loops, + corner_verts, + corner_edges, {}, {reinterpret_cast(vert_normals), mesh->totvert}, {reinterpret_cast(poly_normals), polys.size()}, @@ -2293,7 +2295,7 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, mesh->smoothresh, clnors, nullptr, - {reinterpret_cast(r_loop_normals), loops.size()}); + {reinterpret_cast(r_loop_normals), corner_verts.size()}); } if (free_vert_normals) { diff --git a/source/blender/blenkernel/intern/mball.cc b/source/blender/blenkernel/intern/mball.cc index 14065661367..f6222973a21 100644 --- a/source/blender/blenkernel/intern/mball.cc +++ b/source/blender/blenkernel/intern/mball.cc @@ -685,11 +685,9 @@ void BKE_mball_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob) mesh->totcol = mball->totcol; if (ob->parent && ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) { - int verts_num; - float(*positions)[3] = BKE_mesh_vert_coords_alloc(mesh, &verts_num); - BKE_lattice_deform_coords(ob->parent, ob, positions, verts_num, 0, nullptr, 1.0f); - BKE_mesh_vert_coords_apply(mesh, positions); - MEM_freeN(positions); + BKE_lattice_deform_coords( + ob->parent, ob, BKE_mesh_vert_positions_for_write(mesh), mesh->totvert, 0, nullptr, 1.0f); + BKE_mesh_tag_positions_changed(mesh); } ob->runtime.geometry_set_eval = new GeometrySet(GeometrySet::create_with_mesh(mesh)); diff --git a/source/blender/blenkernel/intern/mball_tessellate.cc b/source/blender/blenkernel/intern/mball_tessellate.cc index 4be58dc1ec3..e4727845fdc 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.cc +++ b/source/blender/blenkernel/intern/mball_tessellate.cc @@ -1470,8 +1470,8 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob) mesh->totpoly = int(process.curindex); MPoly *polys = static_cast( CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CONSTRUCT, mesh->totpoly)); - MLoop *mloop = static_cast( - CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CONSTRUCT, mesh->totpoly * 4)); + int *corner_verts = static_cast(CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totpoly * 4, ".corner_vert")); int loop_offset = 0; for (int i = 0; i < mesh->totpoly; i++) { @@ -1481,11 +1481,11 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob) polys[i].loopstart = loop_offset; polys[i].totloop = count; - mloop[loop_offset].v = uint32_t(indices[0]); - mloop[loop_offset + 1].v = uint32_t(indices[1]); - mloop[loop_offset + 2].v = uint32_t(indices[2]); + corner_verts[loop_offset] = indices[0]; + corner_verts[loop_offset + 1] = indices[1]; + corner_verts[loop_offset + 2] = indices[2]; if (count == 4) { - mloop[loop_offset + 3].v = uint32_t(indices[3]); + corner_verts[loop_offset + 3] = indices[3]; } loop_offset += count; diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 2f94fe9febb..725a97ffb4a 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -256,6 +256,8 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address if (!BLO_write_is_undo(writer)) { /* When converting to the old mesh format, don't save redundant attributes. */ names_to_skip.add_multiple_new({"position", + ".corner_vert", + ".corner_edge", ".hide_vert", ".hide_edge", ".hide_poly", @@ -269,6 +271,8 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address mesh->mvert = BKE_mesh_legacy_convert_positions_to_verts( mesh, temp_arrays_for_legacy_format, vert_layers); + mesh->mloop = BKE_mesh_legacy_convert_corners_to_loops( + mesh, temp_arrays_for_legacy_format, loop_layers); BKE_mesh_legacy_convert_hide_layers_to_flags(mesh); BKE_mesh_legacy_convert_selection_layers_to_flags(mesh); BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh); @@ -285,7 +289,6 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address /* Set deprecated mesh data pointers for forward compatibility. */ mesh->medge = const_cast(mesh->edges().data()); mesh->mpoly = const_cast(mesh->polys().data()); - mesh->mloop = const_cast(mesh->loops().data()); mesh->dvert = const_cast(mesh->deform_verts().data()); } @@ -518,14 +521,12 @@ static bool is_uv_bool_sublayer(CustomDataLayer const *l) /** Thresh is threshold for comparing vertices, UVs, vertex colors, weights, etc. */ static int customdata_compare( - CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, Mesh *m2, const float thresh) + CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, const float thresh) { CustomDataLayer *l1, *l2; int layer_count1 = 0, layer_count2 = 0, j; const uint64_t cd_mask_non_generic = CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_MDEFORMVERT; const uint64_t cd_mask_all_attr = CD_MASK_PROP_ALL | cd_mask_non_generic; - const Span loops_1 = m1->loops(); - const Span loops_2 = m2->loops(); /* The uv selection / pin layers are ignored in the comparisons because * the original flags they replace were ignored as well. Because of the @@ -574,6 +575,12 @@ static int customdata_compare( found_corresponding_layer = true; + if (StringRef(l1->name) == ".corner_edge") { + /* TODO(Hans): This attribute wasn't tested before loops were refactored into separate + * corner edges and corner verts attributes. Remove after updating tests. */ + continue; + } + switch (l1->type) { /* We're order-agnostic for edges here. */ case CD_MEDGE: { @@ -600,32 +607,9 @@ static int customdata_compare( int ptot = m1->totpoly; for (j = 0; j < ptot; j++, p1++, p2++) { - int k; - if (p1->totloop != p2->totloop) { return MESHCMP_POLYMISMATCH; } - - const MLoop *lp1 = &loops_1[p1->loopstart]; - const MLoop *lp2 = &loops_2[p2->loopstart]; - - for (k = 0; k < p1->totloop; k++, lp1++, lp2++) { - if (lp1->v != lp2->v) { - return MESHCMP_POLYVERTMISMATCH; - } - } - } - break; - } - case CD_MLOOP: { - MLoop *lp1 = (MLoop *)l1->data; - MLoop *lp2 = (MLoop *)l2->data; - int ltot = m1->totloop; - - for (j = 0; j < ltot; j++, lp1++, lp2++) { - if (lp1->v != lp2->v) { - return MESHCMP_LOOPMISMATCH; - } } break; } @@ -791,19 +775,19 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh) return "Number of loops don't match"; } - if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, thresh))) { return cmpcode_to_str(c); } - if ((c = customdata_compare(&me1->edata, &me2->edata, me1->totedge, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->edata, &me2->edata, me1->totedge, me1, thresh))) { return cmpcode_to_str(c); } - if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1->totloop, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1->totloop, me1, thresh))) { return cmpcode_to_str(c); } - if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, thresh))) { return cmpcode_to_str(c); } @@ -812,7 +796,7 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh) bool BKE_mesh_attribute_required(const char *name) { - return StringRef(name) == "position"; + return ELEM(StringRef(name), "position", ".corner_vert", ".corner_edge"); } void BKE_mesh_ensure_skin_customdata(Mesh *me) @@ -970,8 +954,13 @@ static void mesh_ensure_cdlayers_primary(Mesh *mesh) if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) { CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, mesh->totedge); } - if (!CustomData_get_layer(&mesh->ldata, CD_MLOOP)) { - CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, mesh->totloop); + if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_vert")) { + CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_vert"); + } + if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge")) { + CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_edge"); } if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) { CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly); @@ -1516,10 +1505,10 @@ void BKE_mesh_auto_smooth_flag_set(Mesh *me, } } -int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, int vert) +int poly_find_loop_from_vert(const MPoly *poly, const int *poly_corner_verts, int vert) { - for (int j = 0; j < poly->totloop; j++, loopstart++) { - if (loopstart->v == vert) { + for (int j = 0; j < poly->totloop; j++) { + if (poly_corner_verts[j] == vert) { return j; } } @@ -1527,14 +1516,17 @@ int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, int vert return -1; } -int poly_get_adj_loops_from_vert(const MPoly *poly, const MLoop *mloop, int vert, int r_adj[2]) +int poly_get_adj_loops_from_vert(const MPoly *poly, + const int *corner_verts, + int vert, + int r_adj[2]) { - int corner = poly_find_loop_from_vert(poly, &mloop[poly->loopstart], vert); + int corner = poly_find_loop_from_vert(poly, &corner_verts[poly->loopstart], vert); if (corner != -1) { /* vertex was found */ - r_adj[0] = ME_POLY_LOOP_PREV(mloop, poly, corner)->v; - r_adj[1] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v; + r_adj[0] = corner_verts[ME_POLY_LOOP_PREV(poly, corner)]; + r_adj[1] = corner_verts[ME_POLY_LOOP_NEXT(poly, corner)]; } return corner; @@ -1553,18 +1545,23 @@ int BKE_mesh_edge_other_vert(const MEdge *edge, int v) } void BKE_mesh_looptri_get_real_edges(const MEdge *edges, - const MLoop *loops, + const int *corner_verts, + const int *corner_edges, const MLoopTri *tri, int r_edges[3]) { for (int i = 2, i_next = 0; i_next < 3; i = i_next++) { - const MLoop *l1 = &loops[tri->tri[i]], *l2 = &loops[tri->tri[i_next]]; - const MEdge *edge = &edges[l1->e]; + const int corner_1 = tri->tri[i]; + const int corner_2 = tri->tri[i_next]; + const int vert_1 = corner_verts[corner_1]; + const int vert_2 = corner_verts[corner_2]; + const int edge_i = corner_edges[corner_1]; + const MEdge *edge = &edges[edge_i]; - bool is_real = (l1->v == edge->v1 && l2->v == edge->v2) || - (l1->v == edge->v2 && l2->v == edge->v1); + bool is_real = (vert_1 == edge->v1 && vert_2 == edge->v2) || + (vert_1 == edge->v2 && vert_2 == edge->v1); - r_edges[i] = is_real ? l1->e : -1; + r_edges[i] = is_real ? edge_i : -1; } } @@ -1859,7 +1856,8 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, mesh->vert_positions(), mesh->edges(), mesh->polys(), - mesh->loops(), + mesh->corner_verts(), + mesh->corner_edges(), {}, mesh->vert_normals(), mesh->poly_normals(), diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index 089cb6a5332..417666d6c75 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -304,7 +304,8 @@ static IMesh meshes_to_imesh(Span meshes, Vector verts(me->totvert); const Span vert_positions = me->vert_positions(); const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); + const Span corner_edges = me->corner_edges(); /* Allocate verts * Skip the matrix multiplication for each point when there is no transform for a mesh, @@ -339,20 +340,19 @@ static IMesh meshes_to_imesh(Span meshes, int flen = poly.totloop; face_vert.resize(flen); face_edge_orig.resize(flen); - const MLoop *l = &loops[poly.loopstart]; for (int i = 0; i < flen; ++i) { - int mverti = r_info->mesh_vert_offset[mi] + l->v; + const int corner_i = poly.loopstart + i; + int mverti = r_info->mesh_vert_offset[mi] + corner_verts[corner_i]; const Vert *fv = r_info->mesh_to_imesh_vert[mverti]; if (need_face_flip) { face_vert[flen - i - 1] = fv; int iedge = i < flen - 1 ? flen - i - 2 : flen - 1; - face_edge_orig[iedge] = e + l->e; + face_edge_orig[iedge] = e + corner_edges[corner_i]; } else { face_vert[i] = fv; - face_edge_orig[i] = e + l->e; + face_edge_orig[i] = e + corner_edges[corner_i]; } - ++l; } r_info->mesh_to_imesh_face[f] = arena.add_face(face_vert, f, face_edge_orig); ++f; @@ -466,7 +466,7 @@ static int fill_orig_loops(const Face *f, MutableSpan r_orig_loops) { r_orig_loops.fill(-1); - const Span orig_loops = orig_me->loops(); + const Span orig_corner_verts = orig_me->corner_verts(); int orig_mplen = orig_poly->totloop; if (f->size() != orig_mplen) { @@ -494,7 +494,7 @@ static int fill_orig_loops(const Face *f, int offset = -1; for (int i = 0; i < orig_mplen; ++i) { int loop_i = i + orig_poly->loopstart; - if (orig_loops[loop_i].v == first_orig_v_in_orig_me) { + if (orig_corner_verts[loop_i] == first_orig_v_in_orig_me) { offset = i; break; } @@ -505,7 +505,7 @@ static int fill_orig_loops(const Face *f, int num_orig_loops_found = 0; for (int mp_loop_index = 0; mp_loop_index < orig_mplen; ++mp_loop_index) { int orig_mp_loop_index = (mp_loop_index + offset) % orig_mplen; - const MLoop *l = &orig_loops[orig_poly->loopstart + orig_mp_loop_index]; + const int vert_i = orig_corner_verts[orig_poly->loopstart + orig_mp_loop_index]; int fv_orig = f->vert[mp_loop_index]->orig; if (fv_orig != NO_INDEX) { fv_orig -= orig_me_vert_offset; @@ -513,9 +513,9 @@ static int fill_orig_loops(const Face *f, fv_orig = NO_INDEX; } } - if (l->v == fv_orig) { - const MLoop *lnext = - &orig_loops[orig_poly->loopstart + ((orig_mp_loop_index + 1) % orig_mplen)]; + if (vert_i == fv_orig) { + const int vert_next = + orig_corner_verts[orig_poly->loopstart + ((orig_mp_loop_index + 1) % orig_mplen)]; int fvnext_orig = f->vert[(mp_loop_index + 1) % orig_mplen]->orig; if (fvnext_orig != NO_INDEX) { fvnext_orig -= orig_me_vert_offset; @@ -523,7 +523,7 @@ static int fill_orig_loops(const Face *f, fvnext_orig = NO_INDEX; } } - if (lnext->v == fvnext_orig) { + if (vert_next == fvnext_orig) { r_orig_loops[mp_loop_index] = orig_poly->loopstart + orig_mp_loop_index; ++num_orig_loops_found; } @@ -543,14 +543,14 @@ static void get_poly2d_cos(const Mesh *me, float r_axis_mat[3][3]) { const Span positions = me->vert_positions(); - const Span loops = me->loops(); - const Span poly_loops = loops.slice(poly->loopstart, poly->totloop); + const Span corner_verts = me->corner_verts(); + const Span poly_verts = corner_verts.slice(poly->loopstart, poly->totloop); /* Project coordinates to 2d in cos_2d, using normal as projection axis. */ - const float3 axis_dominant = bke::mesh::poly_normal_calc(positions, poly_loops); + const float3 axis_dominant = bke::mesh::poly_normal_calc(positions, poly_verts); axis_dominant_v3_to_m3(r_axis_mat, axis_dominant); - for (const int i : poly_loops.index_range()) { - float3 co = positions[poly_loops[i].v]; + for (const int i : poly_verts.index_range()) { + float3 co = positions[poly_verts[i]]; co = math::transform_point(trans_mat, co); *reinterpret_cast(&cos_2d[i]) = (float3x3(r_axis_mat) * co).xy(); } @@ -588,7 +588,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, } CustomData *target_cd = &dest_mesh->ldata; const Span dst_positions = dest_mesh->vert_positions(); - const Span dst_loops = dest_mesh->loops(); + const Span dst_corner_verts = dest_mesh->corner_verts(); for (int i = 0; i < poly->totloop; ++i) { int loop_index = poly->loopstart + i; int orig_loop_index = norig > 0 ? orig_loops[i] : -1; @@ -598,12 +598,13 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, * The coordinate needs to be projected into 2d, just like the interpolating polygon's * coordinates were. The `dest_mesh` coordinates are already in object 0 local space. */ float co[2]; - mul_v2_m3v3(co, axis_mat, dst_positions[dst_loops[loop_index].v]); + mul_v2_m3v3(co, axis_mat, dst_positions[dst_corner_verts[loop_index]]); interp_weights_poly_v2(weights.data(), cos_2d, orig_poly->totloop, co); } for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) { int ty = source_cd->layers[source_layer_i].type; - if (ty == CD_MLOOP) { + if (STREQ(source_cd->layers[source_layer_i].name, ".corner_vert") || + STREQ(source_cd->layers[source_layer_i].name, ".corner_edge")) { continue; } const char *name = source_cd->layers[source_layer_i].name; @@ -722,9 +723,8 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) result->attributes_for_write().lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); int cur_loop_index = 0; - MutableSpan dst_loops = result->loops_for_write(); + MutableSpan dst_corner_verts = result->corner_verts_for_write(); MutableSpan dst_polys = result->polys_for_write(); - MLoop *l = dst_loops.data(); for (int fi : im->face_index_range()) { const Face *f = im->face(fi); const Mesh *orig_me; @@ -738,8 +738,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) for (int j : f->index_range()) { const Vert *vf = f->vert[j]; const int vfi = im->lookup_vert(vf); - l->v = vfi; - ++l; + dst_corner_verts[cur_loop_index] = vfi; ++cur_loop_index; } @@ -762,6 +761,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) /* Now that the MEdges are populated, we can copy over the required attributes and custom layers. */ + const Span dst_corner_edges = result->corner_edges(); for (int fi : im->face_index_range()) { const Face *f = im->face(fi); const MPoly &poly = dst_polys[fi]; @@ -770,7 +770,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) const Mesh *orig_me; int index_in_orig_me; mim.input_medge_for_orig_index(f->edge_orig[j], &orig_me, &index_in_orig_me); - int e_index = dst_loops[poly.loopstart + j].e; + int e_index = dst_corner_edges[poly.loopstart + j]; copy_edge_attributes(result, orig_me, e_index, index_in_orig_me); } } @@ -833,13 +833,13 @@ Mesh *direct_mesh_boolean(Span meshes, /* Store intersecting edge indices. */ if (r_intersecting_edges != nullptr) { const Span polys = result->polys(); - const Span loops = result->loops(); + const Span corner_edges = result->corner_edges(); for (int fi : m_out.face_index_range()) { const Face &face = *m_out.face(fi); const MPoly &poly = polys[fi]; for (int corner_i : face.index_range()) { if (face.is_intersect[corner_i]) { - int e_index = loops[poly.loopstart + corner_i].e; + int e_index = corner_edges[poly.loopstart + corner_i]; r_intersecting_edges->append(e_index); } } diff --git a/source/blender/blenkernel/intern/mesh_calc_edges.cc b/source/blender/blenkernel/intern/mesh_calc_edges.cc index 0d25de3c33c..bef3ad351ec 100644 --- a/source/blender/blenkernel/intern/mesh_calc_edges.cc +++ b/source/blender/blenkernel/intern/mesh_calc_edges.cc @@ -98,22 +98,22 @@ static void add_polygon_edges_to_hash_maps(Mesh *mesh, uint32_t parallel_mask) { const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) { const int task_index = &edge_map - edge_maps.data(); for (const MPoly &poly : polys) { - Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - const MLoop *prev_loop = &poly_loops.last(); - for (const MLoop &next_loop : poly_loops) { + const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + int vert_prev = poly_verts.last(); + for (const int vert : poly_verts) { /* Can only be the same when the mesh data is invalid. */ - if (prev_loop->v != next_loop.v) { - OrderedEdge ordered_edge{prev_loop->v, next_loop.v}; + if (vert_prev != vert) { + OrderedEdge ordered_edge{vert_prev, vert}; /* Only add the edge when it belongs into this map. */ if (task_index == (parallel_mask & ordered_edge.hash2())) { edge_map.lookup_or_add(ordered_edge, {nullptr}); } } - prev_loop = &next_loop; + vert_prev = vert; } } }); @@ -158,17 +158,21 @@ static void update_edge_indices_in_poly_loops(Mesh *mesh, uint32_t parallel_mask) { const Span polys = mesh->polys(); - MutableSpan loops = mesh->loops_for_write(); + const Span corner_verts = mesh->corner_verts(); + MutableSpan corner_edges = mesh->corner_edges_for_write(); threading::parallel_for(IndexRange(mesh->totpoly), 100, [&](IndexRange range) { for (const int poly_index : range) { const MPoly &poly = polys[poly_index]; - MutableSpan poly_loops = loops.slice(poly.loopstart, poly.totloop); + const IndexRange corners(poly.loopstart, poly.totloop); + + int prev_corner = corners.last(); + for (const int next_corner : corners) { + const int vert = corner_verts[next_corner]; + const int vert_prev = corner_verts[prev_corner]; - MLoop *prev_loop = &poly_loops.last(); - for (MLoop &next_loop : poly_loops) { int edge_index; - if (prev_loop->v != next_loop.v) { - OrderedEdge ordered_edge{prev_loop->v, next_loop.v}; + if (vert_prev != vert) { + OrderedEdge ordered_edge{vert_prev, vert}; /* Double lookup: First find the map that contains the edge, then lookup the edge. */ const EdgeMap &edge_map = edge_maps[parallel_mask & ordered_edge.hash2()]; edge_index = edge_map.lookup(ordered_edge).index; @@ -179,8 +183,8 @@ static void update_edge_indices_in_poly_loops(Mesh *mesh, * #76514. */ edge_index = 0; } - prev_loop->e = edge_index; - prev_loop = &next_loop; + corner_edges[prev_corner] = edge_index; + prev_corner = next_corner; } } }); @@ -232,6 +236,10 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select } /* Create new edges. */ + if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge")) { + CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totloop, ".corner_edge"); + } MutableSpan new_edges{ static_cast(MEM_calloc_arrayN(new_totedge, sizeof(MEdge), __func__)), new_totedge}; calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, new_edges); diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index 9cb0c766d29..878edb31d8a 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -76,19 +76,18 @@ using blender::StringRefNull; static CLG_LogRef LOG = {"bke.mesh_convert"}; -static void poly_edgehash_insert(EdgeHash *ehash, const MPoly *poly, const MLoop *mloop) +static void poly_edgehash_insert(EdgeHash *ehash, const MPoly *poly, const Span corner_verts) { - const MLoop *ml, *ml_next; int i = poly->totloop; - ml_next = mloop; /* first loop */ - ml = &ml_next[i - 1]; /* last loop */ + int corner_next = poly->loopstart; /* first loop */ + int corner = corner_next + (i - 1); /* last loop */ while (i-- != 0) { - BLI_edgehash_reinsert(ehash, ml->v, ml_next->v, nullptr); + BLI_edgehash_reinsert(ehash, corner_verts[corner], corner_verts[corner_next], nullptr); - ml = ml_next; - ml_next++; + corner = corner_next; + corner_next++; } } @@ -100,13 +99,14 @@ static void make_edges_mdata_extend(Mesh &mesh) int totedge = mesh.totedge; const Span polys = mesh.polys(); - MutableSpan loops = mesh.loops_for_write(); + const Span corner_verts = mesh.corner_verts(); + MutableSpan corner_edges = mesh.corner_edges_for_write(); const int eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(mesh.totpoly)); EdgeHash *eh = BLI_edgehash_new_ex(__func__, eh_reserve); for (const MPoly &poly : polys) { - poly_edgehash_insert(eh, &poly, &loops[poly.loopstart]); + poly_edgehash_insert(eh, &poly, corner_verts); } const int totedge_new = BLI_edgehash_len(eh); @@ -139,13 +139,14 @@ static void make_edges_mdata_extend(Mesh &mesh) for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; - MLoop *l = &loops[poly.loopstart]; - MLoop *l_prev = (l + (poly.totloop - 1)); + int corner = poly.loopstart; + int corner_prev = poly.loopstart + (poly.totloop - 1); int j; - for (j = 0; j < poly.totloop; j++, l++) { + for (j = 0; j < poly.totloop; j++, corner++) { /* lookup hashed edge index */ - l_prev->e = POINTER_AS_UINT(BLI_edgehash_lookup(eh, l_prev->v, l->v)); - l_prev = l; + corner_edges[corner_prev] = POINTER_AS_UINT( + BLI_edgehash_lookup(eh, corner_verts[corner_prev], corner_verts[corner])); + corner_prev = corner; } } } @@ -206,7 +207,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); MutableAttributeAccessor attributes = mesh->attributes_for_write(); SpanAttributeWriter material_indices = attributes.lookup_or_add_for_write_only_span( @@ -283,16 +284,16 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba a = dl->parts; const int *index = dl->index; while (a--) { - loops[dst_loop + 0].v = startvert + index[0]; - loops[dst_loop + 1].v = startvert + index[2]; - loops[dst_loop + 2].v = startvert + index[1]; + corner_verts[dst_loop + 0] = startvert + index[0]; + corner_verts[dst_loop + 1] = startvert + index[2]; + corner_verts[dst_loop + 2] = startvert + index[1]; polys[dst_poly].loopstart = dst_loop; polys[dst_poly].totloop = 3; material_indices.span[dst_poly] = dl->col; if (mloopuv) { for (int i = 0; i < 3; i++, mloopuv++) { - (*mloopuv)[0] = (loops[dst_loop + i].v - startvert) / float(dl->nr - 1); + (*mloopuv)[0] = (corner_verts[dst_loop + i] - startvert) / float(dl->nr - 1); (*mloopuv)[1] = 0.0f; } } @@ -340,10 +341,10 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba } for (; b < dl->nr; b++) { - loops[dst_loop + 0].v = p1; - loops[dst_loop + 1].v = p3; - loops[dst_loop + 2].v = p4; - loops[dst_loop + 3].v = p2; + corner_verts[dst_loop + 0] = p1; + corner_verts[dst_loop + 1] = p3; + corner_verts[dst_loop + 2] = p4; + corner_verts[dst_loop + 3] = p2; polys[dst_poly].loopstart = dst_loop; polys[dst_poly].totloop = 4; material_indices.span[dst_poly] = dl->col; @@ -365,7 +366,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba for (int i = 0; i < 4; i++, mloopuv++) { /* find uv based on vertex index into grid array */ - int v = loops[dst_loop + i].v - startvert; + int v = corner_verts[dst_loop + i] - startvert; (*mloopuv)[0] = (v / dl->nr) / float(orco_sizev); (*mloopuv)[1] = (v % dl->nr) / float(orco_sizeu); @@ -470,9 +471,7 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed const Span positions = me->vert_positions(); const Span mesh_edges = me->edges(); const Span polys = me->polys(); - const Span loops = me->loops(); - - int totedges = 0; + const Span corner_edges = me->corner_edges(); /* only to detect edge polylines */ int *edge_users; @@ -483,10 +482,9 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed edge_users = (int *)MEM_calloc_arrayN(mesh_edges.size(), sizeof(int), __func__); for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; - const MLoop *ml = &loops[poly.loopstart]; int j; - for (j = 0; j < poly.totloop; j++, ml++) { - edge_users[ml->e]++; + for (j = 0; j < poly.totloop; j++) { + edge_users[corner_edges[poly.loopstart + j]]++; } } @@ -497,7 +495,6 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed edl->edge = &mesh_edges[i]; BLI_addtail(&edges, edl); - totedges++; } } MEM_freeN(edge_users); @@ -519,7 +516,6 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed appendPolyLineVert(&polyline, endVert); totpoly++; BLI_freelinkN(&edges, edges.last); - totedges--; while (ok) { /* while connected edges are found... */ EdgeLink *edl = (EdgeLink *)edges.last; @@ -531,10 +527,9 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed if (edge->v1 == endVert) { endVert = edge->v2; - appendPolyLineVert(&polyline, edge->v2); + appendPolyLineVert(&polyline, endVert); totpoly++; BLI_freelinkN(&edges, edl); - totedges--; ok = true; } else if (edge->v2 == endVert) { @@ -542,7 +537,6 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed appendPolyLineVert(&polyline, endVert); totpoly++; BLI_freelinkN(&edges, edl); - totedges--; ok = true; } else if (edge->v1 == startVert) { @@ -550,7 +544,6 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed prependPolyLineVert(&polyline, startVert); totpoly++; BLI_freelinkN(&edges, edl); - totedges--; ok = true; } else if (edge->v2 == startVert) { @@ -558,7 +551,6 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed prependPolyLineVert(&polyline, startVert); totpoly++; BLI_freelinkN(&edges, edl); - totedges--; ok = true; } @@ -582,18 +574,18 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed /* create new 'nurb' within the curve */ nu = MEM_new("MeshNurb", blender::dna::shallow_zero_initialize()); - nu->pntsu = polys.size(); + nu->pntsu = totpoly; nu->pntsv = 1; nu->orderu = 4; nu->flagu = CU_NURB_ENDPOINT | (closed ? CU_NURB_CYCLIC : 0); /* endpoint */ nu->resolu = 12; - nu->bp = (BPoint *)MEM_calloc_arrayN(polys.size(), sizeof(BPoint), "bpoints"); + nu->bp = (BPoint *)MEM_calloc_arrayN(totpoly, sizeof(BPoint), "bpoints"); /* add points */ vl = (VertLink *)polyline.first; int i; - for (i = 0, bp = nu->bp; i < polys.size(); i++, bp++, vl = (VertLink *)vl->next) { + for (i = 0, bp = nu->bp; i < totpoly; i++, bp++, vl = (VertLink *)vl->next) { copy_v3_v3(bp->vec, positions[vl->index]); bp->f1 = SELECT; bp->radius = bp->weight = 1.0; diff --git a/source/blender/blenkernel/intern/mesh_evaluate.cc b/source/blender/blenkernel/intern/mesh_evaluate.cc index 979c3f6a064..59134f32e27 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.cc +++ b/source/blender/blenkernel/intern/mesh_evaluate.cc @@ -40,43 +40,42 @@ using blender::VArray; namespace blender::bke::mesh { -static float3 poly_center_calc_ngon(const Span vert_positions, - const Span poly_loops) +static float3 poly_center_calc_ngon(const Span vert_positions, const Span poly_verts) { - const float w = 1.0f / float(poly_loops.size()); + const float w = 1.0f / float(poly_verts.size()); float3 center(0); - for (const int i : poly_loops.index_range()) { - center += vert_positions[poly_loops[i].v] * w; + for (const int i : poly_verts.index_range()) { + center += vert_positions[poly_verts[i]] * w; } return center; } -float3 poly_center_calc(const Span vert_positions, const Span poly_loops) +float3 poly_center_calc(const Span vert_positions, const Span poly_verts) { - if (poly_loops.size() == 3) { + if (poly_verts.size() == 3) { float3 center; mid_v3_v3v3v3(center, - vert_positions[poly_loops[0].v], - vert_positions[poly_loops[1].v], - vert_positions[poly_loops[2].v]); + vert_positions[poly_verts[0]], + vert_positions[poly_verts[1]], + vert_positions[poly_verts[2]]); return center; } - if (poly_loops.size() == 4) { + if (poly_verts.size() == 4) { float3 center; mid_v3_v3v3v3v3(center, - vert_positions[poly_loops[0].v], - vert_positions[poly_loops[1].v], - vert_positions[poly_loops[2].v], - vert_positions[poly_loops[3].v]); + vert_positions[poly_verts[0]], + vert_positions[poly_verts[1]], + vert_positions[poly_verts[2]], + vert_positions[poly_verts[3]]); return center; } - return poly_center_calc_ngon(vert_positions, poly_loops); + return poly_center_calc_ngon(vert_positions, poly_verts); } } // namespace blender::bke::mesh -void BKE_mesh_calc_poly_center(const MLoop *poly_loops, +void BKE_mesh_calc_poly_center(const int *poly_verts, const int poly_size, const float (*vert_positions)[3], const int verts_num, @@ -85,51 +84,51 @@ void BKE_mesh_calc_poly_center(const MLoop *poly_loops, copy_v3_v3(r_cent, blender::bke::mesh::poly_center_calc( {reinterpret_cast(vert_positions), verts_num}, - {poly_loops, poly_size})); + {poly_verts, poly_size})); } namespace blender::bke::mesh { -float poly_area_calc(const Span vert_positions, const Span poly_loops) +float poly_area_calc(const Span vert_positions, const Span poly_verts) { - if (poly_loops.size() == 3) { - return area_tri_v3(vert_positions[poly_loops[0].v], - vert_positions[poly_loops[1].v], - vert_positions[poly_loops[2].v]); + if (poly_verts.size() == 3) { + return area_tri_v3(vert_positions[poly_verts[0]], + vert_positions[poly_verts[1]], + vert_positions[poly_verts[2]]); } - Array poly_coords(poly_loops.size()); - for (const int i : poly_loops.index_range()) { - poly_coords[i] = vert_positions[poly_loops[i].v]; + Array poly_coords(poly_verts.size()); + for (const int i : poly_verts.index_range()) { + poly_coords[i] = vert_positions[poly_verts[i]]; } - return area_poly_v3((const float(*)[3])poly_coords.data(), poly_loops.size()); + return area_poly_v3((const float(*)[3])poly_coords.data(), poly_verts.size()); } } // namespace blender::bke::mesh -float BKE_mesh_calc_poly_area(const MLoop *poly_loops, +float BKE_mesh_calc_poly_area(const int *poly_verts, const int poly_size, const float (*vert_positions)[3], const int verts_num) { return blender::bke::mesh::poly_area_calc( - {reinterpret_cast(vert_positions), verts_num}, {poly_loops, poly_size}); + {reinterpret_cast(vert_positions), verts_num}, {poly_verts, poly_size}); } float BKE_mesh_calc_area(const Mesh *me) { const Span positions = me->vert_positions(); const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); float total_area = 0.0f; for (const MPoly &poly : polys) { - total_area += blender::bke::mesh::poly_area_calc(positions, - loops.slice(poly.loopstart, poly.totloop)); + total_area += blender::bke::mesh::poly_area_calc( + positions, corner_verts.slice(poly.loopstart, poly.totloop)); } return total_area; } -static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MLoop *poly_loops, +static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const int *poly_verts, const int poly_size, const float (*positions)[3], float r_cent[3]) @@ -139,11 +138,11 @@ static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MLoop *poly_l zero_v3(r_cent); - v_pivot = positions[poly_loops[0].v]; - v_step1 = positions[poly_loops[1].v]; + v_pivot = positions[poly_verts[0]]; + v_step1 = positions[poly_verts[1]]; for (int i = 2; i < poly_size; i++) { - const float *v_step2 = positions[poly_loops[i].v]; + const float *v_step2 = positions[poly_verts[i]]; /* Calculate the 6x volume of the tetrahedron formed by the 3 vertices * of the triangle and the origin as the fourth vertex */ @@ -174,7 +173,7 @@ namespace blender::bke::mesh { * very low quality as the value moves away from 0.0, see: #65986. */ static float mesh_calc_poly_volume_centroid_with_reference_center(const Span positions, - const Span poly_loops, + const Span poly_verts, const float3 &reference_center, float r_cent[3]) { @@ -182,11 +181,11 @@ static float mesh_calc_poly_volume_centroid_with_reference_center(const Span positions, - const Span poly_loops, + const Span poly_verts, float r_cent[3]) { float total_area = 0.0f; float v1[3], v2[3], v3[3], tri_cent[3]; - const float3 normal = blender::bke::mesh::poly_normal_calc(positions, poly_loops); + const float3 normal = blender::bke::mesh::poly_normal_calc(positions, poly_verts); - copy_v3_v3(v1, positions[poly_loops[0].v]); - copy_v3_v3(v2, positions[poly_loops[1].v]); + copy_v3_v3(v1, positions[poly_verts[0]]); + copy_v3_v3(v2, positions[poly_verts[1]]); zero_v3(r_cent); - for (int i = 2; i < poly_loops.size(); i++) { - copy_v3_v3(v3, positions[poly_loops[i].v]); + for (int i = 2; i < poly_verts.size(); i++) { + copy_v3_v3(v3, positions[poly_verts[i]]); float tri_area = area_tri_signed_v3(v1, v2, v3, normal); total_area += tri_area; @@ -235,22 +234,21 @@ static float poly_area_centroid_calc(const Span positions, } void poly_angles_calc(const Span vert_positions, - const Span poly_loops, + const Span poly_verts, MutableSpan angles) { float nor_prev[3]; float nor_next[3]; - int i_this = poly_loops.size() - 1; + int i_this = poly_verts.size() - 1; int i_next = 0; sub_v3_v3v3( - nor_prev, vert_positions[poly_loops[i_this - 1].v], vert_positions[poly_loops[i_this].v]); + nor_prev, vert_positions[poly_verts[i_this - 1]], vert_positions[poly_verts[i_this]]); normalize_v3(nor_prev); - while (i_next < poly_loops.size()) { - sub_v3_v3v3( - nor_next, vert_positions[poly_loops[i_this].v], vert_positions[poly_loops[i_next].v]); + while (i_next < poly_verts.size()) { + sub_v3_v3v3(nor_next, vert_positions[poly_verts[i_this]], vert_positions[poly_verts[i_next]]); normalize_v3(nor_next); angles[i_this] = angle_normalized_v3v3(nor_prev, nor_next); @@ -288,12 +286,12 @@ bool BKE_mesh_center_median_from_polys(const Mesh *me, float r_cent[3]) int tot = 0; const Span positions = me->vert_positions(); const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); zero_v3(r_cent); for (const MPoly &poly : polys) { int loopend = poly.loopstart + poly.totloop; for (int j = poly.loopstart; j < loopend; j++) { - add_v3_v3(r_cent, positions[loops[j].v]); + add_v3_v3(r_cent, positions[corner_verts[j]]); } tot += poly.totloop; } @@ -323,14 +321,14 @@ bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3]) float poly_cent[3]; const Span positions = me->vert_positions(); const blender::Span polys = me->polys(); - const blender::Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); zero_v3(r_cent); /* calculate a weighted average of polygon centroids */ for (const int i : polys.index_range()) { poly_area = blender::bke::mesh::poly_area_centroid_calc( - positions, loops.slice(polys[i].loopstart, polys[i].totloop), poly_cent); + positions, corner_verts.slice(polys[i].loopstart, polys[i].totloop), poly_cent); madd_v3_v3fl(r_cent, poly_cent, poly_area); total_area += poly_area; @@ -355,7 +353,7 @@ bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3]) float poly_cent[3]; const Span positions = me->vert_positions(); const blender::Span polys = me->polys(); - const blender::Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); /* Use an initial center to avoid numeric instability of geometry far away from the center. */ float init_cent[3]; @@ -366,7 +364,7 @@ bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3]) /* calculate a weighted average of polyhedron centroids */ for (const int i : polys.index_range()) { poly_volume = blender::bke::mesh::mesh_calc_poly_volume_centroid_with_reference_center( - positions, loops.slice(polys[i].loopstart, polys[i].totloop), init_cent, poly_cent); + positions, corner_verts.slice(polys[i].loopstart, polys[i].totloop), init_cent, poly_cent); /* poly_cent is already volume-weighted, so no need to multiply by the volume */ add_v3_v3(r_cent, poly_cent); @@ -399,7 +397,7 @@ static bool mesh_calc_center_centroid_ex(const float (*positions)[3], int /*mverts_num*/, const MLoopTri *looptri, int looptri_num, - const MLoop *mloop, + const int *corner_verts, float r_center[3]) { @@ -413,9 +411,9 @@ static bool mesh_calc_center_centroid_ex(const float (*positions)[3], const MLoopTri *lt; int i; for (i = 0, lt = looptri; i < looptri_num; i++, lt++) { - const float *v1 = positions[mloop[lt->tri[0]].v]; - const float *v2 = positions[mloop[lt->tri[1]].v]; - const float *v3 = positions[mloop[lt->tri[2]].v]; + const float *v1 = positions[corner_verts[lt->tri[0]]]; + const float *v2 = positions[corner_verts[lt->tri[1]]]; + const float *v3 = positions[corner_verts[lt->tri[2]]]; float area; area = area_tri_v3(v1, v2, v3); @@ -437,7 +435,7 @@ void BKE_mesh_calc_volume(const float (*vert_positions)[3], const int mverts_num, const MLoopTri *looptri, const int looptri_num, - const MLoop *mloop, + const int *corner_verts, float *r_volume, float r_center[3]) { @@ -458,16 +456,16 @@ void BKE_mesh_calc_volume(const float (*vert_positions)[3], } if (!mesh_calc_center_centroid_ex( - vert_positions, mverts_num, looptri, looptri_num, mloop, center)) { + vert_positions, mverts_num, looptri, looptri_num, corner_verts, center)) { return; } totvol = 0.0f; for (i = 0, lt = looptri; i < looptri_num; i++, lt++) { - const float *v1 = vert_positions[mloop[lt->tri[0]].v]; - const float *v2 = vert_positions[mloop[lt->tri[1]].v]; - const float *v3 = vert_positions[mloop[lt->tri[2]].v]; + const float *v1 = vert_positions[corner_verts[lt->tri[0]]]; + const float *v2 = vert_positions[corner_verts[lt->tri[1]]]; + const float *v3 = vert_positions[corner_verts[lt->tri[2]]]; float vol; vol = volume_tetrahedron_signed_v3(center, v1, v2, v3); @@ -538,7 +536,8 @@ void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip) } void BKE_mesh_polygon_flip_ex(const MPoly *poly, - MLoop *mloop, + int *corner_verts, + int *corner_edges, CustomData *ldata, float (*lnors)[3], MDisps *mdisp, @@ -546,7 +545,10 @@ void BKE_mesh_polygon_flip_ex(const MPoly *poly, { int loopstart = poly->loopstart; int loopend = loopstart + poly->totloop - 1; - const bool loops_in_ldata = (CustomData_get_layer(ldata, CD_MLOOP) == mloop); + const bool corner_verts_in_data = (CustomData_get_layer_named( + ldata, CD_PROP_INT32, ".corner_vert") == corner_verts); + const bool corner_edges_in_data = (CustomData_get_layer_named( + ldata, CD_PROP_INT32, ".corner_edge") == corner_edges); if (mdisp) { for (int i = loopstart; i <= loopend; i++) { @@ -559,15 +561,18 @@ void BKE_mesh_polygon_flip_ex(const MPoly *poly, /* We also have to update loops edge * (they will get their original 'other edge', that is, * the original edge of their original previous loop)... */ - uint prev_edge_index = mloop[loopstart].e; - mloop[loopstart].e = mloop[loopend].e; + int prev_edge_index = corner_edges[loopstart]; + corner_edges[loopstart] = corner_edges[loopend]; for (loopstart++; loopend > loopstart; loopstart++, loopend--) { - mloop[loopend].e = mloop[loopend - 1].e; - std::swap(mloop[loopstart].e, prev_edge_index); + corner_edges[loopend] = corner_edges[loopend - 1]; + std::swap(corner_edges[loopstart], prev_edge_index); - if (!loops_in_ldata) { - std::swap(mloop[loopstart], mloop[loopend]); + if (!corner_verts_in_data) { + std::swap(corner_verts[loopstart], corner_verts[loopend]); + } + if (!corner_edges_in_data) { + std::swap(corner_edges[loopstart], corner_edges[loopend]); } if (lnors) { swap_v3_v3(lnors[loopstart], lnors[loopend]); @@ -576,21 +581,23 @@ void BKE_mesh_polygon_flip_ex(const MPoly *poly, } /* Even if we did not swap the other 'pivot' loop, we need to set its swapped edge. */ if (loopstart == loopend) { - mloop[loopstart].e = prev_edge_index; + corner_edges[loopstart] = prev_edge_index; } } -void BKE_mesh_polygon_flip(const MPoly *poly, MLoop *mloop, CustomData *ldata, const int totloop) +void BKE_mesh_polygon_flip( + const MPoly *poly, int *corner_verts, int *corner_edges, CustomData *ldata, const int totloop) { MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(ldata, CD_MDISPS, totloop); - BKE_mesh_polygon_flip_ex(poly, mloop, ldata, nullptr, mdisp, true); + BKE_mesh_polygon_flip_ex(poly, corner_verts, corner_edges, ldata, nullptr, mdisp, true); } -void BKE_mesh_polys_flip(const MPoly *polys, MLoop *mloop, CustomData *ldata, int totpoly) +void BKE_mesh_polys_flip( + const MPoly *polys, int *corner_verts, int *corner_edges, CustomData *ldata, int totpoly) { MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(ldata, CD_MDISPS, totpoly); for (const int i : blender::IndexRange(totpoly)) { - BKE_mesh_polygon_flip_ex(&polys[i], mloop, ldata, nullptr, mdisp, true); + BKE_mesh_polygon_flip_ex(&polys[i], corner_verts, corner_edges, ldata, nullptr, mdisp, true); } } @@ -614,7 +621,7 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me) const VArraySpan hide_vert_span{hide_vert}; const Span edges = me->edges(); const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); /* Hide edges when either of their vertices are hidden. */ SpanAttributeWriter hide_edge = attributes.lookup_or_add_for_write_only_span( @@ -630,9 +637,9 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me) ".hide_poly", ATTR_DOMAIN_FACE); for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - hide_poly.span[i] = std::any_of(poly_loops.begin(), poly_loops.end(), [&](const MLoop &loop) { - return hide_vert_span[loop.v]; + const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + hide_poly.span[i] = std::any_of(poly_verts.begin(), poly_verts.end(), [&](const int vert) { + return hide_vert_span[vert]; }); } hide_poly.finish(); @@ -653,7 +660,8 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me) } const VArraySpan hide_poly_span{hide_poly}; const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); + const Span corner_edges = me->corner_edges(); SpanAttributeWriter hide_vert = attributes.lookup_or_add_for_write_only_span( ".hide_vert", ATTR_DOMAIN_POINT); SpanAttributeWriter hide_edge = attributes.lookup_or_add_for_write_only_span( @@ -663,9 +671,9 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me) for (const int i : polys.index_range()) { if (hide_poly_span[i]) { const MPoly &poly = polys[i]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - hide_vert.span[loop.v] = true; - hide_edge.span[loop.e] = true; + for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + hide_vert.span[corner_verts[corner]] = true; + hide_edge.span[corner_edges[corner]] = true; } } } @@ -673,9 +681,9 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me) for (const int i : polys.index_range()) { if (!hide_poly_span[i]) { const MPoly &poly = polys[i]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - hide_vert.span[loop.v] = false; - hide_edge.span[loop.e] = false; + for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + hide_vert.span[corner_verts[corner]] = false; + hide_edge.span[corner_edges[corner]] = false; } } } @@ -713,7 +721,7 @@ void BKE_mesh_flush_select_from_polys(Mesh *me) static void mesh_flush_select_from_verts(const Span edges, const Span polys, - const Span loops, + const Span corner_verts, const VArray &hide_edge, const VArray &hide_poly, const VArray &select_vert, @@ -732,10 +740,9 @@ static void mesh_flush_select_from_verts(const Span edges, for (const int i : polys.index_range()) { if (!hide_poly[i]) { const MPoly &poly = polys[i]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - select_poly[i] = std::all_of(poly_loops.begin(), poly_loops.end(), [&](const MLoop &loop) { - return select_vert[loop.v]; - }); + const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + select_poly[i] = std::all_of( + poly_verts.begin(), poly_verts.end(), [&](const int vert) { return select_vert[vert]; }); } } } @@ -758,7 +765,7 @@ void BKE_mesh_flush_select_from_verts(Mesh *me) mesh_flush_select_from_verts( me->edges(), me->polys(), - me->loops(), + me->corner_verts(), attributes.lookup_or_default(".hide_edge", ATTR_DOMAIN_EDGE, false), attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false), select_vert, @@ -776,7 +783,7 @@ void BKE_mesh_flush_select_from_verts(Mesh *me) void BKE_mesh_calc_relative_deform(const MPoly *polys, const int totpoly, - const MLoop *mloop, + const int *corner_verts, const int totvert, const float (*vert_cos_src)[3], @@ -791,12 +798,12 @@ void BKE_mesh_calc_relative_deform(const MPoly *polys, for (const int i : blender::IndexRange(totpoly)) { const MPoly &poly = polys[i]; - const MLoop *loopstart = mloop + poly.loopstart; + const int *poly_verts = &corner_verts[poly.loopstart]; for (int j = 0; j < poly.totloop; j++) { - uint v_prev = loopstart[(poly.totloop + (j - 1)) % poly.totloop].v; - uint v_curr = loopstart[j].v; - uint v_next = loopstart[(j + 1) % poly.totloop].v; + const int v_prev = poly_verts[(poly.totloop + (j - 1)) % poly.totloop]; + const int v_curr = poly_verts[j]; + const int v_next = poly_verts[(j + 1) % poly.totloop]; float tvec[3]; diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc index b7e5fdc8104..e5180115d52 100644 --- a/source/blender/blenkernel/intern/mesh_fair.cc +++ b/source/blender/blenkernel/intern/mesh_fair.cc @@ -200,11 +200,12 @@ class MeshFairingContext : public FairingContext { MutableSpan positions = mesh->vert_positions_for_write(); edges_ = mesh->edges(); polys = mesh->polys(); - mloop_ = mesh->loops(); + corner_verts_ = mesh->corner_verts(); + corner_edges_ = mesh->corner_edges(); BKE_mesh_vert_loop_map_create(&vlmap_, &vlmap_mem_, polys.data(), - mloop_.data(), + corner_verts_.data(), mesh->totvert, mesh->totpoly, mesh->totloop); @@ -222,7 +223,8 @@ class MeshFairingContext : public FairingContext { } } - loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys, mloop_.size()); + loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys, + corner_verts_.size()); } ~MeshFairingContext() override @@ -235,16 +237,16 @@ class MeshFairingContext : public FairingContext { float r_adj_next[3], float r_adj_prev[3]) override { - const int vert = mloop_[loop].v; + const int vert = corner_verts_[loop]; const MPoly &poly = polys[loop_to_poly_map_[loop]]; - const int corner = poly_find_loop_from_vert(&poly, &mloop_[poly.loopstart], vert); - copy_v3_v3(r_adj_next, co_[ME_POLY_LOOP_NEXT(mloop_, &poly, corner)->v]); - copy_v3_v3(r_adj_prev, co_[ME_POLY_LOOP_PREV(mloop_, &poly, corner)->v]); + const int corner = poly_find_loop_from_vert(&poly, &corner_verts_[poly.loopstart], vert); + copy_v3_v3(r_adj_next, co_[corner_verts_[ME_POLY_LOOP_NEXT(&poly, corner)]]); + copy_v3_v3(r_adj_prev, co_[corner_verts_[ME_POLY_LOOP_PREV(&poly, corner)]]); } int other_vertex_index_from_loop(const int loop, const uint v) override { - const MEdge *edge = &edges_[mloop_[loop].e]; + const MEdge *edge = &edges_[corner_edges_[loop]]; if (edge->v1 == v) { return edge->v2; } @@ -253,7 +255,8 @@ class MeshFairingContext : public FairingContext { protected: Mesh *mesh_; - Span mloop_; + Span corner_verts_; + Span corner_edges_; Span polys; Span edges_; Array loop_to_poly_map_; diff --git a/source/blender/blenkernel/intern/mesh_iterators.cc b/source/blender/blenkernel/intern/mesh_iterators.cc index b1a47e176d3..b8dcc04940c 100644 --- a/source/blender/blenkernel/intern/mesh_iterators.cc +++ b/source/blender/blenkernel/intern/mesh_iterators.cc @@ -194,7 +194,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, const float(*positions)[3] = BKE_mesh_vert_positions(mesh); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); const int *v_index = static_cast( CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX)); const int *f_index = static_cast( @@ -202,26 +202,24 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, if (v_index || f_index) { for (const int poly_i : polys.index_range()) { - for (const int loop_i : - blender::IndexRange(polys[poly_i].loopstart, polys[poly_i].totloop)) { - const int v_idx = v_index ? v_index[loops[loop_i].v] : loops[loop_i].v; + for (const int vert : corner_verts.slice(polys[poly_i].loopstart, polys[poly_i].totloop)) { + const int v_idx = v_index ? v_index[vert] : vert; const int f_idx = f_index ? f_index[poly_i] : poly_i; const float *no = loop_normals ? *loop_normals++ : nullptr; if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) { continue; } - func(userData, v_idx, f_idx, positions[loops[loop_i].v], no); + func(userData, v_idx, f_idx, positions[vert], no); } } } else { for (const int poly_i : polys.index_range()) { - for (const int loop_i : - blender::IndexRange(polys[poly_i].loopstart, polys[poly_i].totloop)) { - const int v_idx = loops[loop_i].v; + for (const int vert : corner_verts.slice(polys[poly_i].loopstart, polys[poly_i].totloop)) { + const int v_idx = vert; const int f_idx = poly_i; const float *no = loop_normals ? *loop_normals++ : nullptr; - func(userData, v_idx, f_idx, positions[loops[loop_i].v], no); + func(userData, v_idx, f_idx, positions[vert], no); } } } @@ -271,7 +269,7 @@ void BKE_mesh_foreach_mapped_face_center( else { const blender::Span positions = mesh->vert_positions(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); const int *index = static_cast(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX)); if (index) { @@ -280,10 +278,10 @@ void BKE_mesh_foreach_mapped_face_center( if (orig == ORIGINDEX_NONE) { continue; } - const Span poly_loops = loops.slice(polys[i].loopstart, polys[i].totloop); - const float3 center = bke::mesh::poly_center_calc(positions, poly_loops); + const Span poly_verts = corner_verts.slice(polys[i].loopstart, polys[i].totloop); + const float3 center = bke::mesh::poly_center_calc(positions, poly_verts); if (flag & MESH_FOREACH_USE_NORMAL) { - const float3 normal = bke::mesh::poly_normal_calc(positions, poly_loops); + const float3 normal = bke::mesh::poly_normal_calc(positions, poly_verts); func(userData, orig, center, normal); } else { @@ -293,10 +291,10 @@ void BKE_mesh_foreach_mapped_face_center( } else { for (const int i : polys.index_range()) { - const Span poly_loops = loops.slice(polys[i].loopstart, polys[i].totloop); - const float3 center = bke::mesh::poly_center_calc(positions, poly_loops); + const Span poly_verts = corner_verts.slice(polys[i].loopstart, polys[i].totloop); + const float3 center = bke::mesh::poly_center_calc(positions, poly_verts); if (flag & MESH_FOREACH_USE_NORMAL) { - const float3 normal = bke::mesh::poly_normal_calc(positions, poly_loops); + const float3 normal = bke::mesh::poly_normal_calc(positions, poly_verts); func(userData, i, center, normal); } else { @@ -315,7 +313,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center( { const float(*positions)[3] = BKE_mesh_vert_positions(mesh); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); blender::Span vert_normals; if (flag & MESH_FOREACH_USE_NORMAL) { vert_normals = mesh->vert_normals(); @@ -329,24 +327,24 @@ void BKE_mesh_foreach_mapped_subdiv_face_center( if (orig == ORIGINDEX_NONE) { continue; } - for (const MLoop &loop : loops.slice(polys[i].loopstart, polys[i].totloop)) { - if (facedot_tags[loop.v]) { + for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) { + if (facedot_tags[vert]) { func(userData, orig, - positions[loop.v], - (flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[loop.v].x : nullptr); + positions[vert], + (flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[vert].x : nullptr); } } } } else { for (const int i : polys.index_range()) { - for (const MLoop &loop : loops.slice(polys[i].loopstart, polys[i].totloop)) { - if (facedot_tags[loop.v]) { + for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) { + if (facedot_tags[vert]) { func(userData, i, - positions[loop.v], - (flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[loop.v].x : nullptr); + positions[vert], + (flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[vert].x : nullptr); } } } diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 82179b6204f..10de69832a5 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -209,18 +209,18 @@ void BKE_mesh_calc_edges_legacy(Mesh *me) const Span verts(static_cast(CustomData_get_layer(&me->vdata, CD_MVERT)), me->totvert); const Span polys = me->polys(); - MutableSpan loops = me->loops_for_write(); - mesh_calc_edges_mdata(verts.data(), - (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE), - loops.data(), - polys.data(), - verts.size(), - me->totface, - loops.size(), - polys.size(), - &edges, - &totedge); + mesh_calc_edges_mdata( + verts.data(), + (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE), + static_cast(CustomData_get_layer_for_write(&me->ldata, CD_MLOOP, me->totloop)), + polys.data(), + verts.size(), + me->totface, + me->totloop, + polys.size(), + &edges, + &totedge); if (totedge == 0) { /* flag that mesh has edges */ @@ -705,6 +705,7 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) &mesh->totpoly); mesh_ensure_tessellation_customdata(mesh); + BKE_mesh_legacy_convert_loops_to_corners(mesh); } /** @@ -964,7 +965,6 @@ static int mesh_tessface_calc(Mesh &mesh, const int looptri_num = poly_to_tri_count(totpoly, totloop); const MPoly *poly, *mpoly; - const MLoop *ml, *mloop; MFace *mface, *mf; MemArena *arena = nullptr; int *mface_to_poly_map; @@ -973,7 +973,7 @@ static int mesh_tessface_calc(Mesh &mesh, uint j; mpoly = (const MPoly *)CustomData_get_layer(pdata, CD_MPOLY); - mloop = (const MLoop *)CustomData_get_layer(ldata, CD_MLOOP); + const Span corner_verts = mesh.corner_verts(); const int *material_indices = static_cast( CustomData_get_layer_named(pdata, CD_PROP_INT32, "material_index")); const bool *sharp_faces = static_cast( @@ -1008,9 +1008,9 @@ static int mesh_tessface_calc(Mesh &mesh, l1 = mp_loopstart + i1; \ l2 = mp_loopstart + i2; \ l3 = mp_loopstart + i3; \ - mf->v1 = mloop[l1].v; \ - mf->v2 = mloop[l2].v; \ - mf->v3 = mloop[l3].v; \ + mf->v1 = corner_verts[l1]; \ + mf->v2 = corner_verts[l2]; \ + mf->v3 = corner_verts[l3]; \ mf->v4 = 0; \ lidx[0] = l1; \ lidx[1] = l2; \ @@ -1031,10 +1031,10 @@ static int mesh_tessface_calc(Mesh &mesh, l2 = mp_loopstart + 1; /* EXCEPTION */ \ l3 = mp_loopstart + 2; /* EXCEPTION */ \ l4 = mp_loopstart + 3; /* EXCEPTION */ \ - mf->v1 = mloop[l1].v; \ - mf->v2 = mloop[l2].v; \ - mf->v3 = mloop[l3].v; \ - mf->v4 = mloop[l4].v; \ + mf->v1 = corner_verts[l1]; \ + mf->v2 = corner_verts[l2]; \ + mf->v3 = corner_verts[l3]; \ + mf->v4 = corner_verts[l4]; \ lidx[0] = l1; \ lidx[1] = l2; \ lidx[2] = l3; \ @@ -1081,10 +1081,10 @@ static int mesh_tessface_calc(Mesh &mesh, zero_v3(normal); /* Calculate the normal, flipped: to get a positive 2D cross product. */ - ml = mloop + mp_loopstart; - co_prev = positions[ml[mp_totloop - 1].v]; - for (j = 0; j < mp_totloop; j++, ml++) { - co_curr = positions[ml->v]; + co_prev = positions[corner_verts[mp_loopstart + mp_totloop - 1]]; + for (j = 0; j < mp_totloop; j++) { + const int vert = corner_verts[mp_loopstart + j]; + co_curr = positions[vert]; add_newell_cross_v3_v3v3(normal, co_prev, co_curr); co_prev = co_curr; } @@ -1095,9 +1095,9 @@ static int mesh_tessface_calc(Mesh &mesh, /* Project verts to 2D. */ axis_dominant_v3_to_m3_negate(axis_mat, normal); - ml = mloop + mp_loopstart; - for (j = 0; j < mp_totloop; j++, ml++) { - mul_v2_m3v3(projverts[j], axis_mat, positions[ml->v]); + for (j = 0; j < mp_totloop; j++) { + const int vert = corner_verts[mp_loopstart + j]; + mul_v2_m3v3(projverts[j], axis_mat, positions[vert]); } BLI_polyfill_calc_arena(projverts, mp_totloop, 1, tris, arena); @@ -1115,9 +1115,9 @@ static int mesh_tessface_calc(Mesh &mesh, l2 = mp_loopstart + tri[1]; l3 = mp_loopstart + tri[2]; - mf->v1 = mloop[l1].v; - mf->v2 = mloop[l2].v; - mf->v3 = mloop[l3].v; + mf->v1 = corner_verts[l1]; + mf->v2 = corner_verts[l2]; + mf->v3 = corner_verts[l3]; mf->v4 = 0; lidx[0] = l1; @@ -1655,6 +1655,19 @@ void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh) /** \name Generic UV Map Conversion * \{ */ +static const bool *layers_find_bool_named(const Span layers, + const blender::StringRef name) +{ + for (const CustomDataLayer &layer : layers) { + if (layer.type == CD_PROP_BOOL) { + if (layer.name == name) { + return static_cast(layer.data); + } + } + } + return nullptr; +} + void BKE_mesh_legacy_convert_uvs_to_struct( Mesh *mesh, blender::ResourceScope &temp_mloopuv_for_convert, @@ -1662,6 +1675,7 @@ void BKE_mesh_legacy_convert_uvs_to_struct( { using namespace blender; using namespace blender::bke; + const int loops_num = mesh->totloop; Vector new_layer_to_write; /* Don't write the boolean UV map sublayers which will be written in the legacy #MLoopUV type. */ @@ -1686,20 +1700,19 @@ void BKE_mesh_legacy_convert_uvs_to_struct( new_layer_to_write.append(layer); continue; } - const Span coords{static_cast(layer.data), mesh->totloop}; + const Span coords{static_cast(layer.data), loops_num}; CustomDataLayer mloopuv_layer = layer; mloopuv_layer.type = CD_MLOOPUV; - MutableSpan mloopuv = temp_mloopuv_for_convert.construct>( - mesh->totloop); + MutableSpan mloopuv = temp_mloopuv_for_convert.construct>(loops_num); mloopuv_layer.data = mloopuv.data(); char buffer[MAX_CUSTOMDATA_LAYER_NAME]; - const bool *vert_selection = static_cast(CustomData_get_layer_named( - &mesh->ldata, CD_PROP_BOOL, BKE_uv_map_vert_select_name_get(layer.name, buffer))); - const bool *edge_selection = static_cast(CustomData_get_layer_named( - &mesh->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(layer.name, buffer))); - const bool *pin = static_cast(CustomData_get_layer_named( - &mesh->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(layer.name, buffer))); + const bool *vert_selection = layers_find_bool_named( + loop_layers_to_write, BKE_uv_map_vert_select_name_get(layer.name, buffer)); + const bool *edge_selection = layers_find_bool_named( + loop_layers_to_write, BKE_uv_map_edge_select_name_get(layer.name, buffer)); + const bool *pin = layers_find_bool_named(loop_layers_to_write, + BKE_uv_map_pin_name_get(layer.name, buffer)); threading::parallel_for(mloopuv.index_range(), 2048, [&](IndexRange range) { for (const int i : range) { @@ -2125,3 +2138,61 @@ void BKE_mesh_legacy_attribute_strings_to_flags(Mesh *mesh) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Face Corner Conversion + * \{ */ + +MLoop *BKE_mesh_legacy_convert_corners_to_loops( + Mesh *mesh, + blender::ResourceScope &temp_arrays_for_convert, + blender::Vector &loop_layers_to_write) +{ + using namespace blender; + const Span corner_verts = mesh->corner_verts(); + const Span corner_edges = mesh->corner_edges(); + + CustomDataLayer mloop_layer{}; + mloop_layer.type = CD_MLOOP; + MutableSpan loops = temp_arrays_for_convert.construct>(mesh->totloop); + mloop_layer.data = loops.data(); + + threading::parallel_for(loops.index_range(), 2048, [&](IndexRange range) { + for (const int i : range) { + loops[i].v = corner_verts[i]; + loops[i].e = corner_edges[i]; + } + }); + + loop_layers_to_write.append(mloop_layer); + return loops.data(); +} + +void BKE_mesh_legacy_convert_loops_to_corners(Mesh *mesh) +{ + using namespace blender; + if (CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_vert") && + CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge")) { + return; + } + const Span loops(static_cast(CustomData_get_layer(&mesh->ldata, CD_MLOOP)), + mesh->totloop); + MutableSpan corner_verts( + static_cast(CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totloop, ".corner_vert")), + mesh->totloop); + MutableSpan corner_edges( + static_cast(CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totloop, ".corner_edge")), + mesh->totloop); + threading::parallel_for(loops.index_range(), 2048, [&](IndexRange range) { + for (const int i : range) { + corner_verts[i] = loops[i].v; + corner_edges[i] = loops[i].e; + } + }); + + CustomData_free_layers(&mesh->ldata, CD_MLOOP, mesh->totloop); +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/mesh_mapping.cc b/source/blender/blenkernel/intern/mesh_mapping.cc index 6ee3d0981b1..f3e53757758 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.cc +++ b/source/blender/blenkernel/intern/mesh_mapping.cc @@ -33,7 +33,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *polys, const bool *hide_poly, const bool *select_poly, - const MLoop *mloop, + const int *corner_verts, const float (*mloopuv)[2], uint totpoly, uint totvert, @@ -92,8 +92,8 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *polys, buf->loop_of_poly_index = ushort(i); buf->poly_index = uint(a); buf->separate = false; - buf->next = vmap->vert[mloop[poly.loopstart + i].v]; - vmap->vert[mloop[poly.loopstart + i].v] = buf; + buf->next = vmap->vert[corner_verts[poly.loopstart + i]]; + vmap->vert[corner_verts[poly.loopstart + i]] = buf; if (use_winding) { copy_v2_v2(tf_uv[i], mloopuv[poly.loopstart + i]); @@ -192,7 +192,7 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap) static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, int **r_mem, const MPoly *polys, - const MLoop *mloop, + const int *corner_verts, int totvert, int totpoly, int totloop, @@ -210,7 +210,7 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, const MPoly &poly = polys[i]; for (j = 0; j < poly.totloop; j++) { - map[mloop[poly.loopstart + j].v].count++; + map[corner_verts[poly.loopstart + j]].count++; } } @@ -228,7 +228,7 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, const MPoly &poly = polys[i]; for (j = 0; j < poly.totloop; j++) { - uint v = mloop[poly.loopstart + j].v; + const int v = corner_verts[poly.loopstart + j]; map[v].indices[map[v].count] = do_loops ? poly.loopstart + j : i; map[v].count++; @@ -242,23 +242,25 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem, const MPoly *polys, - const MLoop *mloop, + const int *corner_verts, int totvert, int totpoly, int totloop) { - mesh_vert_poly_or_loop_map_create(r_map, r_mem, polys, mloop, totvert, totpoly, totloop, false); + mesh_vert_poly_or_loop_map_create( + r_map, r_mem, polys, corner_verts, totvert, totpoly, totloop, false); } void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem, const MPoly *polys, - const MLoop *mloop, + const int *corner_verts, int totvert, int totpoly, int totloop) { - mesh_vert_poly_or_loop_map_create(r_map, r_mem, polys, mloop, totvert, totpoly, totloop, true); + mesh_vert_poly_or_loop_map_create( + r_map, r_mem, polys, corner_verts, totvert, totpoly, totloop, true); } void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, @@ -266,7 +268,7 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, const int totvert, const MLoopTri *mlooptri, const int totlooptri, - const MLoop *mloop, + const int *corner_verts, const int /*totloop*/) { MeshElemMap *map = MEM_cnew_array(size_t(totvert), __func__); @@ -278,7 +280,7 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, /* count face users */ for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) { for (int j = 3; j--;) { - map[mloop[mlt->tri[j]].v].count++; + map[corner_verts[mlt->tri[j]]].count++; } } @@ -295,7 +297,7 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, /* assign looptri-edge users */ for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) { for (int j = 3; j--;) { - MeshElemMap *map_ele = &map[mloop[mlt->tri[j]].v]; + MeshElemMap *map_ele = &map[corner_verts[mlt->tri[j]]]; map_ele->indices[map_ele->count++] = i; } } @@ -387,21 +389,17 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, const int totedge, const MPoly *polys, const int totpoly, - const MLoop *mloop, + const int *corner_edges, const int totloop) { + using namespace blender; MeshElemMap *map = MEM_cnew_array(size_t(totedge), __func__); int *indices = static_cast(MEM_mallocN(sizeof(int) * size_t(totloop) * 2, __func__)); int *index_step; /* count face users */ - for (const int64_t i : blender::IndexRange(totpoly)) { - const MPoly &poly = polys[i]; - const MLoop *ml; - int j = poly.totloop; - for (ml = &mloop[poly.loopstart]; j--; ml++) { - map[ml->e].count += 2; - } + for (const int64_t i : IndexRange(totloop)) { + map[corner_edges[i]].count += 2; } /* create offsets */ @@ -417,12 +415,10 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, /* assign loop-edge users */ for (const int64_t i : blender::IndexRange(totpoly)) { const MPoly &poly = polys[i]; - const MLoop *ml; MeshElemMap *map_ele; const int max_loop = poly.loopstart + poly.totloop; - int j = poly.loopstart; - for (ml = &mloop[j]; j < max_loop; j++, ml++) { - map_ele = &map[ml->e]; + for (int j = poly.loopstart; j < max_loop; j++) { + map_ele = &map[corner_edges[j]]; map_ele->indices[map_ele->count++] = j; map_ele->indices[map_ele->count++] = j + 1; } @@ -439,7 +435,7 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, const int totedge, const MPoly *polys, const int totpoly, - const MLoop *mloop, + const int *corner_edges, const int totloop) { MeshElemMap *map = MEM_cnew_array(size_t(totedge), __func__); @@ -447,13 +443,8 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int *index_step; /* count face users */ - for (const int64_t i : blender::IndexRange(totpoly)) { - const MPoly &poly = polys[i]; - const MLoop *ml; - int j = poly.totloop; - for (ml = &mloop[poly.loopstart]; j--; ml++) { - map[ml->e].count++; - } + for (const int64_t i : blender::IndexRange(totloop)) { + map[corner_edges[i]].count++; } /* create offsets */ @@ -469,10 +460,9 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, /* assign poly-edge users */ for (const int64_t i : blender::IndexRange(totpoly)) { const MPoly &poly = polys[i]; - const MLoop *ml; - int j = poly.totloop; - for (ml = &mloop[poly.loopstart]; j--; ml++) { - MeshElemMap *map_ele = &map[ml->e]; + for (int j = 0; j < poly.totloop; j++) { + const int edge_i = corner_edges[poly.loopstart + j]; + MeshElemMap *map_ele = &map[edge_i]; map_ele->indices[map_ele->count++] = int(i); } } @@ -576,56 +566,58 @@ Array> build_vert_to_edge_map(const Span edges, const int ver } Array> build_vert_to_poly_map(const Span polys, - const Span loops, + const Span corner_verts, int verts_num) { Array> map(verts_num); for (const int64_t i : polys.index_range()) { const MPoly &poly = polys[i]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - map[loop.v].append(int(i)); + for (const int64_t vert_i : corner_verts.slice(poly.loopstart, poly.totloop)) { + map[int(vert_i)].append(int(i)); } } return map; } -Array> build_vert_to_loop_map(const Span loops, const int verts_num) +Array> build_vert_to_loop_map(const Span corner_verts, const int verts_num) { Array> map(verts_num); - for (const int64_t i : loops.index_range()) { - map[loops[i].v].append(int(i)); + for (const int64_t i : corner_verts.index_range()) { + map[corner_verts[i]].append(int(i)); } return map; } -Array> build_edge_to_loop_map(const Span loops, const int edges_num) +Array> build_edge_to_loop_map(const Span corner_edges, const int edges_num) { Array> map(edges_num); - for (const int64_t i : loops.index_range()) { - map[loops[i].e].append(int(i)); + for (const int64_t i : corner_edges.index_range()) { + map[corner_edges[i]].append(int(i)); } return map; } Array> build_edge_to_poly_map(const Span polys, - const Span loops, + const Span corner_edges, const int edges_num) { Array> map(edges_num); for (const int64_t i : polys.index_range()) { const MPoly &poly = polys[i]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - map[loop.e].append(int(i)); + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + map[edge].append(int(i)); } } return map; } -Vector> build_edge_to_loop_map_resizable(const Span loops, const int edges_num) +Vector> build_edge_to_loop_map_resizable(const Span corner_edges, + const int edges_num) + { Vector> map(edges_num); - for (const int64_t i : loops.index_range()) { - map[loops[i].e].append(int(i)); + for (const int64_t i : corner_edges.index_range()) { + map[corner_edges[i]].append(int(i)); } return map; } @@ -651,7 +643,7 @@ using MeshRemap_CheckIslandBoundary = static void poly_edge_loop_islands_calc(const int totedge, const blender::Span polys, - const blender::Span loops, + const blender::Span corner_edges, MeshElemMap *edge_poly_map, const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, @@ -699,8 +691,8 @@ static void poly_edge_loop_islands_calc(const int totedge, totedge, polys.data(), int(polys.size()), - loops.data(), - int(loops.size())); + corner_edges.data(), + int(corner_edges.size())); } poly_groups = static_cast(MEM_callocN(sizeof(int) * size_t(polys.size()), __func__)); @@ -736,7 +728,7 @@ static void poly_edge_loop_islands_calc(const int totedge, BLI_assert(poly_groups[poly] == poly_group_id); for (const int64_t loop : blender::IndexRange(polys[poly].loopstart, polys[poly].totloop)) { - const int edge = int(loops[loop].e); + const int edge = corner_edges[loop]; /* loop over poly users */ const MeshElemMap &map_ele = edge_poly_map[edge]; const int *p = map_ele.indices; @@ -842,7 +834,7 @@ static void poly_edge_loop_islands_calc(const int totedge, int *BKE_mesh_calc_smoothgroups(const int totedge, const MPoly *polys, const int totpoly, - const MLoop *mloop, + const int *corner_edges, const int totloop, const bool *sharp_edges, const bool *sharp_faces, @@ -873,7 +865,7 @@ int *BKE_mesh_calc_smoothgroups(const int totedge, poly_edge_loop_islands_calc(totedge, {polys, totpoly}, - {mloop, totloop}, + {corner_edges, totloop}, nullptr, use_bitflags, poly_is_island_boundary_smooth, @@ -1004,7 +996,8 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, const bool *uv_seams, const MPoly *polys, const int totpoly, - const MLoop *loops, + const int *corner_verts, + const int *corner_edges, const int totloop, const float (*luvs)[2], MeshIslandStore *r_island_store) @@ -1039,11 +1032,11 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE); BKE_mesh_edge_poly_map_create( - &edge_poly_map, &edge_poly_mem, totedge, polys, totpoly, loops, totloop); + &edge_poly_map, &edge_poly_mem, totedge, polys, totpoly, corner_edges, totloop); if (luvs) { BKE_mesh_edge_loop_map_create( - &edge_loop_map, &edge_loop_mem, totedge, polys, totpoly, loops, totloop); + &edge_loop_map, &edge_loop_mem, totedge, polys, totpoly, corner_edges, totloop); } /* TODO: I'm not sure edge seam flag is enough to define UV islands? @@ -1058,23 +1051,23 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, const int /*edge_user_count*/, const MeshElemMap & /*edge_poly_map_elem*/) -> bool { if (luvs) { - const MeshElemMap &edge_to_loops = edge_loop_map[loops[loop_index].e]; + const MeshElemMap &edge_to_loops = edge_loop_map[corner_edges[loop_index]]; BLI_assert(edge_to_loops.count >= 2 && (edge_to_loops.count % 2) == 0); - const uint v1 = loops[edge_to_loops.indices[0]].v; - const uint v2 = loops[edge_to_loops.indices[1]].v; + const int v1 = corner_verts[edge_to_loops.indices[0]]; + const int v2 = corner_verts[edge_to_loops.indices[1]]; const float *uvco_v1 = luvs[edge_to_loops.indices[0]]; const float *uvco_v2 = luvs[edge_to_loops.indices[1]]; for (int i = 2; i < edge_to_loops.count; i += 2) { - if (loops[edge_to_loops.indices[i]].v == v1) { + if (corner_verts[edge_to_loops.indices[i]] == v1) { if (!equals_v2v2(uvco_v1, luvs[edge_to_loops.indices[i]]) || !equals_v2v2(uvco_v2, luvs[edge_to_loops.indices[i + 1]])) { return true; } } else { - BLI_assert(loops[edge_to_loops.indices[i]].v == v2); + BLI_assert(corner_verts[edge_to_loops.indices[i]] == v2); UNUSED_VARS_NDEBUG(v2); if (!equals_v2v2(uvco_v2, luvs[edge_to_loops.indices[i]]) || !equals_v2v2(uvco_v1, luvs[edge_to_loops.indices[i + 1]])) { @@ -1091,7 +1084,7 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, poly_edge_loop_islands_calc(totedge, {polys, totpoly}, - {loops, totloop}, + {corner_edges, totloop}, edge_poly_map, false, mesh_check_island_boundary_uv, @@ -1138,13 +1131,13 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, const MPoly &poly = polys[p_idx]; poly_indices[num_pidx++] = p_idx; for (l_idx = poly.loopstart, pl_idx = 0; pl_idx < poly.totloop; l_idx++, pl_idx++) { - const MLoop *ml = &loops[l_idx]; + const int edge_i = corner_edges[l_idx]; loop_indices[num_lidx++] = l_idx; - if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, ml->e) && - (edge_border_count[ml->e] < 2)) { - edge_border_count[ml->e]++; - if (edge_border_count[ml->e] == 2) { - edge_innercut_indices[num_einnercuts++] = int(ml->e); + if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, edge_i) && + (edge_border_count[edge_i] < 2)) { + edge_border_count[edge_i]++; + if (edge_border_count[edge_i] == 2) { + edge_innercut_indices[num_einnercuts++] = edge_i; } } } @@ -1189,13 +1182,21 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3], const bool *uv_seams, const MPoly *polys, const int totpoly, - const MLoop *loops, + const int *corner_verts, + const int *corner_edges, const int totloop, MeshIslandStore *r_island_store) { UNUSED_VARS(vert_positions, totvert, edges); - return mesh_calc_islands_loop_poly_uv( - totedge, uv_seams, polys, totpoly, loops, totloop, nullptr, r_island_store); + return mesh_calc_islands_loop_poly_uv(totedge, + uv_seams, + polys, + totpoly, + corner_verts, + corner_edges, + totloop, + nullptr, + r_island_store); } bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], @@ -1205,15 +1206,23 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], const bool *uv_seams, MPoly *polys, const int totpoly, - MLoop *loops, + const int *corner_verts, + const int *corner_edges, const int totloop, const float (*luvs)[2], MeshIslandStore *r_island_store) { UNUSED_VARS(vert_positions, totvert, edges); BLI_assert(luvs != nullptr); - return mesh_calc_islands_loop_poly_uv( - totedge, uv_seams, polys, totpoly, loops, totloop, luvs, r_island_store); + return mesh_calc_islands_loop_poly_uv(totedge, + uv_seams, + polys, + totpoly, + corner_verts, + corner_edges, + totloop, + luvs, + r_island_store); } /** \} */ diff --git a/source/blender/blenkernel/intern/mesh_merge_customdata.cc b/source/blender/blenkernel/intern/mesh_merge_customdata.cc index b0eaa53d345..c91850c971b 100644 --- a/source/blender/blenkernel/intern/mesh_merge_customdata.cc +++ b/source/blender/blenkernel/intern/mesh_merge_customdata.cc @@ -117,7 +117,7 @@ void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *me) BKE_mesh_vert_loop_map_create(&vert_to_loop, &vert_map_mem, me->polys().data(), - me->loops().data(), + me->corner_verts().data(), me->totvert, me->totpoly, me->totloop); diff --git a/source/blender/blenkernel/intern/mesh_mirror.cc b/source/blender/blenkernel/intern/mesh_mirror.cc index 3d8ea9223a6..1ec200136ec 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.cc +++ b/source/blender/blenkernel/intern/mesh_mirror.cc @@ -288,7 +288,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, blender::MutableSpan result_edges = result->edges_for_write(); blender::MutableSpan result_polys = result->polys_for_write(); - blender::MutableSpan result_loops = result->loops_for_write(); + blender::MutableSpan result_corner_verts = result->corner_verts_for_write(); + blender::MutableSpan result_corner_edges = result->corner_edges_for_write(); /* adjust mirrored edge vertex indices */ for (const int i : result_edges.index_range().drop_front(src_edges_num)) { @@ -315,18 +316,20 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, CustomData_copy_data(&mesh->ldata, &result->ldata, src_poly[j], mirror_poly.last(j - 1), 1); } - blender::MutableSpan mirror_loops = result_loops.slice(mirror_poly); - const int e = mirror_loops.first().e; + blender::MutableSpan mirror_poly_edges = result_corner_edges.slice(mirror_poly); + const int e = mirror_poly_edges.first(); for (int j = 0; j < mirror_poly.size() - 1; j++) { - mirror_loops[j].e = mirror_loops[j + 1].e; + mirror_poly_edges[j] = mirror_poly_edges[j + 1]; } - mirror_loops.last().e = e; + mirror_poly_edges.last() = e; } /* adjust mirrored loop vertex and edge indices */ - for (const int i : result_loops.index_range().drop_front(src_loops_num)) { - result_loops[i].v += src_verts_num; - result_loops[i].e += src_edges_num; + for (const int i : result_corner_verts.index_range().drop_front(src_loops_num)) { + result_corner_verts[i] += src_verts_num; + } + for (const int i : result_corner_edges.index_range().drop_front(src_loops_num)) { + result_corner_edges[i] += src_edges_num; } /* handle uvs, @@ -373,7 +376,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, /* handle custom split normals */ if (ob->type == OB_MESH && (((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) && CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL) && result->totpoly > 0) { - blender::Array loop_normals(result_loops.size()); + blender::Array loop_normals(result_corner_verts.size()); CustomData *ldata = &result->ldata; short(*clnors)[2] = static_cast( CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, result->totloop)); @@ -394,7 +397,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, blender::bke::mesh::normals_calc_loop(result->vert_positions(), result_edges, result_polys, - result_loops, + result_corner_verts, + result_corner_edges, {}, result->vert_normals(), result->poly_normals(), @@ -456,6 +460,5 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, if (mesh_bisect != nullptr) { BKE_id_free(nullptr, mesh_bisect); } - return result; } diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index a302091a065..84d6423a952 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -149,14 +149,14 @@ namespace blender::bke::mesh { * polygon See Graphics Gems for * computing newell normal. */ -static float3 normal_calc_ngon(const Span vert_positions, const Span poly_loops) +static float3 normal_calc_ngon(const Span vert_positions, const Span poly_verts) { float3 normal(0); /* Newell's Method */ - const float *v_prev = vert_positions[poly_loops.last().v]; - for (const int i : poly_loops.index_range()) { - const float *v_curr = vert_positions[poly_loops[i].v]; + const float *v_prev = vert_positions[poly_verts.last()]; + for (const int i : poly_verts.index_range()) { + const float *v_curr = vert_positions[poly_verts[i]]; add_newell_cross_v3_v3v3(normal, v_prev, v_curr); v_prev = v_curr; } @@ -168,23 +168,23 @@ static float3 normal_calc_ngon(const Span vert_positions, const Span vert_positions, const Span poly_loops) +float3 poly_normal_calc(const Span vert_positions, const Span poly_verts) { - if (poly_loops.size() > 4) { - return normal_calc_ngon(vert_positions, poly_loops); + if (poly_verts.size() > 4) { + return normal_calc_ngon(vert_positions, poly_verts); } - if (poly_loops.size() == 3) { - return math::normal_tri(vert_positions[poly_loops[0].v], - vert_positions[poly_loops[1].v], - vert_positions[poly_loops[2].v]); + if (poly_verts.size() == 3) { + return math::normal_tri(vert_positions[poly_verts[0]], + vert_positions[poly_verts[1]], + vert_positions[poly_verts[2]]); } - if (poly_loops.size() == 4) { + if (poly_verts.size() == 4) { float3 normal; normal_quad_v3(normal, - vert_positions[poly_loops[0].v], - vert_positions[poly_loops[1].v], - vert_positions[poly_loops[2].v], - vert_positions[poly_loops[3].v]); + vert_positions[poly_verts[0]], + vert_positions[poly_verts[1]], + vert_positions[poly_verts[2]], + vert_positions[poly_verts[3]]); return normal; } /* horrible, two sided face! */ @@ -193,7 +193,7 @@ float3 poly_normal_calc(const Span vert_positions, const Span pol } // namespace blender::bke::mesh -void BKE_mesh_calc_poly_normal(const MLoop *poly_loops, +void BKE_mesh_calc_poly_normal(const int *poly_verts, const int poly_size, const float (*vert_positions)[3], const int verts_num, @@ -202,21 +202,22 @@ void BKE_mesh_calc_poly_normal(const MLoop *poly_loops, copy_v3_v3(r_no, blender::bke::mesh::poly_normal_calc( {reinterpret_cast(vert_positions), verts_num}, - {poly_loops, poly_size})); + {poly_verts, poly_size})); } namespace blender::bke::mesh { void normals_calc_polys(const Span positions, const Span polys, - const Span loops, + const Span corner_verts, MutableSpan poly_normals) { BLI_assert(polys.size() == poly_normals.size()); threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int i : range) { const MPoly &poly = polys[i]; - poly_normals[i] = poly_normal_calc(positions, loops.slice(poly.loopstart, poly.totloop)); + poly_normals[i] = poly_normal_calc(positions, + corner_verts.slice(poly.loopstart, poly.totloop)); } }); } @@ -232,7 +233,7 @@ void normals_calc_polys(const Span positions, void normals_calc_poly_vert(const Span positions, const Span polys, - const Span loops, + const Span corner_verts, MutableSpan poly_normals, MutableSpan vert_normals) { @@ -247,7 +248,7 @@ void normals_calc_poly_vert(const Span positions, threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int poly_i : range) { const MPoly &poly = polys[poly_i]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); + const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); float3 &pnor = poly_normals[poly_i]; @@ -258,9 +259,9 @@ void normals_calc_poly_vert(const Span positions, { zero_v3(pnor); /* Newell's Method */ - const float *v_curr = positions[poly_loops[i_end].v]; + const float *v_curr = positions[poly_verts[i_end]]; for (int i_next = 0; i_next <= i_end; i_next++) { - const float *v_next = positions[poly_loops[i_next].v]; + const float *v_next = positions[poly_verts[i_next]]; add_newell_cross_v3_v3v3(pnor, v_curr, v_next); v_curr = v_next; } @@ -273,13 +274,13 @@ void normals_calc_poly_vert(const Span positions, /* Inline version of #accumulate_vertex_normals_poly_v3. */ { float edvec_prev[3], edvec_next[3], edvec_end[3]; - const float *v_curr = positions[poly_loops[i_end].v]; - sub_v3_v3v3(edvec_prev, positions[poly_loops[i_end - 1].v], v_curr); + const float *v_curr = positions[poly_verts[i_end]]; + sub_v3_v3v3(edvec_prev, positions[poly_verts[i_end - 1]], v_curr); normalize_v3(edvec_prev); copy_v3_v3(edvec_end, edvec_prev); for (int i_next = 0, i_curr = i_end; i_next <= i_end; i_curr = i_next++) { - const float *v_next = positions[poly_loops[i_next].v]; + const float *v_next = positions[poly_verts[i_next]]; /* Skip an extra normalization by reusing the first calculated edge. */ if (i_next != i_end) { @@ -294,7 +295,7 @@ void normals_calc_poly_vert(const Span positions, const float fac = saacos(-dot_v3v3(edvec_prev, edvec_next)); const float vnor_add[3] = {pnor[0] * fac, pnor[1] * fac, pnor[2] * fac}; - float *vnor = vert_normals[poly_loops[i_curr].v]; + float *vnor = vert_normals[poly_verts[i_curr]]; add_v3_v3_atomic(vnor, vnor_add); v_curr = v_next; copy_v3_v3(edvec_prev, edvec_next); @@ -344,12 +345,12 @@ blender::Span Mesh::vert_normals() const blender::threading::isolate_task([&]() { const Span positions = this->vert_positions(); const Span polys = this->polys(); - const Span loops = this->loops(); + const Span corner_verts = this->corner_verts(); this->runtime->vert_normals.reinitialize(positions.size()); this->runtime->poly_normals.reinitialize(polys.size()); blender::bke::mesh::normals_calc_poly_vert( - positions, polys, loops, this->runtime->poly_normals, this->runtime->vert_normals); + positions, polys, corner_verts, this->runtime->poly_normals, this->runtime->vert_normals); this->runtime->vert_normals_dirty = false; this->runtime->poly_normals_dirty = false; @@ -375,10 +376,11 @@ blender::Span Mesh::poly_normals() const blender::threading::isolate_task([&]() { const Span positions = this->vert_positions(); const Span polys = this->polys(); - const Span loops = this->loops(); + const Span corner_verts = this->corner_verts(); this->runtime->poly_normals.reinitialize(polys.size()); - blender::bke::mesh::normals_calc_polys(positions, polys, loops, this->runtime->poly_normals); + blender::bke::mesh::normals_calc_polys( + positions, polys, corner_verts, this->runtime->poly_normals); this->runtime->poly_normals_dirty = false; }); @@ -715,7 +717,8 @@ struct LoopSplitTaskDataCommon { /* Read-only. */ Span positions; Span edges; - Span loops; + Span corner_verts; + Span corner_edges; Span polys; Span edge_to_loops; Span loop_to_poly; @@ -731,7 +734,8 @@ struct LoopSplitTaskDataCommon { namespace blender::bke::mesh { static void mesh_edges_sharp_tag(const Span polys, - const Span loops, + const Span corner_verts, + const Span corner_edges, const Span loop_to_poly_map, const Span poly_normals, const Span sharp_faces, @@ -749,8 +753,8 @@ static void mesh_edges_sharp_tag(const Span polys, for (const int poly_i : polys.index_range()) { const MPoly &poly = polys[poly_i]; for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const int vert_i = loops[loop_index].v; - const int edge_i = loops[loop_index].e; + const int vert_i = corner_verts[loop_index]; + const int edge_i = corner_edges[loop_index]; int2 &e2l = edge_to_loops[edge_i]; @@ -772,7 +776,7 @@ static void mesh_edges_sharp_tag(const Span polys, * same vertex, or angle between both its polys' normals is above split_angle value. */ if (!poly_is_smooth(poly_i) || (!sharp_edges.is_empty() && sharp_edges[edge_i]) || - vert_i == loops[e2l[0]].v || is_angle_sharp) { + vert_i == corner_verts[e2l[0]] || is_angle_sharp) { /* NOTE: we are sure that loop != 0 here ;). */ e2l[1] = INDEX_INVALID; @@ -802,7 +806,8 @@ static void mesh_edges_sharp_tag(const Span polys, } void edges_sharp_from_angle_set(const Span polys, - const Span loops, + const Span corner_verts, + const Span corner_edges, const Span poly_normals, const bool *sharp_faces, const float split_angle, @@ -817,10 +822,12 @@ void edges_sharp_from_angle_set(const Span polys, Array edge_to_loops(sharp_edges.size(), int2(0)); /* Simple mapping from a loop to its polygon index. */ - const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, loops.size()); + const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, + corner_verts.size()); mesh_edges_sharp_tag(polys, - loops, + corner_verts, + corner_edges, loop_to_poly, poly_normals, Span(sharp_faces, sharp_faces ? polys.size() : 0), @@ -831,7 +838,7 @@ void edges_sharp_from_angle_set(const Span polys, sharp_edges); } -static void loop_manifold_fan_around_vert_next(const Span loops, +static void loop_manifold_fan_around_vert_next(const Span corner_verts, const Span polys, const Span loop_to_poly, const int *e2lfan_curr, @@ -841,7 +848,7 @@ static void loop_manifold_fan_around_vert_next(const Span loops, int *r_mpfan_curr_index) { const int mlfan_curr_orig = *r_mlfan_curr_index; - const uint vert_fan_orig = loops[mlfan_curr_orig].v; + const uint vert_fan_orig = corner_verts[mlfan_curr_orig]; /* WARNING: This is rather complex! * We have to find our next edge around the vertex (fan mode). @@ -856,7 +863,7 @@ static void loop_manifold_fan_around_vert_next(const Span loops, BLI_assert(*r_mlfan_curr_index >= 0); BLI_assert(*r_mpfan_curr_index >= 0); - const uint vert_fan_next = loops[*r_mlfan_curr_index].v; + const uint vert_fan_next = corner_verts[*r_mlfan_curr_index]; const MPoly &mpfan_next = polys[*r_mpfan_curr_index]; if ((vert_fan_orig == vert_fan_next && vert_fan_orig == mv_pivot_index) || !ELEM(vert_fan_orig, vert_fan_next, mv_pivot_index)) { @@ -882,7 +889,8 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS const Span positions = common_data->positions; const Span edges = common_data->edges; - const Span loops = common_data->loops; + const Span corner_verts = common_data->corner_verts; + const Span corner_edges = common_data->corner_edges; const Span poly_normals = common_data->poly_normals; MutableSpan loop_normals = common_data->loop_normals; @@ -908,10 +916,11 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS if (lnors_spacearr) { float vec_curr[3], vec_prev[3]; - const uint mv_pivot_index = loops[ml_curr_index].v; /* The vertex we are "fanning" around! */ - const MEdge *me_curr = &edges[loops[ml_curr_index].e]; + const uint mv_pivot_index = + corner_verts[ml_curr_index]; /* The vertex we are "fanning" around! */ + const MEdge *me_curr = &edges[corner_edges[ml_curr_index]]; const int vert_2 = me_curr->v1 == mv_pivot_index ? me_curr->v2 : me_curr->v1; - const MEdge *me_prev = &edges[loops[ml_prev_index].e]; + const MEdge *me_prev = &edges[corner_edges[ml_prev_index]]; const int vert_3 = me_prev->v1 == mv_pivot_index ? me_prev->v2 : me_prev->v1; sub_v3_v3v3(vec_curr, positions[vert_2], positions[mv_pivot_index]); @@ -941,7 +950,8 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, const Span positions = common_data->positions; const Span edges = common_data->edges; const Span polys = common_data->polys; - const Span loops = common_data->loops; + const Span corner_verts = common_data->corner_verts; + const Span corner_edges = common_data->corner_edges; const Span edge_to_loops = common_data->edge_to_loops; const Span loop_to_poly = common_data->loop_to_poly; const Span poly_normals = common_data->poly_normals; @@ -960,10 +970,10 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, * same as the vertex normal, but I do not see any easy way to detect that (would need to count * number of sharp edges per vertex, I doubt the additional memory usage would be worth it, * especially as it should not be a common case in real-life meshes anyway). */ - const uint mv_pivot_index = loops[ml_curr_index].v; /* The vertex we are "fanning" around! */ + const int mv_pivot_index = corner_verts[ml_curr_index]; /* The vertex we are "fanning" around! */ /* `ml_curr_index` would be mlfan_prev if we needed that one. */ - const MEdge *me_org = &edges[loops[ml_curr_index].e]; + const MEdge *me_org = &edges[corner_edges[ml_curr_index]]; float vec_curr[3], vec_prev[3], vec_org[3]; float lnor[3] = {0.0f, 0.0f, 0.0f}; @@ -1006,7 +1016,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, // printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e); while (true) { - const MEdge *me_curr = &edges[loops[mlfan_curr_index].e]; + const MEdge *me_curr = &edges[corner_edges[mlfan_curr_index]]; /* Compute edge vectors. * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing * them twice (or more) here. However, time gained is not worth memory and time lost, @@ -1020,7 +1030,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, normalize_v3(vec_curr); } - // printf("\thandling edge %d / loop %d\n", loops[mlfan_curr_index].e, mlfan_curr_index); + // printf("\thandling edge %d / loop %d\n", corner_edges[mlfan_curr_index], mlfan_curr_index); { /* Code similar to accumulate_vertex_normals_poly_v3. */ @@ -1058,7 +1068,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, } } - if (IS_EDGE_SHARP(edge_to_loops[loops[mlfan_curr_index].e]) || (me_curr == me_org)) { + if (IS_EDGE_SHARP(edge_to_loops[corner_edges[mlfan_curr_index]]) || (me_curr == me_org)) { /* Current edge is sharp and we have finished with this fan of faces around this vert, * or this vert is smooth, and we have completed a full turn around it. */ // printf("FAN: Finished!\n"); @@ -1068,10 +1078,10 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, copy_v3_v3(vec_prev, vec_curr); /* Find next loop of the smooth fan. */ - loop_manifold_fan_around_vert_next(loops, + loop_manifold_fan_around_vert_next(corner_verts, polys, loop_to_poly, - edge_to_loops[loops[mlfan_curr_index].e], + edge_to_loops[corner_edges[mlfan_curr_index]], mv_pivot_index, &mlfan_curr_index, &mlfan_vert_index, @@ -1159,7 +1169,6 @@ static void loop_split_worker(TaskPool *__restrict pool, void *taskdata) if (data->flag == LoopSplitTaskData::Type::BlockEnd) { break; } - loop_split_worker_do(common_data, data, edge_vectors); } @@ -1173,7 +1182,8 @@ static void loop_split_worker(TaskPool *__restrict pool, void *taskdata) * Needed because cyclic smooth fans have no obvious 'entry point', * and yet we need to walk them once, and only once. */ -static bool loop_split_generator_check_cyclic_smooth_fan(const Span mloops, +static bool loop_split_generator_check_cyclic_smooth_fan(const Span corner_verts, + const Span corner_edges, const Span polys, const Span edge_to_loops, const Span loop_to_poly, @@ -1183,7 +1193,8 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const Span mloop const int ml_prev_index, const int mp_curr_index) { - const uint mv_pivot_index = mloops[ml_curr_index].v; /* The vertex we are "fanning" around! */ + /* The vertex we are "fanning" around! */ + const uint mv_pivot_index = corner_verts[ml_curr_index]; const int *e2lfan_curr = e2l_prev; if (IS_EDGE_SHARP(e2lfan_curr)) { @@ -1206,7 +1217,7 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const Span mloop while (true) { /* Find next loop of the smooth fan. */ - loop_manifold_fan_around_vert_next(mloops, + loop_manifold_fan_around_vert_next(corner_verts, polys, loop_to_poly, e2lfan_curr, @@ -1215,7 +1226,7 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const Span mloop &mlfan_vert_index, &mpfan_curr_index); - e2lfan_curr = edge_to_loops[mloops[mlfan_curr_index].e]; + e2lfan_curr = edge_to_loops[corner_edges[mlfan_curr_index]]; if (IS_EDGE_SHARP(e2lfan_curr)) { /* Sharp loop/edge, so not a cyclic smooth fan. */ @@ -1241,12 +1252,13 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common { MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; - const Span loops = common_data->loops; + const Span corner_verts = common_data->corner_verts; + const Span corner_edges = common_data->corner_edges; const Span polys = common_data->polys; const Span loop_to_poly = common_data->loop_to_poly; const Span edge_to_loops = common_data->edge_to_loops; - BitVector<> skip_loops(loops.size(), false); + BitVector<> skip_loops(corner_verts.size(), false); LoopSplitTaskData *data_buff = nullptr; int data_idx = 0; @@ -1277,9 +1289,9 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common #if 0 printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)", ml_curr_index, - loops[ml_curr_index].e, - loops[ml_curr_index].v, - IS_EDGE_SHARP(edge_to_loops[loops[ml_curr_index].e]), + corner_edges[ml_curr_index], + corner_verts[ml_curr_index], + IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]), skip_loops[ml_curr_index]); #endif @@ -1293,17 +1305,18 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common * However, this would complicate the code, add more memory usage, and despite its logical * complexity, #loop_manifold_fan_around_vert_next() is quite cheap in term of CPU cycles, * so really think it's not worth it. */ - if (!IS_EDGE_SHARP(edge_to_loops[loops[ml_curr_index].e]) && - (skip_loops[ml_curr_index] || - !loop_split_generator_check_cyclic_smooth_fan(loops, - polys, - edge_to_loops, - loop_to_poly, - edge_to_loops[loops[ml_prev_index].e], - skip_loops, - ml_curr_index, - ml_prev_index, - poly_index))) { + if (!IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]) && + (skip_loops[ml_curr_index] || !loop_split_generator_check_cyclic_smooth_fan( + corner_verts, + corner_edges, + polys, + edge_to_loops, + loop_to_poly, + edge_to_loops[corner_edges[ml_prev_index]], + skip_loops, + ml_curr_index, + ml_prev_index, + poly_index))) { // printf("SKIPPING!\n"); } else { @@ -1323,8 +1336,8 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common memset(data, 0, sizeof(*data)); } - if (IS_EDGE_SHARP(edge_to_loops[loops[ml_curr_index].e]) && - IS_EDGE_SHARP(edge_to_loops[loops[ml_prev_index].e])) { + if (IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]) && + IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_prev_index]])) { data->ml_curr_index = ml_curr_index; data->ml_prev_index = ml_prev_index; data->flag = LoopSplitTaskData::Type::Single; @@ -1376,7 +1389,8 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common void normals_calc_loop(const Span vert_positions, const Span edges, const Span polys, - const Span loops, + const Span corner_verts, + const Span corner_edges, const Span loop_to_poly_map, const Span vert_normals, const Span poly_normals, @@ -1410,7 +1424,7 @@ void normals_calc_loop(const Span vert_positions, copy_v3_v3(r_loop_normals[ml_index], poly_normals[poly_index]); } else { - copy_v3_v3(r_loop_normals[ml_index], vert_normals[loops[ml_index].v]); + copy_v3_v3(r_loop_normals[ml_index], vert_normals[corner_verts[ml_index]]); } } } @@ -1437,7 +1451,7 @@ void normals_calc_loop(const Span vert_positions, Span loop_to_poly; Array local_loop_to_poly_map; if (loop_to_poly_map.is_empty()) { - local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map(polys, loops.size()); + local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map(polys, corner_verts.size()); loop_to_poly = local_loop_to_poly_map; } else { @@ -1458,7 +1472,7 @@ void normals_calc_loop(const Span vert_positions, r_lnors_spacearr = &_lnors_spacearr; } if (r_lnors_spacearr) { - BKE_lnor_spacearr_init(r_lnors_spacearr, loops.size(), MLNOR_SPACEARR_LOOP_INDEX); + BKE_lnor_spacearr_init(r_lnors_spacearr, corner_verts.size(), MLNOR_SPACEARR_LOOP_INDEX); } /* Init data common to all tasks. */ @@ -1466,11 +1480,12 @@ void normals_calc_loop(const Span vert_positions, common_data.lnors_spacearr = r_lnors_spacearr; common_data.loop_normals = r_loop_normals; common_data.clnors_data = {reinterpret_cast(clnors_data), - clnors_data ? loops.size() : 0}; + clnors_data ? corner_verts.size() : 0}; common_data.positions = vert_positions; common_data.edges = edges; common_data.polys = polys; - common_data.loops = loops; + common_data.corner_verts = corner_verts; + common_data.corner_edges = corner_edges; common_data.edge_to_loops = edge_to_loops; common_data.loop_to_poly = loop_to_poly; common_data.poly_normals = poly_normals; @@ -1482,14 +1497,15 @@ void normals_calc_loop(const Span vert_positions, for (const int poly_i : range) { const MPoly &poly = polys[poly_i]; for (const int loop_i : IndexRange(poly.loopstart, poly.totloop)) { - copy_v3_v3(r_loop_normals[loop_i], vert_normals[loops[loop_i].v]); + copy_v3_v3(r_loop_normals[loop_i], vert_normals[corner_verts[loop_i]]); } } }); /* This first loop check which edges are actually smooth, and compute edge vectors. */ mesh_edges_sharp_tag(polys, - loops, + corner_verts, + corner_edges, loop_to_poly, poly_normals, Span(sharp_faces, sharp_faces ? polys.size() : 0), @@ -1499,7 +1515,7 @@ void normals_calc_loop(const Span vert_positions, edge_to_loops, {}); - if (loops.size() < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) { + if (corner_verts.size() < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) { /* Not enough loops to be worth the whole threading overhead. */ loop_split_generator(nullptr, &common_data); } @@ -1537,7 +1553,8 @@ void normals_calc_loop(const Span vert_positions, static void mesh_normals_loop_custom_set(Span positions, Span edges, Span polys, - Span loops, + Span corner_verts, + Span corner_edges, Span vert_normals, Span poly_normals, const bool *sharp_faces, @@ -1552,9 +1569,10 @@ static void mesh_normals_loop_custom_set(Span positions, * when importing custom normals, and modifier (and perhaps from some editing tools later?). So * better to keep some simplicity here, and just call #bke::mesh::normals_calc_loop() twice! */ MLoopNorSpaceArray lnors_spacearr = {nullptr}; - BitVector<> done_loops(loops.size(), false); - Array loop_normals(loops.size()); - const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, loops.size()); + BitVector<> done_loops(corner_verts.size(), false); + Array loop_normals(corner_verts.size()); + const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, + corner_verts.size()); /* In this case we always consider split nors as ON, * and do not want to use angle to define smooth fans! */ const bool use_split_normals = true; @@ -1566,7 +1584,8 @@ static void mesh_normals_loop_custom_set(Span positions, normals_calc_loop(positions, edges, polys, - loops, + corner_verts, + corner_edges, loop_to_poly, vert_normals, poly_normals, @@ -1587,7 +1606,7 @@ static void mesh_normals_loop_custom_set(Span positions, } } else { - for (const int i : loops.index_range()) { + for (const int i : corner_verts.index_range()) { if (is_zero_v3(r_custom_loop_normals[i])) { copy_v3_v3(r_custom_loop_normals[i], loop_normals[i]); } @@ -1606,7 +1625,7 @@ static void mesh_normals_loop_custom_set(Span positions, done_loops.fill(true); } else { - for (const int i : loops.index_range()) { + for (const int i : corner_verts.index_range()) { if (!lnors_spacearr.lspacearr[i]) { /* This should not happen in theory, but in some rare case (probably ugly geometry) * we can get some nullptr loopspacearr at this point. :/ @@ -1636,14 +1655,12 @@ static void mesh_normals_loop_custom_set(Span positions, } LinkNode *loop_link = lnors_spacearr.lspacearr[i]->loops; - const MLoop *prev_ml = nullptr; + int prev_corner = -1; const float *org_nor = nullptr; while (loop_link) { const int lidx = POINTER_AS_INT(loop_link->link); - const MLoop *ml = &loops[lidx]; - const int nidx = lidx; - float *nor = r_custom_loop_normals[nidx]; + float *nor = r_custom_loop_normals[lidx]; if (!org_nor) { org_nor = nor; @@ -1654,14 +1671,16 @@ static void mesh_normals_loop_custom_set(Span positions, * We know those two loops do not point to the same edge, * since we do not allow reversed winding in a same smooth fan. */ const MPoly &poly = polys[loop_to_poly[lidx]]; - const MLoop *mlp = - &loops[(lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1]; - sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true; + const int mlp = (lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1; + const int edge = corner_edges[lidx]; + const int edge_p = corner_edges[mlp]; + const int prev_edge = corner_edges[prev_corner]; + sharp_edges[prev_edge == edge_p ? prev_edge : edge] = true; org_nor = nor; } - prev_ml = ml; + prev_corner = lidx; loop_link = loop_link->next; done_loops[lidx].set(); } @@ -1673,15 +1692,15 @@ static void mesh_normals_loop_custom_set(Span positions, loop_link = lnors_spacearr.lspacearr[i]->loops; if (loop_link && org_nor) { const int lidx = POINTER_AS_INT(loop_link->link); - const MLoop *ml = &loops[lidx]; - const int nidx = lidx; - float *nor = r_custom_loop_normals[nidx]; + float *nor = r_custom_loop_normals[lidx]; if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) { const MPoly &poly = polys[loop_to_poly[lidx]]; - const MLoop *mlp = - &loops[(lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1]; - sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true; + const int mlp = (lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1; + const int edge = corner_edges[lidx]; + const int edge_p = corner_edges[mlp]; + const int prev_edge = corner_edges[prev_corner]; + sharp_edges[prev_edge == edge_p ? prev_edge : edge] = true; } } } @@ -1691,7 +1710,8 @@ static void mesh_normals_loop_custom_set(Span positions, normals_calc_loop(positions, edges, polys, - loops, + corner_verts, + corner_edges, loop_to_poly, vert_normals, poly_normals, @@ -1706,7 +1726,7 @@ static void mesh_normals_loop_custom_set(Span positions, /* And we just have to convert plain object-space custom normals to our * lnor space-encoded ones. */ - for (const int i : loops.index_range()) { + for (const int i : corner_verts.index_range()) { if (!lnors_spacearr.lspacearr[i]) { done_loops[i].reset(); if (G.debug & G_DEBUG) { @@ -1723,7 +1743,7 @@ static void mesh_normals_loop_custom_set(Span positions, LinkNode *loop_link = lnors_spacearr.lspacearr[i]->loops; if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) { BLI_assert(POINTER_AS_INT(loop_link) == i); - const int nidx = use_vertices ? int(loops[i].v) : i; + const int nidx = use_vertices ? corner_verts[i] : i; float *nor = r_custom_loop_normals[nidx]; BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]); @@ -1737,7 +1757,7 @@ static void mesh_normals_loop_custom_set(Span positions, zero_v3(avg_nor); while (loop_link) { const int lidx = POINTER_AS_INT(loop_link->link); - const int nidx = use_vertices ? int(loops[lidx].v) : lidx; + const int nidx = use_vertices ? corner_verts[lidx] : lidx; float *nor = r_custom_loop_normals[nidx]; avg_nor_count++; @@ -1765,7 +1785,8 @@ static void mesh_normals_loop_custom_set(Span positions, void normals_loop_custom_set(const Span vert_positions, const Span edges, const Span polys, - const Span loops, + const Span corner_verts, + const Span corner_edges, const Span vert_normals, const Span poly_normals, const bool *sharp_faces, @@ -1776,7 +1797,8 @@ void normals_loop_custom_set(const Span vert_positions, mesh_normals_loop_custom_set(vert_positions, edges, polys, - loops, + corner_verts, + corner_edges, vert_normals, poly_normals, sharp_faces, @@ -1789,7 +1811,8 @@ void normals_loop_custom_set(const Span vert_positions, void normals_loop_custom_set_from_verts(const Span vert_positions, const Span edges, const Span polys, - const Span loops, + const Span corner_verts, + const Span corner_edges, const Span vert_normals, const Span poly_normals, const bool *sharp_faces, @@ -1800,7 +1823,8 @@ void normals_loop_custom_set_from_verts(const Span vert_positions, mesh_normals_loop_custom_set(vert_positions, edges, polys, - loops, + corner_verts, + corner_edges, vert_normals, poly_normals, sharp_faces, @@ -1833,7 +1857,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const mesh_normals_loop_custom_set(mesh->vert_positions(), mesh->edges(), mesh->polys(), - mesh->loops(), + mesh->corner_verts(), + mesh->corner_edges(), mesh->vert_normals(), mesh->poly_normals(), sharp_faces, @@ -1859,7 +1884,7 @@ void BKE_mesh_set_custom_normals_from_verts(Mesh *mesh, float (*r_custom_vert_no } void BKE_mesh_normals_loop_to_vertex(const int numVerts, - const MLoop *mloops, + const int *corner_verts, const int numLoops, const float (*clnors)[3], float (*r_vert_clnors)[3]) @@ -1870,12 +1895,10 @@ void BKE_mesh_normals_loop_to_vertex(const int numVerts, copy_vn_fl((float *)r_vert_clnors, 3 * numVerts, 0.0f); int i; - const MLoop *ml; - for (i = 0, ml = mloops; i < numLoops; i++, ml++) { - const uint v = ml->v; - - add_v3_v3(r_vert_clnors[v], clnors[i]); - vert_loops_count[v]++; + for (i = 0; i < numLoops; i++) { + const int vert = corner_verts[i]; + add_v3_v3(r_vert_clnors[vert], clnors[i]); + vert_loops_count[vert]++; } for (i = 0; i < numVerts; i++) { diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index 4ccf6a94fc6..d2feef7d002 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -262,9 +262,8 @@ void BKE_mesh_remap_find_best_match_from_mesh(const float (*vert_positions_dst)[ float best_match = FLT_MAX, match; const int numverts_src = me_src->totvert; - float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr); - - mesh_calc_eigen_matrix(nullptr, (const float(*)[3])vcos_src, numverts_src, mat_src); + const float(*vcos_src)[3] = BKE_mesh_vert_positions(me_src); + mesh_calc_eigen_matrix(nullptr, vcos_src, numverts_src, mat_src); mesh_calc_eigen_matrix(vert_positions_dst, nullptr, numverts_dst, mat_dst); BLI_space_transform_global_from_matrices(r_space_transform, mat_dst, mat_src); @@ -289,8 +288,6 @@ void BKE_mesh_remap_find_best_match_from_mesh(const float (*vert_positions_dst)[ } BLI_space_transform_global_from_matrices(r_space_transform, best_mat_dst, mat_src); - - MEM_freeN(vcos_src); } /** \} */ @@ -372,7 +369,7 @@ void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index) } static int mesh_remap_interp_poly_data_get(const MPoly &poly, - const blender::Span loops, + const blender::Span corner_verts, const float (*vcos_src)[3], const float point[3], size_t *buff_size, @@ -383,7 +380,6 @@ static int mesh_remap_interp_poly_data_get(const MPoly &poly, const bool do_weights, int *r_closest_index) { - const MLoop *ml; float(*vco)[3]; float ref_dist_sq = FLT_MAX; int *index; @@ -399,10 +395,10 @@ static int mesh_remap_interp_poly_data_get(const MPoly &poly, } } - for (i = 0, ml = &loops[poly.loopstart], vco = *vcos, index = *indices; i < sources_num; - i++, ml++, vco++, index++) { - *index = use_loops ? int(poly.loopstart) + i : int(ml->v); - copy_v3_v3(*vco, vcos_src[ml->v]); + for (i = 0, vco = *vcos, index = *indices; i < sources_num; i++, vco++, index++) { + const int vert = corner_verts[poly.loopstart + i]; + *index = use_loops ? int(poly.loopstart) + i : vert; + copy_v3_v3(*vco, vcos_src[vert]); if (r_closest_index) { /* Find closest vert/loop in this case. */ const float dist_sq = len_squared_v3v3(point, *vco); @@ -516,7 +512,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, } else if (ELEM(mode, MREMAP_MODE_VERT_EDGE_NEAREST, MREMAP_MODE_VERT_EDGEINTERP_NEAREST)) { const blender::Span edges_src = me_src->edges(); - float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr); + const float(*vcos_src)[3] = BKE_mesh_vert_positions(me_src); BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2); nearest.index = -1; @@ -561,16 +557,14 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, BKE_mesh_remap_item_define_invalid(r_map, i); } } - - MEM_freeN(vcos_src); } else if (ELEM(mode, MREMAP_MODE_VERT_POLY_NEAREST, MREMAP_MODE_VERT_POLYINTERP_NEAREST, MREMAP_MODE_VERT_POLYINTERP_VNORPROJ)) { const blender::Span polys_src = me_src->polys(); - const blender::Span loops_src = me_src->loops(); - float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr); + const blender::Span corner_verts_src = me_src->corner_verts(); + const float(*vcos_src)[3] = BKE_mesh_vert_positions(me_src); const blender::Span vert_normals_dst = me_dst->vert_normals(); size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE; @@ -597,8 +591,8 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist)) { const MLoopTri *lt = &treedata.looptri[rayhit.index]; const int sources_num = mesh_remap_interp_poly_data_get(polys_src[lt->poly], - loops_src, - (const float(*)[3])vcos_src, + corner_verts_src, + vcos_src, rayhit.co, &tmp_buff_size, &vcos, @@ -634,8 +628,8 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, if (mode == MREMAP_MODE_VERT_POLY_NEAREST) { int index; mesh_remap_interp_poly_data_get(polys_src[lt->poly], - loops_src, - (const float(*)[3])vcos_src, + corner_verts_src, + vcos_src, nearest.co, &tmp_buff_size, &vcos, @@ -649,8 +643,8 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, } else if (mode == MREMAP_MODE_VERT_POLYINTERP_NEAREST) { const int sources_num = mesh_remap_interp_poly_data_get(polys_src[lt->poly], - loops_src, - (const float(*)[3])vcos_src, + corner_verts_src, + vcos_src, nearest.co, &tmp_buff_size, &vcos, @@ -670,7 +664,6 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, } } - MEM_freeN(vcos_src); MEM_freeN(vcos); MEM_freeN(indices); MEM_freeN(weights); @@ -721,7 +714,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, if (mode == MREMAP_MODE_EDGE_VERT_NEAREST) { const int num_verts_src = me_src->totvert; const blender::Span edges_src = me_src->edges(); - float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr); + const float(*vcos_src)[3] = BKE_mesh_vert_positions(me_src); MeshElemMap *vert_to_edge_src_map; int *vert_to_edge_src_map_mem; @@ -840,7 +833,6 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, } } - MEM_freeN(vcos_src); MEM_freeN(v_dst_to_src_map); MEM_freeN(vert_to_edge_src_map); MEM_freeN(vert_to_edge_src_map_mem); @@ -873,8 +865,8 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, else if (mode == MREMAP_MODE_EDGE_POLY_NEAREST) { const blender::Span edges_src = me_src->edges(); const blender::Span polys_src = me_src->polys(); - const blender::Span loops_src = me_src->loops(); - float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr); + const blender::Span corner_edges_src = me_src->corner_edges(); + const float(*vcos_src)[3] = BKE_mesh_vert_positions(me_src); BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2); @@ -893,15 +885,15 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { const MLoopTri *lt = &treedata.looptri[nearest.index]; const MPoly &poly_src = polys_src[lt->poly]; - const MLoop *ml_src = &loops_src[poly_src.loopstart]; + const int *corner_edge_src = &corner_edges_src[poly_src.loopstart]; int nloops = poly_src.totloop; float best_dist_sq = FLT_MAX; int best_eidx_src = -1; - for (; nloops--; ml_src++) { - const MEdge *edge_src = &edges_src[ml_src->e]; - float *co1_src = vcos_src[edge_src->v1]; - float *co2_src = vcos_src[edge_src->v2]; + for (; nloops--; corner_edge_src++) { + const MEdge *edge_src = &edges_src[*corner_edge_src]; + const float *co1_src = vcos_src[edge_src->v1]; + const float *co2_src = vcos_src[edge_src->v2]; float co_src[3]; float dist_sq; @@ -909,7 +901,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, dist_sq = len_squared_v3v3(tmp_co, co_src); if (dist_sq < best_dist_sq) { best_dist_sq = dist_sq; - best_eidx_src = int(ml_src->e); + best_eidx_src = *corner_edge_src; } } if (best_eidx_src >= 0) { @@ -921,8 +913,6 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, BKE_mesh_remap_item_define_invalid(r_map, i); } } - - MEM_freeN(vcos_src); } else if (mode == MREMAP_MODE_EDGE_EDGEINTERP_VNORPROJ) { const int num_rays_min = 5, num_rays_max = 100; @@ -1045,7 +1035,7 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, BLI_AStarGraph *as_graph, const blender::Span positions, const blender::Span polys, - const blender::Span loops, + const blender::Span corner_verts, const int edge_idx, BLI_bitmap *done_edges, MeshElemMap *edge_to_poly_map, @@ -1076,8 +1066,8 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, if (poly_status[pidx_isld] == POLY_UNSET) { copy_v3_v3(poly_centers[pidx_isld], - blender::bke::mesh::poly_center_calc(positions, - loops.slice(poly.loopstart, poly.totloop))); + blender::bke::mesh::poly_center_calc( + positions, corner_verts.slice(poly.loopstart, poly.totloop))); BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]); poly_status[pidx_isld] = POLY_CENTER_INIT; } @@ -1106,7 +1096,8 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands, MeshElemMap *edge_to_poly_map, const int numedges, const blender::Span polys, - const blender::Span loops, + const blender::Span corner_verts, + const blender::Span corner_edges, const int numpolys, BLI_AStarGraph *r_as_graph) { @@ -1145,7 +1136,7 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands, r_as_graph, positions, polys, - loops, + corner_verts, island_einnercut_map->indices[i], done_edges, edge_to_poly_map, @@ -1166,9 +1157,9 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands, } for (pl_idx = 0, l_idx = poly.loopstart; pl_idx < poly.totloop; pl_idx++, l_idx++) { - const MLoop *ml = &loops[l_idx]; + const int edge = corner_edges[l_idx]; - if (BLI_BITMAP_TEST(done_edges, ml->e)) { + if (BLI_BITMAP_TEST(done_edges, edge)) { continue; } @@ -1177,8 +1168,8 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands, r_as_graph, positions, polys, - loops, - int(ml->e), + corner_verts, + edge, done_edges, edge_to_poly_map, false, @@ -1238,7 +1229,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, const int numverts_dst, const MEdge *edges_dst, const int numedges_dst, - const MLoop *loops_dst, + const int *corner_verts_dst, + const int *corner_edges_dst, const int numloops_dst, const MPoly *polys_dst, const int numpolys_dst, @@ -1308,10 +1300,11 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, const blender::Span positions_src = me_src->vert_positions(); const int num_verts_src = me_src->totvert; - float(*vcos_src)[3] = nullptr; + const float(*vcos_src)[3] = nullptr; const blender::Span edges_src = me_src->edges(); const blender::Span polys_src = me_src->polys(); - const blender::Span loops_src = me_src->loops(); + const blender::Span corner_verts_src = me_src->corner_verts(); + const blender::Span corner_edges_src = me_src->corner_edges(); blender::Span looptris_src; size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE; @@ -1319,8 +1312,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, int *indices_interp = nullptr; float *weights_interp = nullptr; - const MLoop *ml_src; - const MLoop *ml_dst; const MPoly *mp_dst; int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src; @@ -1328,7 +1319,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, size_t islands_res_buff_size = MREMAP_DEFAULT_BUFSIZE; if (!use_from_vert) { - vcos_src = BKE_mesh_vert_coords_alloc(me_src, nullptr); + vcos_src = BKE_mesh_vert_positions(me_src); vcos_interp = static_cast( MEM_mallocN(sizeof(*vcos_interp) * buff_size_interp, __func__)); @@ -1371,7 +1362,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, {reinterpret_cast(vert_positions_dst), numverts_dst}, {edges_dst, numedges_dst}, {polys_dst, numpolys_dst}, - {loops_dst, numloops_dst}, + {corner_verts_dst, numloops_dst}, + {corner_edges_dst, numloops_dst}, {}, mesh_dst->vert_normals(), mesh_dst->poly_normals(), @@ -1401,18 +1393,18 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src, &vert_to_loop_map_src_buff, polys_src.data(), - loops_src.data(), + corner_verts_src.data(), num_verts_src, int(polys_src.size()), - int(loops_src.size())); + int(corner_verts_src.size())); if (mode & MREMAP_USE_POLY) { BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src, &vert_to_poly_map_src_buff, polys_src.data(), - loops_src.data(), + corner_verts_src.data(), num_verts_src, int(polys_src.size()), - int(loops_src.size())); + int(corner_verts_src.size())); } } @@ -1422,21 +1414,20 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, int(edges_src.size()), polys_src.data(), int(polys_src.size()), - loops_src.data(), - int(loops_src.size())); + corner_edges_src.data(), + int(corner_edges_src.size())); if (use_from_vert) { loop_to_poly_map_src = static_cast( - MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(loops_src.size()), __func__)); + MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(corner_verts_src.size()), __func__)); poly_cents_src.reinitialize(polys_src.size()); for (pidx_src = 0; pidx_src < polys_src.size(); pidx_src++) { const MPoly &poly = polys_src[pidx_src]; - ml_src = &loops_src[poly.loopstart]; for (plidx_src = 0, lidx_src = poly.loopstart; plidx_src < poly.totloop; plidx_src++, lidx_src++) { loop_to_poly_map_src[lidx_src] = pidx_src; } poly_cents_src[pidx_src] = blender::bke::mesh::poly_center_calc( - positions_src, loops_src.slice(poly.loopstart, poly.totloop)); + positions_src, corner_verts_src.slice(poly.loopstart, poly.totloop)); } } @@ -1458,8 +1449,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, uv_seams, polys_src.data(), int(polys_src.size()), - loops_src.data(), - int(loops_src.size()), + corner_verts_src.data(), + corner_edges_src.data(), + int(corner_verts_src.size()), &island_store); num_trees = use_islands ? island_store.islands_num : 1; @@ -1496,7 +1488,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, edge_to_poly_map_src, int(edges_src.size()), polys_src, - loops_src, + corner_verts_src, + corner_edges_src, int(polys_src.size()), &as_graphdata[tindex]); } @@ -1514,7 +1507,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, for (int i = 0; i < isld->count; i++) { const MPoly &poly = polys_src[isld->indices[i]]; for (lidx_src = poly.loopstart; lidx_src < poly.loopstart + poly.totloop; lidx_src++) { - const uint vidx_src = loops_src[lidx_src].v; + const int vidx_src = corner_verts_src[lidx_src]; if (!verts_active[vidx_src]) { verts_active[vidx_src].set(); num_verts_active++; @@ -1553,7 +1546,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } bvhtree_from_mesh_looptri_ex(&treedata[tindex], reinterpret_cast(positions_src.data()), - loops_src.data(), + corner_verts_src.data(), looptris_src.data(), int(looptris_src.size()), looptri_active, @@ -1603,12 +1596,12 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, for (tindex = 0; tindex < num_trees; tindex++) { BVHTreeFromMesh *tdata = &treedata[tindex]; - ml_dst = &loops_dst[mp_dst->loopstart]; - for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) { + for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) { + const int vert_dst = corner_verts_dst[mp_dst->loopstart + plidx_dst]; if (use_from_vert) { MeshElemMap *vert_to_refelem_map_src = nullptr; - copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); + copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); nearest.index = -1; /* Convert the vertex to tree coordinates, if needed. */ @@ -1666,14 +1659,11 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, float *pcent_src; float sqdist; - const MPoly &poly = polys_src[pidx_src]; - ml_src = &loops_src[poly.loopstart]; - if (!pcent_dst_valid) { pcent_dst = blender::bke::mesh::poly_center_calc( {reinterpret_cast(vert_positions_dst), numverts_dst}, - {&loops_dst[mp_dst->loopstart], mp_dst->totloop}); + {&corner_verts_dst[mp_dst->loopstart], mp_dst->totloop}); pcent_dst_valid = true; } pcent_src = poly_cents_src[pidx_src]; @@ -1695,9 +1685,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, /* Our best_index_src is a poly one for now! * Have to find its loop matching our closest vertex. */ const MPoly &poly = polys_src[best_index_src]; - ml_src = &loops_src[poly.loopstart]; - for (plidx_src = 0; plidx_src < poly.totloop; plidx_src++, ml_src++) { - if (int(ml_src->v) == nearest.index) { + for (plidx_src = 0; plidx_src < poly.totloop; plidx_src++) { + const int vert_src = corner_verts_src[poly.loopstart + plidx_src]; + if (vert_src == nearest.index) { best_index_src = plidx_src + poly.loopstart; break; } @@ -1719,7 +1709,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1; float w = 1.0f; - copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); + copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); copy_v3_v3(tmp_no, loop_normals_dst[plidx_dst + mp_dst->loopstart]); /* We do our transform here, since we may do several raycast/nearest queries. */ @@ -1747,7 +1737,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, * is null, it means none of its loop mapped to this source island, * hence we can skip it later. */ - copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); + copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); nearest.index = -1; /* Convert the vertex to tree coordinates, if needed. */ @@ -1773,7 +1763,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } } else { /* Nearest poly either to use all its loops/verts or just closest one. */ - copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); + copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); nearest.index = -1; /* Convert the vertex to tree coordinates, if needed. */ @@ -1902,8 +1892,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, int j; float best_dist_sq = FLT_MAX; - ml_dst = &loops_dst[lidx_dst]; - copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); + copy_v3_v3(tmp_co, vert_positions_dst[corner_verts_dst[lidx_dst]]); /* We do our transform here, * since we may do several raycast/nearest queries. */ @@ -1914,9 +1903,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, pidx_src = (use_islands ? best_island->indices[last_valid_pidx_isld_src] : last_valid_pidx_isld_src); const MPoly &poly = polys_src[pidx_src]; - ml_src = &loops_src[poly.loopstart]; - for (j = 0; j < poly.totloop; j++, ml_src++) { - const float dist_sq = len_squared_v3v3(positions_src[ml_src->v], tmp_co); + for (j = 0; j < poly.totloop; j++) { + const int vert_src = corner_verts_src[poly.loopstart + j]; + const float dist_sq = len_squared_v3v3(positions_src[vert_src], tmp_co); if (dist_sq < best_dist_sq) { best_dist_sq = dist_sq; lidx_src = poly.loopstart + j; @@ -1995,8 +1984,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, float best_dist_sq = FLT_MAX; int j; - ml_dst = &loops_dst[lidx_dst]; - copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); + const int vert_dst = corner_verts_dst[lidx_dst]; + copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); /* We do our transform here, * since we may do several raycast/nearest queries. */ @@ -2025,9 +2014,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, closest_on_tri_to_point_v3(h, tmp_co, - vcos_src[loops_src[lt->tri[0]].v], - vcos_src[loops_src[lt->tri[1]].v], - vcos_src[loops_src[lt->tri[2]].v]); + vcos_src[corner_verts_src[lt->tri[0]]], + vcos_src[corner_verts_src[lt->tri[1]]], + vcos_src[corner_verts_src[lt->tri[2]]]); dist_sq = len_squared_v3v3(tmp_co, h); if (dist_sq < best_dist_sq) { copy_v3_v3(hit_co, h); @@ -2040,8 +2029,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, if (mode == MREMAP_MODE_LOOP_POLY_NEAREST) { mesh_remap_interp_poly_data_get(poly, - loops_src, - (const float(*)[3])vcos_src, + corner_verts_src, + vcos_src, hit_co, &buff_size_interp, &vcos_interp, @@ -2060,18 +2049,17 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, &full_weight); } else { - const int sources_num = mesh_remap_interp_poly_data_get( - poly, - loops_src, - (const float(*)[3])vcos_src, - hit_co, - &buff_size_interp, - &vcos_interp, - true, - &indices_interp, - &weights_interp, - true, - nullptr); + const int sources_num = mesh_remap_interp_poly_data_get(poly, + corner_verts_src, + vcos_src, + hit_co, + &buff_size_interp, + &vcos_interp, + true, + &indices_interp, + &weights_interp, + true, + nullptr); mesh_remap_item_define(r_map, lidx_dst, @@ -2113,9 +2101,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, BLI_astar_solution_free(&as_solution); } - if (vcos_src) { - MEM_freeN(vcos_src); - } if (vert_to_loop_map_src) { MEM_freeN(vert_to_loop_map_src); } @@ -2162,7 +2147,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, const Mesh *mesh_dst, const float (*vert_positions_dst)[3], const int numverts_dst, - const MLoop *loops_dst, + const int *corner_verts_dst, const MPoly *polys_dst, const int numpolys_dst, Mesh *me_src, @@ -2203,7 +2188,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, const MPoly &poly = polys_dst[i]; tmp_co = blender::bke::mesh::poly_center_calc( {reinterpret_cast(vert_positions_dst), numverts_dst}, - {&loops_dst[poly.loopstart], poly.totloop}); + {&corner_verts_dst[poly.loopstart], poly.totloop}); /* Convert the vertex to tree coordinates, if needed. */ if (space_transform) { @@ -2228,7 +2213,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, tmp_co = blender::bke::mesh::poly_center_calc( {reinterpret_cast(vert_positions_dst), numverts_dst}, - {&loops_dst[poly.loopstart], poly.totloop}); + {&corner_verts_dst[poly.loopstart], poly.totloop}); copy_v3_v3(tmp_no, poly_normals_dst[i]); /* Convert the vertex to tree coordinates, if needed. */ @@ -2293,7 +2278,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, pcent_dst = blender::bke::mesh::poly_center_calc( {reinterpret_cast(vert_positions_dst), numverts_dst}, - {&loops_dst[poly.loopstart], poly.totloop}); + {&corner_verts_dst[poly.loopstart], poly.totloop}); copy_v3_v3(tmp_no, poly_normals_dst[i]); @@ -2323,8 +2308,8 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, INIT_MINMAX2(poly_dst_2d_min, poly_dst_2d_max); for (j = 0; j < poly.totloop; j++) { - const MLoop *ml = &loops_dst[j + poly.loopstart]; - copy_v3_v3(tmp_co, vert_positions_dst[ml->v]); + const int vert = corner_verts_dst[poly.loopstart + j]; + copy_v3_v3(tmp_co, vert_positions_dst[vert]); if (space_transform) { BLI_space_transform_apply(space_transform, tmp_co); } diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index e7af9b326ed..1f661f69f12 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -64,13 +64,13 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh, void *update_cb_data) { const Span input_positions = input_mesh->vert_positions(); - const Span input_loops = input_mesh->loops(); + const Span input_corner_verts = input_mesh->corner_verts(); const Span looptris = input_mesh->looptris(); /* Gather the required data for export to the internal quadriflow mesh format. */ Array verttri(looptris.size()); BKE_mesh_runtime_verttri_from_looptri( - verttri.data(), input_loops.data(), looptris.data(), looptris.size()); + verttri.data(), input_corner_verts.data(), looptris.data(), looptris.size()); const int totfaces = looptris.size(); const int totverts = input_mesh->totvert; @@ -120,7 +120,7 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh, Mesh *mesh = BKE_mesh_new_nomain(qrd.out_totverts, 0, qrd.out_totfaces * 4, qrd.out_totfaces); BKE_mesh_copy_parameters(mesh, input_mesh); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); mesh->vert_positions_for_write().copy_from( Span(reinterpret_cast(qrd.out_verts), qrd.out_totverts)); @@ -130,10 +130,10 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh, const int loopstart = i * 4; poly.loopstart = loopstart; poly.totloop = 4; - loops[loopstart].v = qrd.out_faces[loopstart]; - loops[loopstart + 1].v = qrd.out_faces[loopstart + 1]; - loops[loopstart + 2].v = qrd.out_faces[loopstart + 2]; - loops[loopstart + 3].v = qrd.out_faces[loopstart + 3]; + corner_verts[loopstart] = qrd.out_faces[loopstart]; + corner_verts[loopstart + 1] = qrd.out_faces[loopstart + 1]; + corner_verts[loopstart + 2] = qrd.out_faces[loopstart + 2]; + corner_verts[loopstart + 3] = qrd.out_faces[loopstart + 3]; } BKE_mesh_calc_edges(mesh, false, false); @@ -184,7 +184,7 @@ static openvdb::FloatGrid::Ptr remesh_voxel_level_set_create(const Mesh *mesh, const float voxel_size) { const Span positions = mesh->vert_positions(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); const Span looptris = mesh->looptris(); std::vector points(mesh->totvert); @@ -197,8 +197,9 @@ static openvdb::FloatGrid::Ptr remesh_voxel_level_set_create(const Mesh *mesh, for (const int i : IndexRange(looptris.size())) { const MLoopTri &loop_tri = looptris[i]; - triangles[i] = openvdb::Vec3I( - loops[loop_tri.tri[0]].v, loops[loop_tri.tri[1]].v, loops[loop_tri.tri[2]].v); + triangles[i] = openvdb::Vec3I(corner_verts[loop_tri.tri[0]], + corner_verts[loop_tri.tri[1]], + corner_verts[loop_tri.tri[2]]); } openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform( @@ -224,7 +225,7 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set vertices.size(), 0, quads.size() * 4 + tris.size() * 3, quads.size() + tris.size()); MutableSpan vert_positions = mesh->vert_positions_for_write(); MutableSpan mesh_polys = mesh->polys_for_write(); - MutableSpan mesh_loops = mesh->loops_for_write(); + MutableSpan mesh_corner_verts = mesh->corner_verts_for_write(); for (const int i : vert_positions.index_range()) { vert_positions[i] = float3(vertices[i].x(), vertices[i].y(), vertices[i].z()); @@ -235,10 +236,10 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set const int loopstart = i * 4; poly.loopstart = loopstart; poly.totloop = 4; - mesh_loops[loopstart].v = quads[i][0]; - mesh_loops[loopstart + 1].v = quads[i][3]; - mesh_loops[loopstart + 2].v = quads[i][2]; - mesh_loops[loopstart + 3].v = quads[i][1]; + mesh_corner_verts[loopstart] = quads[i][0]; + mesh_corner_verts[loopstart + 1] = quads[i][3]; + mesh_corner_verts[loopstart + 2] = quads[i][2]; + mesh_corner_verts[loopstart + 3] = quads[i][1]; } const int triangle_loop_start = quads.size() * 4; @@ -247,9 +248,9 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set const int loopstart = triangle_loop_start + i * 3; poly.loopstart = loopstart; poly.totloop = 3; - mesh_loops[loopstart].v = tris[i][2]; - mesh_loops[loopstart + 1].v = tris[i][1]; - mesh_loops[loopstart + 2].v = tris[i][0]; + mesh_corner_verts[loopstart] = tris[i][2]; + mesh_corner_verts[loopstart + 1] = tris[i][1]; + mesh_corner_verts[loopstart + 2] = tris[i][0]; } BKE_mesh_calc_edges(mesh, false, false); @@ -316,7 +317,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) MutableAttributeAccessor dst_attributes = target->attributes_for_write(); const Span target_positions = target->vert_positions(); const Span target_polys = target->polys(); - const Span target_loops = target->loops(); + const Span target_corner_verts = target->corner_verts(); const VArray src_face_sets = src_attributes.lookup(".sculpt_face_set", ATTR_DOMAIN_FACE); @@ -343,7 +344,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source) nearest.dist_sq = FLT_MAX; const MPoly &poly = target_polys[i]; const float3 from_co = mesh::poly_center_calc( - target_positions, target_loops.slice(poly.loopstart, poly.totloop)); + target_positions, target_corner_verts.slice(poly.loopstart, poly.totloop)); BLI_bvhtree_find_nearest( bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); if (nearest.index != -1) { @@ -416,7 +417,7 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) BKE_mesh_vert_loop_map_create(&source_lmap, &source_lmap_mem, source->polys().data(), - source->loops().data(), + source->corner_verts().data(), source->totvert, source->totpoly, source->totloop); @@ -424,7 +425,7 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) BKE_mesh_vert_loop_map_create(&target_lmap, &target_lmap_mem, target->polys().data(), - target->loops().data(), + target->corner_verts().data(), target->totvert, target->totpoly, target->totloop); diff --git a/source/blender/blenkernel/intern/mesh_runtime.cc b/source/blender/blenkernel/intern/mesh_runtime.cc index 83f3de9c8fe..662b6d05b71 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.cc +++ b/source/blender/blenkernel/intern/mesh_runtime.cc @@ -117,9 +117,9 @@ const blender::bke::LooseEdgeCache &Mesh::loose_edges() const loose_edges.resize(this->totedge, true); int count = this->totedge; - for (const MLoop &loop : this->loops()) { - if (loose_edges[loop.e]) { - loose_edges[loop.e].reset(); + for (const int edge : this->corner_edges()) { + if (loose_edges[edge]) { + loose_edges[edge].reset(); count--; } } @@ -146,16 +146,16 @@ blender::Span Mesh::looptris() const this->runtime->looptris_cache.ensure([&](blender::Array &r_data) { const Span positions = this->vert_positions(); const Span polys = this->polys(); - const Span loops = this->loops(); + const Span corner_verts = this->corner_verts(); - r_data.reinitialize(poly_to_tri_count(polys.size(), loops.size())); + r_data.reinitialize(poly_to_tri_count(polys.size(), corner_verts.size())); if (BKE_mesh_poly_normals_are_dirty(this)) { - blender::bke::mesh::looptris_calc(positions, polys, loops, r_data); + blender::bke::mesh::looptris_calc(positions, polys, corner_verts, r_data); } else { blender::bke::mesh::looptris_calc_with_normals( - positions, polys, loops, this->poly_normals(), r_data); + positions, polys, corner_verts, this->poly_normals(), r_data); } }); @@ -174,14 +174,14 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh) } void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri, - const MLoop *mloop, + const int *corner_verts, const MLoopTri *looptri, int looptri_num) { for (int i = 0; i < looptri_num; i++) { - r_verttri[i].tri[0] = mloop[looptri[i].tri[0]].v; - r_verttri[i].tri[1] = mloop[looptri[i].tri[1]].v; - r_verttri[i].tri[2] = mloop[looptri[i].tri[2]].v; + r_verttri[i].tri[0] = corner_verts[looptri[i].tri[0]]; + r_verttri[i].tri[1] = corner_verts[looptri[i].tri[1]]; + r_verttri[i].tri[2] = corner_verts[looptri[i].tri[2]]; } } @@ -318,7 +318,8 @@ bool BKE_mesh_runtime_is_valid(Mesh *me_eval) MutableSpan positions = me_eval->vert_positions_for_write(); MutableSpan edges = me_eval->edges_for_write(); MutableSpan polys = me_eval->polys_for_write(); - MutableSpan loops = me_eval->loops_for_write(); + MutableSpan corner_verts = me_eval->corner_verts_for_write(); + MutableSpan corner_edges = me_eval->corner_edges_for_write(); is_valid &= BKE_mesh_validate_all_customdata( &me_eval->vdata, @@ -342,8 +343,9 @@ bool BKE_mesh_runtime_is_valid(Mesh *me_eval) static_cast(CustomData_get_layer_for_write( &me_eval->fdata, CD_MFACE, me_eval->totface)), me_eval->totface, - loops.data(), - loops.size(), + corner_verts.data(), + corner_edges.data(), + corner_verts.size(), polys.data(), polys.size(), me_eval->deform_verts_for_write().data(), diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc index 3fe710d1d69..4c7474e244c 100644 --- a/source/blender/blenkernel/intern/mesh_sample.cc +++ b/source/blender/blenkernel/intern/mesh_sample.cc @@ -21,7 +21,7 @@ BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh, const IndexMask mask, const MutableSpan dst) { - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); const Span looptris = mesh.looptris(); for (const int i : mask) { @@ -29,9 +29,9 @@ BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh, const MLoopTri &looptri = looptris[looptri_index]; const float3 &bary_coord = bary_coords[i]; - const int v0_index = loops[looptri.tri[0]].v; - const int v1_index = loops[looptri.tri[1]].v; - const int v2_index = loops[looptri.tri[2]].v; + const int v0_index = corner_verts[looptri.tri[0]]; + const int v1_index = corner_verts[looptri.tri[1]]; + const int v2_index = corner_verts[looptri.tri[2]]; const T v0 = src[v0_index]; const T v1 = src[v1_index]; @@ -157,21 +157,17 @@ Span MeshAttributeInterpolator::ensure_barycentric_coords() bary_coords_.reinitialize(mask_.min_array_size()); const Span positions = mesh_->vert_positions(); - const Span loops = mesh_->loops(); + const Span corner_verts = mesh_->corner_verts(); const Span looptris = mesh_->looptris(); for (const int i : mask_) { const int looptri_index = looptri_indices_[i]; const MLoopTri &looptri = looptris[looptri_index]; - const int v0_index = loops[looptri.tri[0]].v; - const int v1_index = loops[looptri.tri[1]].v; - const int v2_index = loops[looptri.tri[2]].v; - interp_weights_tri_v3(bary_coords_[i], - positions[v0_index], - positions[v1_index], - positions[v2_index], + positions[corner_verts[looptri.tri[0]]], + positions[corner_verts[looptri.tri[1]]], + positions[corner_verts[looptri.tri[2]]], positions_[i]); } return bary_coords_; @@ -186,20 +182,16 @@ Span MeshAttributeInterpolator::ensure_nearest_weights() nearest_weights_.reinitialize(mask_.min_array_size()); const Span positions = mesh_->vert_positions(); - const Span loops = mesh_->loops(); + const Span corner_verts = mesh_->corner_verts(); const Span looptris = mesh_->looptris(); for (const int i : mask_) { const int looptri_index = looptri_indices_[i]; const MLoopTri &looptri = looptris[looptri_index]; - const int v0_index = loops[looptri.tri[0]].v; - const int v1_index = loops[looptri.tri[1]].v; - const int v2_index = loops[looptri.tri[2]].v; - - const float d0 = len_squared_v3v3(positions_[i], positions[v0_index]); - const float d1 = len_squared_v3v3(positions_[i], positions[v1_index]); - const float d2 = len_squared_v3v3(positions_[i], positions[v2_index]); + const float d0 = len_squared_v3v3(positions_[i], positions[corner_verts[looptri.tri[0]]]); + const float d1 = len_squared_v3v3(positions_[i], positions[corner_verts[looptri.tri[1]]]); + const float d2 = len_squared_v3v3(positions_[i], positions[corner_verts[looptri.tri[2]]]); nearest_weights_[i] = MIN3_PAIR(d0, d1, d2, float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1)); } @@ -259,7 +251,7 @@ int sample_surface_points_spherical(RandomNumberGenerator &rng, Vector &r_positions) { const Span positions = mesh.vert_positions(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); const Span looptris = mesh.looptris(); const float sample_radius_sq = pow2f(sample_radius); @@ -272,9 +264,9 @@ int sample_surface_points_spherical(RandomNumberGenerator &rng, for (const int looptri_index : looptri_indices_to_sample) { const MLoopTri &looptri = looptris[looptri_index]; - const float3 &v0 = positions[loops[looptri.tri[0]].v]; - const float3 &v1 = positions[loops[looptri.tri[1]].v]; - const float3 &v2 = positions[loops[looptri.tri[2]].v]; + const float3 &v0 = positions[corner_verts[looptri.tri[0]]]; + const float3 &v1 = positions[corner_verts[looptri.tri[1]]]; + const float3 &v2 = positions[corner_verts[looptri.tri[2]]]; const float looptri_area = area_tri_v3(v0, v1, v2); @@ -356,7 +348,7 @@ int sample_surface_points_projected( Vector &r_positions) { const Span positions = mesh.vert_positions(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); const Span looptris = mesh.looptris(); int point_count = 0; @@ -398,7 +390,7 @@ int sample_surface_points_projected( const float3 pos = ray_hit.co; const float3 bary_coords = compute_bary_coord_in_triangle( - positions, loops, looptris[looptri_index], pos); + positions, corner_verts, looptris[looptri_index], pos); r_positions.append(pos); r_bary_coords.append(bary_coords); @@ -409,13 +401,13 @@ int sample_surface_points_projected( } float3 compute_bary_coord_in_triangle(const Span vert_positions, - const Span loops, + const Span corner_verts, const MLoopTri &looptri, const float3 &position) { - const float3 &v0 = vert_positions[loops[looptri.tri[0]].v]; - const float3 &v1 = vert_positions[loops[looptri.tri[1]].v]; - const float3 &v2 = vert_positions[loops[looptri.tri[2]].v]; + const float3 &v0 = vert_positions[corner_verts[looptri.tri[0]]]; + const float3 &v1 = vert_positions[corner_verts[looptri.tri[1]]]; + const float3 &v2 = vert_positions[corner_verts[looptri.tri[2]]]; float3 bary_coords; interp_weights_tri_v3(bary_coords, v0, v1, v2, position); return bary_coords; diff --git a/source/blender/blenkernel/intern/mesh_tangent.cc b/source/blender/blenkernel/intern/mesh_tangent.cc index c4d8db512a2..7a7a8a78dd7 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.cc +++ b/source/blender/blenkernel/intern/mesh_tangent.cc @@ -50,7 +50,7 @@ struct BKEMeshToTangent { mikk::float3 GetPosition(const uint face_num, const uint vert_num) { const uint loop_idx = uint(polys[face_num].loopstart) + vert_num; - return mikk::float3(positions[mloops[loop_idx].v]); + return mikk::float3(positions[corner_verts[loop_idx]]); } mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) @@ -71,7 +71,7 @@ struct BKEMeshToTangent { } const MPoly *polys; /* faces */ - const MLoop *mloops; /* faces vertices */ + const int *corner_verts; /* faces vertices */ const float (*positions)[3]; /* vertices */ const float (*luvs)[2]; /* texture coordinates */ const float (*loop_normals)[3]; /* loops' normals */ @@ -81,7 +81,7 @@ struct BKEMeshToTangent { void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3], const int /*numVerts*/, - const MLoop *mloops, + const int *corner_verts, float (*r_looptangent)[4], const float (*loop_normals)[3], const float (*loop_uvs)[2], @@ -93,7 +93,7 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3], /* Compute Mikktspace's tangent normals. */ BKEMeshToTangent mesh_to_tangent; mesh_to_tangent.polys = polys; - mesh_to_tangent.mloops = mloops; + mesh_to_tangent.corner_verts = corner_verts; mesh_to_tangent.positions = vert_positions; mesh_to_tangent.luvs = loop_uvs; mesh_to_tangent.loop_normals = loop_normals; @@ -146,7 +146,7 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, BKE_mesh_calc_loop_tangent_single_ex(BKE_mesh_vert_positions(mesh), mesh->totvert, - mesh->loops().data(), + mesh->corner_verts().data(), r_looptangents, loop_normals, reinterpret_cast(uv_map.data()), @@ -216,7 +216,7 @@ struct SGLSLMeshToTangent { { const MLoopTri *lt; uint loop_index = GetLoop(face_num, vert_num, lt); - return mikk::float3(positions[mloop[loop_index].v]); + return mikk::float3(positions[corner_verts[loop_index]]); } mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) @@ -227,7 +227,7 @@ struct SGLSLMeshToTangent { const float2 &uv = mloopuv[loop_index]; return mikk::float3(uv[0], uv[1], 1.0f); } - const float *l_orco = orco[mloop[loop_index].v]; + const float *l_orco = orco[corner_verts[loop_index]]; float u, v; map_to_sphere(&u, &v, l_orco[0], l_orco[1], l_orco[2]); return mikk::float3(u, v, 1.0f); @@ -249,22 +249,22 @@ struct SGLSLMeshToTangent { float normal[3]; if (poly.totloop == 4) { normal_quad_v3(normal, - positions[mloop[poly.loopstart + 0].v], - positions[mloop[poly.loopstart + 1].v], - positions[mloop[poly.loopstart + 2].v], - positions[mloop[poly.loopstart + 3].v]); + positions[corner_verts[poly.loopstart + 0]], + positions[corner_verts[poly.loopstart + 1]], + positions[corner_verts[poly.loopstart + 2]], + positions[corner_verts[poly.loopstart + 3]]); } else #endif { normal_tri_v3(normal, - positions[mloop[lt->tri[0]].v], - positions[mloop[lt->tri[1]].v], - positions[mloop[lt->tri[2]].v]); + positions[corner_verts[lt->tri[0]]], + positions[corner_verts[lt->tri[1]]], + positions[corner_verts[lt->tri[2]]]); } return mikk::float3(normal); } - return mikk::float3(vert_normals[mloop[loop_index].v]); + return mikk::float3(vert_normals[corner_verts[loop_index]]); } void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) @@ -280,7 +280,7 @@ struct SGLSLMeshToTangent { const MLoopTri *looptri; const float2 *mloopuv; /* texture coordinates */ const MPoly *polys; /* indices */ - const MLoop *mloop; /* indices */ + const int *corner_verts; /* indices */ const float (*positions)[3]; /* vertex coordinates */ const float (*vert_normals)[3]; const float (*orco)[3]; @@ -391,7 +391,7 @@ void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData, void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], const MPoly *polys, const uint polys_len, - const MLoop *mloop, + const int *corner_verts, const MLoopTri *looptri, const uint looptri_len, const bool *sharp_faces, @@ -497,7 +497,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3], mesh2tangent->positions = vert_positions; mesh2tangent->vert_normals = vert_normals; mesh2tangent->polys = polys; - mesh2tangent->mloop = mloop; + mesh2tangent->corner_verts = corner_verts; mesh2tangent->looptri = looptri; mesh2tangent->sharp_faces = sharp_faces; /* NOTE: we assume we do have tessellated loop normals at this point @@ -582,7 +582,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval, BKE_mesh_vert_positions(me_eval), me_eval->polys().data(), uint(me_eval->totpoly), - me_eval->loops().data(), + me_eval->corner_verts().data(), looptris.data(), uint(looptris.size()), static_cast( diff --git a/source/blender/blenkernel/intern/mesh_tessellate.cc b/source/blender/blenkernel/intern/mesh_tessellate.cc index 62c69dc9286..9bd881d0ca5 100644 --- a/source/blender/blenkernel/intern/mesh_tessellate.cc +++ b/source/blender/blenkernel/intern/mesh_tessellate.cc @@ -34,7 +34,7 @@ namespace blender::bke::mesh { /** * \param face_normal: This will be optimized out as a constant. */ -BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span mloop, +BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span corner_verts, const Span polys, const Span positions, uint poly_index, @@ -46,37 +46,37 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span mloop, const uint mp_loopstart = uint(polys[poly_index].loopstart); const uint mp_totloop = uint(polys[poly_index].totloop); -#define ML_TO_MLT(i1, i2, i3) \ - { \ - ARRAY_SET_ITEMS(mlt->tri, mp_loopstart + i1, mp_loopstart + i2, mp_loopstart + i3); \ - mlt->poly = poly_index; \ - } \ - ((void)0) + auto create_tri = [&](uint i1, uint i2, uint i3) { + mlt->tri[0] = mp_loopstart + i1; + mlt->tri[1] = mp_loopstart + i2; + mlt->tri[2] = mp_loopstart + i3; + mlt->poly = poly_index; + }; switch (mp_totloop) { case 3: { - ML_TO_MLT(0, 1, 2); + create_tri(0, 1, 2); break; } case 4: { - ML_TO_MLT(0, 1, 2); + create_tri(0, 1, 2); MLoopTri *mlt_a = mlt++; - ML_TO_MLT(0, 2, 3); + create_tri(0, 2, 3); MLoopTri *mlt_b = mlt; if (UNLIKELY(face_normal ? is_quad_flip_v3_first_third_fast_with_normal( /* Simpler calculation (using the normal). */ - positions[mloop[mlt_a->tri[0]].v], - positions[mloop[mlt_a->tri[1]].v], - positions[mloop[mlt_a->tri[2]].v], - positions[mloop[mlt_b->tri[2]].v], + positions[corner_verts[mlt_a->tri[0]]], + positions[corner_verts[mlt_a->tri[1]]], + positions[corner_verts[mlt_a->tri[2]]], + positions[corner_verts[mlt_b->tri[2]]], normal_precalc) : is_quad_flip_v3_first_third_fast( /* Expensive calculation (no normal). */ - positions[mloop[mlt_a->tri[0]].v], - positions[mloop[mlt_a->tri[1]].v], - positions[mloop[mlt_a->tri[2]].v], - positions[mloop[mlt_b->tri[2]].v]))) { + positions[corner_verts[mlt_a->tri[0]]], + positions[corner_verts[mlt_a->tri[1]]], + positions[corner_verts[mlt_a->tri[2]]], + positions[corner_verts[mlt_b->tri[2]]]))) { /* Flip out of degenerate 0-2 state. */ mlt_a->tri[2] = mlt_b->tri[2]; mlt_b->tri[0] = mlt_a->tri[1]; @@ -84,7 +84,6 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span mloop, break; } default: { - const MLoop *ml; float axis_mat[3][3]; /* Calculate `axis_mat` to project verts to 2D. */ @@ -95,10 +94,9 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span mloop, zero_v3(normal); /* Calc normal, flipped: to get a positive 2D cross product. */ - ml = mloop.data() + mp_loopstart; - co_prev = positions[ml[mp_totloop - 1].v]; - for (uint j = 0; j < mp_totloop; j++, ml++) { - co_curr = positions[ml->v]; + co_prev = positions[corner_verts[mp_totloop - 1]]; + for (uint j = 0; j < mp_totloop; j++) { + co_curr = positions[corner_verts[mp_loopstart + j]]; add_newell_cross_v3_v3v3(normal, co_prev, co_curr); co_prev = co_curr; } @@ -123,9 +121,8 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span mloop, float(*projverts)[2] = static_cast( BLI_memarena_alloc(pf_arena, sizeof(*projverts) * size_t(mp_totloop))); - ml = mloop.data() + mp_loopstart; - for (uint j = 0; j < mp_totloop; j++, ml++) { - mul_v2_m3v3(projverts[j], axis_mat, positions[ml->v]); + for (uint j = 0; j < mp_totloop; j++) { + mul_v2_m3v3(projverts[j], axis_mat, positions[corner_verts[mp_loopstart + j]]); } BLI_polyfill_calc_arena(projverts, mp_totloop, 1, tris, pf_arena); @@ -133,7 +130,7 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span mloop, /* Apply fill. */ for (uint j = 0; j < totfilltri; j++, mlt++) { const uint *tri = tris[j]; - ML_TO_MLT(tri[0], tri[1], tri[2]); + create_tri(tri[0], tri[1], tri[2]); } BLI_memarena_clear(pf_arena); @@ -144,7 +141,7 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span mloop, #undef ML_TO_MLT } -static void mesh_calc_tessellation_for_face(const Span mloop, +static void mesh_calc_tessellation_for_face(const Span corner_verts, const Span polys, const Span positions, uint poly_index, @@ -152,10 +149,10 @@ static void mesh_calc_tessellation_for_face(const Span mloop, MemArena **pf_arena_p) { mesh_calc_tessellation_for_face_impl( - mloop, polys, positions, poly_index, mlt, pf_arena_p, false, nullptr); + corner_verts, polys, positions, poly_index, mlt, pf_arena_p, false, nullptr); } -static void mesh_calc_tessellation_for_face_with_normal(const Span mloop, +static void mesh_calc_tessellation_for_face_with_normal(const Span corner_verts, const Span polys, const Span positions, uint poly_index, @@ -164,10 +161,10 @@ static void mesh_calc_tessellation_for_face_with_normal(const Span mloop, const float normal_precalc[3]) { mesh_calc_tessellation_for_face_impl( - mloop, polys, positions, poly_index, mlt, pf_arena_p, true, normal_precalc); + corner_verts, polys, positions, poly_index, mlt, pf_arena_p, true, normal_precalc); } -static void mesh_recalc_looptri__single_threaded(const Span mloop, +static void mesh_recalc_looptri__single_threaded(const Span corner_verts, const Span polys, const Span positions, int totloop, @@ -181,7 +178,7 @@ static void mesh_recalc_looptri__single_threaded(const Span mloop, if (poly_normals != nullptr) { for (uint poly_index = 0; poly_index < uint(totpoly); poly_index++, poly++) { - mesh_calc_tessellation_for_face_with_normal(mloop, + mesh_calc_tessellation_for_face_with_normal(corner_verts, polys, positions, poly_index, @@ -194,7 +191,7 @@ static void mesh_recalc_looptri__single_threaded(const Span mloop, else { for (uint poly_index = 0; poly_index < uint(totpoly); poly_index++, poly++) { mesh_calc_tessellation_for_face( - mloop, polys, positions, poly_index, &mlooptri[tri_index], &pf_arena); + corner_verts, polys, positions, poly_index, &mlooptri[tri_index], &pf_arena); tri_index += uint(poly->totloop - 2); } } @@ -208,7 +205,7 @@ static void mesh_recalc_looptri__single_threaded(const Span mloop, } struct TessellationUserData { - Span mloop; + Span corner_verts; Span polys; Span positions; @@ -230,7 +227,7 @@ static void mesh_calc_tessellation_for_face_fn(void *__restrict userdata, const TessellationUserData *data = static_cast(userdata); TessellationUserTLS *tls_data = static_cast(tls->userdata_chunk); const int tri_index = poly_to_tri_count(index, data->polys[index].loopstart); - mesh_calc_tessellation_for_face_impl(data->mloop, + mesh_calc_tessellation_for_face_impl(data->corner_verts, data->polys, data->positions, uint(index), @@ -247,7 +244,7 @@ static void mesh_calc_tessellation_for_face_with_normal_fn(void *__restrict user const TessellationUserData *data = static_cast(userdata); TessellationUserTLS *tls_data = static_cast(tls->userdata_chunk); const int tri_index = poly_to_tri_count(index, data->polys[index].loopstart); - mesh_calc_tessellation_for_face_impl(data->mloop, + mesh_calc_tessellation_for_face_impl(data->corner_verts, data->polys, data->positions, uint(index), @@ -268,15 +265,15 @@ static void mesh_calc_tessellation_for_face_free_fn(const void *__restrict /*use static void looptris_calc_all(const Span positions, const Span polys, - const Span loops, + const Span corner_verts, const Span poly_normals, MutableSpan looptris) { - if (loops.size() < MESH_FACE_TESSELLATE_THREADED_LIMIT) { - mesh_recalc_looptri__single_threaded(loops, + if (corner_verts.size() < MESH_FACE_TESSELLATE_THREADED_LIMIT) { + mesh_recalc_looptri__single_threaded(corner_verts, polys, positions, - int(loops.size()), + int(corner_verts.size()), int(polys.size()), looptris.data(), reinterpret_cast(poly_normals.data())); @@ -286,7 +283,7 @@ static void looptris_calc_all(const Span positions, struct TessellationUserData data { }; - data.mloop = loops; + data.corner_verts = corner_verts; data.polys = polys; data.positions = positions; data.mlooptri = looptris; @@ -310,25 +307,25 @@ static void looptris_calc_all(const Span positions, void looptris_calc(const Span vert_positions, const Span polys, - const Span loops, + const Span corner_verts, MutableSpan looptris) { - looptris_calc_all(vert_positions, polys, loops, {}, looptris); + looptris_calc_all(vert_positions, polys, corner_verts, {}, looptris); } void looptris_calc_with_normals(const Span vert_positions, const Span polys, - const Span loops, + const Span corner_verts, const Span poly_normals, MutableSpan looptris) { BLI_assert(!poly_normals.is_empty() || polys.is_empty()); - looptris_calc_all(vert_positions, polys, loops, poly_normals, looptris); + looptris_calc_all(vert_positions, polys, corner_verts, poly_normals, looptris); } } // namespace blender::bke::mesh -void BKE_mesh_recalc_looptri(const MLoop *mloop, +void BKE_mesh_recalc_looptri(const int *corner_verts, const MPoly *polys, const float (*vert_positions)[3], int totvert, @@ -339,7 +336,7 @@ void BKE_mesh_recalc_looptri(const MLoop *mloop, blender::bke::mesh::looptris_calc( {reinterpret_cast(vert_positions), totvert}, {polys, totpoly}, - {mloop, totloop}, + {corner_verts, totloop}, {mlooptri, poly_to_tri_count(totpoly, totloop)}); } diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc index 19e5e525015..f15020c9c46 100644 --- a/source/blender/blenkernel/intern/mesh_validate.cc +++ b/source/blender/blenkernel/intern/mesh_validate.cc @@ -216,7 +216,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, uint totedge, MFace *mfaces, uint totface, - MLoop *mloops, + int *corner_verts, + int *corner_edges, uint totloop, MPoly *polys, uint totpoly, @@ -233,9 +234,9 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, (void)0 #define IS_REMOVED_EDGE(_me) (_me->v2 == _me->v1) -#define REMOVE_LOOP_TAG(_ml) \ +#define REMOVE_LOOP_TAG(corner) \ { \ - _ml->e = INVALID_LOOP_EDGE_MARKER; \ + corner_edges[corner] = INVALID_LOOP_EDGE_MARKER; \ free_flag.polyloops = do_fixes; \ } \ (void)0 @@ -251,7 +252,6 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, blender::MutableVArraySpan material_indices_span(material_indices.varray); MEdge *edge; - MLoop *ml; uint i, j; int *v; @@ -575,27 +575,29 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, /* Ideally we would only have to do that once on all vertices * before we start checking each poly, but several polys can use same vert, * so we have to ensure here all verts of current poly are cleared. */ - for (j = 0, ml = &mloops[sp->loopstart]; j < poly.totloop; j++, ml++) { - if (ml->v < totvert) { - BLI_BITMAP_DISABLE(vert_tag, ml->v); + for (j = 0; j < poly.totloop; j++) { + const int vert = corner_verts[sp->loopstart + j]; + if (vert < totvert) { + BLI_BITMAP_DISABLE(vert_tag, vert); } } /* Test all poly's loops' vert idx. */ - for (j = 0, ml = &mloops[sp->loopstart]; j < poly.totloop; j++, ml++, v++) { - if (ml->v >= totvert) { + for (j = 0; j < poly.totloop; j++, v++) { + const int vert = corner_verts[sp->loopstart + j]; + if (vert >= totvert) { /* Invalid vert idx. */ - PRINT_ERR("\tLoop %u has invalid vert reference (%u)", sp->loopstart + j, ml->v); + PRINT_ERR("\tLoop %u has invalid vert reference (%d)", sp->loopstart + j, vert); sp->invalid = true; } - else if (BLI_BITMAP_TEST(vert_tag, ml->v)) { + else if (BLI_BITMAP_TEST(vert_tag, vert)) { PRINT_ERR("\tPoly %u has duplicated vert reference at corner (%u)", uint(i), j); sp->invalid = true; } else { - BLI_BITMAP_ENABLE(vert_tag, ml->v); + BLI_BITMAP_ENABLE(vert_tag, vert); } - *v = ml->v; + *v = vert; } if (sp->invalid) { @@ -604,9 +606,12 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } /* Test all poly's loops. */ - for (j = 0, ml = &mloops[sp->loopstart]; j < poly.totloop; j++, ml++) { - v1 = ml->v; - v2 = mloops[sp->loopstart + (j + 1) % poly.totloop].v; + for (j = 0; j < poly.totloop; j++) { + const int corner = sp->loopstart + j; + const int vert = corner_verts[corner]; + const int edge_i = corner_edges[corner]; + v1 = vert; + v2 = corner_verts[sp->loopstart + (j + 1) % poly.totloop]; if (!BLI_edgehash_haskey(edge_hash, v1, v2)) { /* Edge not existing. */ PRINT_ERR("\tPoly %u needs missing edge (%d, %d)", sp->index, v1, v2); @@ -617,44 +622,44 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, sp->invalid = true; } } - else if (ml->e >= totedge) { + else if (edge_i >= totedge) { /* Invalid edge idx. * We already know from previous text that a valid edge exists, use it (if allowed)! */ if (do_fixes) { - int prev_e = ml->e; - ml->e = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2)); + int prev_e = edge_i; + corner_edges[corner] = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2)); fix_flag.loops_edge = true; - PRINT_ERR("\tLoop %u has invalid edge reference (%d), fixed using edge %u", - sp->loopstart + j, + PRINT_ERR("\tLoop %d has invalid edge reference (%d), fixed using edge %d", + corner, prev_e, - ml->e); + corner_edges[corner]); } else { - PRINT_ERR("\tLoop %u has invalid edge reference (%u)", sp->loopstart + j, ml->e); + PRINT_ERR("\tLoop %d has invalid edge reference (%d)", corner, edge_i); sp->invalid = true; } } else { - edge = &edges[ml->e]; + edge = &edges[edge_i]; if (IS_REMOVED_EDGE(edge) || !((edge->v1 == v1 && edge->v2 == v2) || (edge->v1 == v2 && edge->v2 == v1))) { /* The pointed edge is invalid (tagged as removed, or vert idx mismatch), * and we already know from previous test that a valid one exists, * use it (if allowed)! */ if (do_fixes) { - int prev_e = ml->e; - ml->e = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2)); + int prev_e = edge_i; + corner_edges[corner] = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2)); fix_flag.loops_edge = true; PRINT_ERR( "\tPoly %u has invalid edge reference (%d, is_removed: %d), fixed using edge " - "%u", + "%d", sp->index, prev_e, IS_REMOVED_EDGE(edge), - ml->e); + corner_edges[corner]); } else { - PRINT_ERR("\tPoly %u has invalid edge reference (%u)", sp->index, ml->e); + PRINT_ERR("\tPoly %u has invalid edge reference (%d)", sp->index, edge_i); sp->invalid = true; } } @@ -733,10 +738,11 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, else { /* Unused loops. */ if (prev_end < sp->loopstart) { - for (j = prev_end, ml = &mloops[prev_end]; j < sp->loopstart; j++, ml++) { + int corner; + for (j = prev_end, corner = prev_end; j < sp->loopstart; j++, corner++) { PRINT_ERR("\tLoop %u is unused.", j); if (do_fixes) { - REMOVE_LOOP_TAG(ml); + REMOVE_LOOP_TAG(corner); } } prev_end = sp->loopstart + sp->numverts; @@ -766,10 +772,11 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } /* We may have some remaining unused loops to get rid of! */ if (prev_end < totloop) { - for (j = prev_end, ml = &mloops[prev_end]; j < totloop; j++, ml++) { + int corner; + for (j = prev_end, corner = prev_end; j < totloop; j++, corner++) { PRINT_ERR("\tLoop %u is unused.", j); if (do_fixes) { - REMOVE_LOOP_TAG(ml); + REMOVE_LOOP_TAG(corner); } } } @@ -1043,7 +1050,8 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_ MutableSpan positions = me->vert_positions_for_write(); MutableSpan edges = me->edges_for_write(); MutableSpan polys = me->polys_for_write(); - MutableSpan loops = me->loops_for_write(); + MutableSpan corner_verts = me->corner_verts_for_write(); + MutableSpan corner_edges = me->corner_edges_for_write(); BKE_mesh_validate_arrays( me, @@ -1053,8 +1061,9 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_ edges.size(), (MFace *)CustomData_get_layer_for_write(&me->fdata, CD_MFACE, me->totface), me->totface, - loops.data(), - loops.size(), + corner_verts.data(), + corner_edges.data(), + corner_verts.size(), polys.data(), polys.size(), me->deform_verts_for_write().data(), @@ -1095,7 +1104,8 @@ bool BKE_mesh_is_valid(Mesh *me) MutableSpan positions = me->vert_positions_for_write(); MutableSpan edges = me->edges_for_write(); MutableSpan polys = me->polys_for_write(); - MutableSpan loops = me->loops_for_write(); + MutableSpan corner_verts = me->corner_verts_for_write(); + MutableSpan corner_edges = me->corner_edges_for_write(); is_valid &= BKE_mesh_validate_arrays( me, @@ -1105,8 +1115,9 @@ bool BKE_mesh_is_valid(Mesh *me) edges.size(), (MFace *)CustomData_get_layer_for_write(&me->fdata, CD_MFACE, me->totface), me->totface, - loops.data(), - loops.size(), + corner_verts.data(), + corner_edges.data(), + corner_verts.size(), polys.data(), polys.size(), me->deform_verts_for_write().data(), @@ -1175,9 +1186,8 @@ void BKE_mesh_strip_loose_faces(Mesh *me) void mesh_strip_polysloops(Mesh *me) { MutableSpan polys = me->polys_for_write(); - MutableSpan loops = me->loops_for_write(); + MutableSpan corner_edges = me->corner_edges_for_write(); - MLoop *l; int a, b; /* New loops idx! */ int *new_idx = (int *)MEM_mallocN(sizeof(int) * me->totloop, __func__); @@ -1192,14 +1202,11 @@ void mesh_strip_polysloops(Mesh *me) invalid = true; } else { - l = &loops[i]; - i = stop - i; /* If one of the poly's loops is invalid, the whole poly is invalid! */ - for (; i--; l++) { - if (l->e == INVALID_LOOP_EDGE_MARKER) { - invalid = true; - break; - } + if (corner_edges.slice(poly.loopstart, poly.totloop) + .as_span() + .contains(INVALID_LOOP_EDGE_MARKER)) { + invalid = true; } } @@ -1217,10 +1224,10 @@ void mesh_strip_polysloops(Mesh *me) } /* And now, get rid of invalid loops. */ - for (a = b = 0, l = loops.data(); a < me->totloop; a++, l++) { - if (l->e != INVALID_LOOP_EDGE_MARKER) { + int corner = 0; + for (a = b = 0; a < me->totloop; a++, corner++) { + if (corner_edges[corner] != INVALID_LOOP_EDGE_MARKER) { if (a != b) { - memcpy(&loops[b], l, sizeof(loops[b])); CustomData_copy_data(&me->ldata, &me->ldata, a, b, 1); } new_idx[a] = b; @@ -1274,9 +1281,9 @@ void mesh_strip_edges(Mesh *me) /* And now, update loops' edge indices. */ /* XXX We hope no loop was pointing to a striped edge! * Else, its e will be set to INVALID_LOOP_EDGE_MARKER :/ */ - MutableSpan loops = me->loops_for_write(); - for (MLoop &loop : loops) { - loop.e = new_idx[loop.e]; + MutableSpan corner_edges = me->corner_edges_for_write(); + for (const int i : corner_edges.index_range()) { + corner_edges[i] = new_idx[corner_edges[i]]; } MEM_freeN(new_idx); diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index 63792623c56..659710a1892 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -7,7 +7,7 @@ * output of a modified mesh. * * This API handles the case when the modifier stack outputs a mesh which does not have - * #Mesh data (#MPoly, #MLoop, #MEdge, etc). + * #Mesh data (#MPoly, corner verts, corner edges, #MEdge, etc). * Currently this is used so the resulting mesh can have #BMEditMesh data, * postponing the converting until it's needed or avoiding conversion entirely * which can be an expensive operation. diff --git a/source/blender/blenkernel/intern/multires.cc b/source/blender/blenkernel/intern/multires.cc index a2f2c52b9cf..a3c88309898 100644 --- a/source/blender/blenkernel/intern/multires.cc +++ b/source/blender/blenkernel/intern/multires.cc @@ -673,7 +673,6 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) if (mdisps && levels > 0) { if (lvl > 0) { - // MLoop *ml = me->mloop; /*UNUSED*/ int nsize = multires_side_tot[lvl]; int hsize = multires_side_tot[mmd->totlvl]; int j; @@ -1629,7 +1628,7 @@ int mdisp_rot_face_to_crn( float mindist = FLT_MAX; for (i = 0; i < poly->totloop; i++) { - float len = len_v3v3(nullptr, positions[mloop[poly->loopstart + i].v]); + float len = len_v3v3(nullptr, positions[corner_verts[poly->loopstart + i]]); if (len < mindist) { mindist = len; minS = i; diff --git a/source/blender/blenkernel/intern/multires_reshape.hh b/source/blender/blenkernel/intern/multires_reshape.hh index d709afca86f..66731f212ea 100644 --- a/source/blender/blenkernel/intern/multires_reshape.hh +++ b/source/blender/blenkernel/intern/multires_reshape.hh @@ -17,7 +17,6 @@ struct GridPaintMask; struct MDisps; struct MEdge; struct Mesh; -struct MLoop; struct MPoly; struct MultiresModifierData; struct Object; @@ -37,7 +36,8 @@ struct MultiresReshapeContext { const float (*base_positions)[3]; blender::Span base_edges; blender::Span base_polys; - blender::Span base_loops; + blender::Span base_corner_verts; + blender::Span base_corner_edges; /* Subdivision surface created for multires modifier. * diff --git a/source/blender/blenkernel/intern/multires_reshape_apply_base.cc b/source/blender/blenkernel/intern/multires_reshape_apply_base.cc index 46a990c6e07..0b48aa8f282 100644 --- a/source/blender/blenkernel/intern/multires_reshape_apply_base.cc +++ b/source/blender/blenkernel/intern/multires_reshape_apply_base.cc @@ -34,9 +34,8 @@ void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *resh /* Update the context in case the vertices were duplicated. */ reshape_context->base_positions = base_positions; - const blender::Span loops = reshape_context->base_loops; - for (const int loop_index : loops.index_range()) { - const MLoop *loop = &loops[loop_index]; + const blender::Span corner_verts = reshape_context->base_corner_verts; + for (const int loop_index : corner_verts.index_range()) { GridCoord grid_coord; grid_coord.grid_index = loop_index; @@ -52,7 +51,7 @@ void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *resh float D[3]; mul_v3_m3v3(D, tangent_matrix, grid_element.displacement); - add_v3_v3v3(base_positions[loop->v], P, D); + add_v3_v3v3(base_positions[corner_verts[loop_index]], P, D); } } @@ -76,7 +75,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape BKE_mesh_vert_poly_map_create(&pmap, &pmap_mem, reshape_context->base_polys.data(), - reshape_context->base_loops.data(), + reshape_context->base_corner_verts.data(), base_mesh->totvert, base_mesh->totpoly, base_mesh->totloop); @@ -102,7 +101,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape /* This double counts, not sure if that's bad or good. */ for (int k = 0; k < poly.totloop; k++) { - const int vndx = reshape_context->base_loops[poly.loopstart + k].v; + const int vndx = reshape_context->base_corner_verts[poly.loopstart + k]; if (vndx != i) { add_v3_v3(center, origco[vndx]); tot++; @@ -116,13 +115,13 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape const MPoly &poly = reshape_context->base_polys[pmap[i].indices[j]]; /* Set up poly, loops, and coords in order to call #bke::mesh::poly_normal_calc(). */ - blender::Array fake_loops(poly.totloop); + blender::Array poly_verts(poly.totloop); blender::Array fake_co(poly.totloop); for (int k = 0; k < poly.totloop; k++) { - const int vndx = reshape_context->base_loops[poly.loopstart + k].v; + const int vndx = reshape_context->base_corner_verts[poly.loopstart + k]; - fake_loops[k].v = k; + poly_verts[k] = k; if (vndx == i) { copy_v3_v3(fake_co[k], center); @@ -132,7 +131,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape } } - const blender::float3 no = blender::bke::mesh::poly_normal_calc(fake_co, fake_loops); + const blender::float3 no = blender::bke::mesh::poly_normal_calc(fake_co, poly_verts); add_v3_v3(avg_no, no); } normalize_v3(avg_no); diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.cc b/source/blender/blenkernel/intern/multires_reshape_smooth.cc index 2586a968b80..bcb13cab559 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.cc +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.cc @@ -850,7 +850,7 @@ static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshap const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; const Mesh *base_mesh = reshape_context->base_mesh; const blender::Span base_polys = reshape_context->base_polys; - const blender::Span base_loops = reshape_context->base_loops; + const blender::Span base_corner_edges = reshape_context->base_corner_edges; reshape_smooth_context->non_loose_base_edge_map = BLI_BITMAP_NEW(base_mesh->totedge, "non_loose_base_edge_map"); @@ -858,12 +858,11 @@ static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshap int num_used_edges = 0; for (const int poly_index : base_polys.index_range()) { const MPoly &base_poly = base_polys[poly_index]; - for (int corner = 0; corner < base_poly.totloop; corner++) { - const MLoop *loop = &base_loops[base_poly.loopstart + corner]; - if (!BLI_BITMAP_TEST_BOOL(reshape_smooth_context->non_loose_base_edge_map, loop->e)) { - BLI_BITMAP_ENABLE(reshape_smooth_context->non_loose_base_edge_map, loop->e); + for (const int edge : base_corner_edges.slice(base_poly.loopstart, base_poly.totloop)) { + if (!BLI_BITMAP_TEST_BOOL(reshape_smooth_context->non_loose_base_edge_map, edge)) { + BLI_BITMAP_ENABLE(reshape_smooth_context->non_loose_base_edge_map, edge); - const float crease = get_effective_crease(reshape_smooth_context, loop->e); + const float crease = get_effective_crease(reshape_smooth_context, edge); if (crease > 0.0f) { ++num_used_edges; } diff --git a/source/blender/blenkernel/intern/multires_reshape_subdivide.cc b/source/blender/blenkernel/intern/multires_reshape_subdivide.cc index 866c35a7a73..f558ad73cda 100644 --- a/source/blender/blenkernel/intern/multires_reshape_subdivide.cc +++ b/source/blender/blenkernel/intern/multires_reshape_subdivide.cc @@ -32,14 +32,14 @@ static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh) using namespace blender::bke; const Span positions = mesh->vert_positions(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); MDisps *mdisps = static_cast( CustomData_get_layer_for_write(&mesh->ldata, CD_MDISPS, mesh->totloop)); for (const int p : polys.index_range()) { const MPoly &poly = polys[p]; - const float3 poly_center = mesh::poly_center_calc(positions, - loops.slice(poly.loopstart, poly.totloop)); + const float3 poly_center = mesh::poly_center_calc( + positions, corner_verts.slice(poly.loopstart, poly.totloop)); for (int l = 0; l < poly.totloop; l++) { const int loop_index = poly.loopstart + l; @@ -50,14 +50,14 @@ static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh) int prev_loop_index = l - 1 >= 0 ? loop_index - 1 : loop_index + poly.totloop - 1; int next_loop_index = l + 1 < poly.totloop ? loop_index + 1 : poly.loopstart; - const MLoop *loop = &loops[loop_index]; - const MLoop *loop_next = &loops[next_loop_index]; - const MLoop *loop_prev = &loops[prev_loop_index]; + const int vert = corner_verts[loop_index]; + const int vert_next = corner_verts[next_loop_index]; + const int vert_prev = corner_verts[prev_loop_index]; copy_v3_v3(disps[0], poly_center); - mid_v3_v3v3(disps[1], positions[loop->v], positions[loop_next->v]); - mid_v3_v3v3(disps[2], positions[loop->v], positions[loop_prev->v]); - copy_v3_v3(disps[3], positions[loop->v]); + mid_v3_v3v3(disps[1], positions[vert], positions[vert_next]); + mid_v3_v3v3(disps[2], positions[vert], positions[vert_prev]); + copy_v3_v3(disps[3], positions[vert]); } } } diff --git a/source/blender/blenkernel/intern/multires_reshape_util.cc b/source/blender/blenkernel/intern/multires_reshape_util.cc index aea8f8a3ca6..62a2667c52f 100644 --- a/source/blender/blenkernel/intern/multires_reshape_util.cc +++ b/source/blender/blenkernel/intern/multires_reshape_util.cc @@ -158,7 +158,8 @@ bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *resh reshape_context->base_positions = BKE_mesh_vert_positions(base_mesh); reshape_context->base_edges = base_mesh->edges(); reshape_context->base_polys = base_mesh->polys(); - reshape_context->base_loops = base_mesh->loops(); + reshape_context->base_corner_verts = base_mesh->corner_verts(); + reshape_context->base_corner_edges = base_mesh->corner_edges(); reshape_context->subdiv = multires_reshape_create_subdiv(nullptr, object, mmd); reshape_context->need_free_subdiv = true; @@ -195,7 +196,8 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape reshape_context->base_positions = BKE_mesh_vert_positions(base_mesh); reshape_context->base_edges = base_mesh->edges(); reshape_context->base_polys = base_mesh->polys(); - reshape_context->base_loops = base_mesh->loops(); + reshape_context->base_corner_verts = base_mesh->corner_verts(); + reshape_context->base_corner_edges = base_mesh->corner_edges(); reshape_context->subdiv = multires_reshape_create_subdiv(depsgraph, object, mmd); reshape_context->need_free_subdiv = true; @@ -229,7 +231,8 @@ bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_co reshape_context->base_positions = BKE_mesh_vert_positions(base_mesh); reshape_context->base_edges = base_mesh->edges(); reshape_context->base_polys = base_mesh->polys(); - reshape_context->base_loops = base_mesh->loops(); + reshape_context->base_corner_verts = base_mesh->corner_verts(); + reshape_context->base_corner_edges = base_mesh->corner_edges(); reshape_context->subdiv = subdiv_ccg->subdiv; reshape_context->need_free_subdiv = false; @@ -276,7 +279,8 @@ bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape reshape_context->base_positions = BKE_mesh_vert_positions(base_mesh); reshape_context->base_edges = base_mesh->edges(); reshape_context->base_polys = base_mesh->polys(); - reshape_context->base_loops = base_mesh->loops(); + reshape_context->base_corner_verts = base_mesh->corner_verts(); + reshape_context->base_corner_edges = base_mesh->corner_edges(); reshape_context->cd_vertex_crease = (const float *)CustomData_get_layer(&base_mesh->edata, CD_CREASE); diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.cc b/source/blender/blenkernel/intern/multires_unsubdivide.cc index eac1c869aa5..be6b1251942 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.cc +++ b/source/blender/blenkernel/intern/multires_unsubdivide.cc @@ -643,7 +643,7 @@ static void store_grid_data(MultiresUnsubdivideContext *context, { Mesh *original_mesh = context->original_mesh; const blender::Span polys = original_mesh->polys(); - const blender::Span loops = original_mesh->loops(); + const blender::Span corner_verts = original_mesh->corner_verts(); const MPoly &poly = polys[BM_elem_index_get(f)]; const int corner_vertex_index = BM_elem_index_get(v); @@ -653,8 +653,7 @@ static void store_grid_data(MultiresUnsubdivideContext *context, int loop_offset = 0; for (int i = 0; i < poly.totloop; i++) { const int loop_index = poly.loopstart + i; - const MLoop *l = &loops[loop_index]; - if (l->v == corner_vertex_index) { + if (corner_verts[loop_index] == corner_vertex_index) { loop_offset = i; break; } @@ -967,22 +966,22 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract( * necessary. */ static bool multires_unsubdivide_flip_grid_x_axis(const blender::Span polys, - const blender::Span loops, + const blender::Span corner_verts, int poly_index, int loop, int v_x) { const MPoly &poly = polys[poly_index]; - const MLoop *l_first = &loops[poly.loopstart]; - if ((loop == (poly.loopstart + (poly.totloop - 1))) && l_first->v == v_x) { + const int v_first = corner_verts[poly.loopstart]; + if ((loop == (poly.loopstart + (poly.totloop - 1))) && v_first == v_x) { return true; } int next_l_index = loop + 1; if (next_l_index < poly.loopstart + poly.totloop) { - const MLoop *l_next = &loops[next_l_index]; - if (l_next->v == v_x) { + const int v_next = corner_verts[next_l_index]; + if (v_next == v_x) { return true; } } @@ -1045,7 +1044,7 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte &bm_base_mesh->ldata, CD_PROP_INT32, base_l_layer_index); const blender::Span polys = base_mesh->polys(); - const blender::Span loops = base_mesh->loops(); + const blender::Span corner_verts = base_mesh->corner_verts(); /* Main loop for extracting the grids. Iterates over the base mesh vertices. */ BM_ITER_MESH (v, &iter, bm_base_mesh, BM_VERTS_OF_MESH) { @@ -1084,7 +1083,7 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte /* Check the orientation of the loops in case that is needed to flip the x and y axis * when extracting the grid. */ const bool flip_grid = multires_unsubdivide_flip_grid_x_axis( - polys, loops, base_mesh_face_index, base_mesh_loop_index, corner_x_index); + polys, corner_verts, base_mesh_face_index, base_mesh_loop_index, corner_x_index); /* Extract the grid for that loop. */ context->base_mesh_grids[base_mesh_loop_index].grid_index = base_mesh_loop_index; diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index c648a339b0a..2b7bce2e8a4 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -1057,7 +1057,7 @@ struct FaceDupliData_Mesh { int totface; const MPoly *polys; - const MLoop *mloop; + const int *corner_verts; Span vert_positions; const float (*orco)[3]; const float2 *mloopuv; @@ -1156,15 +1156,14 @@ static DupliObject *face_dupli_from_mesh(const DupliContext *ctx, /* Mesh variables. */ const MPoly &poly, - const MLoop *mloopstart, + const int *poly_verts, const Span vert_positions) { const int coords_len = poly.totloop; Array coords(coords_len); - const MLoop *ml = mloopstart; - for (int i = 0; i < coords_len; i++, ml++) { - coords[i] = vert_positions[ml->v]; + for (int i = 0; i < coords_len; i++) { + coords[i] = vert_positions[poly_verts[i]]; } return face_dupli(ctx, inst_ob, child_imat, index, use_scale, scale_fac, coords); @@ -1207,7 +1206,7 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, { FaceDupliData_Mesh *fdd = (FaceDupliData_Mesh *)userdata; const MPoly *polys = fdd->polys; - const MLoop *mloop = fdd->mloop; + const int *corner_verts = fdd->corner_verts; const float(*orco)[3] = fdd->orco; const float2 *mloopuv = fdd->mloopuv; const int totface = fdd->totface; @@ -1222,7 +1221,7 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, for (const int a : blender::IndexRange(totface)) { const MPoly &poly = polys[a]; - const MLoop *loopstart = mloop + poly.loopstart; + const int *poly_verts = &corner_verts[poly.loopstart]; DupliObject *dob = face_dupli_from_mesh(fdd->params.ctx, inst_ob, child_imat, @@ -1230,13 +1229,13 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, use_scale, scale_fac, poly, - loopstart, + poly_verts, fdd->vert_positions); const float w = 1.0f / float(poly.totloop); if (orco) { for (int j = 0; j < poly.totloop; j++) { - madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w); + madd_v3_v3fl(dob->orco, orco[poly_verts[j]], w); } } if (mloopuv) { @@ -1320,7 +1319,7 @@ static void make_duplis_faces(const DupliContext *ctx) fdd.params = fdd_params; fdd.totface = me_eval->totpoly; fdd.polys = me_eval->polys().data(); - fdd.mloop = me_eval->loops().data(); + fdd.corner_verts = me_eval->corner_verts().data(); fdd.vert_positions = me_eval->vert_positions(); fdd.mloopuv = (uv_idx != -1) ? (const float2 *)CustomData_get_layer_n( &me_eval->ldata, CD_PROP_FLOAT2, uv_idx) : @@ -1331,9 +1330,8 @@ static void make_duplis_faces(const DupliContext *ctx) } } -static const DupliGenerator gen_dupli_faces = { - /*type*/ OB_DUPLIFACES, - /*make_duplis*/ make_duplis_faces}; +static const DupliGenerator gen_dupli_faces = {/*type*/ OB_DUPLIFACES, + /*make_duplis*/ make_duplis_faces}; /** \} */ @@ -1680,9 +1678,8 @@ static void make_duplis_particles(const DupliContext *ctx) } } -static const DupliGenerator gen_dupli_particles = { - /*type*/ OB_DUPLIPARTS, - /*make_duplis*/ make_duplis_particles}; +static const DupliGenerator gen_dupli_particles = {/*type*/ OB_DUPLIPARTS, + /*make_duplis*/ make_duplis_particles}; /** \} */ diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 42eb3ceff4a..4c9165c2c33 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1697,7 +1697,7 @@ static void sculpt_update_object( * and tools use the Face Sets data from the base mesh when Multires is active. */ ss->vert_positions = BKE_mesh_vert_positions_for_write(me); ss->polys = me->polys().data(); - ss->mloop = me->loops().data(); + ss->corner_verts = me->corner_verts().data(); } else { ss->totvert = me->totvert; @@ -1705,7 +1705,7 @@ static void sculpt_update_object( ss->totfaces = me->totpoly; ss->vert_positions = BKE_mesh_vert_positions_for_write(me); ss->polys = me->polys().data(); - ss->mloop = me->loops().data(); + ss->corner_verts = me->corner_verts().data(); ss->multires.active = false; ss->multires.modifier = nullptr; ss->multires.level = 0; @@ -1766,7 +1766,7 @@ static void sculpt_update_object( BKE_mesh_vert_poly_map_create(&ss->pmap, &ss->pmap_mem, me->polys().data(), - me->loops().data(), + me->corner_verts().data(), me->totvert, me->totpoly, me->totloop); @@ -1986,7 +1986,7 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, { Mesh *me = static_cast(ob->data); const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); int ret = 0; const float *paint_mask = static_cast( @@ -2020,22 +2020,22 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, /* mask center */ for (j = 0; j < poly.totloop; j++) { - const MLoop *l = &loops[poly.loopstart + j]; - avg += paint_mask[l->v]; + const int vert = corner_verts[poly.loopstart + j]; + avg += paint_mask[vert]; } avg /= float(poly.totloop); /* fill in multires mask corner */ for (j = 0; j < poly.totloop; j++) { GridPaintMask *gpm = &gmask[poly.loopstart + j]; - const MLoop *l = &loops[poly.loopstart + j]; - const MLoop *prev = ME_POLY_LOOP_PREV(loops, &poly, j); - const MLoop *next = ME_POLY_LOOP_NEXT(loops, &poly, j); + const int vert = corner_verts[poly.loopstart + j]; + const int prev = ME_POLY_LOOP_PREV(&poly, j); + const int next = ME_POLY_LOOP_NEXT(&poly, j); gpm->data[0] = avg; - gpm->data[1] = (paint_mask[l->v] + paint_mask[next->v]) * 0.5f; - gpm->data[2] = (paint_mask[l->v] + paint_mask[prev->v]) * 0.5f; - gpm->data[3] = paint_mask[l->v]; + gpm->data[1] = (paint_mask[vert] + paint_mask[corner_verts[next]]) * 0.5f; + gpm->data[2] = (paint_mask[vert] + paint_mask[corner_verts[prev]]) * 0.5f; + gpm->data[3] = paint_mask[vert]; } } } @@ -2183,17 +2183,17 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool MutableSpan positions = me->vert_positions_for_write(); const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); MLoopTri *looptri = static_cast( MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__)); - blender::bke::mesh::looptris_calc(positions, polys, loops, {looptri, looptris_num}); + blender::bke::mesh::looptris_calc(positions, polys, corner_verts, {looptri, looptris_num}); BKE_pbvh_build_mesh(pbvh, me, polys.data(), - loops.data(), + corner_verts.data(), reinterpret_cast(positions.data()), me->totvert, &me->vdata, @@ -2204,10 +2204,8 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool const bool is_deformed = check_sculpt_object_deformed(ob, true); if (is_deformed && me_eval_deform != nullptr) { - int totvert; - float(*v_cos)[3] = BKE_mesh_vert_coords_alloc(me_eval_deform, &totvert); - BKE_pbvh_vert_coords_apply(pbvh, v_cos, totvert); - MEM_freeN(v_cos); + BKE_pbvh_vert_coords_apply( + pbvh, BKE_mesh_vert_positions(me_eval_deform), me_eval_deform->totvert); } return pbvh; diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index 0db48119969..29a34c291ba 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -336,7 +336,7 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node) const MLoopTri *lt = &pbvh->looptri[node->prim_indices[i]]; for (int j = 0; j < 3; j++) { face_vert_indices[i][j] = map_insert_vert( - pbvh, map, &node->face_verts, &node->uniq_verts, pbvh->mloop[lt->tri[j]].v); + pbvh, map, &node->face_verts, &node->uniq_verts, pbvh->corner_verts[lt->tri[j]]); } if (has_visible == false) { @@ -688,7 +688,8 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node) args->face_sets_color_default = pbvh->face_sets_color_default; args->face_sets_color_seed = pbvh->face_sets_color_seed; args->vert_positions = pbvh->vert_positions; - args->mloop = pbvh->mloop; + args->corner_verts = {pbvh->corner_verts, pbvh->mesh->totloop}; + args->corner_edges = pbvh->mesh ? pbvh->mesh->corner_edges() : blender::Span(); args->polys = pbvh->polys; args->mlooptri = pbvh->looptri; @@ -823,7 +824,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh) void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh, const MPoly *polys, - const MLoop *mloop, + const int *corner_verts, float (*vert_positions)[3], int totvert, CustomData *vdata, @@ -842,7 +843,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, &mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->totpoly)); pbvh->material_indices = static_cast( CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, "material_index")); - pbvh->mloop = mloop; + pbvh->corner_verts = corner_verts; pbvh->looptri = looptri; pbvh->vert_positions = vert_positions; /* Make sure cached normals start out calculated. */ @@ -884,7 +885,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, BB_reset((BB *)bbc); for (int j = 0; j < sides; j++) { - BB_expand((BB *)bbc, vert_positions[pbvh->mloop[lt->tri[j]].v]); + BB_expand((BB *)bbc, vert_positions[pbvh->corner_verts[lt->tri[j]]]); } BBC_update_centroid(bbc); @@ -955,7 +956,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh, pbvh->pdata = &me->pdata; pbvh->polys = me->polys().data(); - pbvh->mloop = me->loops().data(); + pbvh->corner_verts = me->corner_verts().data(); /* We also need the base mesh for PBVH draw. */ pbvh->mesh = me; @@ -1417,10 +1418,10 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, for (int i = 0; i < totface; i++) { const MLoopTri *lt = &pbvh->looptri[faces[i]]; - const uint vtri[3] = { - pbvh->mloop[lt->tri[0]].v, - pbvh->mloop[lt->tri[1]].v, - pbvh->mloop[lt->tri[2]].v, + const int vtri[3] = { + pbvh->corner_verts[lt->tri[0]], + pbvh->corner_verts[lt->tri[1]], + pbvh->corner_verts[lt->tri[2]], }; const int sides = 3; @@ -1429,7 +1430,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, const MPoly &poly = pbvh->polys[lt->poly]; fn = blender::bke::mesh::poly_normal_calc( {reinterpret_cast(pbvh->vert_positions), pbvh->totvert}, - {&pbvh->mloop[poly.loopstart], poly.totloop}); + {&pbvh->corner_verts[poly.loopstart], poly.totloop}); mpoly_prev = lt->poly; } @@ -2206,7 +2207,7 @@ void BKE_pbvh_vert_tag_update_normal(PBVH *pbvh, PBVHVertRef vertex) void BKE_pbvh_node_get_loops(PBVH *pbvh, PBVHNode *node, const int **r_loop_indices, - const MLoop **r_loops) + const int **r_corner_verts) { BLI_assert(BKE_pbvh_type(pbvh) == PBVH_FACES); @@ -2214,8 +2215,8 @@ void BKE_pbvh_node_get_loops(PBVH *pbvh, *r_loop_indices = node->loop_indices; } - if (r_loops) { - *r_loops = pbvh->mloop; + if (r_corner_verts) { + *r_corner_verts = pbvh->corner_verts; } } @@ -2548,7 +2549,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh, float *r_face_normal) { const float(*positions)[3] = pbvh->vert_positions; - const MLoop *mloop = pbvh->mloop; + const int *corner_verts = pbvh->corner_verts; const int *faces = node->prim_indices; int totface = node->totprim; bool hit = false; @@ -2571,9 +2572,9 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh, } else { /* intersect with current coordinates */ - co[0] = positions[mloop[lt->tri[0]].v]; - co[1] = positions[mloop[lt->tri[1]].v]; - co[2] = positions[mloop[lt->tri[2]].v]; + co[0] = positions[corner_verts[lt->tri[0]]]; + co[1] = positions[corner_verts[lt->tri[1]]]; + co[2] = positions[corner_verts[lt->tri[2]]]; } if (ray_face_intersection_tri(ray_start, isect_precalc, co[0], co[1], co[2], depth)) { @@ -2593,7 +2594,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh, if (j == 0 || len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) { copy_v3_v3(nearest_vertex_co, co[j]); - r_active_vertex->i = mloop[lt->tri[j]].v; + r_active_vertex->i = corner_verts[lt->tri[j]]; *r_active_face_index = lt->poly; } } @@ -2858,7 +2859,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh, float *dist_sq) { const float(*positions)[3] = pbvh->vert_positions; - const MLoop *mloop = pbvh->mloop; + const int *corner_verts = pbvh->corner_verts; const int *faces = node->prim_indices; int i, totface = node->totprim; bool hit = false; @@ -2885,9 +2886,9 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh, /* intersect with current coordinates */ hit |= ray_face_nearest_tri(ray_start, ray_normal, - positions[mloop[lt->tri[0]].v], - positions[mloop[lt->tri[1]].v], - positions[mloop[lt->tri[2]].v], + positions[corner_verts[lt->tri[0]]], + positions[corner_verts[lt->tri[1]]], + positions[corner_verts[lt->tri[2]]], depth, dist_sq); } @@ -3740,16 +3741,16 @@ static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step) pbvh_face_iter_verts_reserve(fd, poly.totloop); - const MLoop *ml = fd->mloop_ + poly.loopstart; + const int *poly_verts = &fd->corner_verts_[poly.loopstart]; const int grid_area = fd->subdiv_key_.grid_area; - for (int i = 0; i < poly.totloop; i++, ml++) { + for (int i = 0; i < poly.totloop; i++) { if (fd->pbvh_type_ == PBVH_GRIDS) { /* Grid corners. */ fd->verts[i].i = (poly.loopstart + i) * grid_area + grid_area - 1; } else { - fd->verts[i].i = ml->v; + fd->verts[i].i = poly_verts[i]; } } break; @@ -3778,7 +3779,7 @@ void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd) ATTR_FALLTHROUGH; case PBVH_FACES: fd->polys_ = pbvh->polys; - fd->mloop_ = pbvh->mloop; + fd->corner_verts_ = pbvh->corner_verts; fd->looptri_ = pbvh->looptri; fd->hide_poly_ = pbvh->hide_poly; fd->face_sets_ = pbvh->face_sets; diff --git a/source/blender/blenkernel/intern/pbvh_colors.cc b/source/blender/blenkernel/intern/pbvh_colors.cc index 73a32dea777..507d3ed9315 100644 --- a/source/blender/blenkernel/intern/pbvh_colors.cc +++ b/source/blender/blenkernel/intern/pbvh_colors.cc @@ -97,12 +97,12 @@ static void pbvh_vertex_color_get(const PBVH &pbvh, PBVHVertRef vertex, float r_ const MPoly &poly = pbvh.polys[i_poly]; Span colors{static_cast(pbvh.color_layer->data) + poly.loopstart, poly.totloop}; - Span loops{pbvh.mloop + poly.loopstart, poly.totloop}; + Span poly_verts{pbvh.corner_verts + poly.loopstart, poly.totloop}; - for (const int i_loop : IndexRange(poly.totloop)) { - if (loops[i_loop].v == index) { + for (const int i : poly_verts.index_range()) { + if (poly_verts[i] == index) { float temp[4]; - to_float(colors[i_loop], temp); + to_float(colors[i], temp); add_v4_v4(r_color, temp); count++; @@ -131,11 +131,11 @@ static void pbvh_vertex_color_set(PBVH &pbvh, PBVHVertRef vertex, const float co const MPoly &poly = pbvh.polys[i_poly]; MutableSpan colors{static_cast(pbvh.color_layer->data) + poly.loopstart, poly.totloop}; - Span loops{pbvh.mloop + poly.loopstart, poly.totloop}; + Span poly_verts{pbvh.corner_verts + poly.loopstart, poly.totloop}; - for (const int i_loop : IndexRange(poly.totloop)) { - if (loops[i_loop].v == index) { - from_float(color, colors[i_loop]); + for (const int i : poly_verts.index_range()) { + if (poly_verts[i] == index) { + from_float(color, colors[i]); } } } diff --git a/source/blender/blenkernel/intern/pbvh_intern.hh b/source/blender/blenkernel/intern/pbvh_intern.hh index cf051e20540..0936c333c48 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.hh +++ b/source/blender/blenkernel/intern/pbvh_intern.hh @@ -7,7 +7,6 @@ */ struct PBVHGPUFormat; -struct MLoop; struct MLoopTri; struct MPoly; struct MeshElemMap; @@ -71,7 +70,7 @@ struct PBVHNode { const int *vert_indices; unsigned int uniq_verts, face_verts; - /* Array of indices into the Mesh's MLoop array. + /* Array of indices into the Mesh's corner array. * PBVH_FACES only. */ int *loop_indices; @@ -161,7 +160,7 @@ struct PBVH { bool *hide_poly; /** Material indices. Only valid for polygon meshes. */ const int *material_indices; - const MLoop *mloop; + const int *corner_verts; const MLoopTri *looptri; CustomData *vdata; CustomData *ldata; diff --git a/source/blender/blenkernel/intern/pbvh_pixels.cc b/source/blender/blenkernel/intern/pbvh_pixels.cc index 0a3f485610f..4aaa4d96a87 100644 --- a/source/blender/blenkernel/intern/pbvh_pixels.cc +++ b/source/blender/blenkernel/intern/pbvh_pixels.cc @@ -409,9 +409,9 @@ static void update_geom_primitives(PBVH &pbvh, const uv_islands::MeshData &mesh_ PBVHData &pbvh_data = BKE_pbvh_pixels_data_get(pbvh); pbvh_data.clear_data(); for (const MLoopTri &looptri : mesh_data.looptris) { - pbvh_data.geom_primitives.append(int3(mesh_data.loops[looptri.tri[0]].v, - mesh_data.loops[looptri.tri[1]].v, - mesh_data.loops[looptri.tri[2]].v)); + pbvh_data.geom_primitives.append(int3(mesh_data.corner_verts[looptri.tri[0]], + mesh_data.corner_verts[looptri.tri[1]], + mesh_data.corner_verts[looptri.tri[2]])); } } @@ -672,7 +672,7 @@ static bool update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image uv_islands::MeshData mesh_data( {pbvh->looptri, pbvh->totprim}, - {pbvh->mloop, mesh->totloop}, + {pbvh->corner_verts, mesh->totloop}, uv_map, {static_cast(static_cast(pbvh->vert_positions)), pbvh->totvert}); uv_islands::UVIslands islands(mesh_data); diff --git a/source/blender/blenkernel/intern/pbvh_pixels_copy.cc b/source/blender/blenkernel/intern/pbvh_pixels_copy.cc index b09a192ec8b..214b74f060a 100644 --- a/source/blender/blenkernel/intern/pbvh_pixels_copy.cc +++ b/source/blender/blenkernel/intern/pbvh_pixels_copy.cc @@ -157,9 +157,9 @@ class NonManifoldUVEdges : public Vector> { int vertex_i) { for (int i = 0; i < 3; i++) { - int loop_i = loop_tri.tri[i]; - const MLoop &loop = mesh_data.loops[loop_i]; - if (loop.v == vertex_i) { + const int loop_i = loop_tri.tri[i]; + const int vert = mesh_data.corner_verts[loop_i]; + if (vert == vertex_i) { return mesh_data.uv_map[loop_i]; } } diff --git a/source/blender/blenkernel/intern/pbvh_uv_islands.cc b/source/blender/blenkernel/intern/pbvh_uv_islands.cc index 511f4cf27d5..649cf39803b 100644 --- a/source/blender/blenkernel/intern/pbvh_uv_islands.cc +++ b/source/blender/blenkernel/intern/pbvh_uv_islands.cc @@ -38,17 +38,17 @@ static int primitive_get_other_uv_vertex(const MeshData &mesh_data, const int v1, const int v2) { - const Span mesh_loops = mesh_data.loops; + const Span corner_verts = mesh_data.corner_verts; BLI_assert(ELEM(v1, - mesh_loops[looptri.tri[0]].v, - mesh_loops[looptri.tri[1]].v, - mesh_loops[looptri.tri[2]].v)); + corner_verts[looptri.tri[0]], + corner_verts[looptri.tri[1]], + corner_verts[looptri.tri[2]])); BLI_assert(ELEM(v2, - mesh_loops[looptri.tri[0]].v, - mesh_loops[looptri.tri[1]].v, - mesh_loops[looptri.tri[2]].v)); + corner_verts[looptri.tri[0]], + corner_verts[looptri.tri[1]], + corner_verts[looptri.tri[2]])); for (const int loop : looptri.tri) { - const int vert = mesh_loops[loop].v; + const int vert = corner_verts[loop]; if (!ELEM(vert, v1, v2)) { return vert; } @@ -74,7 +74,7 @@ static bool primitive_has_shared_uv_edge(const Span uv_map, static int get_uv_loop(const MeshData &mesh_data, const MLoopTri &looptri, const int vert) { for (const int loop : looptri.tri) { - if (mesh_data.loops[loop].v == vert) { + if (mesh_data.corner_verts[loop] == vert) { return loop; } } @@ -106,8 +106,8 @@ static void mesh_data_init_edges(MeshData &mesh_data) const MLoopTri &tri = mesh_data.looptris[i]; Vector edges; for (int j = 0; j < 3; j++) { - int v1 = mesh_data.loops[tri.tri[j]].v; - int v2 = mesh_data.loops[tri.tri[(j + 1) % 3]].v; + int v1 = mesh_data.corner_verts[tri.tri[j]]; + int v2 = mesh_data.corner_verts[tri.tri[(j + 1) % 3]]; void **edge_index_ptr; int64_t edge_index; @@ -199,11 +199,11 @@ static void mesh_data_init(MeshData &mesh_data) } MeshData::MeshData(const Span looptris, - const Span loops, + const Span corner_verts, const Span uv_map, const Span vert_positions) : looptris(looptris), - loops(loops), + corner_verts(corner_verts), uv_map(uv_map), vert_positions(vert_positions), vert_to_edge_map(vert_positions.size()), @@ -231,7 +231,7 @@ UVVertex::UVVertex() } UVVertex::UVVertex(const MeshData &mesh_data, const int loop) - : vertex(mesh_data.loops[loop].v), uv(mesh_data.uv_map[loop]) + : vertex(mesh_data.corner_verts[loop]), uv(mesh_data.uv_map[loop]) { uv_vertex_init_flags(*this); } @@ -520,18 +520,18 @@ struct FanSegment { flags.found = false; /* Reorder so the first edge starts with the given vertex. */ - if (mesh_data.loops[primitive->tri[1]].v == vertex) { + if (mesh_data.corner_verts[primitive->tri[1]] == vertex) { vert_order[0] = 1; vert_order[1] = 2; vert_order[2] = 0; } - else if (mesh_data.loops[primitive->tri[2]].v == vertex) { + else if (mesh_data.corner_verts[primitive->tri[2]] == vertex) { vert_order[0] = 2; vert_order[1] = 0; vert_order[2] = 1; } else { - BLI_assert(mesh_data.loops[primitive->tri[0]].v == vertex); + BLI_assert(mesh_data.corner_verts[primitive->tri[0]] == vertex); vert_order[0] = 0; vert_order[1] = 1; vert_order[2] = 2; @@ -542,9 +542,9 @@ struct FanSegment { { std::stringstream ss; ss << "# p:" << primitive->poly; - ss << " v1:" << mesh_data.loops[primitive->tri[vert_order[0]]].v; - ss << " v2:" << mesh_data.loops[primitive->tri[vert_order[1]]].v; - ss << " v3:" << mesh_data.loops[primitive->tri[vert_order[2]]].v; + ss << " v1:" << mesh_data.corner_verts[primitive->tri[vert_order[0]]]; + ss << " v2:" << mesh_data.corner_verts[primitive->tri[vert_order[1]]]; + ss << " v3:" << mesh_data.corner_verts[primitive->tri[vert_order[2]]]; ss << " uv1:" << uvs[0]; ss << " uv2:" << uvs[1]; ss << " uv3:" << uvs[2]; @@ -633,9 +633,9 @@ struct Fan { void init_uv_coordinates(const MeshData &mesh_data, UVVertex &uv_vertex) { for (FanSegment &fan_edge : segments) { - int other_v = mesh_data.loops[fan_edge.primitive->tri[fan_edge.vert_order[0]]].v; + int other_v = mesh_data.corner_verts[fan_edge.primitive->tri[fan_edge.vert_order[0]]]; if (other_v == uv_vertex.vertex) { - other_v = mesh_data.loops[fan_edge.primitive->tri[fan_edge.vert_order[1]]].v; + other_v = mesh_data.corner_verts[fan_edge.primitive->tri[fan_edge.vert_order[1]]]; } for (UVEdge *edge : uv_vertex.uv_edges) { @@ -663,7 +663,7 @@ struct Fan { bool contains_vertex_on_outside(const MeshData &mesh_data, const int vertex_index) const { for (const FanSegment &segment : segments) { - int v2 = mesh_data.loops[segment.primitive->tri[segment.vert_order[1]]].v; + int v2 = mesh_data.corner_verts[segment.primitive->tri[segment.vert_order[1]]]; if (vertex_index == v2) { return true; } @@ -680,8 +680,8 @@ struct Fan { { int current_vert = from_vertex; for (FanSegment *segment : path) { - int v1 = mesh_data.loops[segment->primitive->tri[segment->vert_order[1]]].v; - int v2 = mesh_data.loops[segment->primitive->tri[segment->vert_order[2]]].v; + int v1 = mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[1]]]; + int v2 = mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[2]]]; if (!ELEM(current_vert, v1, v2)) { return false; } @@ -711,7 +711,8 @@ struct Fan { int index = 0; while (true) { FanSegment *segment = edge_order[index]; - int v2 = mesh_data.loops[segment->primitive->tri[segment->vert_order[from_vert_order]]].v; + int v2 = + mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[from_vert_order]]]; if (v2 == from_vertex) { break; } @@ -722,7 +723,7 @@ struct Fan { FanSegment *segment = edge_order[index]; result.append(segment); - int v3 = mesh_data.loops[segment->primitive->tri[segment->vert_order[to_vert_order]]].v; + int v3 = mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[to_vert_order]]]; if (v3 == to_vertex) { break; } @@ -817,12 +818,12 @@ static void add_uv_primitive_shared_uv_edge(const MeshData &mesh_data, const int loop_1 = get_uv_loop(mesh_data, looptri, connected_vert_1->vertex); vert_template.uv = connected_vert_1->uv; - vert_template.vertex = mesh_data.loops[loop_1].v; + vert_template.vertex = mesh_data.corner_verts[loop_1]; UVVertex *vert_1_ptr = island.lookup_or_create(vert_template); const int loop_2 = get_uv_loop(mesh_data, looptri, connected_vert_2->vertex); vert_template.uv = connected_vert_2->uv; - vert_template.vertex = mesh_data.loops[loop_2].v; + vert_template.vertex = mesh_data.corner_verts[loop_2]; UVVertex *vert_2_ptr = island.lookup_or_create(vert_template); UVEdge edge_template; @@ -1337,7 +1338,7 @@ const UVVertex *UVPrimitive::get_uv_vertex(const MeshData &mesh_data, const uint8_t mesh_vert_index) const { const MLoopTri &looptri = mesh_data.looptris[this->primitive_i]; - const int mesh_vertex = mesh_data.loops[looptri.tri[mesh_vert_index]].v; + const int mesh_vertex = mesh_data.corner_verts[looptri.tri[mesh_vert_index]]; for (const UVEdge *uv_edge : edges) { for (const UVVertex *uv_vert : uv_edge->vertices) { if (uv_vert->vertex == mesh_vertex) { diff --git a/source/blender/blenkernel/intern/pbvh_uv_islands.hh b/source/blender/blenkernel/intern/pbvh_uv_islands.hh index f38a7c79ea5..4ae3fe34993 100644 --- a/source/blender/blenkernel/intern/pbvh_uv_islands.hh +++ b/source/blender/blenkernel/intern/pbvh_uv_islands.hh @@ -119,7 +119,7 @@ class TriangleToEdgeMap { struct MeshData { public: const Span looptris; - const Span loops; + const Span corner_verts; const Span uv_map; const Span vert_positions; @@ -140,7 +140,7 @@ struct MeshData { public: explicit MeshData(Span looptris, - Span loops, + Span corner_verts, const Span uv_map, const Span vert_positions); }; diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 3499839e03d..f0d3b09feed 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -406,7 +406,7 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) totvert = mesh->totvert; looptri = BKE_mesh_runtime_looptri_ensure(mesh); tottri = BKE_mesh_runtime_looptri_len(mesh); - const MLoop *mloop = BKE_mesh_loops(mesh); + const int *corner_verts = BKE_mesh_corner_verts(mesh); /* sanity checking - potential case when no data will be present */ if ((totvert == 0) || (tottri == 0)) { @@ -431,9 +431,9 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) const MLoopTri *lt = &looptri[i]; int vtri[3]; - vtri[0] = mloop[lt->tri[0]].v; - vtri[1] = mloop[lt->tri[1]].v; - vtri[2] = mloop[lt->tri[2]].v; + vtri[0] = corner_verts[lt->tri[0]]; + vtri[1] = corner_verts[lt->tri[1]]; + vtri[2] = corner_verts[lt->tri[2]]; RB_trimesh_add_triangle_indices(mdata, i, UNPACK3(vtri)); } @@ -681,10 +681,10 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) totvert = mesh->totvert; lt = BKE_mesh_runtime_looptri_ensure(mesh); tottri = BKE_mesh_runtime_looptri_len(mesh); - const MLoop *mloop = BKE_mesh_loops(mesh); + const int *corner_verts = BKE_mesh_corner_verts(mesh); if (totvert > 0 && tottri > 0) { - BKE_mesh_calc_volume(positions, totvert, lt, tottri, mloop, &volume, NULL); + BKE_mesh_calc_volume(positions, totvert, lt, tottri, corner_verts, &volume, NULL); const float volume_scale = mat4_to_volume_scale(ob->object_to_world); volume *= fabsf(volume_scale); } @@ -755,10 +755,10 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3]) totvert = mesh->totvert; looptri = BKE_mesh_runtime_looptri_ensure(mesh); tottri = BKE_mesh_runtime_looptri_len(mesh); - const MLoop *mloop = BKE_mesh_loops(mesh); if (totvert > 0 && tottri > 0) { - BKE_mesh_calc_volume(positions, totvert, looptri, tottri, mloop, NULL, r_center); + BKE_mesh_calc_volume( + positions, totvert, looptri, tottri, BKE_mesh_corner_verts(mesh), NULL, r_center); } } break; diff --git a/source/blender/blenkernel/intern/shrinkwrap.cc b/source/blender/blenkernel/intern/shrinkwrap.cc index 2b3122f8865..a7a59e8aa8c 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.cc +++ b/source/blender/blenkernel/intern/shrinkwrap.cc @@ -115,6 +115,7 @@ bool BKE_shrinkwrap_init_tree( data->mesh = mesh; data->polys = mesh->polys().data(); + data->corner_edges = mesh->corner_edges().data(); data->vert_normals = reinterpret_cast(mesh->vert_normals().data()), data->sharp_faces = static_cast( CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_face")); @@ -190,16 +191,18 @@ static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata, static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh) { + using namespace blender; const float(*positions)[3] = BKE_mesh_vert_positions(mesh); const blender::Span edges = mesh->edges(); - const blender::Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); + const Span corner_edges = mesh->corner_edges(); /* Count faces per edge (up to 2). */ char *edge_mode = static_cast( MEM_calloc_arrayN(size_t(mesh->totedge), sizeof(char), __func__)); for (int i = 0; i < mesh->totloop; i++) { - uint eidx = loops[i].e; + const int eidx = corner_edges[i]; if (edge_mode[eidx] < 2) { edge_mode[eidx]++; @@ -240,7 +243,8 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh) for (const int64_t i : looptris.index_range()) { int real_edges[3]; - BKE_mesh_looptri_get_real_edges(edges.data(), loops.data(), &looptris[i], real_edges); + BKE_mesh_looptri_get_real_edges( + edges.data(), corner_verts.data(), corner_edges.data(), &looptris[i], real_edges); for (int j = 0; j < 3; j++) { if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) { @@ -1012,11 +1016,12 @@ static void mesh_looptri_target_project(void *userdata, const ShrinkwrapTreeData *tree = (ShrinkwrapTreeData *)userdata; const BVHTreeFromMesh *data = &tree->treeData; const MLoopTri *lt = &data->looptri[index]; - const MLoop *loop[3] = { - &data->loop[lt->tri[0]], &data->loop[lt->tri[1]], &data->loop[lt->tri[2]]}; - const float *vtri_co[3] = {data->vert_positions[loop[0]->v], - data->vert_positions[loop[1]->v], - data->vert_positions[loop[2]->v]}; + const int tri_verts[3] = {data->corner_verts[lt->tri[0]], + data->corner_verts[lt->tri[1]], + data->corner_verts[lt->tri[2]]}; + const float *vtri_co[3] = {data->vert_positions[tri_verts[0]], + data->vert_positions[tri_verts[1]], + data->vert_positions[tri_verts[2]]}; float raw_hit_co[3], hit_co[3], hit_no[3], dist_sq, vtri_no[3][3]; /* First find the closest point and bail out if it's worse than the current solution. */ @@ -1038,9 +1043,9 @@ static void mesh_looptri_target_project(void *userdata, } /* Decode normals */ - copy_v3_v3(vtri_no[0], tree->vert_normals[loop[0]->v]); - copy_v3_v3(vtri_no[1], tree->vert_normals[loop[1]->v]); - copy_v3_v3(vtri_no[2], tree->vert_normals[loop[2]->v]); + copy_v3_v3(vtri_no[0], tree->vert_normals[tri_verts[0]]); + copy_v3_v3(vtri_no[1], tree->vert_normals[tri_verts[1]]); + copy_v3_v3(vtri_no[2], tree->vert_normals[tri_verts[2]]); /* Solve the equations for the triangle */ if (target_project_solve_point_tri(vtri_co, vtri_no, co, raw_hit_co, dist_sq, hit_co, hit_no)) { @@ -1051,7 +1056,7 @@ static void mesh_looptri_target_project(void *userdata, const BLI_bitmap *is_boundary = tree->boundary->edge_is_boundary; int edges[3]; - BKE_mesh_looptri_get_real_edges(data->edge, data->loop, lt, edges); + BKE_mesh_looptri_get_real_edges(data->edge, data->corner_verts, tree->corner_edges, lt, edges); for (int i = 0; i < 3; i++) { if (edges[i] >= 0 && BLI_BITMAP_TEST(is_boundary, edges[i])) { @@ -1178,9 +1183,9 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree, /* Interpolate smooth normals if enabled. */ if (!(tree->sharp_faces && tree->sharp_faces[tri->poly])) { - const uint32_t vert_indices[3] = {treeData->loop[tri->tri[0]].v, - treeData->loop[tri->tri[1]].v, - treeData->loop[tri->tri[2]].v}; + const int vert_indices[3] = {treeData->corner_verts[tri->tri[0]], + treeData->corner_verts[tri->tri[1]], + treeData->corner_verts[tri->tri[2]]}; float w[3], no[3][3], tmp_co[3]; /* Custom and auto smooth split normals. */ @@ -1530,7 +1535,6 @@ void BKE_shrinkwrap_mesh_nearest_surface_deform(bContext *C, Object *ob_source, Scene *sce = CTX_data_scene(C); ShrinkwrapModifierData ssmd = {{nullptr}}; ModifierEvalContext ctx = {depsgraph, ob_source, ModifierApplyFlag(0)}; - int totvert; ssmd.target = ob_target; ssmd.shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE; @@ -1538,13 +1542,17 @@ void BKE_shrinkwrap_mesh_nearest_surface_deform(bContext *C, Object *ob_source, ssmd.keepDist = 0.0f; Mesh *src_me = static_cast(ob_source->data); - float(*vertexCos)[3] = BKE_mesh_vert_coords_alloc(src_me, &totvert); - shrinkwrapModifier_deform(&ssmd, &ctx, sce, ob_source, src_me, nullptr, -1, vertexCos, totvert); - - BKE_mesh_vert_coords_apply(src_me, vertexCos); - - MEM_freeN(vertexCos); + shrinkwrapModifier_deform(&ssmd, + &ctx, + sce, + ob_source, + src_me, + nullptr, + -1, + BKE_mesh_vert_positions_for_write(src_me), + src_me->totvert); + BKE_mesh_tag_positions_changed(src_me); } void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 92beefcbc2d..b563a2a3675 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -588,7 +588,7 @@ static void add_mesh_quad_diag_springs(Object *ob) nofquads = count_mesh_quads(me); if (nofquads) { - const MLoop *mloop = BKE_mesh_loops(me); + const int *corner_verts = BKE_mesh_corner_verts(me); const MPoly *polys = BKE_mesh_polys(me); BodySpring *bs; @@ -602,12 +602,12 @@ static void add_mesh_quad_diag_springs(Object *ob) for (int a = 0; a < me->totpoly; a++) { const MPoly *poly = &polys[a]; if (poly->totloop == 4) { - bs->v1 = mloop[poly->loopstart + 0].v; - bs->v2 = mloop[poly->loopstart + 2].v; + bs->v1 = corner_verts[poly->loopstart + 0]; + bs->v2 = corner_verts[poly->loopstart + 2]; bs->springtype = SB_STIFFQUAD; bs++; - bs->v1 = mloop[poly->loopstart + 1].v; - bs->v2 = mloop[poly->loopstart + 3].v; + bs->v1 = corner_verts[poly->loopstart + 1]; + bs->v2 = corner_verts[poly->loopstart + 3]; bs->springtype = SB_STIFFQUAD; bs++; } @@ -2753,22 +2753,22 @@ static void mesh_faces_to_scratch(Object *ob) int a; const float(*vert_positions)[3] = BKE_mesh_vert_positions(me); const MPoly *polys = BKE_mesh_polys(me); - const MLoop *loops = BKE_mesh_loops(me); + const int *corner_verts = BKE_mesh_corner_verts(me); /* Allocate and copy faces. */ sb->scratch->totface = poly_to_tri_count(me->totpoly, me->totloop); looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__); BKE_mesh_recalc_looptri( - loops, polys, vert_positions, me->totvert, me->totloop, me->totpoly, looptri); + corner_verts, polys, vert_positions, me->totvert, me->totloop, me->totpoly, looptri); bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface, "SB_body_Faces"); for (a = 0; a < sb->scratch->totface; a++, lt++, bodyface++) { - bodyface->v1 = loops[lt->tri[0]].v; - bodyface->v2 = loops[lt->tri[1]].v; - bodyface->v3 = loops[lt->tri[2]].v; + bodyface->v1 = corner_verts[lt->tri[0]]; + bodyface->v2 = corner_verts[lt->tri[1]]; + bodyface->v3 = corner_verts[lt->tri[2]]; zero_v3(bodyface->ext_force); bodyface->ext_force[0] = bodyface->ext_force[1] = bodyface->ext_force[2] = 0.0f; bodyface->flag = 0; diff --git a/source/blender/blenkernel/intern/subdiv_ccg.cc b/source/blender/blenkernel/intern/subdiv_ccg.cc index a1b779d07e6..d1e2d841c8a 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.cc +++ b/source/blender/blenkernel/intern/subdiv_ccg.cc @@ -1986,7 +1986,7 @@ const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg) static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, - const MLoop *mloop, + const int *corner_verts, const MPoly *polys, int *r_v1, int *r_v2) @@ -1994,22 +1994,22 @@ static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_cc const int grid_size_1 = subdiv_ccg->grid_size - 1; const int poly_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord->grid_index); const MPoly &poly = polys[poly_index]; - *r_v1 = mloop[coord->grid_index].v; + *r_v1 = corner_verts[coord->grid_index]; - const int corner = poly_find_loop_from_vert(&poly, &mloop[poly.loopstart], *r_v1); + const int corner = poly_find_loop_from_vert(&poly, &corner_verts[poly.loopstart], *r_v1); if (coord->x == grid_size_1) { - const MLoop *next = ME_POLY_LOOP_NEXT(mloop, &poly, corner); - *r_v2 = next->v; + const int next = ME_POLY_LOOP_NEXT(&poly, corner); + *r_v2 = corner_verts[next]; } if (coord->y == grid_size_1) { - const MLoop *prev = ME_POLY_LOOP_PREV(mloop, &poly, corner); - *r_v2 = prev->v; + const int prev = ME_POLY_LOOP_PREV(&poly, corner); + *r_v2 = corner_verts[prev]; } } SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord, - const MLoop *mloop, + const int *corner_verts, const MPoly *polys, int *r_v1, int *r_v2) @@ -2023,18 +2023,19 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const Subdi } if (coord->x == grid_size_1 && coord->y == grid_size_1) { /* Grid corner adjacent to a coarse mesh vertex. */ - *r_v1 = *r_v2 = mloop[coord->grid_index].v; + *r_v1 = *r_v2 = corner_verts[coord->grid_index]; return SUBDIV_CCG_ADJACENT_VERTEX; } /* Grid corner adjacent to the middle of a coarse mesh edge. */ - adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, mloop, polys, r_v1, r_v2); + adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2); return SUBDIV_CCG_ADJACENT_EDGE; } if (is_boundary_grid_coord(subdiv_ccg, coord)) { if (!is_inner_edge_grid_coordinate(subdiv_ccg, coord)) { /* Grid boundary adjacent to a coarse mesh edge. */ - adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, mloop, polys, r_v1, r_v2); + adjacet_vertices_index_from_adjacent_edge( + subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2); return SUBDIV_CCG_ADJACENT_EDGE; } } diff --git a/source/blender/blenkernel/intern/subdiv_converter_mesh.cc b/source/blender/blenkernel/intern/subdiv_converter_mesh.cc index b28fe42b1c5..a36f7cf021b 100644 --- a/source/blender/blenkernel/intern/subdiv_converter_mesh.cc +++ b/source/blender/blenkernel/intern/subdiv_converter_mesh.cc @@ -37,7 +37,8 @@ struct ConverterStorage { const float (*vert_positions)[3]; blender::Span edges; blender::Span polys; - blender::Span loops; + blender::Span corner_verts; + blender::Span corner_edges; /* CustomData layer for vertex sharpnesses. */ const float *cd_vertex_crease; @@ -135,10 +136,9 @@ static void get_face_vertices(const OpenSubdiv_Converter *converter, { ConverterStorage *storage = static_cast(converter->user_data); const MPoly &poly = storage->polys[manifold_face_index]; - const blender::Span loops = storage->loops; - for (int corner = 0; corner < poly.totloop; corner++) { - manifold_face_vertices[corner] = - storage->manifold_vertex_index[loops[poly.loopstart + corner].v]; + for (int i = 0; i < poly.totloop; i++) { + const int vert = storage->corner_verts[poly.loopstart + i]; + manifold_face_vertices[i] = storage->manifold_vertex_index[vert]; } } @@ -216,7 +216,7 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la storage->polys.data(), (const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"), (const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".select_poly"), - storage->loops.data(), + storage->corner_verts.data(), mloopuv, num_poly, num_vert, @@ -355,17 +355,18 @@ static void initialize_manifold_indices(ConverterStorage *storage) { const Mesh *mesh = storage->mesh; const blender::Span edges = storage->edges; - const blender::Span loops = storage->loops; const blender::Span polys = storage->polys; + const blender::Span corner_verts = storage->corner_verts; + const blender::Span corner_edges = storage->corner_edges; /* Set bits of elements which are not loose. */ BLI_bitmap *vert_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map"); BLI_bitmap *edge_used_map = BLI_BITMAP_NEW(mesh->totedge, "edge used map"); for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) { const MPoly &poly = polys[poly_index]; - for (int corner = 0; corner < poly.totloop; corner++) { - const MLoop *loop = &loops[poly.loopstart + corner]; - BLI_BITMAP_ENABLE(vert_used_map, loop->v); - BLI_BITMAP_ENABLE(edge_used_map, loop->e); + for (int i = 0; i < poly.totloop; i++) { + const int corner = poly.loopstart + i; + BLI_BITMAP_ENABLE(vert_used_map, corner_verts[corner]); + BLI_BITMAP_ENABLE(edge_used_map, corner_edges[corner]); } } initialize_manifold_index_array(vert_used_map, @@ -403,7 +404,8 @@ static void init_user_data(OpenSubdiv_Converter *converter, user_data->vert_positions = BKE_mesh_vert_positions(mesh); user_data->edges = mesh->edges(); user_data->polys = mesh->polys(); - user_data->loops = mesh->loops(); + user_data->corner_verts = mesh->corner_verts(); + user_data->corner_edges = mesh->corner_edges(); user_data->cd_vertex_crease = static_cast( CustomData_get_layer(&mesh->vdata, CD_CREASE)); user_data->cd_edge_crease = static_cast( diff --git a/source/blender/blenkernel/intern/subdiv_eval.cc b/source/blender/blenkernel/intern/subdiv_eval.cc index 8dac6807872..3387b23bd22 100644 --- a/source/blender/blenkernel/intern/subdiv_eval.cc +++ b/source/blender/blenkernel/intern/subdiv_eval.cc @@ -83,7 +83,7 @@ static void set_coarse_positions(Subdiv *subdiv, { const float(*positions)[3] = BKE_mesh_vert_positions(mesh); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); /* Mark vertices which needs new coordinates. */ /* TODO(sergey): This is annoying to calculate this on every update, * maybe it's better to cache this mapping. Or make it possible to have @@ -91,9 +91,8 @@ static void set_coarse_positions(Subdiv *subdiv, BLI_bitmap *vertex_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map"); for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) { const MPoly &poly = polys[poly_index]; - for (int corner = 0; corner < poly.totloop; corner++) { - const MLoop *loop = &loops[poly.loopstart + corner]; - BLI_BITMAP_ENABLE(vertex_used_map, loop->v); + for (int i = 0; i < poly.totloop; i++) { + BLI_BITMAP_ENABLE(vertex_used_map, corner_verts[poly.loopstart + i]); } } /* Use a temporary buffer so we do not upload vertices one at a time to the GPU. */ diff --git a/source/blender/blenkernel/intern/subdiv_foreach.cc b/source/blender/blenkernel/intern/subdiv_foreach.cc index 8231f0e7ca0..bc73b4fa061 100644 --- a/source/blender/blenkernel/intern/subdiv_foreach.cc +++ b/source/blender/blenkernel/intern/subdiv_foreach.cc @@ -69,7 +69,8 @@ struct SubdivForeachTaskContext { const Mesh *coarse_mesh; blender::Span coarse_edges; blender::Span coarse_polys; - blender::Span coarse_loops; + blender::Span coarse_corner_verts; + blender::Span coarse_corner_edges; const SubdivToMeshSettings *settings; /* Callbacks. */ const SubdivForeachContext *foreach_context; @@ -290,12 +291,12 @@ static void subdiv_foreach_corner_vertices_regular_do( const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index]; for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner]; + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; if (check_usage && - BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_loop->v)) { + BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_vert)) { continue; } - const int coarse_vertex_index = coarse_loop->v; + const int coarse_vertex_index = coarse_vert; const int subdiv_vertex_index = ctx->vertices_corner_offset + coarse_vertex_index; const float u = weights[corner][0]; const float v = weights[corner][1]; @@ -329,12 +330,12 @@ static void subdiv_foreach_corner_vertices_special_do( const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index]; for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) { - const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner]; + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; if (check_usage && - BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_loop->v)) { + BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_vert)) { continue; } - const int coarse_vertex_index = coarse_loop->v; + const int coarse_vertex_index = coarse_vert; const int subdiv_vertex_index = ctx->vertices_corner_offset + coarse_vertex_index; vertex_corner(ctx->foreach_context, tls, @@ -416,14 +417,14 @@ static void subdiv_foreach_edge_vertices_regular_do(SubdivForeachTaskContext *ct const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data(); const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index]; for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner]; - const int coarse_edge_index = coarse_loop->e; + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; + const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; if (check_usage && BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) { continue; } const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index]; - const bool flip = (coarse_edge->v2 == coarse_loop->v); + const bool flip = (coarse_edge->v2 == coarse_vert); int subdiv_vertex_index = ctx->vertices_edge_offset + coarse_edge_index * num_subdiv_vertices_per_coarse_edge; for (int vertex_index = 0; vertex_index < num_subdiv_vertices_per_coarse_edge; @@ -479,14 +480,14 @@ static void subdiv_foreach_edge_vertices_special_do(SubdivForeachTaskContext *ct const int ptex_face_start_index = ctx->face_ptex_offset[coarse_poly_index]; int ptex_face_index = ptex_face_start_index; for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) { - const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner]; - const int coarse_edge_index = coarse_loop->e; + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; + const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; if (check_usage && BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) { continue; } const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index]; - const bool flip = (coarse_edge->v2 == coarse_loop->v); + const bool flip = (coarse_edge->v2 == coarse_vert); int subdiv_vertex_index = ctx->vertices_edge_offset + coarse_edge_index * num_subdiv_vertices_per_coarse_edge; int vertex_delta = 1; @@ -778,11 +779,12 @@ static void subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext *c } /* Connect inner part of patch to boundary. */ for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner]; - const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e]; + const int coarse_vert_index = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; + const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; + const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index]; const int start_edge_vertex = ctx->vertices_edge_offset + - coarse_loop->e * num_subdiv_vertices_per_coarse_edge; - const bool flip = (coarse_edge->v2 == coarse_loop->v); + coarse_edge_index * num_subdiv_vertices_per_coarse_edge; + const bool flip = (coarse_edge->v2 == coarse_vert_index); int side_start_index = start_vertex_index; int side_stride = 0; /* Calculate starting vertex of corresponding inner part of ptex. */ @@ -886,15 +888,16 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c } } /* Connect inner path of patch to boundary. */ - const MLoop *prev_coarse_loop = - &ctx->coarse_loops[coarse_poly->loopstart + coarse_poly->totloop - 1]; + int prev_corner = coarse_poly->totloop - 1; for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner]; + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; + const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; + const int coarse_prev_edge = ctx->coarse_corner_edges[coarse_poly->loopstart + prev_corner]; { - const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e]; + const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_i]; const int start_edge_vertex = ctx->vertices_edge_offset + - coarse_loop->e * num_subdiv_vertices_per_coarse_edge; - const bool flip = (coarse_edge->v2 == coarse_loop->v); + coarse_edge_i * num_subdiv_vertices_per_coarse_edge; + const bool flip = (coarse_edge->v2 == coarse_vert); int side_start_index; if (ptex_face_resolution >= 3) { side_start_index = start_vertex_index + num_inner_vertices_per_ptex * corner; @@ -911,10 +914,10 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c } } if (ptex_face_resolution >= 3) { - const MEdge *coarse_edge = &ctx->coarse_edges[prev_coarse_loop->e]; + const MEdge *coarse_edge = &ctx->coarse_edges[coarse_prev_edge]; const int start_edge_vertex = ctx->vertices_edge_offset + - prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge; - const bool flip = (coarse_edge->v2 == coarse_loop->v); + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge; + const bool flip = (coarse_edge->v2 == coarse_vert); int side_start_index = start_vertex_index + num_inner_vertices_per_ptex * corner; for (int i = 0; i < ptex_face_resolution - 2; i++, subdiv_edge_index++) { const int v1 = (flip) ? (start_edge_vertex + (resolution - i - 3)) : @@ -924,7 +927,7 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, false, v1, v2); } } - prev_coarse_loop = coarse_loop; + prev_corner = corner; } } @@ -1134,30 +1137,35 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx, } } /* Loops for faces connecting inner ptex part with boundary. */ - const MLoop *prev_coarse_loop = - &ctx->coarse_loops[coarse_poly->loopstart + coarse_poly->totloop - 1]; + int prev_corner_index = coarse_poly->totloop - 1; for (int corner = 0; corner < coarse_poly->totloop; corner++) { - const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner]; - const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e]; - const MEdge *prev_coarse_edge = &ctx->coarse_edges[prev_coarse_loop->e]; + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; + const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; + const int coase_prev_vert = + ctx->coarse_corner_verts[coarse_poly->loopstart + prev_corner_index]; + const int coarse_prev_edge = + ctx->coarse_corner_edges[coarse_poly->loopstart + prev_corner_index]; + + const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_i]; + const MEdge *prev_coarse_edge = &ctx->coarse_edges[coarse_prev_edge]; const int start_edge_vertex = ctx->vertices_edge_offset + - coarse_loop->e * num_subdiv_vertices_per_coarse_edge; - const bool flip = (coarse_edge->v2 == coarse_loop->v); + coarse_edge_i * num_subdiv_vertices_per_coarse_edge; + const bool flip = (coarse_edge->v2 == coarse_vert); int side_start_index = start_vertex_index; int side_stride = 0; - int v0 = ctx->vertices_corner_offset + coarse_loop->v; + int v0 = ctx->vertices_corner_offset + coarse_vert; int v3, e3; int e2_offset, e2_stride; float u, v, delta_u, delta_v; - if (prev_coarse_loop->v == prev_coarse_edge->v1) { - v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge + + if (coase_prev_vert == prev_coarse_edge->v1) { + v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge + num_subdiv_vertices_per_coarse_edge - 1; - e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge + + e3 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge + num_subdiv_edges_per_coarse_edge - 1; } else { - v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge; - e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge; + v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge; + e3 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge; } /* Calculate starting vertex of corresponding inner part of ptex. */ if (corner == 0) { @@ -1214,11 +1222,11 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx, const int v2 = side_start_index + side_stride * i; int e0; if (flip) { - e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge + + e0 = ctx->edge_boundary_offset + coarse_edge_i * num_subdiv_edges_per_coarse_edge + num_subdiv_edges_per_coarse_edge - i - 1; } else { - e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge + i; + e0 = ctx->edge_boundary_offset + coarse_edge_i * num_subdiv_edges_per_coarse_edge + i; } int e1 = start_edge_index + num_edges_per_ptex_face_get(resolution - 2) + corner * num_subdiv_vertices_per_coarse_edge + i; @@ -1259,7 +1267,7 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx, v3 = v2; e3 = e1; } - prev_coarse_loop = coarse_loop; + prev_corner_index = corner; } } @@ -1436,30 +1444,32 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, } } /* Loops for faces connecting inner ptex part with boundary. */ - const MLoop *prev_coarse_loop = - &ctx->coarse_loops[coarse_poly->loopstart + coarse_poly->totloop - 1]; for (int prev_corner = coarse_poly->totloop - 1, corner = 0; corner < coarse_poly->totloop; prev_corner = corner, corner++) { - const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner]; - const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e]; - const MEdge *prev_coarse_edge = &ctx->coarse_edges[prev_coarse_loop->e]; - const bool flip = (coarse_edge->v2 == coarse_loop->v); + const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner]; + const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly->loopstart + corner]; + const int coase_prev_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + prev_corner]; + const int coarse_prev_edge = ctx->coarse_corner_edges[coarse_poly->loopstart + prev_corner]; + + const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_i]; + const MEdge *prev_coarse_edge = &ctx->coarse_edges[coarse_prev_edge]; + const bool flip = (coarse_edge->v2 == coarse_vert); const int start_edge_vertex = ctx->vertices_edge_offset + - coarse_loop->e * num_subdiv_vertices_per_coarse_edge; + coarse_edge_i * num_subdiv_vertices_per_coarse_edge; const int corner_vertex_index = start_vertex_index + corner * num_inner_vertices_per_ptex; const int corner_edge_index = start_edge_index + corner * num_inner_edges_per_ptex_face; /* Create loops for polygons along U axis. */ - int v0 = ctx->vertices_corner_offset + coarse_loop->v; + int v0 = ctx->vertices_corner_offset + coarse_vert; int v3, e3; - if (prev_coarse_loop->v == prev_coarse_edge->v1) { - v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge + + if (coase_prev_vert == prev_coarse_edge->v1) { + v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge + num_subdiv_vertices_per_coarse_edge - 1; - e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge + + e3 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge + num_subdiv_edges_per_coarse_edge - 1; } else { - v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge; - e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge; + v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge; + e3 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge; } for (int i = 0; i <= ptex_face_inner_resolution; i++, subdiv_loop_index += 4) { int v1; @@ -1478,11 +1488,11 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, } int e0; if (flip) { - e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge + + e0 = ctx->edge_boundary_offset + coarse_edge_i * num_subdiv_edges_per_coarse_edge + num_subdiv_edges_per_coarse_edge - i - 1; } else { - e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge + i; + e0 = ctx->edge_boundary_offset + coarse_edge_i * num_subdiv_edges_per_coarse_edge + i; } int e1 = start_edge_index + corner * (2 * ptex_face_inner_resolution + 1); if (ptex_face_resolution >= 3) { @@ -1529,14 +1539,14 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, e3 = e1; } /* Create loops for polygons along V axis. */ - const bool flip_prev = (prev_coarse_edge->v2 == coarse_loop->v); + const bool flip_prev = (prev_coarse_edge->v2 == coarse_vert); v0 = corner_vertex_index; - if (prev_coarse_loop->v == prev_coarse_edge->v1) { - v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge + + if (coase_prev_vert == prev_coarse_edge->v1) { + v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge + num_subdiv_vertices_per_coarse_edge - 1; } else { - v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge; + v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge; } e3 = start_edge_index + coarse_poly->totloop * (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) + @@ -1563,12 +1573,12 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, int v2 = flip_prev ? v3 - 1 : v3 + 1; int e2; if (flip_prev) { - e2 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge + + e2 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge + num_subdiv_edges_per_coarse_edge - 2 - i; } else { - e2 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge + - 1 + i; + e2 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge + 1 + + i; } const float u = 0.0f; const float v = du * (i + 1); @@ -1595,7 +1605,6 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx, v3 = v2; e3 = e1; } - prev_coarse_loop = coarse_loop; } } @@ -1724,9 +1733,10 @@ static void subdiv_foreach_mark_non_loose_geometry(SubdivForeachTaskContext *ctx for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) { const MPoly &coarse_poly = ctx->coarse_polys[poly_index]; for (int corner = 0; corner < coarse_poly.totloop; corner++) { - const MLoop *loop = &ctx->coarse_loops[coarse_poly.loopstart + corner]; - BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, loop->e); - BLI_BITMAP_ENABLE(ctx->coarse_vertices_used_map, loop->v); + BLI_BITMAP_ENABLE(ctx->coarse_vertices_used_map, + ctx->coarse_corner_verts[coarse_poly.loopstart + corner]); + BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, + ctx->coarse_corner_verts[coarse_poly.loopstart + corner]); } } } @@ -1797,7 +1807,8 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv, ctx.coarse_mesh = coarse_mesh; ctx.coarse_edges = coarse_mesh->edges(); ctx.coarse_polys = coarse_mesh->polys(); - ctx.coarse_loops = coarse_mesh->loops(); + ctx.coarse_corner_verts = coarse_mesh->corner_verts(); + ctx.coarse_corner_edges = coarse_mesh->corner_edges(); ctx.settings = mesh_settings; ctx.foreach_context = context; subdiv_foreach_ctx_init(subdiv, &ctx); diff --git a/source/blender/blenkernel/intern/subdiv_mesh.cc b/source/blender/blenkernel/intern/subdiv_mesh.cc index 5db8b815b33..4945a9180dc 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.cc +++ b/source/blender/blenkernel/intern/subdiv_mesh.cc @@ -32,6 +32,7 @@ using blender::float2; using blender::float3; +using blender::MutableSpan; using blender::Span; /* -------------------------------------------------------------------- */ @@ -44,14 +45,15 @@ struct SubdivMeshContext { const float (*coarse_positions)[3]; blender::Span coarse_edges; blender::Span coarse_polys; - blender::Span coarse_loops; + blender::Span coarse_corner_verts; Subdiv *subdiv; Mesh *subdiv_mesh; blender::MutableSpan subdiv_positions; blender::MutableSpan subdiv_edges; blender::MutableSpan subdiv_polys; - blender::MutableSpan subdiv_loops; + blender::MutableSpan subdiv_corner_verts; + blender::MutableSpan subdiv_corner_edges; /* Cached custom data arrays for faster access. */ int *vert_origindex; @@ -95,7 +97,8 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx) ctx->subdiv_positions = subdiv_mesh->vert_positions_for_write(); ctx->subdiv_edges = subdiv_mesh->edges_for_write(); ctx->subdiv_polys = subdiv_mesh->polys_for_write(); - ctx->subdiv_loops = subdiv_mesh->loops_for_write(); + ctx->subdiv_corner_verts = subdiv_mesh->corner_verts_for_write(); + ctx->subdiv_corner_edges = subdiv_mesh->corner_edges_for_write(); /* Pointers to original indices layers. */ ctx->vert_origindex = static_cast( CustomData_get_layer_for_write(&subdiv_mesh->vdata, CD_ORIGINDEX, subdiv_mesh->totvert)); @@ -138,16 +141,15 @@ static void subdiv_mesh_context_free(SubdivMeshContext *ctx) struct LoopsOfPtex { /* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */ - const MLoop *first_loop; + int first_loop; /* Last loop of the ptex, starts at ptex (0, 0) and goes in v direction. */ - const MLoop *last_loop; + int last_loop; /* For quad coarse faces only. */ - const MLoop *second_loop; - const MLoop *third_loop; + int second_loop; + int third_loop; }; -static void loops_of_ptex_get(const SubdivMeshContext *ctx, - LoopsOfPtex *loops_of_ptex, +static void loops_of_ptex_get(LoopsOfPtex *loops_of_ptex, const MPoly *coarse_poly, const int ptex_of_poly_index) { @@ -159,15 +161,15 @@ static void loops_of_ptex_get(const SubdivMeshContext *ctx, const int last_ptex_loop_index = coarse_poly->loopstart + (ptex_of_poly_index + coarse_poly->totloop - 1) % coarse_poly->totloop; - loops_of_ptex->first_loop = &ctx->coarse_loops[first_ptex_loop_index]; - loops_of_ptex->last_loop = &ctx->coarse_loops[last_ptex_loop_index]; + loops_of_ptex->first_loop = first_ptex_loop_index; + loops_of_ptex->last_loop = last_ptex_loop_index; if (coarse_poly->totloop == 4) { loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1; loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2; } else { - loops_of_ptex->second_loop = nullptr; - loops_of_ptex->third_loop = nullptr; + loops_of_ptex->second_loop = -1; + loops_of_ptex->third_loop = -1; } } @@ -206,13 +208,12 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx, const MPoly &coarse_poly) { const Mesh *coarse_mesh = ctx->coarse_mesh; - const blender::Span coarse_loops = ctx->coarse_loops; if (coarse_poly.totloop == 4) { vertex_interpolation->vertex_data = &coarse_mesh->vdata; - vertex_interpolation->vertex_indices[0] = coarse_loops[coarse_poly.loopstart + 0].v; - vertex_interpolation->vertex_indices[1] = coarse_loops[coarse_poly.loopstart + 1].v; - vertex_interpolation->vertex_indices[2] = coarse_loops[coarse_poly.loopstart + 2].v; - vertex_interpolation->vertex_indices[3] = coarse_loops[coarse_poly.loopstart + 3].v; + vertex_interpolation->vertex_indices[0] = ctx->coarse_corner_verts[coarse_poly.loopstart + 0]; + vertex_interpolation->vertex_indices[1] = ctx->coarse_corner_verts[coarse_poly.loopstart + 1]; + vertex_interpolation->vertex_indices[2] = ctx->coarse_corner_verts[coarse_poly.loopstart + 2]; + vertex_interpolation->vertex_indices[3] = ctx->coarse_corner_verts[coarse_poly.loopstart + 3]; vertex_interpolation->vertex_data_storage_allocated = false; } else { @@ -236,7 +237,7 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx, blender::Array indices(coarse_poly.totloop); for (int i = 0; i < coarse_poly.totloop; i++) { weights[i] = weight; - indices[i] = coarse_loops[coarse_poly.loopstart + i].v; + indices[i] = ctx->coarse_corner_verts[coarse_poly.loopstart + i]; } CustomData_interp(&coarse_mesh->vdata, &vertex_interpolation->vertex_data_storage, @@ -258,13 +259,12 @@ static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx, } else { const CustomData *vertex_data = &ctx->coarse_mesh->vdata; - const blender::Span coarse_loops = ctx->coarse_loops; LoopsOfPtex loops_of_ptex; - loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner); + loops_of_ptex_get(&loops_of_ptex, coarse_poly, corner); /* Ptex face corner corresponds to a poly loop with same index. */ CustomData_copy_data(vertex_data, &vertex_interpolation->vertex_data_storage, - coarse_loops[coarse_poly->loopstart + corner].v, + ctx->coarse_corner_verts[coarse_poly->loopstart + corner], 0, 1); /* Interpolate remaining ptex face corners, which hits loops @@ -273,17 +273,15 @@ static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx, * TODO(sergey): Re-use one of interpolation results from previous * iteration. */ const float weights[2] = {0.5f, 0.5f}; - const int first_loop_index = loops_of_ptex.first_loop - coarse_loops.data(); - const int last_loop_index = loops_of_ptex.last_loop - coarse_loops.data(); + const int first_loop_index = loops_of_ptex.first_loop; + const int last_loop_index = loops_of_ptex.last_loop; const int first_indices[2] = { - int(coarse_loops[first_loop_index].v), - int(coarse_loops[coarse_poly->loopstart + - (first_loop_index - coarse_poly->loopstart + 1) % coarse_poly->totloop] - .v)}; - const int last_indices[2] = { - int(coarse_loops[first_loop_index].v), - int(coarse_loops[last_loop_index].v), - }; + ctx->coarse_corner_verts[first_loop_index], + ctx->coarse_corner_verts[coarse_poly->loopstart + + (first_loop_index - coarse_poly->loopstart + 1) % + coarse_poly->totloop]}; + const int last_indices[2] = {ctx->coarse_corner_verts[first_loop_index], + ctx->coarse_corner_verts[last_loop_index]}; CustomData_interp(vertex_data, &vertex_interpolation->vertex_data_storage, first_indices, @@ -391,9 +389,8 @@ static void loop_interpolation_from_corner(const SubdivMeshContext *ctx, } else { const CustomData *loop_data = &ctx->coarse_mesh->ldata; - const blender::Span coarse_loops = ctx->coarse_loops; LoopsOfPtex loops_of_ptex; - loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner); + loops_of_ptex_get(&loops_of_ptex, coarse_poly, corner); /* Ptex face corner corresponds to a poly loop with same index. */ CustomData_free_elem(&loop_interpolation->loop_data_storage, 0, 1); CustomData_copy_data( @@ -405,14 +402,11 @@ static void loop_interpolation_from_corner(const SubdivMeshContext *ctx, * iteration. */ const float weights[2] = {0.5f, 0.5f}; const int base_loop_index = coarse_poly->loopstart; - const int first_loop_index = loops_of_ptex.first_loop - coarse_loops.data(); + const int first_loop_index = loops_of_ptex.first_loop; const int second_loop_index = base_loop_index + (first_loop_index - base_loop_index + 1) % coarse_poly->totloop; const int first_indices[2] = {first_loop_index, second_loop_index}; - const int last_indices[2] = { - int(loops_of_ptex.last_loop - coarse_loops.data()), - int(loops_of_ptex.first_loop - coarse_loops.data()), - }; + const int last_indices[2] = {loops_of_ptex.last_loop, loops_of_ptex.first_loop}; CustomData_interp( loop_data, &loop_interpolation->loop_data_storage, first_indices, weights, nullptr, 2, 1); CustomData_interp( @@ -828,12 +822,11 @@ static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context, * \{ */ static void subdiv_interpolate_loop_data(const SubdivMeshContext *ctx, - MLoop *subdiv_loop, + const int subdiv_loop_index, const LoopsForInterpolation *loop_interpolation, const float u, const float v) { - const int subdiv_loop_index = subdiv_loop - ctx->subdiv_loops.data(); const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), u * v, (1.0f - u) * v}; CustomData_interp(loop_interpolation->loop_data, &ctx->subdiv_mesh->ldata, @@ -846,7 +839,7 @@ static void subdiv_interpolate_loop_data(const SubdivMeshContext *ctx, } static void subdiv_eval_uv_layer(SubdivMeshContext *ctx, - MLoop *subdiv_loop, + const int corner_index, const int ptex_face_index, const float u, const float v) @@ -855,10 +848,9 @@ static void subdiv_eval_uv_layer(SubdivMeshContext *ctx, return; } Subdiv *subdiv = ctx->subdiv; - const int mloop_index = subdiv_loop - ctx->subdiv_loops.data(); for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) { BKE_subdiv_eval_face_varying( - subdiv, layer_index, ptex_face_index, u, v, ctx->uv_layers[layer_index][mloop_index]); + subdiv, layer_index, ptex_face_index, u, v, ctx->uv_layers[layer_index][corner_index]); } } @@ -905,12 +897,11 @@ static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context, SubdivMeshContext *ctx = static_cast(foreach_context->user_data); SubdivMeshTLS *tls = static_cast(tls_v); const MPoly &coarse_poly = ctx->coarse_polys[coarse_poly_index]; - MLoop *subdiv_loop = &ctx->subdiv_loops[subdiv_loop_index]; subdiv_mesh_ensure_loop_interpolation(ctx, tls, &coarse_poly, coarse_corner); - subdiv_interpolate_loop_data(ctx, subdiv_loop, &tls->loop_interpolation, u, v); - subdiv_eval_uv_layer(ctx, subdiv_loop, ptex_face_index, u, v); - subdiv_loop->v = subdiv_vertex_index; - subdiv_loop->e = subdiv_edge_index; + subdiv_interpolate_loop_data(ctx, subdiv_loop_index, &tls->loop_interpolation, u, v); + subdiv_eval_uv_layer(ctx, subdiv_loop_index, ptex_face_index, u, v); + ctx->subdiv_corner_verts[subdiv_loop_index] = subdiv_vertex_index; + ctx->subdiv_corner_edges[subdiv_loop_index] = subdiv_edge_index; } /** \} */ @@ -1182,7 +1173,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv, subdiv_context.coarse_positions = BKE_mesh_vert_positions(coarse_mesh); subdiv_context.coarse_edges = coarse_mesh->edges(); subdiv_context.coarse_polys = coarse_mesh->polys(); - subdiv_context.coarse_loops = coarse_mesh->loops(); + subdiv_context.coarse_corner_verts = coarse_mesh->corner_verts(); subdiv_context.subdiv = subdiv; subdiv_context.have_displacement = (subdiv->displacement_evaluator != nullptr); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.cc b/source/blender/blenkernel/intern/subsurf_ccg.cc index 3bdf8a27136..43066341ae0 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.cc +++ b/source/blender/blenkernel/intern/subsurf_ccg.cc @@ -228,13 +228,13 @@ static int getFaceIndex( } static void get_face_uv_map_vert( - UvVertMap *vmap, const MPoly *polys, MLoop *ml, int fi, CCGVertHDL *fverts) + UvVertMap *vmap, const MPoly *polys, const int *poly_verts, int fi, CCGVertHDL *fverts) { UvMapVert *v, *nv; int j, nverts = polys[fi].totloop; for (j = 0; j < nverts; j++) { - for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, ml[j].v); v; v = v->next) { + for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, poly_verts[j]); v; v = v->next) { if (v->separate) { nv = v; } @@ -253,7 +253,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, const float (*mloopuv)[2]) { MPoly *polys = dm->getPolyArray(dm); - MLoop *mloop = dm->getLoopArray(dm); + int *corner_verts = dm->getCornerVertArray(dm); int totvert = dm->getNumVerts(dm); int totface = dm->getNumPolys(dm); int i, seam; @@ -270,7 +270,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, * Also, initially intention is to treat merged vertices from mirror modifier as seams. * This fixes a very old regression (2.49 was correct here) */ vmap = BKE_mesh_uv_vert_map_create( - polys, nullptr, nullptr, mloop, mloopuv, totface, totvert, limit, false, true); + polys, nullptr, nullptr, corner_verts, mloopuv, totface, totvert, limit, false, true); if (!vmap) { return 0; } @@ -312,12 +312,11 @@ static int ss_sync_from_uv(CCGSubSurf *ss, int nverts = poly.totloop; int j, j_next; CCGFace *origf = ccgSubSurf_getFace(origss, POINTER_FROM_INT(i)); - // uint *fv = &poly.v1; - MLoop *ml = mloop + poly.loopstart; + /* uint *fv = &poly.v1; */ fverts.reinitialize(nverts); - get_face_uv_map_vert(vmap, polys, ml, i, fverts.data()); + get_face_uv_map_vert(vmap, &poly, &corner_verts[poly.loopstart], i, fverts.data()); for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) { uint v0 = POINTER_AS_UINT(fverts[j_next]); @@ -338,13 +337,12 @@ static int ss_sync_from_uv(CCGSubSurf *ss, /* create faces */ for (i = 0; i < totface; i++) { const MPoly &poly = polys[i]; - MLoop *ml = &mloop[poly.loopstart]; int nverts = poly.totloop; CCGFace *f; fverts.reinitialize(nverts); - get_face_uv_map_vert(vmap, polys, ml, i, fverts.data()); + get_face_uv_map_vert(vmap, polys, &corner_verts[poly.loopstart], i, fverts.data()); ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), nverts, fverts.data(), &f); } @@ -539,7 +537,7 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss, float(*positions)[3] = (float(*)[3])dm->getVertArray(dm); MEdge *edges = dm->getEdgeArray(dm); MEdge *edge; - MLoop *mloop = dm->getLoopArray(dm), *ml; + int *corner_verts = dm->getCornerVertArray(dm); MPoly *polys = dm->getPolyArray(dm); int totvert = dm->getNumVerts(dm); int totedge = dm->getNumEdges(dm); @@ -588,9 +586,9 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss, fverts.reinitialize(poly.totloop); - ml = mloop + poly.loopstart; - for (j = 0; j < poly.totloop; j++, ml++) { - fverts[j] = POINTER_FROM_UINT(ml->v); + int corner = poly.loopstart; + for (j = 0; j < poly.totloop; j++, corner++) { + fverts[j] = POINTER_FROM_UINT(corner_verts[corner]); } /* This is very bad, means mesh is internally inconsistent. @@ -965,7 +963,8 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *edges) struct CopyFinalLoopArrayData { CCGDerivedMesh *ccgdm; - MLoop *mloop; + int *corner_verts; + int *corner_edges; int grid_size; int *grid_offset; int edge_size; @@ -984,38 +983,39 @@ static void copyFinalLoopArray_task_cb(void *__restrict userdata, CCGFace *f = ccgdm->faceMap[iter].face; const int num_verts = ccgSubSurf_getFaceNumVerts(f); const int grid_index = data->grid_offset[iter]; - const size_t loop_index = 4 * size_t(grid_index) * (grid_size - 1) * (grid_size - 1); - MLoop *ml = &data->mloop[loop_index]; + int *corner_verts = data->corner_verts; + int *corner_edges = data->corner_edges; + + size_t loop_i = 4 * size_t(grid_index) * (grid_size - 1) * (grid_size - 1); for (int S = 0; S < num_verts; S++) { for (int y = 0; y < grid_size - 1; y++) { for (int x = 0; x < grid_size - 1; x++) { - uint v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edge_size, grid_size); - uint v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edge_size, grid_size); - uint v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edge_size, grid_size); - uint v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edge_size, grid_size); + const int v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edge_size, grid_size); + const int v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edge_size, grid_size); + const int v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edge_size, grid_size); + const int v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edge_size, grid_size); - ml->v = v1; - ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v1, v2)); - ml++; + if (corner_verts) { + corner_verts[loop_i + 0] = v1; + corner_verts[loop_i + 1] = v2; + corner_verts[loop_i + 2] = v3; + corner_verts[loop_i + 3] = v4; + } + if (corner_edges) { + corner_edges[loop_i + 0] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v1, v2)); + corner_edges[loop_i + 1] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v2, v3)); + corner_edges[loop_i + 2] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v3, v4)); + corner_edges[loop_i + 3] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v4, v1)); + } - ml->v = v2; - ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v2, v3)); - ml++; - - ml->v = v3; - ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v3, v4)); - ml++; - - ml->v = v4; - ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v4, v1)); - ml++; + loop_i += 4; } } } } -static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop) +static void ccgDM_copyFinalCornerVertArray(DerivedMesh *dm, int *r_corner_verts) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; CCGSubSurf *ss = ccgdm->ss; @@ -1040,7 +1040,53 @@ static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop) CopyFinalLoopArrayData data; data.ccgdm = ccgdm; - data.mloop = mloop; + data.corner_verts = r_corner_verts; + data.corner_edges = NULL; + data.grid_size = ccgSubSurf_getGridSize(ss); + data.grid_offset = dm->getGridOffset(dm); + data.edge_size = ccgSubSurf_getEdgeSize(ss); + + /* NOTE: For a dense subdivision we've got enough work for each face and + * hence can dedicate whole thread to single face. For less dense + * subdivision we handle multiple faces per thread. + */ + data.mloop_index = data.grid_size >= 5 ? 1 : 8; + + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.min_iter_per_thread = 1; + + BLI_task_parallel_range( + 0, ccgSubSurf_getNumFaces(ss), &data, copyFinalLoopArray_task_cb, &settings); +} + +static void ccgDM_copyFinalCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges) +{ + CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; + CCGSubSurf *ss = ccgdm->ss; + + if (!ccgdm->ehash) { + BLI_mutex_lock(&ccgdm->loops_cache_lock); + if (!ccgdm->ehash) { + MEdge *medge; + EdgeHash *ehash; + + ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData); + medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm); + + for (int i = 0; i < ccgdm->dm.numEdgeData; i++) { + BLI_edgehash_insert(ehash, medge[i].v1, medge[i].v2, POINTER_FROM_INT(i)); + } + + atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash); + } + BLI_mutex_unlock(&ccgdm->loops_cache_lock); + } + + CopyFinalLoopArrayData data; + data.ccgdm = ccgdm; + data.corner_verts = NULL; + data.corner_edges = r_corner_edges; data.grid_size = ccgSubSurf_getGridSize(ss); data.grid_offset = dm->getGridOffset(dm); data.edge_size = ccgSubSurf_getEdgeSize(ss); @@ -1446,7 +1492,8 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm) ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray; ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray; - ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray; + ccgdm->dm.copyCornerVertArray = ccgDM_copyFinalCornerVertArray; + ccgdm->dm.copyCornerEdgeArray = ccgDM_copyFinalCornerEdgeArray; ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray; ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer; diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 3cae7e580a2..530a9a9e683 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -1313,6 +1313,19 @@ const VolumeGrid *BKE_volume_grid_find_for_read(const Volume *volume, const char return nullptr; } +VolumeGrid *BKE_volume_grid_find_for_write(Volume *volume, const char *name) +{ + int num_grids = BKE_volume_num_grids(volume); + for (int i = 0; i < num_grids; i++) { + VolumeGrid *grid = BKE_volume_grid_get_for_write(volume, i); + if (STREQ(BKE_volume_grid_name(grid), name)) { + return grid; + } + } + + return nullptr; +} + /* Grid Loading */ bool BKE_volume_grid_load(const Volume *volume, const VolumeGrid *grid) diff --git a/source/blender/blenkernel/intern/volume_to_mesh.cc b/source/blender/blenkernel/intern/volume_to_mesh.cc index 9c64277525c..69d8bb0f12f 100644 --- a/source/blender/blenkernel/intern/volume_to_mesh.cc +++ b/source/blender/blenkernel/intern/volume_to_mesh.cc @@ -115,7 +115,7 @@ void fill_mesh_from_openvdb_data(const Span vdb_verts, const int loop_offset, MutableSpan vert_positions, MutableSpan polys, - MutableSpan loops) + MutableSpan corner_verts) { /* Write vertices. */ vert_positions.slice(vert_offset, vdb_verts.size()).copy_from(vdb_verts.cast()); @@ -126,7 +126,7 @@ void fill_mesh_from_openvdb_data(const Span vdb_verts, polys[poly_offset + i].totloop = 3; for (int j = 0; j < 3; j++) { /* Reverse vertex order to get correct normals. */ - loops[loop_offset + 3 * i + j].v = vert_offset + vdb_tris[i][2 - j]; + corner_verts[loop_offset + 3 * i + j] = vert_offset + vdb_tris[i][2 - j]; } } @@ -138,7 +138,7 @@ void fill_mesh_from_openvdb_data(const Span vdb_verts, polys[quad_offset + i].totloop = 4; for (int j = 0; j < 4; j++) { /* Reverse vertex order to get correct normals. */ - loops[quad_loop_offset + 4 * i + j].v = vert_offset + vdb_quads[i][3 - j]; + corner_verts[quad_loop_offset + 4 * i + j] = vert_offset + vdb_quads[i][3 - j]; } } } @@ -177,7 +177,7 @@ Mesh *volume_to_mesh(const openvdb::GridBase &grid, 0, mesh->vert_positions_for_write(), mesh->polys_for_write(), - mesh->loops_for_write()); + mesh->corner_verts_for_write()); BKE_mesh_calc_edges(mesh, false, false); BKE_mesh_smooth_flag_set(mesh, false); diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh index 81ffa7eade8..46d104ab59c 100644 --- a/source/blender/blenlib/BLI_array_utils.hh +++ b/source/blender/blenlib/BLI_array_utils.hh @@ -10,6 +10,24 @@ namespace blender::array_utils { +/** + * Fill the destination span by copying all values from the `src` array. Threaded based on + * grain-size. + */ +void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size = 4096); + +/** + * Fill the destination span by copying all values from the `src` array. Threaded based on + * grain-size. + */ +template +inline void copy(const Span src, MutableSpan dst, const int64_t grain_size = 4096) +{ + BLI_assert(src.size() == dst.size()); + threading::parallel_for(src.index_range(), grain_size, [&](const IndexRange range) { + dst.slice(range).copy_from(src.slice(range)); + }); +} /** * Fill the destination span by copying masked values from the `src` array. Threaded based on * grain-size. diff --git a/source/blender/blenlib/BLI_math_basis_types.hh b/source/blender/blenlib/BLI_math_basis_types.hh index 94732c0266f..640dac5d777 100644 --- a/source/blender/blenlib/BLI_math_basis_types.hh +++ b/source/blender/blenlib/BLI_math_basis_types.hh @@ -420,7 +420,7 @@ struct CartesianBasis { }; /** - * Create an CartesianBasis for converting from \a a orientation to \a b orientation. + * Create an CartesianBasis using two orthogonal axes. * The third axis is chosen by right hand rule to follow blender coordinate system. * \a forward is Y axis in blender coordinate system. * \a up is Z axis in blender coordinate system. diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh index 6f119a49f01..a13e3df7877 100644 --- a/source/blender/blenlib/BLI_memory_utils.hh +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -156,7 +156,29 @@ template class AlignedBuffer { */ template class TypedBuffer { private: - BLI_NO_UNIQUE_ADDRESS AlignedBuffer buffer_; + /** Required so that `sizeof(T)` is not required when `Size` is 0. */ + static constexpr size_t get_size() + { + if constexpr (Size == 0) { + return 0; + } + else { + return sizeof(T) * size_t(Size); + } + } + + /** Required so that `alignof(T)` is not required when `Size` is 0. */ + static constexpr size_t get_alignment() + { + if constexpr (Size == 0) { + return 1; + } + else { + return alignof(T); + } + } + + BLI_NO_UNIQUE_ADDRESS AlignedBuffer buffer_; public: operator T *() diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh index 6f9a158c1d8..02795689f72 100644 --- a/source/blender/blenlib/BLI_vector.hh +++ b/source/blender/blenlib/BLI_vector.hh @@ -108,6 +108,17 @@ class Vector { template friend class Vector; + /** Required in case `T` is an incomplete type. */ + static constexpr bool is_nothrow_move_constructible() + { + if constexpr (InlineBufferCapacity == 0) { + return true; + } + else { + return std::is_nothrow_move_constructible_v; + } + } + public: /** * Create an empty vector. @@ -234,7 +245,7 @@ class Vector { */ template Vector(Vector &&other) noexcept( - std::is_nothrow_move_constructible_v) + is_nothrow_move_constructible()) : Vector(NoExceptConstructor(), other.allocator_) { const int64_t size = other.size(); diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc index 1e1ef354461..4abf9ce5e34 100644 --- a/source/blender/blenlib/intern/array_utils.cc +++ b/source/blender/blenlib/intern/array_utils.cc @@ -4,6 +4,15 @@ namespace blender::array_utils { +void copy(const GVArray &src, GMutableSpan dst, const int64_t grain_size) +{ + BLI_assert(src.type() == dst.type()); + BLI_assert(src.size() == dst.size()); + threading::parallel_for(src.index_range(), grain_size, [&](const IndexRange range) { + src.materialize_to_uninitialized(range, dst.data()); + }); +} + void copy(const GVArray &src, const IndexMask selection, GMutableSpan dst, diff --git a/source/blender/blenlib/tests/BLI_math_rotation_types_test.cc b/source/blender/blenlib/tests/BLI_math_rotation_types_test.cc index 26171c6855a..e6a0576c7dd 100644 --- a/source/blender/blenlib/tests/BLI_math_rotation_types_test.cc +++ b/source/blender/blenlib/tests/BLI_math_rotation_types_test.cc @@ -63,18 +63,12 @@ TEST(math_rotation_types, Euler3Order) /* Asserts those match. * Do not do it in the header to avoid including the DNA header everywhere. */ - BLI_STATIC_ASSERT( - static_cast(EulerOrder::XYZ) == static_cast(eRotationModes::ROT_MODE_XYZ), ""); - BLI_STATIC_ASSERT( - static_cast(EulerOrder::XZY) == static_cast(eRotationModes::ROT_MODE_XZY), ""); - BLI_STATIC_ASSERT( - static_cast(EulerOrder::YXZ) == static_cast(eRotationModes::ROT_MODE_YXZ), ""); - BLI_STATIC_ASSERT( - static_cast(EulerOrder::YZX) == static_cast(eRotationModes::ROT_MODE_YZX), ""); - BLI_STATIC_ASSERT( - static_cast(EulerOrder::ZXY) == static_cast(eRotationModes::ROT_MODE_ZXY), ""); - BLI_STATIC_ASSERT( - static_cast(EulerOrder::ZYX) == static_cast(eRotationModes::ROT_MODE_ZYX), ""); + BLI_STATIC_ASSERT(int(EulerOrder::XYZ) == int(eRotationModes::ROT_MODE_XYZ), ""); + BLI_STATIC_ASSERT(int(EulerOrder::XZY) == int(eRotationModes::ROT_MODE_XZY), ""); + BLI_STATIC_ASSERT(int(EulerOrder::YXZ) == int(eRotationModes::ROT_MODE_YXZ), ""); + BLI_STATIC_ASSERT(int(EulerOrder::YZX) == int(eRotationModes::ROT_MODE_YZX), ""); + BLI_STATIC_ASSERT(int(EulerOrder::ZXY) == int(eRotationModes::ROT_MODE_ZXY), ""); + BLI_STATIC_ASSERT(int(EulerOrder::ZYX) == int(eRotationModes::ROT_MODE_ZYX), ""); EXPECT_EQ(float3(Euler3(0, 1, 2, EulerOrder::XYZ).ijk()), float3(0, 1, 2)); EXPECT_EQ(float3(Euler3(0, 1, 2, EulerOrder::XZY).ijk()), float3(0, 2, 1)); diff --git a/source/blender/blenlib/tests/BLI_vector_test.cc b/source/blender/blenlib/tests/BLI_vector_test.cc index 29bf6c0cfb1..fc8090a2cb1 100644 --- a/source/blender/blenlib/tests/BLI_vector_test.cc +++ b/source/blender/blenlib/tests/BLI_vector_test.cc @@ -859,4 +859,14 @@ TEST(vector, RemoveChunkExceptions) EXPECT_EQ(vec.size(), 7); } +struct RecursiveType { + Vector my_vector; +}; + +TEST(vector, RecursiveStructure) +{ + RecursiveType my_recursive_type; + my_recursive_type.my_vector.append({}); +} + } // namespace blender::tests diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index e28688b6bab..58896d432a8 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -313,27 +313,6 @@ void BLO_read_invalidate_message(BlendHandle *bh, struct Main *bmain, const char #define BLO_GROUP_MAX 32 #define BLO_EMBEDDED_STARTUP_BLEND "" -/** - * Check whether given path ends with a blend file compatible extension - * (`.blend`, `.ble` or `.blend.gz`). - * - * \param str: The path to check. - * \return true is this path ends with a blender file extension. - */ -bool BLO_has_bfile_extension(const char *str); -/** - * Try to explode given path into its 'library components' - * (i.e. a .blend file, id type/group, and data-block itself). - * - * \param path: the full path to explode. - * \param r_dir: the string that'll contain path up to blend file itself ('library' path). - * WARNING! Must be #FILE_MAX_LIBEXTRA long (it also stores group and name strings)! - * \param r_group: the string that'll contain 'group' part of the path, if any. May be NULL. - * \param r_name: the string that'll contain data's name part of the path, if any. May be NULL. - * \return true if path contains a blend file. - */ -bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name); - /* -------------------------------------------------------------------- */ /** \name BLO Blend File Linking API * \{ */ diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index 80d8232156b..74c8442c212 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -1306,76 +1306,6 @@ void blo_filedata_free(FileData *fd) /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Public Utilities - * \{ */ - -bool BLO_has_bfile_extension(const char *str) -{ - const char *ext_test[4] = {".blend", ".ble", ".blend.gz", nullptr}; - return BLI_path_extension_check_array(str, ext_test); -} - -bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name) -{ - /* We might get some data names with slashes, - * so we have to go up in path until we find blend file itself, - * then we know next path item is group, and everything else is data name. */ - char *slash = nullptr, *prev_slash = nullptr, c = '\0'; - - r_dir[0] = '\0'; - if (r_group) { - *r_group = nullptr; - } - if (r_name) { - *r_name = nullptr; - } - - /* if path leads to an existing directory, we can be sure we're not (in) a library */ - if (BLI_is_dir(path)) { - return false; - } - - strcpy(r_dir, path); - - while ((slash = (char *)BLI_path_slash_rfind(r_dir))) { - char tc = *slash; - *slash = '\0'; - if (BLO_has_bfile_extension(r_dir) && BLI_is_file(r_dir)) { - break; - } - if (STREQ(r_dir, BLO_EMBEDDED_STARTUP_BLEND)) { - break; - } - - if (prev_slash) { - *prev_slash = c; - } - prev_slash = slash; - c = tc; - } - - if (!slash) { - return false; - } - - if (slash[1] != '\0') { - BLI_assert(strlen(slash + 1) < BLO_GROUP_MAX); - if (r_group) { - *r_group = slash + 1; - } - } - - if (prev_slash && (prev_slash[1] != '\0')) { - BLI_assert(strlen(prev_slash + 1) < MAX_ID_NAME - 2); - if (r_name) { - *r_name = prev_slash + 1; - } - } - - return true; -} - BlendThumbnail *BLO_thumbnail_from_file(const char *filepath) { FileData *fd; diff --git a/source/blender/blenloader/intern/versioning_290.cc b/source/blender/blenloader/intern/versioning_290.cc index c71becf5606..718bd66f746 100644 --- a/source/blender/blenloader/intern/versioning_290.cc +++ b/source/blender/blenloader/intern/versioning_290.cc @@ -49,6 +49,7 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_mesh.hh" +#include "BKE_mesh_legacy_convert.h" #include "BKE_multires.h" #include "BKE_node.h" @@ -820,6 +821,7 @@ void blo_do_versions_290(FileData *fd, Library * /*lib*/, Main *bmain) for (const int i : polys.index_range()) { if (polys[i].totloop == 2) { bool changed; + BKE_mesh_legacy_convert_loops_to_corners(me); BKE_mesh_validate_arrays( me, BKE_mesh_vert_positions_for_write(me), @@ -828,7 +830,8 @@ void blo_do_versions_290(FileData *fd, Library * /*lib*/, Main *bmain) me->totedge, (MFace *)CustomData_get_layer_for_write(&me->fdata, CD_MFACE, me->totface), me->totface, - me->loops_for_write().data(), + me->corner_verts_for_write().data(), + me->corner_edges_for_write().data(), polys.size(), polys.data(), me->totpoly, diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index b7465e37186..5aab24d4eb5 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -39,6 +39,7 @@ static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh) BKE_mesh_legacy_uv_seam_from_flags(&mesh); BKE_mesh_legacy_convert_verts_to_positions(&mesh); BKE_mesh_legacy_attribute_flags_to_strings(&mesh); + BKE_mesh_legacy_convert_loops_to_corners(&mesh); } static void version_motion_tracking_legacy_camera_object(MovieClip &movieclip) diff --git a/source/blender/blenloader/intern/writefile.cc b/source/blender/blenloader/intern/writefile.cc index 299735ccab0..eb4975bebfe 100644 --- a/source/blender/blenloader/intern/writefile.cc +++ b/source/blender/blenloader/intern/writefile.cc @@ -1141,6 +1141,16 @@ static bool write_file_handle(Main *mainvar, * asap afterward. */ id_lib_extern(id_iter); } + else if (ID_FAKE_USERS(id_iter) > 0) { + /* Even though fake user is not directly editable by the user on linked data, it is a + * common 'work-around' to set it in library files on data-blocks that need to be linked + * but typically do not have an actual real user (e.g. texts, etc.). + * See e.g. #105687 and #103867. + * + * Would be good to find a better solution, but for now consider these as directly linked + * as well. */ + id_lib_extern(id_iter); + } else { id_iter->tag |= LIB_TAG_INDIRECT; id_iter->tag &= ~LIB_TAG_EXTERN; diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index 0b8ad1970b9..2f039000e8b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -118,6 +118,8 @@ bool BM_attribute_stored_in_bmesh_builtin(const StringRef name) { return ELEM(name, "position", + ".corner_vert", + ".corner_edge", ".hide_vert", ".hide_edge", ".hide_poly", @@ -131,19 +133,21 @@ bool BM_attribute_stored_in_bmesh_builtin(const StringRef name) } static BMFace *bm_face_create_from_mpoly(BMesh &bm, - Span loops, + Span poly_verts, + Span poly_edges, Span vtable, Span etable) { - Array verts(loops.size()); - Array edges(loops.size()); + const int size = poly_verts.size(); + Array verts(size); + Array edges(size); - for (const int i : loops.index_range()) { - verts[i] = vtable[loops[i].v]; - edges[i] = etable[loops[i].e]; + for (const int i : IndexRange(size)) { + verts[i] = vtable[poly_verts[i]]; + edges[i] = etable[poly_edges[i]]; } - return BM_face_create(&bm, verts.data(), edges.data(), loops.size(), nullptr, BM_CREATE_SKIP_CD); + return BM_face_create(&bm, verts.data(), edges.data(), size, nullptr, BM_CREATE_SKIP_CD); } struct MeshToBMeshLayerInfo { @@ -484,7 +488,8 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar } const Span polys = me->polys(); - const Span mloop = me->loops(); + const Span corner_verts = me->corner_verts(); + const Span corner_edges = me->corner_edges(); /* Only needed for selection. */ @@ -495,8 +500,11 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar int totloops = 0; for (const int i : polys.index_range()) { - BMFace *f = bm_face_create_from_mpoly( - *bm, mloop.slice(polys[i].loopstart, polys[i].totloop), vtable, etable); + BMFace *f = bm_face_create_from_mpoly(*bm, + corner_verts.slice(polys[i].loopstart, polys[i].totloop), + corner_edges.slice(polys[i].loopstart, polys[i].totloop), + vtable, + etable); if (!ftable.is_empty()) { ftable[i] = f; } @@ -950,6 +958,8 @@ static void assert_bmesh_has_no_mesh_only_attributes(const BMesh &bm) { (void)bm; /* Unused in the release builds. */ BLI_assert(CustomData_get_layer_named(&bm.vdata, CD_PROP_FLOAT3, "position") == nullptr); + BLI_assert(CustomData_get_layer_named(&bm.ldata, CD_PROP_FLOAT3, ".corner_vert") == nullptr); + BLI_assert(CustomData_get_layer_named(&bm.ldata, CD_PROP_FLOAT3, ".corner_edge") == nullptr); /* The "hide" attributes are stored as flags on #BMesh. */ BLI_assert(CustomData_get_layer_named(&bm.vdata, CD_PROP_BOOL, ".hide_vert") == nullptr); @@ -1354,15 +1364,16 @@ static void bm_to_mesh_faces(const BMesh &bm, static void bm_to_mesh_loops(const BMesh &bm, const Span bm_loops, Mesh &mesh) { - CustomData_add_layer(&mesh.ldata, CD_MLOOP, CD_SET_DEFAULT, mesh.totloop); + CustomData_add_layer_named(&mesh.ldata, CD_PROP_INT32, CD_CONSTRUCT, bm.totloop, ".corner_vert"); + CustomData_add_layer_named(&mesh.ldata, CD_PROP_INT32, CD_CONSTRUCT, bm.totloop, ".corner_edge"); const Vector info = bm_to_mesh_copy_info_calc(bm.ldata, mesh.ldata); - MutableSpan dst_loops = mesh.loops_for_write(); - threading::parallel_for(dst_loops.index_range(), 1024, [&](const IndexRange range) { + MutableSpan dst_corner_verts = mesh.corner_verts_for_write(); + MutableSpan dst_corner_edges = mesh.corner_edges_for_write(); + threading::parallel_for(dst_corner_verts.index_range(), 1024, [&](const IndexRange range) { for (const int loop_i : range) { const BMLoop &src_loop = *bm_loops[loop_i]; - MLoop &dst_loop = dst_loops[loop_i]; - dst_loop.v = BM_elem_index_get(src_loop.v); - dst_loop.e = BM_elem_index_get(src_loop.e); + dst_corner_verts[loop_i] = BM_elem_index_get(src_loop.v); + dst_corner_edges[loop_i] = BM_elem_index_get(src_loop.e); bmesh_block_copy_to_mesh_attributes(info, loop_i, src_loop.head.data); } }); diff --git a/source/blender/depsgraph/intern/depsgraph_registry.cc b/source/blender/depsgraph/intern/depsgraph_registry.cc index 96336167b5a..dea87550542 100644 --- a/source/blender/depsgraph/intern/depsgraph_registry.cc +++ b/source/blender/depsgraph/intern/depsgraph_registry.cc @@ -5,6 +5,9 @@ * \ingroup depsgraph */ +#include +#include + #include "intern/depsgraph_registry.h" #include "BLI_utildefines.h" @@ -13,7 +16,19 @@ namespace blender::deg { -using GraphRegistry = Map
>; +/* Global registry for dependency graphs associated with a main database. + * + * Threads may add or remove depsgraphs for different mains concurrently + * (for example for preview rendering), but not the same main. */ + +/* Use pointer for map value to ensure span returned by get_all_registered_graphs + * remains unchanged as other mains are added or removed. */ +typedef std::unique_ptr> GraphSetPtr; +struct GraphRegistry { + Map
map; + std::mutex mutex; +}; + static GraphRegistry &get_graph_registry() { static GraphRegistry graph_registry; @@ -22,28 +37,37 @@ static GraphRegistry &get_graph_registry() void register_graph(Depsgraph *depsgraph) { + GraphRegistry &graph_registry = get_graph_registry(); Main *bmain = depsgraph->bmain; - get_graph_registry().lookup_or_add_default(bmain).add_new(depsgraph); + + std::lock_guard lock{graph_registry.mutex}; + graph_registry.map + .lookup_or_add_cb(bmain, []() { return std::make_unique>(); }) + ->add_new(depsgraph); } void unregister_graph(Depsgraph *depsgraph) { Main *bmain = depsgraph->bmain; GraphRegistry &graph_registry = get_graph_registry(); - VectorSet &graphs = graph_registry.lookup(bmain); - graphs.remove(depsgraph); + + std::lock_guard lock{graph_registry.mutex}; + GraphSetPtr &graphs = graph_registry.map.lookup(bmain); + graphs->remove(depsgraph); /* If this was the last depsgraph associated with the main, remove the main entry as well. */ - if (graphs.is_empty()) { - graph_registry.remove(bmain); + if (graphs->is_empty()) { + graph_registry.map.remove(bmain); } } Span get_all_registered_graphs(Main *bmain) { - VectorSet *graphs = get_graph_registry().lookup_ptr(bmain); - if (graphs != nullptr) { - return *graphs; + GraphRegistry &graph_registry = get_graph_registry(); + std::lock_guard lock{graph_registry.mutex}; + GraphSetPtr *graphs = graph_registry.map.lookup_ptr(bmain); + if (graphs) { + return **graphs; } return {}; } diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 01aa63bb38f..9706cecb54d 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -144,6 +144,7 @@ set(SRC engines/eevee_next/eevee_film.cc engines/eevee_next/eevee_hizbuffer.cc engines/eevee_next/eevee_instance.cc + engines/eevee_next/eevee_irradiance_cache.cc engines/eevee_next/eevee_light.cc engines/eevee_next/eevee_material.cc engines/eevee_next/eevee_motion_blur.cc @@ -275,6 +276,7 @@ set(SRC engines/eevee_next/eevee_film.hh engines/eevee_next/eevee_hizbuffer.hh engines/eevee_next/eevee_instance.hh + engines/eevee_next/eevee_irradiance_cache.hh engines/eevee_next/eevee_light.hh engines/eevee_next/eevee_material.hh engines/eevee_next/eevee_motion_blur.hh @@ -425,6 +427,9 @@ set(GLSL_SRC engines/eevee_next/shaders/eevee_colorspace_lib.glsl engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl engines/eevee_next/shaders/eevee_transparency_lib.glsl + engines/eevee_next/shaders/eevee_debug_surfels_vert.glsl + engines/eevee_next/shaders/eevee_debug_surfels_frag.glsl + engines/eevee_next/shaders/eevee_deferred_light_frag.glsl engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl engines/eevee_next/shaders/eevee_depth_of_field_bokeh_lut_comp.glsl engines/eevee_next/shaders/eevee_depth_of_field_downsample_comp.glsl @@ -444,6 +449,7 @@ set(GLSL_SRC engines/eevee_next/shaders/eevee_film_cryptomatte_post_comp.glsl engines/eevee_next/shaders/eevee_film_frag.glsl engines/eevee_next/shaders/eevee_film_lib.glsl + engines/eevee_next/shaders/eevee_gbuffer_lib.glsl engines/eevee_next/shaders/eevee_geom_curves_vert.glsl engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl engines/eevee_next/shaders/eevee_geom_mesh_vert.glsl @@ -484,6 +490,7 @@ set(GLSL_SRC engines/eevee_next/shaders/eevee_shadow_tilemap_finalize_comp.glsl engines/eevee_next/shaders/eevee_shadow_tilemap_init_comp.glsl engines/eevee_next/shaders/eevee_shadow_tilemap_lib.glsl + engines/eevee_next/shaders/eevee_spherical_harmonics_lib.glsl engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl engines/eevee_next/shaders/eevee_surf_depth_frag.glsl engines/eevee_next/shaders/eevee_surf_forward_frag.glsl diff --git a/source/blender/draw/DRW_pbvh.hh b/source/blender/draw/DRW_pbvh.hh index 22c21fc9c8d..58a32944337 100644 --- a/source/blender/draw/DRW_pbvh.hh +++ b/source/blender/draw/DRW_pbvh.hh @@ -10,6 +10,7 @@ /* Needed for BKE_ccg.h. */ #include "BLI_assert.h" #include "BLI_bitmap.h" +#include "BLI_span.hh" #include "BKE_ccg.h" @@ -23,7 +24,6 @@ struct DMFlagMat; struct Mesh; struct MLoopTri; struct CustomData; -struct MLoop; struct MPoly; struct SubdivCCG; struct BMesh; @@ -34,7 +34,8 @@ struct PBVH_GPU_Args { BMesh *bm; const Mesh *me; const float (*vert_positions)[3]; - const MLoop *mloop; + blender::Span corner_verts; + blender::Span corner_edges; const MPoly *polys; int mesh_verts_num, mesh_faces_num, mesh_grids_num; CustomData *vdata, *ldata, *pdata; diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 48d00011681..9afd398c8b4 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -280,7 +280,7 @@ static void eevee_draw_scene(void *vedata) SET_FLAG_FROM_TEST(clear_bits, (stl->effects->enabled_effects & EFFECT_SSS), GPU_STENCIL_BIT); GPU_framebuffer_clear(fbl->main_fb, clear_bits, clear_col, clear_depth, clear_stencil); - /* Depth prepass */ + /* Depth pre-pass. */ DRW_stats_group_start("Prepass"); DRW_draw_pass(psl->depth_ps); DRW_stats_group_end(); diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index a4bd789438d..1d31c5fdeed 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -107,14 +107,14 @@ void EEVEE_lookdev_init(EEVEE_Data *vedata) /* Make the viewport width scale the lookdev spheres a bit. * Scale between 1000px and 2000px. */ const float viewport_scale = clamp_f( - BLI_rcti_size_x(rect) / (2000.0f * U.dpi_fac), 0.5f, 1.0f); - const int sphere_size = U.lookdev_sphere_size * U.dpi_fac * viewport_scale; + BLI_rcti_size_x(rect) / (2000.0f * UI_SCALE_FAC), 0.5f, 1.0f); + const int sphere_size = U.lookdev_sphere_size * UI_SCALE_FAC * viewport_scale; if (sphere_size != effects->sphere_size || rect->xmax != effects->anchor[0] || rect->ymin != effects->anchor[1]) { /* Make sphere resolution adaptive to viewport_scale, DPI and #U.lookdev_sphere_size. */ float res_scale = clamp_f( - (U.lookdev_sphere_size / 400.0f) * viewport_scale * U.dpi_fac, 0.1f, 1.0f); + (U.lookdev_sphere_size / 400.0f) * viewport_scale * UI_SCALE_FAC, 0.1f, 1.0f); if (res_scale > 0.7f) { effects->sphere_lod = DRW_LOD_HIGH; diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 6f47007c3c5..1be0901085e 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -607,7 +607,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl GPU_framebuffer_bind(fbl->main_fb); GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil); - /* Depth prepass */ + /* Depth pre-pass. */ DRW_draw_pass(psl->depth_ps); /* Create minmax texture */ EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1); diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index 4ee21cf8c2e..8050d728ebc 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -136,57 +136,32 @@ void accumulate_light(vec3 light, float fac, inout vec4 accum) } /* Same thing as Cycles without the comments to make it shorter. */ -vec3 ensure_valid_reflection(vec3 Ng, vec3 I, vec3 N) +vec3 ensure_valid_specular_reflection(vec3 Ng, vec3 I, vec3 N) { vec3 R = -reflect(I, N); + float Iz = dot(I, Ng); + /* Reflection rays may always be at least as shallow as the incoming ray. */ - float threshold = min(0.9 * dot(Ng, I), 0.025); + float threshold = min(0.9 * Iz, 0.025); if (dot(Ng, R) >= threshold) { return N; } - float NdotNg = dot(N, Ng); - vec3 X = normalize(N - NdotNg * Ng); + vec3 X = normalize(N - dot(N, Ng) * Ng); + float Ix = dot(I, X); - float Ix = dot(I, X), Iz = dot(I, Ng); - float Ix2 = sqr(Ix), Iz2 = sqr(Iz); - float a = Ix2 + Iz2; + float a = sqr(Ix) + sqr(Iz); + float b = 2.0 * (a + Iz * threshold); + float c = sqr(threshold + Iz); - float b = sqrt(Ix2 * (a - sqr(threshold))); - float c = Iz * threshold + a; + float Nz2 = (Ix < 0.0) ? 0.25 * (b + safe_sqrt(sqr(b) - 4.0 * a * c)) / a : + 0.25 * (b - safe_sqrt(sqr(b) - 4.0 * a * c)) / a; - float fac = 0.5 / a; - float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c); - bool valid1 = (N1_z2 > 1e-5) && (N1_z2 <= (1.0 + 1e-5)); - bool valid2 = (N2_z2 > 1e-5) && (N2_z2 <= (1.0 + 1e-5)); + float Nx = safe_sqrt(1.0 - Nz2); + float Nz = safe_sqrt(Nz2); - vec2 N_new; - if (valid1 && valid2) { - /* If both are possible, do the expensive reflection-based check. */ - vec2 N1 = vec2(safe_sqrt(1.0 - N1_z2), safe_sqrt(N1_z2)); - vec2 N2 = vec2(safe_sqrt(1.0 - N2_z2), safe_sqrt(N2_z2)); - - float R1 = 2.0 * (N1.x * Ix + N1.y * Iz) * N1.y - Iz; - float R2 = 2.0 * (N2.x * Ix + N2.y * Iz) * N2.y - Iz; - - valid1 = (R1 >= 1e-5); - valid2 = (R2 >= 1e-5); - if (valid1 && valid2) { - N_new = (R1 < R2) ? N1 : N2; - } - else { - N_new = (R1 > R2) ? N1 : N2; - } - } - else if (valid1 || valid2) { - float Nz2 = valid1 ? N1_z2 : N2_z2; - N_new = vec2(safe_sqrt(1.0 - Nz2), safe_sqrt(Nz2)); - } - else { - return Ng; - } - return N_new.x * X + N_new.y * Ng; + return Nx * X + Nz * Ng; } /* ----------- Cone angle Approximation --------- */ diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl index b16fb266f34..c03b66ae174 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl @@ -53,7 +53,7 @@ ClosureEvalGlossy closure_Glossy_eval_init(inout ClosureInputGlossy cl_in, cl_out.radiance = vec3(0.0); #ifndef STEP_RESOLVE /* SSR */ - cl_in.N = ensure_valid_reflection(cl_common.Ng, cl_common.V, cl_in.N); + cl_in.N = ensure_valid_specular_reflection(cl_common.Ng, cl_common.V, cl_in.N); #endif float NV = dot(cl_in.N, cl_common.V); diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index bc778dc874d..c54d537db61 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -105,6 +105,9 @@ #define RBUFS_AOV_COLOR_SLOT 5 #define RBUFS_AOV_VALUE_SLOT 6 #define RBUFS_CRYPTOMATTE_SLOT 7 +/* G-buffer reuses render passes slots. */ +#define GBUF_CLOSURE_SLOT RBUFS_LIGHT_SLOT +#define GBUF_COLOR_SLOT RBUFS_DIFF_COLOR_SLOT /* Uniform Buffers. */ /* Only during prepass. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_film.cc b/source/blender/draw/engines/eevee_next/eevee_film.cc index beab3bdb196..d49ddd7866e 100644 --- a/source/blender/draw/engines/eevee_next/eevee_film.cc +++ b/source/blender/draw/engines/eevee_next/eevee_film.cc @@ -649,7 +649,7 @@ void Film::accumulate(const DRWView *view, GPUTexture *combined_final_tx) draw::View drw_view("MainView", view); - DRW_manager_get()->submit(accumulate_ps_, drw_view); + inst_.manager->submit(accumulate_ps_, drw_view); combined_tx_.swap(); weight_tx_.swap(); diff --git a/source/blender/draw/engines/eevee_next/eevee_gbuffer.hh b/source/blender/draw/engines/eevee_next/eevee_gbuffer.hh new file mode 100644 index 00000000000..177641c4993 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/eevee_gbuffer.hh @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup eevee + * + * Gbuffer layout used for deferred shading pipeline. + */ + +#pragma once + +#include "DRW_render.h" + +#include "eevee_material.hh" +#include "eevee_shader_shared.hh" + +namespace blender::eevee { + +class Instance; + +/** + * Full-screen textures containing geometric and surface data. + * Used by deferred shading passes. Only one gbuffer is allocated per view + * and is reused for each deferred layer. This is why there can only be temporary + * texture inside it. + * + * Everything is stored inside two array texture, one for each format. This is to fit the + * limitation of the number of images we can bind on a single shader. + * + * First layer is always for reflection. All parameters to shoot a reflection ray are inside + * this layer. + * + * - Layer 1 : Reflection + * - R : Normal packed X + * - G : Normal packed Y + * - B : Roughness + * - A : Unused (Could be used for anisotropic roughness) + * + * Second layer is either for diffuse or transmission. Material mixing both are not + * physically based and are uncommon. So in order to save bandwidth and texture memory, we only + * store one. We use random sampling to mix between both. All parameters to shoot a refraction + * ray are inside this layer. + * + * - Layer 2 : Refraction + * - R : Normal packed X + * - G : Normal packed Y + * - B : Roughness (isotropic) + * - A : IOR + * + * - Layer 2 : Diffuse / Sub-Surface Scattering + * - R : Normal packed X + * - G : Normal packed Y + * - B : Thickness + * - A : Unused (Could be used for diffuse roughness) + * + * Layer 3 is only allocated if Sub-Surface Scattering is needed. All parameters for + * screen-space scattering are inside this layer. + * + * - Layer 3 : Sub-Surface Scattering + * - R : Scattering radius R + * - G : Scattering radius G + * - B : Scattering radius B + * - A : Object ID + * + * For each output closure, we also output the color to apply after the lighting computation. + * The color is stored with a 2 exponent that allows input color with component higher than 1. + * Color degradation is expected to happen in this case. + */ +struct GBuffer { + /* TODO(fclem): Use texture from pool once they support texture array. */ + Texture closure_tx = {"GbufferClosure"}; + Texture color_tx = {"GbufferColor"}; + + void acquire(int2 extent, eClosureBits closure_bits_) + { + const bool use_sss = (closure_bits_ & CLOSURE_SSS) != 0; + eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE; + closure_tx.ensure_2d_array(GPU_RGBA16, extent, use_sss ? 3 : 2, usage); + color_tx.ensure_2d_array(GPU_RGB10_A2, extent, 2, usage); + } + + void release() + { + /* TODO(fclem): Use texture from pool once they support texture array. */ + // closure_tx.release(); + // color_tx.release(); + } +}; + +} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index cc5a61d661b..b0a40d27982 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -70,6 +70,7 @@ void Instance::init(const int2 &output_res, shadows.init(); motion_blur.init(); main_view.init(); + irradiance_cache.init(); } void Instance::set_time(float time) @@ -104,6 +105,7 @@ void Instance::begin_sync() velocity.begin_sync(); /* NOTE: Also syncs camera. */ lights.begin_sync(); shadows.begin_sync(); + pipelines.begin_sync(); cryptomatte.begin_sync(); gpencil_engine_enabled = false; @@ -113,10 +115,10 @@ void Instance::begin_sync() depth_of_field.sync(); motion_blur.sync(); hiz_buffer.sync(); - pipelines.sync(); main_view.sync(); world.sync(); film.sync(); + irradiance_cache.sync(); } void Instance::scene_sync() @@ -204,6 +206,7 @@ void Instance::end_sync() sampling.end_sync(); film.end_sync(); cryptomatte.end_sync(); + pipelines.end_sync(); } void Instance::render_sync() diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh index ba17289604c..8e7855961e4 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.hh +++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh @@ -19,7 +19,9 @@ #include "eevee_cryptomatte.hh" #include "eevee_depth_of_field.hh" #include "eevee_film.hh" +#include "eevee_gbuffer.hh" #include "eevee_hizbuffer.hh" +#include "eevee_irradiance_cache.hh" #include "eevee_light.hh" #include "eevee_material.hh" #include "eevee_motion_blur.hh" @@ -53,6 +55,7 @@ class Instance { MotionBlurModule motion_blur; DepthOfField depth_of_field; Cryptomatte cryptomatte; + GBuffer gbuffer; HiZBuffer hiz_buffer; Sampling sampling; Camera camera; @@ -60,6 +63,7 @@ class Instance { RenderBuffers render_buffers; MainView main_view; World world; + IrradianceCache irradiance_cache; /** Input data. */ Depsgraph *depsgraph; @@ -103,7 +107,8 @@ class Instance { film(*this), render_buffers(*this), main_view(*this), - world(*this){}; + world(*this), + irradiance_cache(*this){}; ~Instance(){}; void init(const int2 &output_res, diff --git a/source/blender/draw/engines/eevee_next/eevee_irradiance_cache.cc b/source/blender/draw/engines/eevee_next/eevee_irradiance_cache.cc new file mode 100644 index 00000000000..890ef35c3b5 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/eevee_irradiance_cache.cc @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_rand.hh" +#include "eevee_instance.hh" + +#include "eevee_irradiance_cache.hh" + +namespace blender::eevee { + +void IrradianceCache::generate_random_surfels() +{ + const int surfels_len = 256; + debug_surfels.resize(surfels_len); + + RandomNumberGenerator rng; + rng.seed(0); + + for (DebugSurfel &surfel : debug_surfels) { + float3 random = rng.get_unit_float3(); + surfel.position = random * 3.0f; + surfel.normal = random; + surfel.color = float4(rng.get_float(), rng.get_float(), rng.get_float(), 1.0f); + } + + debug_surfels.push_update(); +} + +void IrradianceCache::init() +{ + if (debug_surfels_sh_ == nullptr) { + debug_surfels_sh_ = inst_.shaders.static_shader_get(DEBUG_SURFELS); + } + + /* TODO: Remove this. */ + generate_random_surfels(); +} + +void IrradianceCache::sync() +{ + debug_pass_sync(); +} + +void IrradianceCache::debug_pass_sync() +{ + if (inst_.debug_mode == eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS) { + debug_surfels_ps_.init(); + debug_surfels_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL); + debug_surfels_ps_.shader_set(debug_surfels_sh_); + debug_surfels_ps_.bind_ssbo("surfels_buf", debug_surfels); + debug_surfels_ps_.push_constant("surfel_radius", 0.25f); + debug_surfels_ps_.draw_procedural(GPU_PRIM_TRI_STRIP, debug_surfels.size(), 4); + } +} + +void IrradianceCache::debug_draw(View &view, GPUFrameBuffer *view_fb) +{ + if (inst_.debug_mode == eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS) { + inst_.info = "Debug Mode: Irradiance Cache Surfels"; + GPU_framebuffer_bind(view_fb); + inst_.manager->submit(debug_surfels_ps_, view); + } +} + +} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_irradiance_cache.hh b/source/blender/draw/engines/eevee_next/eevee_irradiance_cache.hh new file mode 100644 index 00000000000..bc5be19332f --- /dev/null +++ b/source/blender/draw/engines/eevee_next/eevee_irradiance_cache.hh @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "eevee_shader_shared.hh" + +namespace blender::eevee { + +class Instance; + +class IrradianceCache { + private: + Instance &inst_; + + DebugSurfelBuf debug_surfels; + PassSimple debug_surfels_ps_ = {"IrradianceCache.Debug"}; + GPUShader *debug_surfels_sh_ = nullptr; + + /* TODO: Remove this. */ + void generate_random_surfels(); + + public: + IrradianceCache(Instance &inst) : inst_(inst){}; + ~IrradianceCache(){}; + + void init(); + void sync(); + + void debug_pass_sync(); + void debug_draw(View &view, GPUFrameBuffer *view_fb); +}; + +} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_material.cc b/source/blender/draw/engines/eevee_next/eevee_material.cc index 43c91dc32d5..a210681517a 100644 --- a/source/blender/draw/engines/eevee_next/eevee_material.cc +++ b/source/blender/draw/engines/eevee_next/eevee_material.cc @@ -193,11 +193,6 @@ MaterialPass MaterialModule::material_pass_get(Object *ob, inst_.sampling.reset(); } - if ((pipeline_type == MAT_PIPE_DEFERRED) && - GPU_material_flag_get(matpass.gpumat, GPU_MATFLAG_SHADER_TO_RGBA)) { - pipeline_type = MAT_PIPE_FORWARD; - } - if (ELEM(pipeline_type, MAT_PIPE_FORWARD, MAT_PIPE_FORWARD_PREPASS, @@ -240,10 +235,6 @@ Material &MaterialModule::material_sync(Object *ob, (has_motion ? MAT_PIPE_DEFERRED_PREPASS_VELOCITY : MAT_PIPE_DEFERRED_PREPASS); - /* TEST until we have deferred pipeline up and running. */ - surface_pipe = MAT_PIPE_FORWARD; - prepass_pipe = has_motion ? MAT_PIPE_FORWARD_PREPASS_VELOCITY : MAT_PIPE_FORWARD_PREPASS; - MaterialKey material_key(blender_mat, geometry_type, surface_pipe); Material &mat = material_map_.lookup_or_add_cb(material_key, [&]() { diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc index 94ce44522ba..8b6f0ccfdce 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc @@ -278,4 +278,229 @@ void ForwardPipeline::render(View &view, /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Deferred Layer + * \{ */ + +void DeferredLayer::begin_sync() +{ + { + prepass_ps_.init(); + { + /* Common resources. */ + + /* Textures. */ + prepass_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx); + /* Uniform Buf. */ + prepass_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get()); + + inst_.velocity.bind_resources(&prepass_ps_); + inst_.sampling.bind_resources(&prepass_ps_); + } + + DRWState state_depth_only = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; + DRWState state_depth_color = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | + DRW_STATE_WRITE_COLOR; + + prepass_double_sided_static_ps_ = &prepass_ps_.sub("DoubleSided.Static"); + prepass_double_sided_static_ps_->state_set(state_depth_only); + + prepass_single_sided_static_ps_ = &prepass_ps_.sub("SingleSided.Static"); + prepass_single_sided_static_ps_->state_set(state_depth_only | DRW_STATE_CULL_BACK); + + prepass_double_sided_moving_ps_ = &prepass_ps_.sub("DoubleSided.Moving"); + prepass_double_sided_moving_ps_->state_set(state_depth_color); + + prepass_single_sided_moving_ps_ = &prepass_ps_.sub("SingleSided.Moving"); + prepass_single_sided_moving_ps_->state_set(state_depth_color | DRW_STATE_CULL_BACK); + } + { + gbuffer_ps_.init(); + gbuffer_ps_.clear_stencil(0x00u); + gbuffer_ps_.state_stencil(0x01u, 0x01u, 0x01u); + + { + /* Common resources. */ + + /* G-buffer. */ + gbuffer_ps_.bind_image(GBUF_CLOSURE_SLOT, &inst_.gbuffer.closure_tx); + gbuffer_ps_.bind_image(GBUF_COLOR_SLOT, &inst_.gbuffer.color_tx); + /* RenderPasses. */ + gbuffer_ps_.bind_image(RBUFS_NORMAL_SLOT, &inst_.render_buffers.normal_tx); + /* TODO(fclem): Pack all render pass into the same texture. */ + // gbuffer_ps_.bind_image(RBUFS_DIFF_COLOR_SLOT, &inst_.render_buffers.diffuse_color_tx); + gbuffer_ps_.bind_image(RBUFS_SPEC_COLOR_SLOT, &inst_.render_buffers.specular_color_tx); + gbuffer_ps_.bind_image(RBUFS_EMISSION_SLOT, &inst_.render_buffers.emission_tx); + /* AOVs. */ + gbuffer_ps_.bind_image(RBUFS_AOV_COLOR_SLOT, &inst_.render_buffers.aov_color_tx); + gbuffer_ps_.bind_image(RBUFS_AOV_VALUE_SLOT, &inst_.render_buffers.aov_value_tx); + /* Cryptomatte. */ + gbuffer_ps_.bind_image(RBUFS_CRYPTOMATTE_SLOT, &inst_.render_buffers.cryptomatte_tx); + /* Storage Buf. */ + gbuffer_ps_.bind_ssbo(RBUFS_AOV_BUF_SLOT, &inst_.film.aovs_info); + /* Textures. */ + gbuffer_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx); + /* Uniform Buf. */ + gbuffer_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get()); + + inst_.sampling.bind_resources(&gbuffer_ps_); + inst_.cryptomatte.bind_resources(&gbuffer_ps_); + } + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM | DRW_STATE_DEPTH_EQUAL | + DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS; + + gbuffer_double_sided_ps_ = &gbuffer_ps_.sub("DoubleSided"); + gbuffer_double_sided_ps_->state_set(state); + + gbuffer_single_sided_ps_ = &gbuffer_ps_.sub("SingleSided"); + gbuffer_single_sided_ps_->state_set(state | DRW_STATE_CULL_BACK); + } +} + +void DeferredLayer::end_sync() +{ + /* Use stencil test to reject pixel not written by this layer. */ + /* WORKAROUND: Stencil write is only here to avoid rasterizer discard. */ + DRWState state = DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_EQUAL; + /* Allow output to combined pass for the last pass. */ + DRWState state_write_color = state | DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM; + + if (closure_bits_ & (CLOSURE_DIFFUSE | CLOSURE_REFLECTION)) { + const bool is_last_eval_pass = true; + + eval_light_ps_.init(); + eval_light_ps_.state_set(is_last_eval_pass ? state_write_color : state); + eval_light_ps_.state_stencil(0x00u, 0x01u, 0xFFu); + eval_light_ps_.shader_set(inst_.shaders.static_shader_get(DEFERRED_LIGHT)); + eval_light_ps_.bind_image("out_diffuse_light_img", &diffuse_light_tx_); + eval_light_ps_.bind_image("out_specular_light_img", &specular_light_tx_); + eval_light_ps_.bind_texture("gbuffer_closure_tx", &inst_.gbuffer.closure_tx); + eval_light_ps_.bind_texture("gbuffer_color_tx", &inst_.gbuffer.color_tx); + eval_light_ps_.push_constant("is_last_eval_pass", is_last_eval_pass); + eval_light_ps_.bind_image(RBUFS_LIGHT_SLOT, &inst_.render_buffers.light_tx); + eval_light_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx); + + inst_.lights.bind_resources(&eval_light_ps_); + inst_.shadows.bind_resources(&eval_light_ps_); + inst_.sampling.bind_resources(&eval_light_ps_); + inst_.hiz_buffer.bind_resources(&eval_light_ps_); + + eval_light_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS); + eval_light_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3); + } +} + +PassMain::Sub *DeferredLayer::prepass_add(::Material *blender_mat, + GPUMaterial *gpumat, + bool has_motion) +{ + PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ? + (has_motion ? prepass_single_sided_moving_ps_ : + prepass_single_sided_static_ps_) : + (has_motion ? prepass_double_sided_moving_ps_ : + prepass_double_sided_static_ps_); + + return &pass->sub(GPU_material_get_name(gpumat)); +} + +PassMain::Sub *DeferredLayer::material_add(::Material *blender_mat, GPUMaterial *gpumat) +{ + closure_bits_ |= shader_closure_bits_from_flag(gpumat); + + PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ? + gbuffer_single_sided_ps_ : + gbuffer_double_sided_ps_; + return &pass->sub(GPU_material_get_name(gpumat)); +} + +void DeferredLayer::render(View &view, + Framebuffer &prepass_fb, + Framebuffer &combined_fb, + int2 extent) +{ + + GPU_framebuffer_bind(prepass_fb); + inst_.manager->submit(prepass_ps_, view); + + inst_.hiz_buffer.set_dirty(); + inst_.shadows.set_view(view); + + inst_.gbuffer.acquire(extent, closure_bits_); + + GPU_framebuffer_bind(combined_fb); + inst_.manager->submit(gbuffer_ps_, view); + + eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE; + diffuse_light_tx_.acquire(extent, GPU_RGBA16F, usage); + specular_light_tx_.acquire(extent, GPU_RGBA16F, usage); + diffuse_light_tx_.clear(float4(0.0f)); + specular_light_tx_.clear(float4(0.0f)); + + inst_.manager->submit(eval_light_ps_, view); + + diffuse_light_tx_.release(); + specular_light_tx_.release(); + + inst_.gbuffer.release(); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Deferred Pipeline + * + * Closure data are written to intermediate buffer allowing screen space processing. + * \{ */ + +void DeferredPipeline::begin_sync() +{ + opaque_layer_.begin_sync(); + refraction_layer_.begin_sync(); +} + +void DeferredPipeline::end_sync() +{ + opaque_layer_.end_sync(); + refraction_layer_.end_sync(); +} + +PassMain::Sub *DeferredPipeline::prepass_add(::Material *blender_mat, + GPUMaterial *gpumat, + bool has_motion) +{ + if (blender_mat->blend_flag & MA_BL_SS_REFRACTION) { + return refraction_layer_.prepass_add(blender_mat, gpumat, has_motion); + } + else { + return opaque_layer_.prepass_add(blender_mat, gpumat, has_motion); + } +} + +PassMain::Sub *DeferredPipeline::material_add(::Material *blender_mat, GPUMaterial *gpumat) +{ + if (blender_mat->blend_flag & MA_BL_SS_REFRACTION) { + return refraction_layer_.material_add(blender_mat, gpumat); + } + else { + return opaque_layer_.material_add(blender_mat, gpumat); + } +} + +void DeferredPipeline::render(View &view, + Framebuffer &prepass_fb, + Framebuffer &combined_fb, + int2 extent) +{ + DRW_stats_group_start("Deferred.Opaque"); + opaque_layer_.render(view, prepass_fb, combined_fb, extent); + DRW_stats_group_end(); + + DRW_stats_group_start("Deferred.Refract"); + refraction_layer_.render(view, prepass_fb, combined_fb, extent); + DRW_stats_group_end(); +} + +/** \} */ + } // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.hh b/source/blender/draw/engines/eevee_next/eevee_pipeline.hh index a437ca8c522..d390fad4775 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.hh +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.hh @@ -113,6 +113,77 @@ class ForwardPipeline { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Deferred lighting. + * \{ */ + +class DeferredLayer { + private: + Instance &inst_; + + PassMain prepass_ps_ = {"Prepass"}; + PassMain::Sub *prepass_single_sided_static_ps_ = nullptr; + PassMain::Sub *prepass_single_sided_moving_ps_ = nullptr; + PassMain::Sub *prepass_double_sided_static_ps_ = nullptr; + PassMain::Sub *prepass_double_sided_moving_ps_ = nullptr; + + PassMain gbuffer_ps_ = {"Shading"}; + PassMain::Sub *gbuffer_single_sided_ps_ = nullptr; + PassMain::Sub *gbuffer_double_sided_ps_ = nullptr; + + PassSimple eval_light_ps_ = {"EvalLights"}; + + /* Closures bits from the materials in this pass. */ + eClosureBits closure_bits_; + + /** + * Accumulation textures for all stages of lighting evaluation (Light, SSR, SSSS, SSGI ...). + * These are split and separate from the main radiance buffer in order to accumulate light for + * the render passes and avoid too much bandwidth waste. Otherwise, we would have to load the + * BSDF color and do additive blending for each of the lighting step. + * + * NOTE: Not to be confused with the render passes. + */ + TextureFromPool diffuse_light_tx_ = {"diffuse_light_accum_tx"}; + TextureFromPool specular_light_tx_ = {"specular_light_accum_tx"}; + + public: + DeferredLayer(Instance &inst) : inst_(inst){}; + + void begin_sync(); + void end_sync(); + + PassMain::Sub *prepass_add(::Material *blender_mat, GPUMaterial *gpumat, bool has_motion); + PassMain::Sub *material_add(::Material *blender_mat, GPUMaterial *gpumat); + + void render(View &view, Framebuffer &prepass_fb, Framebuffer &combined_fb, int2 extent); +}; + +class DeferredPipeline { + private: + Instance &inst_; + + /* Gbuffer filling passes. We could have an arbitrary number of them but for now we just have + * a hardcoded number of them. */ + DeferredLayer opaque_layer_; + DeferredLayer refraction_layer_; + DeferredLayer volumetric_layer_; + + public: + DeferredPipeline(Instance &inst) + : inst_(inst), opaque_layer_(inst), refraction_layer_(inst), volumetric_layer_(inst){}; + + void begin_sync(); + void end_sync(); + + PassMain::Sub *prepass_add(::Material *material, GPUMaterial *gpumat, bool has_motion); + PassMain::Sub *material_add(::Material *material, GPUMaterial *gpumat); + + void render(View &view, Framebuffer &prepass_fb, Framebuffer &combined_fb, int2 extent); +}; + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Utility texture * @@ -197,22 +268,25 @@ class UtilityTexture : public Texture { class PipelineModule { public: WorldPipeline world; - // DeferredPipeline deferred; + DeferredPipeline deferred; ForwardPipeline forward; ShadowPipeline shadow; - // VelocityPipeline velocity; UtilityTexture utility_tx; public: - PipelineModule(Instance &inst) : world(inst), forward(inst), shadow(inst){}; + PipelineModule(Instance &inst) : world(inst), deferred(inst), forward(inst), shadow(inst){}; - void sync() + void begin_sync() { - // deferred.sync(); + deferred.begin_sync(); forward.sync(); shadow.sync(); - // velocity.sync(); + } + + void end_sync() + { + deferred.end_sync(); } PassMain::Sub *material_add(Object *ob, @@ -222,7 +296,7 @@ class PipelineModule { { switch (pipeline_type) { case MAT_PIPE_DEFERRED_PREPASS: - // return deferred.prepass_add(blender_mat, gpumat, false); + return deferred.prepass_add(blender_mat, gpumat, false); case MAT_PIPE_FORWARD_PREPASS: if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) { return forward.prepass_transparent_add(ob, blender_mat, gpumat); @@ -230,7 +304,7 @@ class PipelineModule { return forward.prepass_opaque_add(blender_mat, gpumat, false); case MAT_PIPE_DEFERRED_PREPASS_VELOCITY: - // return deferred.prepass_add(blender_mat, gpumat, true); + return deferred.prepass_add(blender_mat, gpumat, true); case MAT_PIPE_FORWARD_PREPASS_VELOCITY: if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) { return forward.prepass_transparent_add(ob, blender_mat, gpumat); @@ -238,7 +312,7 @@ class PipelineModule { return forward.prepass_opaque_add(blender_mat, gpumat, true); case MAT_PIPE_DEFERRED: - // return deferred.material_add(blender_mat, gpumat); + return deferred.material_add(blender_mat, gpumat); case MAT_PIPE_FORWARD: if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) { return forward.material_transparent_add(ob, blender_mat, gpumat); diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index cdf2115c743..116d6004642 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -86,6 +86,8 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_ return "eevee_film_comp"; case FILM_CRYPTOMATTE_POST: return "eevee_film_cryptomatte_post"; + case DEFERRED_LIGHT: + return "eevee_deferred_light"; case HIZ_DEBUG: return "eevee_hiz_debug"; case HIZ_UPDATE: @@ -98,6 +100,8 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_ return "eevee_motion_blur_tiles_flatten_render"; case MOTION_BLUR_TILE_FLATTEN_VIEWPORT: return "eevee_motion_blur_tiles_flatten_viewport"; + case DEBUG_SURFELS: + return "eevee_debug_surfels"; case DOF_BOKEH_LUT: return "eevee_depth_of_field_bokeh_lut"; case DOF_DOWNSAMPLE: @@ -239,6 +243,11 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu } } + /* WORKAROUND: Needed because node_tree isn't present in test shaders. */ + if (pipeline_type == MAT_PIPE_DEFERRED) { + info.define("MAT_RENDER_PASS_SUPPORT"); + } + if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) { info.define("MAT_TRANSPARENT"); /* Transparent material do not have any velocity specific pipeline. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.hh b/source/blender/draw/engines/eevee_next/eevee_shader.hh index d589c55cb50..d987105e3fc 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader.hh @@ -30,6 +30,10 @@ enum eShaderType { FILM_COMP, FILM_CRYPTOMATTE_POST, + DEFERRED_LIGHT, + + DEBUG_SURFELS, + DOF_BOKEH_LUT, DOF_DOWNSAMPLE, DOF_FILTER, diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh index fb8b355c38f..3b4345c3a2b 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh @@ -48,6 +48,10 @@ enum eDebugMode : uint32_t { * Show incorrectly downsample tiles in red. */ DEBUG_HIZ_VALIDATION = 2u, + /** + * Display IrradianceCache surfels. + */ + DEBUG_IRRADIANCE_CACHE_SURFELS = 3u, /** * Show tiles depending on their status. */ @@ -821,6 +825,21 @@ static inline ShadowTileDataPacked shadow_tile_pack(ShadowTileData tile) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Debug + * \{ */ + +struct DebugSurfel { + packed_float3 position; + int _pad0; + packed_float3 normal; + int _pad1; + float4 color; +}; +BLI_STATIC_ASSERT_ALIGN(DebugSurfel, 16) + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Hierarchical-Z Buffer * \{ */ @@ -928,6 +947,7 @@ using DepthOfFieldDataBuf = draw::UniformBuffer; using DepthOfFieldScatterListBuf = draw::StorageArrayBuffer; using DrawIndirectBuf = draw::StorageBuffer; using FilmDataBuf = draw::UniformBuffer; +using DebugSurfelBuf = draw::StorageArrayBuffer; using HiZDataBuf = draw::UniformBuffer; using LightCullingDataBuf = draw::StorageBuffer; using LightCullingKeyBuf = draw::StorageArrayBuffer; diff --git a/source/blender/draw/engines/eevee_next/eevee_view.cc b/source/blender/draw/engines/eevee_next/eevee_view.cc index d7cb4985a9b..d2d8f80feb7 100644 --- a/source/blender/draw/engines/eevee_next/eevee_view.cc +++ b/source/blender/draw/engines/eevee_next/eevee_view.cc @@ -123,8 +123,7 @@ void ShadingView::render() /* TODO(fclem): Move it after the first prepass (and hiz update) once pipeline is stabilized. */ inst_.lights.set_view(render_view_new_, extent_); - // inst_.pipelines.deferred.render( - // render_view_, rt_buffer_opaque_, rt_buffer_refract_, depth_tx_, combined_tx_); + inst_.pipelines.deferred.render(render_view_new_, prepass_fb_, combined_fb_, extent_); // inst_.lightprobes.draw_cache_display(); @@ -136,6 +135,8 @@ void ShadingView::render() inst_.hiz_buffer.debug_draw(render_view_new_, combined_fb_); inst_.shadows.debug_draw(render_view_new_, combined_fb_); + inst_.irradiance_cache.debug_draw(render_view_new_, combined_fb_); + GPUTexture *combined_final_tx = render_postfx(rbufs.combined_tx); inst_.film.accumulate(sub_view_, combined_final_tx); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_debug_surfels_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_debug_surfels_frag.glsl new file mode 100644 index 00000000000..ed6bfc8f87f --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_debug_surfels_frag.glsl @@ -0,0 +1,21 @@ + +void main() +{ + DebugSurfel surfel = surfels_buf[surfel_index]; + out_color = surfel.color; + + /* Display surfels as circles. */ + if (distance(P, surfel.position) > surfel_radius) { + discard; + return; + } + + /* Display backfacing surfels with a transparent checkerboard grid. */ + if (!gl_FrontFacing) { + ivec2 grid_uv = ivec2(gl_FragCoord) / 5; + if ((grid_uv.x + grid_uv.y) % 2 == 0) { + discard; + return; + } + } +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_debug_surfels_vert.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_debug_surfels_vert.glsl new file mode 100644 index 00000000000..fc08f418827 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_debug_surfels_vert.glsl @@ -0,0 +1,38 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) + +void main() +{ + surfel_index = gl_InstanceID; + DebugSurfel surfel = surfels_buf[surfel_index]; + + vec3 lP; + + switch (gl_VertexID) { + case 0: + lP = vec3(-1, 1, 0); + break; + case 1: + lP = vec3(-1, -1, 0); + break; + case 2: + lP = vec3(1, 1, 0); + break; + case 3: + lP = vec3(1, -1, 0); + break; + } + + vec3 N = surfel.normal; + vec3 T, B; + make_orthonormal_basis(N, T, B); + + mat4 model_matrix = mat4(vec4(T * surfel_radius, 0), + vec4(B * surfel_radius, 0), + vec4(N * surfel_radius, 0), + vec4(surfel.position, 1)); + + P = (model_matrix * vec4(lP, 1)).xyz; + + gl_Position = point_world_to_ndc(P); +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl new file mode 100644 index 00000000000..80dcaaf67cb --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl @@ -0,0 +1,97 @@ + +/** + * Compute light objects lighting contribution using Gbuffer data. + * + * Output light either directly to the radiance buffers or to temporary radiance accumulation + * buffer that will be processed by other deferred lighting passes. + */ + +#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + + float depth = texelFetch(hiz_tx, ivec2(gl_FragCoord.xy), 0).r; + vec3 P = get_world_space_from_depth(uvcoordsvar.xy, depth); + + /* TODO(fclem): High precision derivative. */ + vec3 Ng = safe_normalize(cross(dFdx(P), dFdy(P))); + vec3 V = cameraVec(P); + float vP_z = dot(cameraForward, P) - dot(cameraForward, cameraPos); + + vec4 gbuffer_0_packed = texelFetch(gbuffer_closure_tx, ivec3(texel, 0), 0); + vec4 gbuffer_1_packed = texelFetch(gbuffer_closure_tx, ivec3(texel, 1), 0); + + ClosureReflection reflection_data; + reflection_data.N = gbuffer_normal_unpack(gbuffer_0_packed.xy); + reflection_data.roughness = gbuffer_0_packed.z; + + ClosureDiffuse diffuse_data; + diffuse_data.N = gbuffer_normal_unpack(gbuffer_1_packed.xy); + /* These are only set for SSS case. */ + diffuse_data.sss_radius = vec3(0.0); + diffuse_data.sss_id = 0u; + float thickness = 0.0; + + bool is_refraction = gbuffer_is_refraction(gbuffer_1_packed); + if (is_refraction) { + /* Still evaluate the diffuse light so that dithered SSS / Refraction combination still + * produces a complete diffuse light buffer that will be correctly convolved by the SSSS. + * The refraction pixels will just set the diffuse radiance to 0. */ + } + else if (false /* TODO */) { + vec4 gbuffer_2_packed = texelFetch(gbuffer_closure_tx, ivec3(texel, 2), 0); + diffuse_data.sss_radius = gbuffer_sss_radii_unpack(gbuffer_2_packed.xyz); + diffuse_data.sss_id = gbuffer_object_id_unorm16_unpack(gbuffer_2_packed.w); + thickness = gbuffer_thickness_pack(gbuffer_1_packed.z); + } + + vec3 diffuse_light = vec3(0.0); + vec3 reflection_light = vec3(0.0); + + light_eval( + diffuse_data, reflection_data, P, Ng, V, vP_z, thickness, diffuse_light, reflection_light); + + if (is_last_eval_pass) { + /* Apply color and output lighting to render-passes. */ + vec4 color_0_packed = texelFetch(gbuffer_color_tx, ivec3(texel, 0), 0); + vec4 color_1_packed = texelFetch(gbuffer_color_tx, ivec3(texel, 1), 0); + + reflection_data.color = gbuffer_color_unpack(color_0_packed); + diffuse_data.color = gbuffer_color_unpack(color_1_packed); + + if (is_refraction) { + diffuse_data.color = vec3(0.0); + } + + reflection_light *= reflection_data.color; + diffuse_light *= diffuse_data.color; + /* Add radiance to light pass. */ + imageStore( + rp_light_img, ivec3(texel, RENDER_PASS_LAYER_DIFFUSE_LIGHT), vec4(diffuse_light, 1.0)); + imageStore( + rp_light_img, ivec3(texel, RENDER_PASS_LAYER_SPECULAR_LIGHT), vec4(reflection_light, 1.0)); + /* Add radiance to combined pass. */ + out_radiance = vec4(diffuse_light + reflection_light, 0.0); + out_transmittance = vec4(1.0); + } + else { + /* Store lighting for next deferred pass. */ + + /* Output diffuse light along with object ID for sub-surface screen space processing. */ + vec4 diffuse_radiance; + diffuse_radiance.xyz = diffuse_light; + diffuse_radiance.w = gbuffer_object_id_f16_pack(diffuse_data.sss_id); + imageStore(out_diffuse_light_img, texel, diffuse_radiance); + + imageStore(out_specular_light_img, texel, vec4(reflection_light, 0.0)); + + /* Final radiance will be amended by the last pass. + * This should do nothing as color write should be disabled in this case. */ + out_radiance = vec4(0.0); + out_transmittance = vec4(0.0); + } +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_gbuffer_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_gbuffer_lib.glsl new file mode 100644 index 00000000000..8156166f42f --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_gbuffer_lib.glsl @@ -0,0 +1,106 @@ + +/** + * G-buffer: Packing and upacking of G-buffer data. + * + * See #GBuffer for a breakdown of the G-buffer layout. + */ + +#pragma BLENDER_REQUIRE(gpu_shader_math_vector_lib.glsl) + +vec2 gbuffer_normal_pack(vec3 N) +{ + N /= length_manhattan(N); + N.xy = (N.z >= 0.0) ? N.xy : ((1.0 - abs(N.yx)) * sign(N.xy)); + N.xy = N.xy * 0.5 + 0.5; + return N.xy; +} + +vec3 gbuffer_normal_unpack(vec2 N_packed) +{ + N_packed = N_packed * 2.0 - 1.0; + vec3 N = vec3(N_packed.x, N_packed.y, 1.0 - abs(N_packed.x) - abs(N_packed.y)); + float t = clamp(-N.z, 0.0, 1.0); + N.x += (N.x >= 0.0) ? -t : t; + N.y += (N.y >= 0.0) ? -t : t; + return normalize(N); +} + +float gbuffer_ior_pack(float ior) +{ + return (ior > 1.0) ? (1.0 - 0.5 / ior) : (0.5 * ior); +} + +float gbuffer_ior_unpack(float ior_packed) +{ + return (ior_packed > 0.5) ? (-1.0 / (ior_packed * 2.0 + 2.0)) : (2.0 * ior_packed); +} + +float gbuffer_thickness_pack(float thickness) +{ + /* TODO(fclem): Something better. */ + return gbuffer_ior_pack(thickness); +} + +float gbuffer_thickness_unpack(float thickness_packed) +{ + /* TODO(fclem): Something better. */ + return gbuffer_ior_unpack(thickness_packed); +} + +vec3 gbuffer_sss_radii_pack(vec3 sss_radii) +{ + /* TODO(fclem): Something better. */ + return vec3( + gbuffer_ior_pack(sss_radii.x), gbuffer_ior_pack(sss_radii.y), gbuffer_ior_pack(sss_radii.z)); +} + +vec3 gbuffer_sss_radii_unpack(vec3 sss_radii_packed) +{ + /* TODO(fclem): Something better. */ + return vec3(gbuffer_ior_unpack(sss_radii_packed.x), + gbuffer_ior_unpack(sss_radii_packed.y), + gbuffer_ior_unpack(sss_radii_packed.z)); +} + +vec4 gbuffer_color_pack(vec3 color) +{ + float max_comp = max(color.x, max(color.y, color.z)); + /* Store 2bit exponent inside Alpha. Allows values up to 8 with some color degradation. + * Above 8, the result will be clampped when writing the data to the output buffer. */ + float exponent = (max_comp > 1) ? ((max_comp > 2) ? ((max_comp > 4) ? 3.0 : 2.0) : 1.0) : 0.0; + /* TODO(fclem): Could try dithering to avoid banding artifacts on higher exponents. */ + return vec4(color / exp2(exponent), exponent / 3.0); +} + +vec3 gbuffer_color_unpack(vec4 color_packed) +{ + float exponent = color_packed.a * 3.0; + return color_packed.rgb * exp2(exponent); +} + +float gbuffer_object_id_unorm16_pack(uint object_id) +{ + return float(object_id & 0xFFFFu) / float(0xFFFF); +} + +uint gbuffer_object_id_unorm16_unpack(float object_id_packed) +{ + return uint(object_id_packed * float(0xFFFF)); +} + +float gbuffer_object_id_f16_pack(uint object_id) +{ + /* TODO(fclem): Make use of all the 16 bits in a half float. + * This here only correctly represent values up to 1024. */ + return float(object_id); +} + +uint gbuffer_object_id_f16_unpack(float object_id_packed) +{ + return uint(object_id_packed); +} + +bool gbuffer_is_refraction(vec4 gbuffer) +{ + return gbuffer.w < 1.0; +} \ No newline at end of file diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl index 965780d9bcf..db38baab6a4 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl @@ -29,14 +29,16 @@ bool closure_select(float weight, inout float total_weight, inout float r) float x = weight / total_weight; bool chosen = (r < x); /* Assuming that if r is in the interval [0,x] or [x,1], it's still uniformly distributed within - * that interval, so you remapping to [0,1] again to explore this space of probability. */ + * that interval, so remapping to [0,1] again to explore this space of probability. */ r = (chosen) ? (r / x) : ((r - x) / (1.0 - x)); return chosen; } #define SELECT_CLOSURE(destination, random, candidate) \ if (closure_select(candidate.weight, destination.weight, random)) { \ + float tmp = destination.weight; \ destination = candidate; \ + destination.weight = tmp; \ } float g_closure_rand; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_frag.glsl index dd946ffb637..7bc51513da1 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_frag.glsl @@ -82,7 +82,7 @@ void main() { vec2 screen_uv = gl_FragCoord.xy / vec2(fb_resolution); - float opaque_depth = texelFetch(hiz_tx, int2(gl_FragCoord.xy), fb_lod).r; + float opaque_depth = texelFetch(hiz_tx, ivec2(gl_FragCoord.xy), fb_lod).r; vec3 ws_opaque = get_world_space_from_depth(screen_uv, opaque_depth); vec3 ws_near_plane = get_world_space_from_depth(screen_uv, 0); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_spherical_harmonics_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_spherical_harmonics_lib.glsl new file mode 100644 index 00000000000..ed907207193 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_spherical_harmonics_lib.glsl @@ -0,0 +1,215 @@ + +/* -------------------------------------------------------------------- */ +/** \name Spherical Harmonics Functions + * + * `L` denote the row and `M` the column in the spherical harmonics table (1). + * `p` denote positive column and `n` negative ones. + * + * Use precomputed constants to avoid constant folding differences across compilers. + * Note that (2) doesn't use Condon-Shortley phase whereas our implementation does. + * + * Reference: + * (1) https://en.wikipedia.org/wiki/Spherical_harmonics#/media/File:Sphericalfunctions.svg + * (2) https://en.wikipedia.org/wiki/Table_of_spherical_harmonics#Real_spherical_harmonics + * (3) https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ + * + * \{ */ + +/* L0 Band. */ +float spherical_harmonics_L0_M0(vec3 v) +{ + return 0.282094792; +} + +/* L1 Band. */ +float spherical_harmonics_L1_Mn1(vec3 v) +{ + return -0.488602512 * v.y; +} +float spherical_harmonics_L1_M0(vec3 v) +{ + return 0.488602512 * v.z; +} +float spherical_harmonics_L1_Mp1(vec3 v) +{ + return -0.488602512 * v.x; +} + +/* L2 Band. */ +float spherical_harmonics_L2_Mn2(vec3 v) +{ + return 1.092548431 * (v.x * v.y); +} +float spherical_harmonics_L2_Mn1(vec3 v) +{ + return -1.092548431 * (v.y * v.z); +} +float spherical_harmonics_L2_M0(vec3 v) +{ + return 0.315391565 * (3.0 * v.z * v.z - 1.0); +} +float spherical_harmonics_L2_Mp1(vec3 v) +{ + return -1.092548431 * (v.x * v.z); +} +float spherical_harmonics_L2_Mp2(vec3 v) +{ + return 0.546274215 * (v.x * v.x - v.y * v.y); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Structure + * \{ */ + +struct SphericalHarmonicBandL0 { + vec3 M0; +}; + +struct SphericalHarmonicBandL1 { + vec3 Mn1; + vec3 M0; + vec3 Mp1; +}; + +struct SphericalHarmonicBandL2 { + vec3 Mn2; + vec3 Mn1; + vec3 M0; + vec3 Mp1; + vec3 Mp2; +}; + +struct SphericalHarmonicL0 { + SphericalHarmonicBandL0 L0; +}; + +struct SphericalHarmonicL1 { + SphericalHarmonicBandL0 L0; + SphericalHarmonicBandL1 L1; +}; + +struct SphericalHarmonicL2 { + SphericalHarmonicBandL0 L0; + SphericalHarmonicBandL1 L1; + SphericalHarmonicBandL2 L2; +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Encode + * + * Decompose an input signal into spherical harmonic coefficients. + * \{ */ + +void spherical_harmonics_L0_encode_signal_sample(vec3 direction, + vec3 amplitude, + inout SphericalHarmonicBandL0 r_L0) +{ + r_L0.M0 += spherical_harmonics_L0_M0(direction) * amplitude; +} + +void spherical_harmonics_L1_encode_signal_sample(vec3 direction, + vec3 amplitude, + inout SphericalHarmonicBandL1 r_L1) +{ + r_L1.Mn1 += spherical_harmonics_L1_Mn1(direction) * amplitude; + r_L1.M0 += spherical_harmonics_L1_M0(direction) * amplitude; + r_L1.Mp1 += spherical_harmonics_L1_Mp1(direction) * amplitude; +} + +void spherical_harmonics_L2_encode_signal_sample(vec3 direction, + vec3 amplitude, + inout SphericalHarmonicBandL2 r_L2) +{ + r_L2.Mn2 += spherical_harmonics_L2_Mn2(direction) * amplitude; + r_L2.Mn1 += spherical_harmonics_L2_Mn1(direction) * amplitude; + r_L2.M0 += spherical_harmonics_L2_M0(direction) * amplitude; + r_L2.Mp1 += spherical_harmonics_L2_Mp1(direction) * amplitude; + r_L2.Mp2 += spherical_harmonics_L2_Mp2(direction) * amplitude; +} + +void spherical_harmonics_encode_signal_sample(vec3 direction, + vec3 amplitude, + inout SphericalHarmonicL0 sh) +{ + spherical_harmonics_L0_encode_signal_sample(direction, amplitude, sh.L0); +} + +void spherical_harmonics_encode_signal_sample(vec3 direction, + vec3 amplitude, + inout SphericalHarmonicL1 sh) +{ + spherical_harmonics_L0_encode_signal_sample(direction, amplitude, sh.L0); + spherical_harmonics_L1_encode_signal_sample(direction, amplitude, sh.L1); +} + +void spherical_harmonics_encode_signal_sample(vec3 direction, + vec3 amplitude, + inout SphericalHarmonicL2 sh) +{ + spherical_harmonics_L0_encode_signal_sample(direction, amplitude, sh.L0); + spherical_harmonics_L1_encode_signal_sample(direction, amplitude, sh.L1); + spherical_harmonics_L2_encode_signal_sample(direction, amplitude, sh.L2); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Decode + * + * Evaluate an encoded signal in a given unit vector direction. + * \{ */ + +vec3 spherical_harmonics_L0_evaluate(vec3 direction, SphericalHarmonicBandL0 L0) +{ + return spherical_harmonics_L0_M0(direction) * L0.M0; +} + +vec3 spherical_harmonics_L1_evaluate(vec3 direction, SphericalHarmonicBandL1 L1) +{ + return spherical_harmonics_L1_Mn1(direction) * L1.Mn1 + + spherical_harmonics_L1_M0(direction) * L1.M0 + + spherical_harmonics_L1_Mp1(direction) * L1.Mp1; +} + +vec3 spherical_harmonics_L2_evaluate(vec3 direction, SphericalHarmonicBandL2 L2) +{ + return spherical_harmonics_L2_Mn2(direction) * L2.Mn2 + + spherical_harmonics_L2_Mn1(direction) * L2.Mn1 + + spherical_harmonics_L2_M0(direction) * L2.M0 + + spherical_harmonics_L2_Mp1(direction) * L2.Mp1 + + spherical_harmonics_L2_Mp2(direction) * L2.Mp2; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Evaluation + * \{ */ + +/** + * Convolve a spherical harmonic encoded irradiance signal as a lambertian reflection. + * Returns the lambertian radiance (cosine lobe divided by PI) so the coefficients simplify to 1, + * 2/3 and 1/4. See this reference for more explanation: + * https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ + */ +vec3 spherical_harmonics_evaluate_lambert(vec3 N, SphericalHarmonicL0 sh) +{ + return spherical_harmonics_L0_evaluate(N, sh.L0); +} +vec3 spherical_harmonics_evaluate_lambert(vec3 N, SphericalHarmonicL1 sh) +{ + return spherical_harmonics_L0_evaluate(N, sh.L0) + + spherical_harmonics_L1_evaluate(N, sh.L1) * (2.0 / 3.0); +} +vec3 spherical_harmonics_evaluate_lambert(vec3 N, SphericalHarmonicL2 sh) +{ + return spherical_harmonics_L0_evaluate(N, sh.L0) + + spherical_harmonics_L1_evaluate(N, sh.L1) * (2.0 / 3.0) + + spherical_harmonics_L2_evaluate(N, sh.L2) * (1.0 / 4.0); +} + +/** \} */ diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl index 7848c4a0611..d84d0a030e2 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl @@ -3,17 +3,136 @@ * Deferred lighting evaluation: Lighting is evaluated in a separate pass. * * Outputs shading parameter per pixel using a randomized set of BSDFs. - **/ + * Some render-pass are written during this pass. + */ +#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl) #pragma BLENDER_REQUIRE(common_view_lib.glsl) #pragma BLENDER_REQUIRE(common_math_lib.glsl) #pragma BLENDER_REQUIRE(common_hair_lib.glsl) #pragma BLENDER_REQUIRE(eevee_surf_lib.glsl) #pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) + +vec4 closure_to_rgba(Closure cl) +{ + vec4 out_color; + out_color.rgb = g_emission; + out_color.a = saturate(1.0 - avg(g_transmittance)); + + /* Reset for the next closure tree. */ + closure_weights_reset(); + + return out_color; +} void main() { init_globals(); + float noise = utility_tx_fetch(utility_tx, gl_FragCoord.xy, UTIL_BLUE_NOISE_LAYER).r; + g_closure_rand = fract(noise + sampling_rng_1D_get(SAMPLING_CLOSURE)); + + fragment_displacement(); + nodetree_surface(); + + g_holdout = saturate(g_holdout); + + out_transmittance = vec4(1.0 - g_holdout); + float transmittance_mono = saturate(avg(g_transmittance)); + + float thickness = nodetree_thickness(); + + g_diffuse_data.color *= g_diffuse_data.weight; + g_reflection_data.color *= g_reflection_data.weight; + g_refraction_data.color *= g_refraction_data.weight; + + /* TODO(fclem): This feels way too complex for what is it. */ + bool has_any_bsdf_weight = g_diffuse_data.weight != 0.0 || g_reflection_data.weight != 0.0 || + g_refraction_data.weight != 0.0; + vec3 out_normal = has_any_bsdf_weight ? vec3(0.0) : g_data.N; + out_normal += g_diffuse_data.N * g_diffuse_data.weight; + out_normal += g_reflection_data.N * g_reflection_data.weight; + out_normal += g_refraction_data.N * g_refraction_data.weight; + out_normal = safe_normalize(out_normal); + + vec3 specular_color = g_reflection_data.color + g_refraction_data.color; + + /* ----- Render Passes output ----- */ + + ivec2 out_texel = ivec2(gl_FragCoord.xy); +#ifdef MAT_RENDER_PASS_SUPPORT /* Needed because node_tree isn't present in test shaders. */ + /* Some render pass can be written during the gbuffer pass. Light passes are written later. */ + vec4 cryptomatte_output = vec4(cryptomatte_object_buf[resource_id], node_tree.crypto_hash, 0.0); + imageStore(rp_cryptomatte_img, out_texel, cryptomatte_output); + imageStore(rp_normal_img, out_texel, vec4(out_normal, 1.0)); + /* TODO(fclem): For now, just don't do anything. In the future all render passes should be in an + * array texture and have a UBO with indirection to the correct layer. */ + // imageStore(rp_diffuse_color_img, out_texel, vec4(g_diffuse_data.color, 1.0)); + imageStore(rp_specular_color_img, out_texel, vec4(specular_color, 1.0)); + imageStore(rp_emission_img, out_texel, vec4(g_emission, 1.0)); +#endif + + /* ----- GBuffer output ----- */ + + if (true) { + /* Reflection. */ + vec4 out_reflect = vec4(gbuffer_normal_pack(g_reflection_data.N), + g_reflection_data.roughness, + g_reflection_data.roughness); + imageStore(out_gbuff_closure_img, ivec3(out_texel, 0), out_reflect); + + vec4 color = gbuffer_color_pack(g_reflection_data.color); + imageStore(out_gbuff_color_img, ivec3(out_texel, 0), color); + } + + /* TODO(fclem) other RNG. */ + float refract_rand = fract(g_closure_rand * 6.1803398875); + float combined_weight = g_refraction_data.weight + g_diffuse_data.weight; + bool output_refraction = combined_weight > 0.0 && + (refract_rand * combined_weight) < g_refraction_data.weight; + if (output_refraction) { + /* Refraction. */ + vec4 closure; + closure.xy = gbuffer_normal_pack(g_refraction_data.N); + closure.z = g_refraction_data.roughness; + closure.w = gbuffer_ior_pack(g_refraction_data.ior); + /* Clamp to just bellow 1 to be able to distinguish between refraction and diffuse. + * Ceiling value is chosen by the storage format (16bit UNORM). */ + closure.w = min(closure.w, float(0xFFFFu - 1u) / float(0xFFFFu)); + imageStore(out_gbuff_closure_img, ivec3(out_texel, 1), closure); + + vec4 color = gbuffer_color_pack(g_refraction_data.color); + imageStore(out_gbuff_color_img, ivec3(out_texel, 1), color); + } + else { + /* Diffuse. */ + vec4 closure; + closure.xy = gbuffer_normal_pack(g_diffuse_data.N); + closure.z = gbuffer_thickness_pack(thickness); + /* Used to detect the refraction case. Could be used for roughness. */ + closure.w = 1.0; + imageStore(out_gbuff_closure_img, ivec3(out_texel, 1), closure); + + vec4 color = gbuffer_color_pack(g_diffuse_data.color); + imageStore(out_gbuff_color_img, ivec3(out_texel, 1), color); + } + + if (true) { + /* SubSurface Scattering. */ + vec4 closure; + closure.xyz = gbuffer_sss_radii_pack(g_diffuse_data.sss_radius); + closure.w = gbuffer_object_id_unorm16_pack(g_diffuse_data.sss_id); + imageStore(out_gbuff_closure_img, ivec3(out_texel, 2), closure); + } + + /* ----- Radiance output ----- */ + + /* Only output emission during the gbuffer pass. */ + out_radiance = vec4(g_emission, 0.0); + out_radiance.rgb *= 1.0 - g_holdout; + + out_transmittance.rgb = g_transmittance; + out_transmittance.a = saturate(avg(g_transmittance)); } diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh new file mode 100644 index 00000000000..f5bc967e5b6 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "eevee_defines.hh" +#include "gpu_shader_create_info.hh" + +#define image_out(slot, qualifier, format, name) \ + image(slot, format, qualifier, ImageType::FLOAT_2D, name, Frequency::PASS) +#define image_array_out(slot, qualifier, format, name) \ + image(slot, format, qualifier, ImageType::FLOAT_2D_ARRAY, name, Frequency::PASS) + +/** + * Specific deferred pass accumulate the computed lighting to either: + * - a split diffuse / specular temporary light buffer. + * or to + * - the combined pass & the light render-pass (if needed). + * + * This is in order to minimize the number of blending step. + */ +GPU_SHADER_CREATE_INFO(eevee_deferred_base) + /* Early fragment test is needed to avoid processing fragments without correct GBuffer data. */ + .early_fragment_test(true) + /* Select which output to write to. */ + .push_constant(Type::BOOL, "is_last_eval_pass") + /* Combined pass output. */ + .fragment_out(0, Type::VEC4, "out_radiance", DualBlend::SRC_0) + .fragment_out(0, Type::VEC4, "out_transmittance", DualBlend::SRC_1) + /* Light pass output. */ + .image_array_out(RBUFS_LIGHT_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_light_img") + /* Chaining to next pass. */ + .image_out(2, Qualifier::READ_WRITE, GPU_RGBA16F, "out_diffuse_light_img") + .image_out(3, Qualifier::READ_WRITE, GPU_RGBA16F, "out_specular_light_img"); + +GPU_SHADER_CREATE_INFO(eevee_deferred_light) + .fragment_source("eevee_deferred_light_frag.glsl") + .sampler(0, ImageType::FLOAT_2D_ARRAY, "gbuffer_closure_tx") + .sampler(1, ImageType::FLOAT_2D_ARRAY, "gbuffer_color_tx") + .additional_info("eevee_shared", + "eevee_utility_texture", + "eevee_light_data", + "eevee_shadow_data", + "eevee_deferred_base", + "eevee_hiz_data", + "draw_view", + "draw_fullscreen") + .do_static_compilation(true); + +#undef image_array_out diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_irradiance_cache_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_irradiance_cache_info.hh new file mode 100644 index 00000000000..0bc27f5ae2e --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_irradiance_cache_info.hh @@ -0,0 +1,16 @@ +#include "eevee_defines.hh" +#include "gpu_shader_create_info.hh" + +GPU_SHADER_INTERFACE_INFO(eeve_debug_surfel_iface, "") + .smooth(Type::VEC3, "P") + .flat(Type::INT, "surfel_index"); + +GPU_SHADER_CREATE_INFO(eevee_debug_surfels) + .additional_info("eevee_shared", "draw_view") + .vertex_source("eevee_debug_surfels_vert.glsl") + .vertex_out(eeve_debug_surfel_iface) + .fragment_source("eevee_debug_surfels_frag.glsl") + .fragment_out(0, Type::VEC4, "out_color") + .storage_buf(0, Qualifier::READ, "DebugSurfel", "surfels_buf[]") + .push_constant(Type::FLOAT, "surfel_radius") + .do_static_compilation(true); diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh index 0ef16bf3522..f16113a5efc 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh @@ -88,11 +88,11 @@ GPU_SHADER_CREATE_INFO(eevee_aov_out) GPU_SHADER_CREATE_INFO(eevee_render_pass_out) .define("MAT_RENDER_PASS_SUPPORT") - .image_out(RBUFS_NORMAL_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_normal_img") - .image_array_out(RBUFS_LIGHT_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_light_img") - .image_out(RBUFS_DIFF_COLOR_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_diffuse_color_img") - .image_out(RBUFS_SPEC_COLOR_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_specular_color_img") - .image_out(RBUFS_EMISSION_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_emission_img"); + .image_out(RBUFS_NORMAL_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_normal_img") + .image_array_out(RBUFS_LIGHT_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_light_img") + .image_out(RBUFS_DIFF_COLOR_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_diffuse_color_img") + .image_out(RBUFS_SPEC_COLOR_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_specular_color_img") + .image_out(RBUFS_EMISSION_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_emission_img"); GPU_SHADER_CREATE_INFO(eevee_cryptomatte_out) .storage_buf(CRYPTOMATTE_BUF_SLOT, Qualifier::READ, "vec2", "cryptomatte_object_buf[]") @@ -101,23 +101,29 @@ GPU_SHADER_CREATE_INFO(eevee_cryptomatte_out) GPU_SHADER_CREATE_INFO(eevee_surf_deferred) .vertex_out(eevee_surf_iface) /* NOTE: This removes the possibility of using gl_FragDepth. */ - // .early_fragment_test(true) - /* Direct output. */ + .early_fragment_test(true) + /* Direct output. (Emissive, Holdout) */ .fragment_out(0, Type::VEC4, "out_radiance", DualBlend::SRC_0) .fragment_out(0, Type::VEC4, "out_transmittance", DualBlend::SRC_1) - /* Gbuffer. */ - // .image_out(0, Qualifier::WRITE, GPU_R11F_G11F_B10F, "gbuff_transmit_color") - // .image_out(1, Qualifier::WRITE, GPU_R11F_G11F_B10F, "gbuff_transmit_data") - // .image_out(2, Qualifier::WRITE, GPU_RGBA16F, "gbuff_transmit_normal") - // .image_out(3, Qualifier::WRITE, GPU_R11F_G11F_B10F, "gbuff_reflection_color") - // .image_out(4, Qualifier::WRITE, GPU_RGBA16F, "gbuff_reflection_normal") - // .image_out(5, Qualifier::WRITE, GPU_R11F_G11F_B10F, "gbuff_emission") - /* Render-passes. */ - // .image_out(6, Qualifier::READ_WRITE, GPU_RGBA16F, "rpass_volume_light") + /* Everything is stored inside a two layered target, one for each format. This is to fit the + * limitation of the number of images we can bind on a single shader. */ + .image_array_out(GBUF_CLOSURE_SLOT, Qualifier::WRITE, GPU_RGBA16, "out_gbuff_closure_img") + .image_array_out(GBUF_COLOR_SLOT, Qualifier::WRITE, GPU_RGB10_A2, "out_gbuff_color_img") + /* Render-passes need to be declared manually to avoid overlap with the G-buffer which reuse + * some of binding points. */ + .image_out(RBUFS_NORMAL_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_normal_img") + // .image_array_out(RBUFS_LIGHT_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_light_img") + /* TODO(fclem): Merge all render-pass into the same texture array. */ + // .image_out(RBUFS_DIFF_COLOR_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_diffuse_color_img") + .image_out(RBUFS_SPEC_COLOR_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_specular_color_img") + .image_out(RBUFS_EMISSION_SLOT, Qualifier::WRITE, GPU_RGBA16F, "rp_emission_img") .fragment_source("eevee_surf_deferred_frag.glsl") .additional_info("eevee_camera", "eevee_utility_texture", "eevee_sampling_data", + /* Added manually to avoid overlap. */ + // "eevee_render_pass_out", + "eevee_cryptomatte_out", "eevee_aov_out"); GPU_SHADER_CREATE_INFO(eevee_surf_forward) diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 9cabb729c45..518b4654f9b 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -221,7 +221,7 @@ static void external_cache_populate(void *vedata, Object *ob) } struct GPUBatch *geom = DRW_cache_object_surface_get(ob); if (geom) { - /* Depth Prepass */ + /* Depth Pre-pass. */ DRW_shgroup_call(stl->g_data->depth_shgrp, geom, ob); } } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 8b5a752758e..712f5d7d51a 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -309,7 +309,7 @@ typedef struct GPENCIL_PrivateData { float fade_3d_object_opacity; /* Mask opacity uniform. */ float mask_opacity; - /* Xray transparency in solid mode. */ + /* X-ray transparency in solid mode. */ float xray_alpha; /* Mask invert uniform. */ int mask_invert; diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.cc b/source/blender/draw/engines/overlay/overlay_edit_uv.cc index 5a63f97d689..d712b163c9b 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_uv.cc +++ b/source/blender/draw/engines/overlay/overlay_edit_uv.cc @@ -158,7 +158,7 @@ void OVERLAY_edit_uv_init(OVERLAY_Data *vedata) pd->edit_uv.uv_opacity = sima->uv_opacity; pd->edit_uv.do_tiled_image_overlay = show_overlays && is_image_type && is_tiled_image; pd->edit_uv.do_tiled_image_border_overlay = is_image_type && is_tiled_image; - pd->edit_uv.dash_length = 4.0f * UI_DPI_FAC; + pd->edit_uv.dash_length = 4.0f * UI_SCALE_FAC; pd->edit_uv.line_style = edit_uv_line_style_from_space_image(sima); pd->edit_uv.do_smooth_wire = ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) != 0); pd->edit_uv.do_stencil_overlay = show_overlays && do_stencil_overlay; @@ -237,7 +237,7 @@ void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) GPUShader *sh = OVERLAY_shader_edit_uv_verts_get(); pd->edit_uv_verts_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps); - const float point_size = UI_GetThemeValuef(TH_VERTEX_SIZE) * U.dpi_fac; + const float point_size = UI_GetThemeValuef(TH_VERTEX_SIZE) * UI_SCALE_FAC; DRW_shgroup_uniform_block(pd->edit_uv_verts_grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_float_copy( @@ -261,7 +261,7 @@ void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) /* uv face dots */ if (pd->edit_uv.do_face_dots) { - const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) * U.dpi_fac; + const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) * UI_SCALE_FAC; GPUShader *sh = OVERLAY_shader_edit_uv_face_dots_get(); pd->edit_uv_face_dots_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps); DRW_shgroup_uniform_block(pd->edit_uv_face_dots_grp, "globalsBlock", G_draw.block_ubo); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index d32523a574f..30a174754cc 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -225,7 +225,7 @@ static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCa int i; BM_ITER_MESH_INDEX (f, &iter, mr->bm, BM_FACES_OF_MESH, i) { if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - const int mat = min_ii(f->mat_nr, mat_last); + const int mat = clamp_i(f->mat_nr, 0, mat_last); tri_first_index[i] = mat_tri_offs[mat]; mat_tri_offs[mat] += f->len - 2; } @@ -238,7 +238,7 @@ static void mesh_render_data_polys_sorted_build(MeshRenderData *mr, MeshBufferCa for (int i = 0; i < mr->poly_len; i++) { if (!(mr->use_hide && mr->hide_poly && mr->hide_poly[i])) { const MPoly &poly = mr->polys[i]; - const int mat = min_ii(mr->material_indices ? mr->material_indices[i] : 0, mat_last); + const int mat = mr->material_indices ? clamp_i(mr->material_indices[i], 0, mat_last) : 0; tri_first_index[i] = mat_tri_offs[mat]; mat_tri_offs[mat] += poly.totloop - 2; } @@ -263,7 +263,7 @@ static void mesh_render_data_mat_tri_len_bm_range_fn(void *__restrict userdata, BMesh *bm = mr->bm; BMFace *efa = BM_face_at_index(bm, iter); if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - int mat = min_ii(efa->mat_nr, mr->mat_len - 1); + int mat = clamp_i(efa->mat_nr, 0, mr->mat_len - 1); mat_tri_len[mat] += efa->len - 2; } } @@ -277,7 +277,9 @@ static void mesh_render_data_mat_tri_len_mesh_range_fn(void *__restrict userdata const MPoly &poly = mr->polys[iter]; if (!(mr->use_hide && mr->hide_poly && mr->hide_poly[iter])) { - int mat = min_ii(mr->material_indices ? mr->material_indices[iter] : 0, mr->mat_len - 1); + const int mat = mr->material_indices ? + clamp_i(mr->material_indices[iter], 0, mr->mat_len - 1) : + 0; mat_tri_len[mat] += poly.totloop - 2; } } @@ -363,7 +365,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ mr->poly_normals = mr->me->poly_normals(); } if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { - mr->loop_normals.reinitialize(mr->loops.size()); + mr->loop_normals.reinitialize(mr->corner_verts.size()); short(*clnors)[2] = static_cast( CustomData_get_layer_for_write(&mr->me->ldata, CD_CUSTOMLOOPNORMAL, mr->me->totloop)); const bool *sharp_edges = static_cast( @@ -371,7 +373,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ blender::bke::mesh::normals_calc_loop(mr->vert_positions, mr->edges, mr->polys, - mr->loops, + mr->corner_verts, + mr->corner_edges, {}, mr->vert_normals, mr->poly_normals, @@ -546,7 +549,8 @@ MeshRenderData *mesh_render_data_create(Object *object, mr->vert_positions = mr->me->vert_positions(); mr->edges = mr->me->edges(); mr->polys = mr->me->polys(); - mr->loops = mr->me->loops(); + mr->corner_verts = mr->me->corner_verts(); + mr->corner_edges = mr->me->corner_edges(); mr->v_origindex = static_cast(CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX)); mr->e_origindex = static_cast(CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX)); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index 980b9856491..55ab3c32fe0 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -358,7 +358,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, CustomData_get_named_layer(cd_ldata, CD_PROP_FLOAT2, name) : CustomData_get_render_layer(cd_ldata, CD_PROP_FLOAT2); } - if (layer != -1) { + if (layer != -1 && !CustomData_layer_is_anonymous(cd_ldata, CD_PROP_FLOAT2, layer)) { cd_used.uv |= (1 << layer); } break; diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 2f0dd84af8c..6e30eef72d3 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -838,8 +838,12 @@ static DRWSubdivCache *mesh_batch_cache_ensure_subdiv_cache(MeshBatchCache *mbc) static void draw_subdiv_invalidate_evaluator_for_orco(Subdiv *subdiv, Mesh *mesh) { + if (!(subdiv && subdiv->evaluator)) { + return; + } + const bool has_orco = CustomData_has_layer(&mesh->vdata, CD_ORCO); - if (has_orco && subdiv->evaluator && !subdiv->evaluator->hasVertexData(subdiv->evaluator)) { + if (has_orco && !subdiv->evaluator->hasVertexData(subdiv->evaluator)) { /* If we suddenly have/need original coordinates, recreate the evaluator if the extra * source was not created yet. The refiner also has to be recreated as refinement for source * and vertex data is done only once. */ @@ -2113,13 +2117,13 @@ static bool draw_subdiv_create_requested_buffers(Object *ob, bm = mesh->edit_mesh->bm; } + draw_subdiv_invalidate_evaluator_for_orco(runtime_data->subdiv_gpu, mesh_eval); + Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, mesh_eval, true); if (!subdiv) { return false; } - draw_subdiv_invalidate_evaluator_for_orco(subdiv, mesh_eval); - if (!BKE_subdiv_eval_begin_from_mesh( subdiv, mesh_eval, nullptr, SUBDIV_EVALUATOR_TYPE_GPU, evaluator_cache)) { /* This could happen in two situations: diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc index 6b7f0b109d1..74ae3911f37 100644 --- a/source/blender/draw/intern/draw_manager_data.cc +++ b/source/blender/draw/intern/draw_manager_data.cc @@ -1235,9 +1235,7 @@ static void sculpt_draw_cb(DRWSculptCallbackData *scd, if (scd->use_mats) { index = drw_pbvh_material_index_get(batches); - if (index >= scd->num_shading_groups) { - index = 0; - } + index = clamp_i(index, 0, scd->num_shading_groups - 1); } DRWShadingGroup *shgrp = scd->shading_groups[index]; diff --git a/source/blender/draw/intern/draw_manager_text.cc b/source/blender/draw/intern/draw_manager_text.cc index 6ebcf72db3a..31215ec0090 100644 --- a/source/blender/draw/intern/draw_manager_text.cc +++ b/source/blender/draw/intern/draw_manager_text.cc @@ -127,7 +127,7 @@ static void drw_text_cache_draw_ex(DRWTextStore *dt, ARegion *region) const uiStyle *style = UI_style_get(); - BLF_size(font_id, style->widget.points * U.dpi_fac); + BLF_size(font_id, style->widget.points * UI_SCALE_FAC); BLI_memiter_iter_init(dt->cache_strings, &it); while ((vos = static_cast(BLI_memiter_iter_step(&it)))) { @@ -249,7 +249,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_INDICES) && (em->selectmode & SCE_SELECT_EDGE)) { edge_tex_count += 1; } - const short edge_tex_sep = short((edge_tex_count - 1) * 5.0f * U.dpi_fac); + const short edge_tex_sep = short((edge_tex_count - 1) * 5.0f * UI_SCALE_FAC); /* Make the precision of the display value proportionate to the grid-size. */ diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index a5f2461f06c..c8d99de3a16 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -347,7 +347,7 @@ struct PBVHBatches { const MPoly &poly = args->polys[tri->poly]; const float3 fno = blender::bke::mesh::poly_normal_calc( {reinterpret_cast(args->vert_positions), args->mesh_verts_num}, - {&args->mloop[poly.loopstart], poly.totloop}); + {&args->corner_verts[poly.loopstart], poly.totloop}); normal_float_to_short_v3(no, fno); } } @@ -546,10 +546,10 @@ struct PBVHBatches { void fill_vbo_faces(PBVHVbo &vbo, PBVH_GPU_Args *args) { + const blender::Span corner_verts = args->corner_verts; auto foreach_faces = [&](std::function func) { int buffer_i = 0; - const MLoop *mloop = args->mloop; for (int i : IndexRange(args->totprim)) { int face_index = args->mlooptri[args->prim_indices[i]].poly; @@ -561,7 +561,7 @@ struct PBVHBatches { const MLoopTri *tri = args->mlooptri + args->prim_indices[i]; for (int j : IndexRange(3)) { - func(buffer_i, j, mloop[tri->tri[j]].v, tri); + func(buffer_i, j, corner_verts[tri->tri[j]], tri); buffer_i++; } } @@ -990,7 +990,8 @@ struct PBVHBatches { } int r_edges[3]; - BKE_mesh_looptri_get_real_edges(edges.data(), args->mloop, lt, r_edges); + BKE_mesh_looptri_get_real_edges( + edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges); if (r_edges[0] != -1) { edge_count++; @@ -1015,7 +1016,8 @@ struct PBVHBatches { } int r_edges[3]; - BKE_mesh_looptri_get_real_edges(edges.data(), args->mloop, lt, r_edges); + BKE_mesh_looptri_get_real_edges( + edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges); if (r_edges[0] != -1) { GPU_indexbuf_add_line_verts(&elb_lines, vertex_i, vertex_i + 1); diff --git a/source/blender/draw/intern/draw_texture_pool.cc b/source/blender/draw/intern/draw_texture_pool.cc index dc155399425..d572cc75b27 100644 --- a/source/blender/draw/intern/draw_texture_pool.cc +++ b/source/blender/draw/intern/draw_texture_pool.cc @@ -206,7 +206,8 @@ void DRW_texture_pool_reset(DRWTexturePool *pool) } } - BLI_assert(pool->tmp_tex_acquired.is_empty()); + BLI_assert_msg(pool->tmp_tex_acquired.is_empty(), + "Missing a TextureFromPool.release() before end of draw."); for (GPUTexture *tmp_tex : pool->tmp_tex_pruned) { GPU_texture_free(tmp_tex); } diff --git a/source/blender/draw/intern/draw_view.hh b/source/blender/draw/intern/draw_view.hh index 3e93e0043aa..1c64fb549a8 100644 --- a/source/blender/draw/intern/draw_view.hh +++ b/source/blender/draw/intern/draw_view.hh @@ -75,6 +75,12 @@ class View { /** Disable a range in the multi-view array. Disabled view will not produce any instances. */ void disable(IndexRange range); + /** Enable or disable every visibility test (frustum culling, HiZ culling). */ + void visibility_test(bool enable) + { + do_visibility_ = enable; + } + /** * Update culling data using a compute shader. * This is to be used if the matrices were updated externally diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index 7991e7b256c..1f76174de88 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -78,7 +78,8 @@ struct MeshRenderData { blender::Span vert_positions; blender::Span edges; blender::Span polys; - blender::Span loops; + blender::Span corner_verts; + blender::Span corner_edges; BMVert *eve_act; BMEdge *eed_act; BMFace *efa_act; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc index c71fc5619ad..d8bd1a34864 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc @@ -209,7 +209,6 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, void *_data) { MeshExtract_EditUvElem_Data *data = static_cast(_data); - const MLoop *mloop = mr->loops.data(); const int ml_index_end = poly->loopstart + poly->totloop; bool mp_hidden, mp_select; @@ -224,12 +223,11 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, } for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; + const int edge = mr->corner_edges[ml_index]; const int ml_index_last = poly->totloop + poly->loopstart - 1; const int ml_index_next = (ml_index == ml_index_last) ? poly->loopstart : (ml_index + 1); - const bool real_edge = (mr->e_origindex == nullptr || - mr->e_origindex[ml->e] != ORIGINDEX_NONE); + const bool real_edge = (mr->e_origindex == nullptr || mr->e_origindex[edge] != ORIGINDEX_NONE); edituv_edge_add(data, mp_hidden || !real_edge, mp_select, ml_index, ml_index_next); } } @@ -402,9 +400,9 @@ static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert = mr->corner_verts[ml_index]; - const bool real_vert = !mr->v_origindex || mr->v_origindex[ml->v] != ORIGINDEX_NONE; + const bool real_vert = !mr->v_origindex || mr->v_origindex[vert] != ORIGINDEX_NONE; edituv_point_add(data, mp_hidden || !real_vert, mp_select, ml_index); } } @@ -560,10 +558,10 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert = mr->corner_verts[ml_index]; const bool real_fdot = !mr->p_origindex || (mr->p_origindex[poly_index] != ORIGINDEX_NONE); - const bool subd_fdot = facedot_tags[ml->v]; + const bool subd_fdot = facedot_tags[vert]; edituv_facedot_add(data, mp_hidden || !real_fdot || !subd_fdot, mp_select, poly_index); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc index c27ba8bdf89..4e8516f508c 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc @@ -50,8 +50,8 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; - if (facedot_tags[ml->v] && !hidden) { + const int vert = mr->corner_verts[ml_index]; + if (facedot_tags[vert] && !hidden) { GPU_indexbuf_set_point_vert(elb, poly_index, poly_index); return; } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc index 49179307011..b044756c71d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc @@ -62,13 +62,13 @@ static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_last = poly->loopstart + (poly->totloop - 1); int ml_index = ml_index_last, ml_index_next = poly->loopstart; do { - const MLoop *ml = &mr->loops[ml_index]; - if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[ml->e]) || - ((e_origindex) && (e_origindex[ml->e] == ORIGINDEX_NONE)))) { - GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next); + const int edge = mr->corner_edges[ml_index]; + if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[edge]) || + ((e_origindex) && (e_origindex[edge] == ORIGINDEX_NONE)))) { + GPU_indexbuf_set_line_verts(elb, edge, ml_index, ml_index_next); } else { - GPU_indexbuf_set_line_restart(elb, ml->e); + GPU_indexbuf_set_line_restart(elb, edge); } } while ((ml_index = ml_index_next++) != ml_index_last); } @@ -76,8 +76,8 @@ static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_last = poly->loopstart + (poly->totloop - 1); int ml_index = ml_index_last, ml_index_next = poly->loopstart; do { - const MLoop *ml = &mr->loops[ml_index]; - GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next); + const int edge = mr->corner_edges[ml_index]; + GPU_indexbuf_set_line_verts(elb, edge, ml_index, ml_index_next); } while ((ml_index = ml_index_next++) != ml_index_last); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc index 39253de805d..c1a9fe7ef19 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc @@ -123,9 +123,9 @@ static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr, if (hidden) { return; } - lines_adjacency_triangle(mr->loops[mlt->tri[0]].v, - mr->loops[mlt->tri[1]].v, - mr->loops[mlt->tri[2]].v, + lines_adjacency_triangle(mr->corner_verts[mlt->tri[0]], + mr->corner_verts[mlt->tri[1]], + mr->corner_verts[mlt->tri[2]], mlt->tri[0], mlt->tri[1], mlt->tri[2], diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc index 082299e82f0..b4680191a36 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc @@ -43,9 +43,8 @@ static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, MeshExtract_LinePaintMask_Data *data = static_cast(_data); const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int e_index = mr->corner_edges[ml_index]; - const int e_index = ml->e; if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[e_index]) || ((mr->e_origindex) && (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc index f0bf091d6ad..d283a064d72 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc @@ -76,8 +76,7 @@ static void extract_points_iter_poly_mesh(const MeshRenderData *mr, GPUIndexBufBuilder *elb = static_cast(_userdata); const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; - vert_set_mesh(elb, mr, ml->v, ml_index); + vert_set_mesh(elb, mr, mr->corner_verts[ml_index], ml_index); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc index 20e90dc249f..596e6e6750a 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc @@ -185,7 +185,8 @@ static void fill_vertbuf_with_attribute(const MeshRenderData *mr, BLI_assert(custom_data); const int layer_index = request.layer_index; - const MLoop *mloop = mr->loops.data(); + const Span corner_verts = mr->corner_verts; + const Span corner_edges = mr->corner_edges; const AttributeType *attr_data = static_cast( CustomData_get_layer_n(custom_data, request.cd_type, layer_index)); @@ -194,8 +195,8 @@ static void fill_vertbuf_with_attribute(const MeshRenderData *mr, switch (request.domain) { case ATTR_DOMAIN_POINT: - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++, mloop++) { - *vbo_data = Converter::convert_value(attr_data[mloop->v]); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++) { + *vbo_data = Converter::convert_value(attr_data[corner_verts[ml_index]]); } break; case ATTR_DOMAIN_CORNER: @@ -204,8 +205,8 @@ static void fill_vertbuf_with_attribute(const MeshRenderData *mr, } break; case ATTR_DOMAIN_EDGE: - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++, mloop++) { - *vbo_data = Converter::convert_value(attr_data[mloop->e]); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++) { + *vbo_data = Converter::convert_value(attr_data[corner_edges[ml_index]]); } break; case ATTR_DOMAIN_FACE: diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc index 8a9fb4a184a..340fa51f184 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc @@ -106,26 +106,27 @@ static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert = mr->corner_verts[ml_index]; + const int edge = mr->corner_edges[ml_index]; if (data->use_edge_render) { - data->vbo_data[ml_index] = optimal_display_edges[ml->e] ? 255 : 0; + data->vbo_data[ml_index] = optimal_display_edges[edge] ? 255 : 0; } else { /* Count loop per edge to detect non-manifold. */ - if (data->edge_loop_count[ml->e] < 3) { - data->edge_loop_count[ml->e]++; + if (data->edge_loop_count[edge] < 3) { + data->edge_loop_count[edge]++; } - if (data->edge_loop_count[ml->e] == 2) { + if (data->edge_loop_count[edge] == 2) { /* Manifold */ const int ml_index_last = poly->totloop + poly->loopstart - 1; const int ml_index_other = (ml_index == ml_index_last) ? poly->loopstart : (ml_index + 1); - const MLoop *ml_next = &mr->loops[ml_index_other]; + const int vert_next = mr->corner_verts[ml_index_other]; float ratio = loop_edge_factor_get(mr->poly_normals[poly_index], - mr->vert_positions[ml->v], - mr->vert_normals[ml->v], - mr->vert_positions[ml_next->v]); + mr->vert_positions[vert], + mr->vert_normals[vert], + mr->vert_positions[vert_next]); data->vbo_data[ml_index] = ratio * 253 + 1; } else { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc index 553ad0cb4c9..1d56228c089 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc @@ -153,12 +153,11 @@ static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; EditLoopData *data = vbo_data + ml_index; memset(data, 0x0, sizeof(*data)); BMFace *efa = bm_original_face_get(mr, poly_index); - BMEdge *eed = bm_original_edge_get(mr, ml->e); - BMVert *eve = bm_original_vert_get(mr, ml->v); + BMVert *eve = bm_original_vert_get(mr, mr->corner_verts[ml_index]); + BMEdge *eed = bm_original_edge_get(mr, mr->corner_edges[ml_index]); if (efa) { mesh_render_data_face_flag(mr, efa, {-1, -1, -1, -1}, data); } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc index e93c341f73d..1d31665d041 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc @@ -77,14 +77,12 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, MeshExtract_EditUVData_Data *data = static_cast(_data); const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; - EditLoopData *eldata = &data->vbo_data[ml_index]; memset(eldata, 0x0, sizeof(*eldata)); BMFace *efa = bm_original_face_get(mr, poly_index); if (efa) { - BMEdge *eed = bm_original_edge_get(mr, ml->e); - BMVert *eve = bm_original_vert_get(mr, ml->v); + BMVert *eve = bm_original_vert_get(mr, mr->corner_verts[ml_index]); + BMEdge *eed = bm_original_edge_get(mr, mr->corner_edges[ml_index]); if (eed && eve) { /* Loop on an edge endpoint. */ BMLoop *l = BM_face_edge_share_loop(efa, eed); @@ -97,8 +95,7 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, * For this, we check if the previous loop was on an edge. */ const int ml_index_last = poly->loopstart + poly->totloop - 1; const int l_prev = (ml_index == poly->loopstart) ? ml_index_last : (ml_index - 1); - const MLoop *ml_prev = &mr->loops[l_prev]; - eed = bm_original_edge_get(mr, ml_prev->e); + eed = bm_original_edge_get(mr, mr->corner_edges[l_prev]); } if (eed) { /* Mapped points on an edge between two edit verts. */ diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc index 014c5ed63e6..bca1efa1f48 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc @@ -173,8 +173,8 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr av, data->uv[ml_index_last], data->uv[l_next_tmp], - mr->vert_positions[mr->loops[ml_index_last].v], - mr->vert_positions[mr->loops[l_next_tmp].v]); + mr->vert_positions[mr->corner_verts[ml_index_last]], + mr->vert_positions[mr->corner_verts[l_next_tmp]]); /* Save last edge. */ copy_v2_v2(last_auv, auv[1]); copy_v3_v3(last_av, av[1]); @@ -193,8 +193,8 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr av, data->uv[ml_index], data->uv[l_next], - mr->vert_positions[mr->loops[ml_index].v], - mr->vert_positions[mr->loops[l_next].v]); + mr->vert_positions[mr->corner_verts[ml_index]], + mr->vert_positions[mr->corner_verts[l_next]]); } edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[ml_index]); } @@ -248,7 +248,7 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache *subdi /* HACK to fix #68857 */ if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) { int layer = CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2); - if (layer != -1) { + if (layer != -1 && !CustomData_layer_is_anonymous(cd_ldata, CD_PROP_FLOAT2, layer)) { uv_layers |= (1 << layer); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc index 8566a07d764..685e247a5a0 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc @@ -77,8 +77,8 @@ static void compute_area_ratio(const MeshRenderData *mr, const float2 *uv_data = (const float2 *)CustomData_get_layer(&mr->me->ldata, CD_PROP_FLOAT2); for (int poly_index = 0; poly_index < mr->poly_len; poly_index++) { const MPoly &poly = mr->polys[poly_index]; - const float area = bke::mesh::poly_area_calc(mr->vert_positions, - mr->loops.slice(poly.loopstart, poly.totloop)); + const float area = bke::mesh::poly_area_calc( + mr->vert_positions, mr->corner_verts.slice(poly.loopstart, poly.totloop)); float uvarea = area_poly_v2(reinterpret_cast(&uv_data[poly.loopstart]), poly.totloop); tot_area += area; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc index 0ac3bf50bf5..8736d15f454 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc @@ -79,15 +79,15 @@ static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert = mr->corner_verts[ml_index]; if (mr->use_subsurf_fdots) { - if (facedot_tags[ml->v]) { - copy_v3_v3(center[poly_index], mr->vert_positions[ml->v]); + if (facedot_tags[vert]) { + copy_v3_v3(center[poly_index], mr->vert_positions[vert]); break; } } else { - add_v3_v3(center[poly_index], mr->vert_positions[ml->v]); + add_v3_v3(center[poly_index], mr->vert_positions[vert]); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc index 113d5ddea56..c5f04823f8a 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc @@ -78,9 +78,9 @@ static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert = mr->corner_verts[ml_index]; if (mr->use_subsurf_fdots) { - if (facedot_tags[ml->v]) { + if (facedot_tags[vert]) { copy_v2_v2(data->vbo_data[poly_index], data->uv_data[ml_index]); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc index bd15573d859..3bbf3a43080 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc @@ -66,7 +66,7 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert = mr->corner_verts[ml_index]; GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index]; if (!mr->loop_normals.is_empty()) { *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); @@ -75,14 +75,14 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[poly_index]); } else { - *lnor_data = GPU_normal_convert_i10_v3(mr->vert_normals[ml->v]); + *lnor_data = GPU_normal_convert_i10_v3(mr->vert_normals[vert]); } /* Flag for paint mode overlay. * Only use origindex in edit mode where it is used to display the edge-normals. * In paint mode it will use the un-mapped data to draw the wire-frame. */ if (hidden || - (mr->edit_bmesh && (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { + (mr->edit_bmesh && (mr->v_origindex) && mr->v_origindex[vert] == ORIGINDEX_NONE)) { lnor_data->w = -1; } else if (mr->select_poly && mr->select_poly[poly_index]) { @@ -190,7 +190,7 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert = mr->corner_verts[ml_index]; gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index]; if (!mr->loop_normals.is_empty()) { normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); @@ -199,14 +199,14 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[poly_index]); } else { - normal_float_to_short_v3(&lnor_data->x, mr->vert_normals[ml->v]); + normal_float_to_short_v3(&lnor_data->x, mr->vert_normals[vert]); } /* Flag for paint mode overlay. * Only use origindex in edit mode where it is used to display the edge-normals. * In paint mode it will use the un-mapped data to draw the wire-frame. */ if (hidden || - (mr->edit_bmesh && (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { + (mr->edit_bmesh && (mr->v_origindex) && mr->v_origindex[vert] == ORIGINDEX_NONE)) { lnor_data->w = -1; } else if (mr->select_poly && mr->select_poly[poly_index]) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc index 55f65dac942..c0788cb4eb2 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc @@ -217,9 +217,9 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) const Span looptris = mr->looptris; for (const int i : looptris.index_range()) { const int index = looptris[i].poly; - const float *cos[3] = {mr->vert_positions[mr->loops[looptris[i].tri[0]].v], - mr->vert_positions[mr->loops[looptris[i].tri[1]].v], - mr->vert_positions[mr->loops[looptris[i].tri[2]].v]}; + const float *cos[3] = {mr->vert_positions[mr->corner_verts[looptris[i].tri[0]]], + mr->vert_positions[mr->corner_verts[looptris[i].tri[1]]], + mr->vert_positions[mr->corner_verts[looptris[i].tri[2]]]}; float ray_co[3]; float ray_no[3]; @@ -260,7 +260,7 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) struct BVHTree_OverlapData { Span positions; - Span loops; + Span corner_verts; Span looptris; float epsilon; }; @@ -276,12 +276,12 @@ static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int /*threa return false; } - const float *tri_a_co[3] = {data->positions[data->loops[tri_a->tri[0]].v], - data->positions[data->loops[tri_a->tri[1]].v], - data->positions[data->loops[tri_a->tri[2]].v]}; - const float *tri_b_co[3] = {data->positions[data->loops[tri_b->tri[0]].v], - data->positions[data->loops[tri_b->tri[1]].v], - data->positions[data->loops[tri_b->tri[2]].v]}; + const float *tri_a_co[3] = {data->positions[data->corner_verts[tri_a->tri[0]]], + data->positions[data->corner_verts[tri_a->tri[1]]], + data->positions[data->corner_verts[tri_a->tri[2]]]}; + const float *tri_b_co[3] = {data->positions[data->corner_verts[tri_b->tri[0]]], + data->positions[data->corner_verts[tri_b->tri[1]]], + data->positions[data->corner_verts[tri_b->tri[2]]]}; float ix_pair[2][3]; int verts_shared = 0; @@ -343,7 +343,7 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect) struct BVHTree_OverlapData data = {}; data.positions = mr->vert_positions; - data.loops = mr->loops; + data.corner_verts = mr->corner_verts; data.looptris = mr->looptris; data.epsilon = BLI_bvhtree_get_epsilon(tree); @@ -450,14 +450,14 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) fac = 0.0f; for (int i = 1; i <= poly.totloop; i++) { - const MLoop *l_prev = &mr->loops[poly.loopstart + (i - 1) % poly.totloop]; - const MLoop *l_curr = &mr->loops[poly.loopstart + (i + 0) % poly.totloop]; - const MLoop *l_next = &mr->loops[poly.loopstart + (i + 1) % poly.totloop]; + const int corner_prev = poly.loopstart + (i - 1) % poly.totloop; + const int corner_curr = poly.loopstart + (i + 0) % poly.totloop; + const int corner_next = poly.loopstart + (i + 1) % poly.totloop; float no_corner[3]; normal_tri_v3(no_corner, - mr->vert_positions[l_prev->v], - mr->vert_positions[l_curr->v], - mr->vert_positions[l_next->v]); + mr->vert_positions[mr->corner_verts[corner_prev]], + mr->vert_positions[mr->corner_verts[corner_curr]], + mr->vert_positions[mr->corner_verts[corner_next]]); /* simple way to detect (what is most likely) concave */ if (dot_v3v3(f_no, no_corner) < 0.0f) { negate_v3(no_corner); @@ -533,11 +533,11 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) for (const int poly_index : mr->polys.index_range()) { const MPoly &poly = mr->polys[poly_index]; for (int i = 0; i < poly.totloop; i++) { - const MLoop *l_curr = &mr->loops[poly.loopstart + (i + 0) % poly.totloop]; - const MLoop *l_next = &mr->loops[poly.loopstart + (i + 1) % poly.totloop]; + const int vert_curr = mr->corner_verts[poly.loopstart + (i + 0) % poly.totloop]; + const int vert_next = mr->corner_verts[poly.loopstart + (i + 1) % poly.totloop]; float angle; void **pval; - bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval); + bool value_is_init = BLI_edgehash_ensure_p(eh, vert_curr, vert_next, &pval); if (!value_is_init) { *pval = (void *)&mr->poly_normals[poly_index]; /* non-manifold edge, yet... */ @@ -548,7 +548,7 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) const float *f2_no = static_cast(*pval); angle = angle_normalized_v3v3(f1_no, f2_no); angle = is_edge_convex_v3( - mr->vert_positions[l_curr->v], mr->vert_positions[l_next->v], f1_no, f2_no) ? + mr->vert_positions[vert_curr], mr->vert_positions[vert_next], f1_no, f2_no) ? angle : -angle; /* Tag as manifold. */ @@ -558,8 +558,8 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) /* non-manifold edge */ angle = DEG2RADF(90.0f); } - float *col1 = &vert_angles[l_curr->v]; - float *col2 = &vert_angles[l_next->v]; + float *col1 = &vert_angles[vert_curr]; + float *col2 = &vert_angles[vert_next]; *col1 = max_ff(*col1, angle); *col2 = max_ff(*col2, angle); } @@ -580,9 +580,9 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) BLI_edgehashIterator_free(ehi); BLI_edgehash_free(eh, nullptr); - const MLoop *ml = mr->loops.data(); - for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) { - r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange); + for (int l_index = 0; l_index < mr->loop_len; l_index++) { + const int vert = mr->corner_verts[l_index]; + r_sharp[l_index] = sharp_remap(vert_angles[vert], min, max, minmax_irange); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc index db0de3761e3..ef212b25387 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc @@ -68,10 +68,10 @@ static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, { const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert = mr->corner_verts[ml_index]; MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; float *loop_orco = orco_data->vbo_data[ml_index]; - copy_v3_v3(loop_orco, orco_data->orco[ml->v]); + copy_v3_v3(loop_orco, orco_data->orco[vert]); loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc index d9fc2b71d15..b9813feaecb 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -91,18 +91,18 @@ static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert_i = mr->corner_verts[ml_index]; PosNorLoop *vert = &data->vbo_data[ml_index]; - const bool vert_hidden = mr->hide_vert && mr->hide_vert[ml->v]; - copy_v3_v3(vert->pos, mr->vert_positions[ml->v]); - vert->nor = data->normals[ml->v].low; + const bool vert_hidden = mr->hide_vert && mr->hide_vert[vert_i]; + copy_v3_v3(vert->pos, mr->vert_positions[vert_i]); + vert->nor = data->normals[vert_i].low; /* Flag for paint mode overlay. */ if (poly_hidden || vert_hidden || - ((mr->v_origindex) && (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { + ((mr->v_origindex) && (mr->v_origindex[vert_i] == ORIGINDEX_NONE))) { vert->nor.w = -1; } - else if (mr->select_vert && mr->select_vert[ml->v]) { + else if (mr->select_vert && mr->select_vert[vert_i]) { vert->nor.w = 1; } else { @@ -464,22 +464,21 @@ static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, MeshExtract_PosNorHQ_Data *data = static_cast(_data); const bool poly_hidden = mr->hide_poly && mr->hide_poly[poly - mr->polys.data()]; - const MLoop *mloop = mr->loops.data(); const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mloop[ml_index]; + const int vert_i = mr->corner_verts[ml_index]; - const bool vert_hidden = mr->hide_vert && mr->hide_vert[ml->v]; + const bool vert_hidden = mr->hide_vert && mr->hide_vert[vert_i]; PosNorHQLoop *vert = &data->vbo_data[ml_index]; - copy_v3_v3(vert->pos, mr->vert_positions[ml->v]); - copy_v3_v3_short(vert->nor, data->normals[ml->v].high); + copy_v3_v3(vert->pos, mr->vert_positions[vert_i]); + copy_v3_v3_short(vert->nor, data->normals[vert_i].high); /* Flag for paint mode overlay. */ if (poly_hidden || vert_hidden || - ((mr->v_origindex) && (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { + ((mr->v_origindex) && (mr->v_origindex[vert_i] == ORIGINDEX_NONE))) { vert->nor[3] = -1; } - else if (mr->select_vert && mr->select_vert[ml->v]) { + else if (mr->select_vert && mr->select_vert[vert_i]) { vert->nor[3] = 1; } else { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc index 163ebf3a2f8..40dedd12cc9 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc @@ -39,7 +39,6 @@ static void extract_sculpt_data_init(const MeshRenderData *mr, GPUVertBuf *vbo = static_cast(buf); GPUVertFormat *format = get_sculpt_data_format(); - CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; CustomData *cd_pdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->pdata : &mr->me->pdata; @@ -56,7 +55,6 @@ static void extract_sculpt_data_init(const MeshRenderData *mr, }; gpuSculptData *vbo_data = (gpuSculptData *)GPU_vertbuf_get_data(vbo); - const MLoop *loops = (const MLoop *)CustomData_get_layer(cd_ldata, CD_MLOOP); if (mr->extract_type == MR_EXTRACT_BMESH) { int cd_mask_ofs = CustomData_get_offset(cd_vdata, CD_PAINT_MASK); @@ -92,7 +90,7 @@ static void extract_sculpt_data_init(const MeshRenderData *mr, for (int l = 0; l < poly.totloop; l++) { float v_mask = 0.0f; if (cd_mask) { - v_mask = cd_mask[loops[mp_loop].v]; + v_mask = cd_mask[mr->corner_verts[mp_loop]]; } vbo_data->mask = v_mask; @@ -131,7 +129,7 @@ static void extract_sculpt_data_init_subdiv(const DRWSubdivCache *subdiv_cache, const float *cd_mask = (const float *)CustomData_get_layer(cd_vdata, CD_PAINT_MASK); const Span coarse_polys = coarse_mesh->polys(); - const Span coarse_loops = coarse_mesh->loops(); + const Span coarse_corner_verts = coarse_mesh->corner_verts(); if (cd_mask) { GPUVertFormat mask_format = {0}; @@ -147,8 +145,7 @@ static void extract_sculpt_data_init_subdiv(const DRWSubdivCache *subdiv_cache, for (int loop_index = poly.loopstart; loop_index < poly.loopstart + poly.totloop; loop_index++) { - const MLoop *ml = &coarse_loops[loop_index]; - *v_mask++ = cd_mask[ml->v]; + *v_mask++ = cd_mask[coarse_corner_verts[loop_index]]; } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc index 3c40c481c8f..efc06c4e4e6 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc @@ -127,8 +127,8 @@ static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr, { const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; - (*(int32_t **)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e; + const int edge = mr->corner_edges[ml_index]; + (*(int32_t **)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[edge] : edge; } } @@ -139,8 +139,8 @@ static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr, { const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; - (*(int32_t **)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v; + const int vert = mr->corner_verts[ml_index]; + (*(int32_t **)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[vert] : vert; } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc index e7da5722f56..9e5007bf172 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc @@ -117,7 +117,7 @@ static void extract_tan_init_common(const MeshRenderData *mr, BKE_mesh_calc_loop_tangent_ex(reinterpret_cast(mr->vert_positions.data()), mr->polys.data(), mr->polys.size(), - mr->loops.data(), + mr->corner_verts.data(), mr->looptris.data(), mr->tri_len, mr->sharp_faces, @@ -130,7 +130,7 @@ static void extract_tan_init_common(const MeshRenderData *mr, reinterpret_cast(mr->loop_normals.data()), orco, r_loop_data, - mr->loops.size(), + mr->corner_verts.size(), &tangent_mask); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc index bc73c59f556..c6d5a5fc697 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc @@ -5,8 +5,8 @@ * \ingroup draw */ +#include "BLI_array_utils.hh" #include "BLI_math_vector_types.hh" -#include "BLI_string.h" #include "draw_subdivision.h" #include "extract_mesh.hh" @@ -31,7 +31,7 @@ static bool mesh_extract_uv_format_init(GPUVertFormat *format, /* HACK to fix #68857 */ if (extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) { int layer = CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2); - if (layer != -1) { + if (layer != -1 && !CustomData_layer_is_anonymous(cd_ldata, CD_PROP_FLOAT2, layer)) { uv_layers |= (1 << layer); } } @@ -91,8 +91,9 @@ static void extract_uv_init(const MeshRenderData *mr, GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, v_len); - float2 *uv_data = static_cast(GPU_vertbuf_get_data(vbo)); - for (int i = 0; i < MAX_MTFACE; i++) { + MutableSpan uv_data(static_cast(GPU_vertbuf_get_data(vbo)), v_len); + int vbo_index = 0; + for (const int i : IndexRange(MAX_MTFACE)) { if (uv_layers & (1 << i)) { if (mr->extract_type == MR_EXTRACT_BMESH) { int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_PROP_FLOAT2, i); @@ -102,18 +103,17 @@ static void extract_uv_init(const MeshRenderData *mr, BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(efa); do { - float *luv = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_ofs); - memcpy(uv_data, luv, sizeof(*uv_data)); - uv_data++; + uv_data[vbo_index] = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_ofs); + vbo_index++; } while ((l_iter = l_iter->next) != l_first); } } else { - const float2 *layer_data = static_cast( - CustomData_get_layer_n(cd_ldata, CD_PROP_FLOAT2, i)); - for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) { - memcpy(uv_data, layer_data, sizeof(*uv_data)); - } + const Span uv_map( + static_cast(CustomData_get_layer_n(cd_ldata, CD_PROP_FLOAT2, i)), + mr->loop_len); + array_utils::copy(uv_map, uv_data.slice(vbo_index, mr->loop_len)); + vbo_index += mr->loop_len; } } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc index 7a88e2308d2..efc234bf2cc 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc @@ -140,9 +140,9 @@ static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, MeshExtract_Weight_Data *data = static_cast(_data); const int ml_index_end = poly->loopstart + poly->totloop; for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { - const MLoop *ml = &mr->loops[ml_index]; + const int vert = mr->corner_verts[ml_index]; if (data->dvert != nullptr) { - const MDeformVert *dvert = &data->dvert[ml->v]; + const MDeformVert *dvert = &data->dvert[vert]; data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate); } else { diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 48f7b67edba..ed73e9d0eae 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -5262,7 +5262,7 @@ void ANIM_channel_draw_widgets(const bContext *C, * a callback available (e.g. broken F-Curve rename) */ if (acf->name_prop(ale, &ptr, &prop)) { - const short margin_x = 3 * round_fl_to_int(UI_DPI_FAC); + const short margin_x = 3 * round_fl_to_int(UI_SCALE_FAC); const short width = ac->region->winx - offset - (margin_x * 2); uiBut *but; diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 5609517a9f0..3b26382fee4 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -3651,7 +3651,12 @@ static bool get_normalized_fcurve_bounds(FCurve *fcu, rctf *r_bounds) { const bool fcu_selection_only = false; - BKE_fcurve_calc_bounds(fcu, fcu_selection_only, include_handles, range, r_bounds); + const bool found_bounds = BKE_fcurve_calc_bounds( + fcu, fcu_selection_only, include_handles, range, r_bounds); + + if (!found_bounds) { + return false; + } const short mapping_flag = ANIM_get_normalization_flags(ac); diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index ccefb4e75ef..e54044700e7 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -177,8 +177,8 @@ void ANIM_draw_action_framerange( immUniform4f("color1", color[0], color[1], color[2], color[3]); immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.0f); - immUniform1i("size1", 2 * U.dpi_fac); - immUniform1i("size2", 4 * U.dpi_fac); + immUniform1i("size1", 2 * UI_SCALE_FAC); + immUniform1i("size2", 4 * UI_SCALE_FAC); if (sfra < efra) { immRectf(pos, v2d->cur.xmin, ymin, sfra, ymax); diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 694eb1f7035..74ed7e22fd4 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -251,7 +251,7 @@ static bool region_position_is_over_marker(View2D *v2d, ListBase *markers, float float pixel_distance = UI_view2d_scale_get_x(v2d) * fabsf(nearest_marker->frame - frame_at_position); - return pixel_distance <= UI_DPI_ICON_SIZE; + return pixel_distance <= UI_ICON_SIZE; } /* --------------------------------- */ @@ -419,7 +419,7 @@ static void draw_marker_name(const uchar *text_color, } #endif - const int icon_half_width = UI_DPI_ICON_SIZE * 0.6; + const int icon_half_width = UI_ICON_SIZE * 0.6; const struct uiFontStyleDraw_Params fs_params = {.align = UI_STYLE_TEXT_LEFT, .word_wrap = 0}; const struct rcti rect = { .xmin = marker_x + icon_half_width, @@ -440,7 +440,7 @@ static void draw_marker_line(const uchar *color, int xpos, int ymin, int ymax) float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniformColor4ubv(color); immUniform1i("colors_len", 0); /* "simple" mode */ @@ -482,17 +482,17 @@ static void draw_marker(const uiFontStyle *fstyle, GPU_blend(GPU_BLEND_ALPHA); - draw_marker_line(line_color, xpos, UI_DPI_FAC * 20, region_height); + draw_marker_line(line_color, xpos, UI_SCALE_FAC * 20, region_height); int icon_id = marker_get_icon_id(marker, flag); - UI_icon_draw(xpos - 0.55f * UI_DPI_ICON_SIZE, UI_DPI_FAC * 18, icon_id); + UI_icon_draw(xpos - 0.55f * UI_ICON_SIZE, UI_SCALE_FAC * 18, icon_id); GPU_blend(GPU_BLEND_NONE); - float name_y = UI_DPI_FAC * 18; + float name_y = UI_SCALE_FAC * 18; /* Give an offset to the marker that is elevated. */ if (is_elevated) { - name_y += UI_DPI_FAC * 10; + name_y += UI_SCALE_FAC * 10; } draw_marker_name(text_color, fstyle, marker, xpos, xmax, name_y); } @@ -537,7 +537,7 @@ static void get_marker_region_rect(View2D *v2d, rctf *rect) static void get_marker_clip_frame_range(View2D *v2d, float xscale, int r_range[2]) { - float font_width_max = (10 * UI_DPI_FAC) / xscale; + float font_width_max = (10 * UI_SCALE_FAC) / xscale; r_range[0] = v2d->cur.xmin - sizeof(((TimeMarker *)NULL)->name) * font_width_max; r_range[1] = v2d->cur.xmax + font_width_max; } diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index ebeac6552cd..532002c2355 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -42,7 +42,7 @@ void ED_time_scrub_region_rect_get(const ARegion *region, rcti *rect) static int get_centered_text_y(const rcti *rect) { - return BLI_rcti_cent_y(rect) - UI_DPI_FAC * 4; + return BLI_rcti_cent_y(rect) - UI_SCALE_FAC * 4; } static void draw_background(const rcti *rect) @@ -84,9 +84,9 @@ static void draw_current_frame(const Scene *scene, char frame_str[64]; get_current_time_str(scene, display_seconds, current_frame, sizeof(frame_str), frame_str); float text_width = UI_fontstyle_string_width(fstyle, frame_str); - float box_width = MAX2(text_width + 8 * UI_DPI_FAC, 24 * UI_DPI_FAC); - float box_padding = 3 * UI_DPI_FAC; - const int line_outline = max_ii(1, round_fl_to_int(1 * UI_DPI_FAC)); + float box_width = MAX2(text_width + 8 * UI_SCALE_FAC, 24 * UI_SCALE_FAC); + float box_padding = 3 * UI_SCALE_FAC; + const int line_outline = max_ii(1, round_fl_to_int(1 * UI_SCALE_FAC)); float bg_color[4]; UI_GetThemeColorShade4fv(TH_CFRAME, -5, bg_color); @@ -134,7 +134,7 @@ static void draw_current_frame(const Scene *scene, 1.0f, outline_color, U.pixelsize, - 4 * UI_DPI_FAC); + 4 * UI_SCALE_FAC); uchar text_color[4]; UI_GetThemeColor4ubv(TH_HEADER_TEXT_HI, text_color); @@ -176,7 +176,7 @@ void ED_time_scrub_draw(const ARegion *region, draw_background(&scrub_region_rect); rcti numbers_rect = scrub_region_rect; - numbers_rect.ymin = get_centered_text_y(&scrub_region_rect) - 4 * UI_DPI_FAC; + numbers_rect.ymin = get_centered_text_y(&scrub_region_rect) - 4 * UI_SCALE_FAC; if (discrete_frames) { UI_view2d_draw_scale_x__discrete_frames_or_seconds( region, v2d, &numbers_rect, scene, display_seconds, TH_TEXT); @@ -217,8 +217,8 @@ void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *region, bDope RNA_pointer_create(&CTX_wm_screen(C)->id, &RNA_DopeSheet, dopesheet, &ptr); const uiStyle *style = UI_style_get_dpi(); - const float padding_x = 2 * UI_DPI_FAC; - const float padding_y = UI_DPI_FAC; + const float padding_x = 2 * UI_SCALE_FAC; + const float padding_y = UI_SCALE_FAC; uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS); uiLayout *layout = UI_block_layout(block, diff --git a/source/blender/editors/armature/meshlaplacian.cc b/source/blender/editors/armature/meshlaplacian.cc index 17f3d35b425..71120a413b2 100644 --- a/source/blender/editors/armature/meshlaplacian.cc +++ b/source/blender/editors/armature/meshlaplacian.cc @@ -74,7 +74,7 @@ struct LaplacianSystem { struct HeatWeighting { const MLoopTri *mlooptri; - blender::Span loops; /* needed to find vertices by index */ + blender::Span corner_verts; /* needed to find vertices by index */ int verts_num; int tris_num; float (*verts)[3]; /* vertex coordinates */ @@ -382,14 +382,14 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr { BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata; const MLoopTri *lt = &data->sys->heat.mlooptri[index]; - const blender::Span loops = data->sys->heat.loops; + const blender::Span corner_verts = data->sys->heat.corner_verts; float(*verts)[3] = data->sys->heat.verts; const float *vtri_co[3]; float dist_test; - vtri_co[0] = verts[loops[lt->tri[0]].v]; - vtri_co[1] = verts[loops[lt->tri[1]].v]; - vtri_co[2] = verts[loops[lt->tri[2]].v]; + vtri_co[0] = verts[corner_verts[lt->tri[0]]]; + vtri_co[1] = verts[corner_verts[lt->tri[1]]]; + vtri_co[2] = verts[corner_verts[lt->tri[2]]]; #ifdef USE_KDOPBVH_WATERTIGHT if (isect_ray_tri_watertight_v3( @@ -414,7 +414,7 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr static void heat_ray_tree_create(LaplacianSystem *sys) { const MLoopTri *looptri = sys->heat.mlooptri; - const blender::Span loops = sys->heat.loops; + const blender::Span corner_verts = sys->heat.corner_verts; float(*verts)[3] = sys->heat.verts; int tris_num = sys->heat.tris_num; int verts_num = sys->heat.verts_num; @@ -429,9 +429,9 @@ static void heat_ray_tree_create(LaplacianSystem *sys) float bb[6]; int vtri[3]; - vtri[0] = loops[lt->tri[0]].v; - vtri[1] = loops[lt->tri[1]].v; - vtri[2] = loops[lt->tri[2]].v; + vtri[0] = corner_verts[lt->tri[0]]; + vtri[1] = corner_verts[lt->tri[1]]; + vtri[2] = corner_verts[lt->tri[2]]; INIT_MINMAX(bb, bb + 3); minmax_v3v3_v3(bb, bb + 3, verts[vtri[0]]); @@ -581,7 +581,7 @@ static void heat_calc_vnormals(LaplacianSystem *sys) static void heat_laplacian_create(LaplacianSystem *sys) { const MLoopTri *mlooptri = sys->heat.mlooptri, *lt; - const blender::Span loops = sys->heat.loops; + const blender::Span corner_verts = sys->heat.corner_verts; int tris_num = sys->heat.tris_num; int verts_num = sys->heat.verts_num; int a; @@ -598,9 +598,9 @@ static void heat_laplacian_create(LaplacianSystem *sys) for (a = 0, lt = mlooptri; a < tris_num; a++, lt++) { int vtri[3]; - vtri[0] = loops[lt->tri[0]].v; - vtri[1] = loops[lt->tri[1]].v; - vtri[2] = loops[lt->tri[2]].v; + vtri[0] = corner_verts[lt->tri[0]]; + vtri[1] = corner_verts[lt->tri[1]]; + vtri[2] = corner_verts[lt->tri[2]]; laplacian_add_triangle(sys, UNPACK3(vtri)); } @@ -658,7 +658,7 @@ void heat_bone_weighting(Object *ob, const blender::Span vert_positions = me->vert_positions(); const blender::Span polys = me->polys(); - const blender::Span loops = me->loops(); + const blender::Span corner_verts = me->corner_verts(); bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; @@ -677,8 +677,8 @@ void heat_bone_weighting(Object *ob, &me->vdata, CD_PROP_BOOL, ".select_vert"); if (select_vert) { for (const int i : polys.index_range()) { - for (const MLoop &loop : loops.slice(polys[i].loopstart, polys[i].totloop)) { - mask[loop.v] = select_vert[loop.v]; + for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) { + mask[vert] = select_vert[vert]; } } } @@ -689,8 +689,8 @@ void heat_bone_weighting(Object *ob, if (select_poly) { for (const int i : polys.index_range()) { if (select_poly[i]) { - for (const MLoop &loop : loops.slice(polys[i].loopstart, polys[i].totloop)) { - mask[loop.v] = 1; + for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) { + mask[vert] = 1; } } } @@ -705,10 +705,11 @@ void heat_bone_weighting(Object *ob, mlooptri = static_cast( MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tris_num, __func__)); - blender::bke::mesh::looptris_calc(vert_positions, polys, loops, {mlooptri, sys->heat.tris_num}); + blender::bke::mesh::looptris_calc( + vert_positions, polys, corner_verts, {mlooptri, sys->heat.tris_num}); sys->heat.mlooptri = mlooptri; - sys->heat.loops = loops; + sys->heat.corner_verts = corner_verts; sys->heat.verts_num = me->totvert; sys->heat.verts = verts; sys->heat.root = root; @@ -926,7 +927,7 @@ typedef struct MeshDeformBind { /* avoid DM function calls during intersections */ struct { blender::Span polys; - blender::Span loops; + blender::Span corner_verts; blender::Span looptris; blender::Span poly_normals; } cagemesh_cache; @@ -957,7 +958,7 @@ static void harmonic_ray_callback(void *userdata, { MeshRayCallbackData *data = static_cast(userdata); MeshDeformBind *mdb = data->mdb; - const blender::Span loops = mdb->cagemesh_cache.loops; + const blender::Span corner_verts = mdb->cagemesh_cache.corner_verts; const blender::Span poly_normals = mdb->cagemesh_cache.poly_normals; MeshDeformIsect *isec = data->isec; float no[3], co[3], dist; @@ -965,9 +966,9 @@ static void harmonic_ray_callback(void *userdata, const MLoopTri *lt = &mdb->cagemesh_cache.looptris[index]; - face[0] = mdb->cagecos[loops[lt->tri[0]].v]; - face[1] = mdb->cagecos[loops[lt->tri[1]].v]; - face[2] = mdb->cagecos[loops[lt->tri[2]].v]; + face[0] = mdb->cagecos[corner_verts[lt->tri[0]]]; + face[1] = mdb->cagecos[corner_verts[lt->tri[1]]]; + face[2] = mdb->cagecos[corner_verts[lt->tri[2]]]; bool isect_ray_tri = isect_ray_tri_watertight_v3( ray->origin, ray->isect_precalc, UNPACK3(face), &dist, nullptr); @@ -1031,7 +1032,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, harmonic_ray_callback, &data, BVH_RAYCAST_WATERTIGHT) != -1) { - const blender::Span loops = mdb->cagemesh_cache.loops; + const blender::Span corner_verts = mdb->cagemesh_cache.corner_verts; const MLoopTri *lt = &mdb->cagemesh_cache.looptris[hit.index]; const MPoly &poly = mdb->cagemesh_cache.polys[lt->poly]; const float(*cagecos)[3] = mdb->cagecos; @@ -1055,7 +1056,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, /* compute mean value coordinates for interpolation */ for (int i = 0; i < poly.totloop; i++) { - copy_v3_v3(mp_cagecos[i], cagecos[loops[poly.loopstart + i].v]); + copy_v3_v3(mp_cagecos[i], cagecos[corner_verts[poly.loopstart + i]]); } interp_weights_poly_v3(isect->poly_weights, @@ -1224,11 +1225,11 @@ static float meshdeform_boundary_phi(const MeshDeformBind *mdb, const MDefBoundIsect *isect, int cagevert) { - const blender::Span loops = mdb->cagemesh_cache.loops; + const blender::Span corner_verts = mdb->cagemesh_cache.corner_verts; const MPoly &poly = mdb->cagemesh_cache.polys[isect->poly_index]; for (int i = 0; i < poly.totloop; i++) { - if (loops[poly.loopstart + i].v == cagevert) { + if (corner_verts[poly.loopstart + i] == cagevert) { return isect->poly_weights[i]; } } @@ -1629,7 +1630,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin { Mesh *me = mdb->cagemesh; mdb->cagemesh_cache.polys = me->polys(); - mdb->cagemesh_cache.loops = me->loops(); + mdb->cagemesh_cache.corner_verts = me->corner_verts(); mdb->cagemesh_cache.looptris = me->looptris(); mdb->cagemesh_cache.poly_normals = me->poly_normals(); } diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt index a4d05ebaffe..9d5f10eddd2 100644 --- a/source/blender/editors/asset/CMakeLists.txt +++ b/source/blender/editors/asset/CMakeLists.txt @@ -24,6 +24,7 @@ set(SRC intern/asset_catalog.cc intern/asset_filter.cc intern/asset_handle.cc + intern/asset_import.cc intern/asset_indexer.cc intern/asset_library_reference.cc intern/asset_library_reference_enum.cc @@ -37,6 +38,7 @@ set(SRC ED_asset_catalog.hh ED_asset_filter.h ED_asset_handle.h + ED_asset_import.h ED_asset_indexer.h ED_asset_library.h ED_asset_list.h diff --git a/source/blender/editors/asset/ED_asset_handle.h b/source/blender/editors/asset/ED_asset_handle.h index 436194fd885..8bfd4f7150e 100644 --- a/source/blender/editors/asset/ED_asset_handle.h +++ b/source/blender/editors/asset/ED_asset_handle.h @@ -21,6 +21,7 @@ extern "C" { struct AssetHandle; +struct AssetRepresentation *ED_asset_handle_get_representation(const struct AssetHandle *asset); const char *ED_asset_handle_get_name(const struct AssetHandle *asset); struct AssetMetaData *ED_asset_handle_get_metadata(const struct AssetHandle *asset); struct ID *ED_asset_handle_get_local_id(const struct AssetHandle *asset); @@ -45,11 +46,4 @@ void ED_asset_handle_get_full_library_path( std::optional ED_asset_handle_get_import_method( const struct AssetHandle *asset); -namespace blender::ed::asset { - -/** If the ID already exists in the database, return it, otherwise add it. */ -ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain, AssetHandle asset); - -} // namespace blender::ed::asset - #endif diff --git a/source/blender/editors/asset/ED_asset_import.h b/source/blender/editors/asset/ED_asset_import.h new file mode 100644 index 00000000000..16c06c6416c --- /dev/null +++ b/source/blender/editors/asset/ED_asset_import.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup edasset + */ + +#pragma once + +#include "DNA_ID_enums.h" + +struct AssetRepresentation; +struct Main; + +#ifdef __cplusplus +extern "C" { +#endif + +struct ID *ED_asset_get_local_id_from_asset_or_append_and_reuse( + struct Main *bmain, const struct AssetRepresentation *asset_c_ptr, ID_Type idtype); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/asset/ED_asset_list.h b/source/blender/editors/asset/ED_asset_list.h index 30f961421a5..19528c5dde6 100644 --- a/source/blender/editors/asset/ED_asset_list.h +++ b/source/blender/editors/asset/ED_asset_list.h @@ -6,11 +6,12 @@ #pragma once +#include "DNA_asset_types.h" + #ifdef __cplusplus extern "C" { #endif -struct AssetHandle; struct AssetLibraryReference; struct ID; struct bContext; @@ -49,6 +50,9 @@ void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new); */ void ED_assetlist_storage_exit(void); +AssetHandle ED_assetlist_asset_get_by_index(const AssetLibraryReference *library_reference, + int asset_index); + struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle); /** diff --git a/source/blender/editors/asset/ED_asset_list.hh b/source/blender/editors/asset/ED_asset_list.hh index 524fee274f8..eeca6390bca 100644 --- a/source/blender/editors/asset/ED_asset_list.hh +++ b/source/blender/editors/asset/ED_asset_list.hh @@ -30,4 +30,8 @@ blender::asset_system::AssetLibrary *ED_assetlist_library_get_once_available( /* Can return false to stop iterating. */ using AssetListIterFn = blender::FunctionRef; +/** + * \warning Never keep the asset handle passed to \a fn outside of \a fn's scope. While iterating, + * the file data wrapped by the asset handle can be freed, since the file cache has a maximum size. + */ void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn); diff --git a/source/blender/editors/asset/intern/asset_handle.cc b/source/blender/editors/asset/intern/asset_handle.cc index 4a6a7fda40b..824d5d0ed08 100644 --- a/source/blender/editors/asset/intern/asset_handle.cc +++ b/source/blender/editors/asset/intern/asset_handle.cc @@ -9,13 +9,20 @@ #include "AS_asset_representation.h" #include "AS_asset_representation.hh" +#include "BKE_blendfile.h" + +#include "BLI_string.h" + #include "DNA_space_types.h" -#include "BLO_readfile.h" +#include "DNA_space_types.h" #include "ED_asset_handle.h" -#include "WM_api.h" +AssetRepresentation *ED_asset_handle_get_representation(const AssetHandle *asset) +{ + return asset->file_data->asset; +} const char *ED_asset_handle_get_name(const AssetHandle *asset) { @@ -53,36 +60,11 @@ void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle, { *r_full_lib_path = '\0'; - std::string asset_path = AS_asset_representation_full_path_get(asset_handle->file_data->asset); - if (asset_path.empty()) { + std::string library_path = AS_asset_representation_full_library_path_get( + asset_handle->file_data->asset); + if (library_path.empty()) { return; } - BLO_library_path_explode(asset_path.c_str(), r_full_lib_path, nullptr, nullptr); + BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX); } - -namespace blender::ed::asset { - -ID *get_local_id_from_asset_or_append_and_reuse(Main &bmain, const AssetHandle asset) -{ - if (ID *local_id = ED_asset_handle_get_local_id(&asset)) { - return local_id; - } - - char blend_path[FILE_MAX_LIBEXTRA]; - ED_asset_handle_get_full_library_path(&asset, blend_path); - const char *id_name = ED_asset_handle_get_name(&asset); - - return WM_file_append_datablock(&bmain, - nullptr, - nullptr, - nullptr, - blend_path, - ED_asset_handle_get_id_type(&asset), - id_name, - BLO_LIBLINK_APPEND_RECURSIVE | - BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR | - BLO_LIBLINK_APPEND_LOCAL_ID_REUSE); -} - -} // namespace blender::ed::asset diff --git a/source/blender/editors/asset/intern/asset_import.cc b/source/blender/editors/asset/intern/asset_import.cc new file mode 100644 index 00000000000..f78084dd38c --- /dev/null +++ b/source/blender/editors/asset/intern/asset_import.cc @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup edasset + */ + +#include "AS_asset_representation.h" +#include "AS_asset_representation.hh" + +#include "BLO_readfile.h" + +#include "WM_api.h" + +#include "ED_asset_import.h" + +using namespace blender; + +ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(Main *bmain, + const AssetRepresentation *asset_c_ptr, + ID_Type idtype) +{ + const asset_system::AssetRepresentation &asset = + *reinterpret_cast(asset_c_ptr); + + if (ID *local_id = asset.local_id()) { + return local_id; + } + + std::string blend_path = asset.get_identifier().full_library_path(); + if (blend_path.empty()) { + return nullptr; + } + + return WM_file_append_datablock(bmain, + nullptr, + nullptr, + nullptr, + blend_path.c_str(), + idtype, + asset.get_name().c_str(), + BLO_LIBLINK_APPEND_RECURSIVE | + BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR | + BLO_LIBLINK_APPEND_LOCAL_ID_REUSE); +} diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc index 78859a9206d..c7df300ed24 100644 --- a/source/blender/editors/asset/intern/asset_list.cc +++ b/source/blender/editors/asset/intern/asset_list.cc @@ -112,6 +112,8 @@ class AssetList : NonCopyable { void ensurePreviewsJob(const bContext *C); void clear(bContext *C); + AssetHandle asset_get_by_index(int index) const; + bool needsRefetch() const; bool isLoaded() const; asset_system::AssetLibrary *asset_library() const; @@ -139,7 +141,7 @@ void AssetList::setup() filelist_setlibrary(files, &library_ref_); filelist_setfilter_options( files, - false, + true, true, true, /* Just always hide parent, prefer to not add an extra user option for this. */ FILE_TYPE_BLENDERLIB, @@ -246,6 +248,11 @@ void AssetList::clear(bContext *C) WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, nullptr); } +AssetHandle AssetList::asset_get_by_index(int index) const +{ + return {filelist_file(filelist_, index)}; +} + /** * \return True if the asset-list needs a UI redraw. */ @@ -472,6 +479,13 @@ asset_system::AssetLibrary *ED_assetlist_library_get_once_available( return list->asset_library(); } +AssetHandle ED_assetlist_asset_get_by_index(const AssetLibraryReference *library_reference, + int asset_index) +{ + const AssetList *list = AssetListStorage::lookup_list(*library_reference); + return list->asset_get_by_index(asset_index); +} + ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle) { ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data); diff --git a/source/blender/editors/asset/intern/asset_temp_id_consumer.cc b/source/blender/editors/asset/intern/asset_temp_id_consumer.cc index 076a332c472..d8525d4150f 100644 --- a/source/blender/editors/asset/intern/asset_temp_id_consumer.cc +++ b/source/blender/editors/asset/intern/asset_temp_id_consumer.cc @@ -8,9 +8,15 @@ */ #include +#include + +#include "AS_asset_representation.h" +#include "AS_asset_representation.hh" #include "DNA_space_types.h" +#include "ED_asset.h" + #include "BKE_report.h" #include "BLI_utility_mixins.hh" @@ -19,17 +25,16 @@ #include "MEM_guardedalloc.h" -#include "ED_asset_handle.h" #include "ED_asset_temp_id_consumer.h" using namespace blender; class AssetTemporaryIDConsumer : NonCopyable, NonMovable { - const AssetHandle &handle_; + const AssetRepresentation *asset_; TempLibraryContext *temp_lib_context_ = nullptr; public: - AssetTemporaryIDConsumer(const AssetHandle &handle) : handle_(handle) + AssetTemporaryIDConsumer(const AssetRepresentation *asset) : asset_(asset) { } ~AssetTemporaryIDConsumer() @@ -41,20 +46,20 @@ class AssetTemporaryIDConsumer : NonCopyable, NonMovable { ID *get_local_id() { - return ED_asset_handle_get_local_id(&handle_); + return AS_asset_representation_local_id_get(asset_); } ID *import_id(ID_Type id_type, Main &bmain, ReportList &reports) { - const char *asset_name = ED_asset_handle_get_name(&handle_); - char blend_file_path[FILE_MAX_LIBEXTRA]; - ED_asset_handle_get_full_library_path(&handle_, blend_file_path); + const char *asset_name = AS_asset_representation_name_get(asset_); + std::string blend_file_path = AS_asset_representation_full_library_path_get(asset_); temp_lib_context_ = BLO_library_temp_load_id( - &bmain, blend_file_path, id_type, asset_name, &reports); + &bmain, blend_file_path.c_str(), id_type, asset_name, &reports); if (temp_lib_context_ == nullptr || temp_lib_context_->temp_id == nullptr) { - BKE_reportf(&reports, RPT_ERROR, "Unable to load %s from %s", asset_name, blend_file_path); + BKE_reportf( + &reports, RPT_ERROR, "Unable to load %s from %s", asset_name, blend_file_path.c_str()); return nullptr; } @@ -70,7 +75,7 @@ AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle) } BLI_assert(handle->file_data->asset != nullptr); return reinterpret_cast( - MEM_new(__func__, *handle)); + MEM_new(__func__, ED_asset_handle_get_representation(handle))); } void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer) diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 66fb3cb06a3..b4fa97a0e0a 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -665,7 +665,7 @@ static void curve_draw_exec_precalc(wmOperator *op) selem_prev = selem; } scale_px = ((len_3d > 0.0f) && (len_2d > 0.0f)) ? (len_3d / len_2d) : 0.0f; - float error_threshold = (cps->error_threshold * U.dpi_fac) * scale_px; + float error_threshold = (cps->error_threshold * UI_SCALE_FAC) * scale_px; RNA_property_float_set(op->ptr, prop, error_threshold); } @@ -684,7 +684,7 @@ static void curve_draw_exec_precalc(wmOperator *op) } if (len_squared_v2v2(selem_first->mval, selem_last->mval) <= - square_f(STROKE_CYCLIC_DIST_PX * U.dpi_fac)) { + square_f(STROKE_CYCLIC_DIST_PX * UI_SCALE_FAC)) { use_cyclic = true; } } diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index 7e267b93101..960be0b5032 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -580,7 +580,7 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob, const Mesh &surface_mesh = *static_cast(surface_ob.data); const Span surface_positions = surface_mesh.vert_positions(); - const Span loops = surface_mesh.loops(); + const Span corner_verts = surface_mesh.corner_verts(); const Span surface_looptris = surface_mesh.looptris(); VArraySpan surface_uv_map; if (curves_id.surface_uv_map != nullptr) { @@ -640,9 +640,9 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob, const float2 &uv0 = surface_uv_map[corner0]; const float2 &uv1 = surface_uv_map[corner1]; const float2 &uv2 = surface_uv_map[corner2]; - const float3 &p0_su = surface_positions[loops[corner0].v]; - const float3 &p1_su = surface_positions[loops[corner1].v]; - const float3 &p2_su = surface_positions[loops[corner2].v]; + const float3 &p0_su = surface_positions[corner_verts[corner0]]; + const float3 &p1_su = surface_positions[corner_verts[corner1]]; + const float3 &p2_su = surface_positions[corner_verts[corner2]]; float3 bary_coords; interp_weights_tri_v3(bary_coords, p0_su, p1_su, p2_su, new_first_point_pos_su); const float2 uv = attribute_math::mix3(bary_coords, uv0, uv1, uv2); @@ -676,9 +676,9 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob, const MLoopTri &looptri = surface_looptris[lookup_result.looptri_index]; const float3 &bary_coords = lookup_result.bary_weights; - const float3 &p0_su = surface_positions[loops[looptri.tri[0]].v]; - const float3 &p1_su = surface_positions[loops[looptri.tri[1]].v]; - const float3 &p2_su = surface_positions[loops[looptri.tri[2]].v]; + const float3 &p0_su = surface_positions[corner_verts[looptri.tri[0]]]; + const float3 &p1_su = surface_positions[corner_verts[looptri.tri[1]]]; + const float3 &p2_su = surface_positions[corner_verts[looptri.tri[2]]]; float3 new_first_point_pos_su; interp_v3_v3v3v3(new_first_point_pos_su, p0_su, p1_su, p2_su, bary_coords); diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc index 2120f711c6a..ffd24515742 100644 --- a/source/blender/editors/geometry/geometry_attributes.cc +++ b/source/blender/editors/geometry/geometry_attributes.cc @@ -107,36 +107,6 @@ static int geometry_attribute_add_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static void next_color_attribute(ID *id, const StringRefNull name, bool is_render) -{ - const CustomDataLayer *layer = BKE_id_attributes_color_find(id, name.c_str()); - int index = BKE_id_attribute_to_index(id, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); - - index++; - - layer = BKE_id_attribute_from_index(id, index, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); - - if (!layer) { - index = 0; - layer = BKE_id_attribute_from_index(id, index, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); - } - - if (layer) { - if (is_render) { - BKE_id_attributes_active_color_set(id, layer->name); - } - else { - BKE_id_attributes_default_color_set(id, layer->name); - } - } -} - -static void next_color_attributes(ID *id, const StringRefNull name) -{ - next_color_attribute(id, name, false); /* active */ - next_color_attribute(id, name, true); /* render */ -} - void GEOMETRY_OT_attribute_add(wmOperatorType *ot) { /* identifiers */ @@ -182,8 +152,6 @@ static int geometry_attribute_remove_exec(bContext *C, wmOperator *op) ID *id = static_cast(ob->data); CustomDataLayer *layer = BKE_id_attributes_active_get(id); - next_color_attributes(id, layer->name); - if (!BKE_id_attribute_remove(id, layer->name, op->reports)) { return OPERATOR_CANCELLED; } @@ -436,8 +404,6 @@ static int geometry_color_attribute_remove_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - next_color_attributes(id, active_name); - if (!BKE_id_attribute_remove(id, active_name.c_str(), op->reports)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c index cde702294d0..ca31d8e43ad 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c @@ -126,7 +126,7 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, if (draw_options & ED_GIZMO_ARROW_DRAW_FLAG_STEM) { const float stem_width = arrow->gizmo.line_width * U.pixelsize + - (select ? ARROW_SELECT_THRESHOLD_PX * U.dpi_fac : 0); + (select ? ARROW_SELECT_THRESHOLD_PX * UI_SCALE_FAC : 0); immUniform1f("lineWidth", stem_width); wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_STRIP); } diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c index dca19dcf516..731b1b07193 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c @@ -251,14 +251,14 @@ static void button2d_draw_intern(const bContext *C, if (is_3d) { const float fac = 2.0f; GPU_matrix_translate_2f(-(fac / 2), -(fac / 2)); - GPU_matrix_scale_2f(fac / (ICON_DEFAULT_WIDTH * UI_DPI_FAC), - fac / (ICON_DEFAULT_HEIGHT * UI_DPI_FAC)); + GPU_matrix_scale_2f(fac / (ICON_DEFAULT_WIDTH * UI_SCALE_FAC), + fac / (ICON_DEFAULT_HEIGHT * UI_SCALE_FAC)); pos[0] = 1.0f; pos[1] = 1.0f; } else { - pos[0] = gz->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_DPI_FAC; - pos[1] = gz->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_DPI_FAC; + pos[0] = gz->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * UI_SCALE_FAC; + pos[1] = gz->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * UI_SCALE_FAC; GPU_matrix_pop(); need_to_pop = false; } @@ -327,7 +327,7 @@ static int gizmo_button2d_cursor_get(wmGizmo *gz) static bool gizmo_button2d_bounds(bContext *C, wmGizmo *gz, rcti *r_bounding_box) { ScrArea *area = CTX_wm_area(C); - float rad = CIRCLE_RESOLUTION_3D * U.dpi_fac / 2.0f; + float rad = CIRCLE_RESOLUTION_3D * UI_SCALE_FAC / 2.0f; const float *co = NULL; float matrix_final[4][4]; float co_proj[3]; diff --git a/source/blender/editors/include/ED_asset.h b/source/blender/editors/include/ED_asset.h index d7e7880e114..c5c835c6171 100644 --- a/source/blender/editors/include/ED_asset.h +++ b/source/blender/editors/include/ED_asset.h @@ -25,6 +25,7 @@ void ED_operatortypes_asset(void); #include "../asset/ED_asset_catalog.h" #include "../asset/ED_asset_filter.h" #include "../asset/ED_asset_handle.h" +#include "../asset/ED_asset_import.h" #include "../asset/ED_asset_library.h" #include "../asset/ED_asset_list.h" #include "../asset/ED_asset_mark_clear.h" diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index dc3951ab770..9507ab4d476 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -48,6 +48,7 @@ struct bPoseChannel; struct bScreen; struct rctf; struct rcti; +struct wmEvent; struct wmGizmo; struct wmWindow; struct wmWindowManager; @@ -863,6 +864,20 @@ int ED_view3d_backbuf_sample_size_clamp(struct ARegion *region, float dist); void ED_view3d_select_id_validate(struct ViewContext *vc); +/** Check if the last auto-dist can be used. */ +bool ED_view3d_autodist_last_check(struct wmWindow *win, const struct wmEvent *event); +/** + * \return true when `r_ofs` is set. + * \warning #ED_view3d_autodist_last_check should be called first to ensure the data is available. + */ +bool ED_view3d_autodist_last_get(struct wmWindow *win, float r_ofs[3]); +void ED_view3d_autodist_last_set(struct wmWindow *win, + const struct wmEvent *event, + const float ofs[3], + const bool has_depth); +/** Clear and free auto-dist data. */ +void ED_view3d_autodist_last_clear(struct wmWindow *win); + /** * Get the world-space 3d location from a screen-space 2d point. * TODO: Implement #alphaoverride. We don't want to zoom into billboards. diff --git a/source/blender/editors/include/UI_grid_view.hh b/source/blender/editors/include/UI_grid_view.hh index 6f3dfa1978b..2681567783e 100644 --- a/source/blender/editors/include/UI_grid_view.hh +++ b/source/blender/editors/include/UI_grid_view.hh @@ -162,7 +162,7 @@ class GridViewBuilder { /** Build \a grid_view into the previously provided block, clipped by \a view_bounds (view space, * typically `View2D.cur`). */ - void build_grid_view(AbstractGridView &grid_view, const View2D &v2d); + void build_grid_view(AbstractGridView &grid_view, const View2D &v2d, uiLayout &layout); }; /** \} */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index f5c1a397a8c..0ad39f8c05f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -319,12 +319,6 @@ enum { UI_BUT_CHECKBOX_INVERT = 1 << 25, }; -/* scale fixed button widths by this to account for DPI */ - -#define UI_DPI_FAC (U.dpi_fac) -/* 16 to copy ICON_DEFAULT_HEIGHT */ -#define UI_DPI_ICON_SIZE ((float)16 * UI_DPI_FAC) - /** * Button types, bits stored in 1 value... and a short even! * - bits 0-4: #uiBut.bitnr (0-31) diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh index fc03b0218c0..147b48b454e 100644 --- a/source/blender/editors/include/UI_interface.hh +++ b/source/blender/editors/include/UI_interface.hh @@ -8,6 +8,7 @@ #include +#include "BLI_function_ref.hh" #include "BLI_string_ref.hh" #include "BLI_vector.hh" @@ -17,8 +18,10 @@ namespace blender::nodes::geo_eval_log { struct GeometryAttributeInfo; } +struct PointerRNA; struct StructRNA; struct uiBlock; +struct uiList; struct uiSearchItems; namespace blender::ui { @@ -53,6 +56,60 @@ void attribute_search_add_items(StringRefNull str, } // namespace blender::ui +enum eUIListFilterResult { + /** Never show this item, even when filter results are inverted (#UILST_FLT_EXCLUDE). */ + UI_LIST_ITEM_NEVER_SHOW, + /** Show this item, unless filter results are inverted (#UILST_FLT_EXCLUDE). */ + UI_LIST_ITEM_FILTER_MATCHES, + /** Don't show this item, unless filter results are inverted (#UILST_FLT_EXCLUDE). */ + UI_LIST_ITEM_FILTER_MISMATCHES, +}; + +/** + * Function object for UI list item filtering that does the default name comparison with '*' + * wildcards. Create an instance of this once and pass it to #UI_list_filter_and_sort_items(), do + * NOT create an instance for every item, this would be costly. + */ +class uiListNameFilter { + /* Storage with an inline buffer for smaller strings (small buffer optimization). */ + struct { + char filter_buff[32]; + char *filter_dyn = nullptr; + } storage_; + char *filter_ = nullptr; + + public: + uiListNameFilter(uiList &list); + ~uiListNameFilter(); + + eUIListFilterResult operator()(const PointerRNA &itemptr, + blender::StringRefNull name, + int index); +}; + +using uiListItemFilterFn = blender::FunctionRef; +using uiListItemGetNameFn = + blender::FunctionRef; + +/** + * Filter list items using \a item_filter_fn and sort the result. This respects the normal UI list + * filter settings like alphabetical sorting (#UILST_FLT_SORT_ALPHA), and result inverting + * (#UILST_FLT_EXCLUDE). + * + * Call this from a #uiListType::filter_items callback with any #item_filter_fn. #uiListNameFilter + * can be used to apply the default name based filtering. + * + * \param get_name_fn: In some cases the name cannot be retrieved via RNA. This function can be set + * to provide the name still. + */ +void UI_list_filter_and_sort_items(uiList *ui_list, + const struct bContext *C, + uiListItemFilterFn item_filter_fn, + PointerRNA *dataptr, + const char *propname, + uiListItemGetNameFn get_name_fn = nullptr); + /** * Override this for all available view types. */ diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh index 872a6085060..bdda2e13985 100644 --- a/source/blender/editors/include/UI_tree_view.hh +++ b/source/blender/editors/include/UI_tree_view.hh @@ -306,12 +306,8 @@ class BasicTreeViewItem : public AbstractTreeViewItem { * \{ */ class TreeViewBuilder { - uiBlock &block_; - public: - TreeViewBuilder(uiBlock &block); - - void build_tree_view(AbstractTreeView &tree_view); + static void build_tree_view(AbstractTreeView &tree_view, uiLayout &layout); }; /** \} */ diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index f0bf04ed408..673ed93e1cd 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -60,11 +60,11 @@ enum eView2D_CommonViewTypes { #define V2D_SCROLL_MIN_ALPHA (0.4f) /* Minimum size needs to include outline which varies with line width. */ -#define V2D_SCROLL_MIN_WIDTH ((5.0f * U.dpi_fac) + (2.0f * U.pixelsize)) +#define V2D_SCROLL_MIN_WIDTH ((5.0f * UI_SCALE_FAC) + (2.0f * U.pixelsize)) /* When to start showing the full-width scroller. */ -#define V2D_SCROLL_HIDE_WIDTH (AREAMINX * U.dpi_fac) -#define V2D_SCROLL_HIDE_HEIGHT (HEADERY * U.dpi_fac) +#define V2D_SCROLL_HIDE_WIDTH (AREAMINX * UI_SCALE_FAC) +#define V2D_SCROLL_HIDE_HEIGHT (HEADERY * UI_SCALE_FAC) /** Scroll bars with 'handles' used for scale (zoom). */ #define V2D_SCROLL_HANDLE_HEIGHT (0.6f * U.widget_unit) @@ -74,7 +74,7 @@ enum eView2D_CommonViewTypes { #define V2D_SCROLL_HANDLE_SIZE_HOTSPOT (0.6f * U.widget_unit) /** Don't allow scroll thumb to show below this size (so it's never too small to click on). */ -#define V2D_SCROLL_THUMB_SIZE_MIN (30.0 * UI_DPI_FAC) +#define V2D_SCROLL_THUMB_SIZE_MIN (30.0 * UI_SCALE_FAC) /** \} */ @@ -490,8 +490,8 @@ void UI_view2d_smooth_view(const struct bContext *C, const struct rctf *cur, int smooth_viewtx); -#define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC) -#define UI_TIME_SCRUB_MARGIN_Y (23 * UI_DPI_FAC) +#define UI_MARKER_MARGIN_Y (42 * UI_SCALE_FAC) +#define UI_TIME_SCRUB_MARGIN_Y (23 * UI_SCALE_FAC) /** \} */ diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 94eeab27159..6f593c74fb9 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -280,7 +280,7 @@ static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block) rcti rect; ui_but_to_pixelrect(&rect, region, block, static_cast(block->buttons.last)); const float buttons_width = float(rect.xmax) + UI_HEADER_OFFSET; - const float region_width = float(region->sizex) * U.dpi_fac; + const float region_width = float(region->sizex) * UI_SCALE_FAC; if (region_width <= buttons_width) { return; @@ -469,7 +469,7 @@ void ui_block_bounds_calc(uiBlock *block) /* hardcoded exception... but that one is annoying with larger safety */ uiBut *bt = static_cast(block->buttons.first); - const int xof = ((bt && STRPREFIX(bt->str, "ERROR")) ? 10 : 40) * U.dpi_fac; + const int xof = ((bt && STRPREFIX(bt->str, "ERROR")) ? 10 : 40) * UI_SCALE_FAC; block->safety.xmin = block->rect.xmin - xof; block->safety.ymin = block->rect.ymin - xof; @@ -4993,7 +4993,7 @@ int UI_preview_tile_size_x(void) int UI_preview_tile_size_y(void) { const uiStyle *style = UI_style_get(); - const float font_height = style->widget.points * UI_DPI_FAC; + const float font_height = style->widget.points * UI_SCALE_FAC; const float pad = PREVIEW_TILE_PAD; return round_fl_to_int(UI_preview_tile_size_y_no_label() + font_height + diff --git a/source/blender/editors/interface/interface_context_menu.cc b/source/blender/editors/interface/interface_context_menu.cc index 0d697cb268f..eb944b7f30e 100644 --- a/source/blender/editors/interface/interface_context_menu.cc +++ b/source/blender/editors/interface/interface_context_menu.cc @@ -180,8 +180,8 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *region, void *arg) uiItemL(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), ICON_HAND); uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); - const int bounds_offset[2] = {int(-100 * U.dpi_fac), int(36 * U.dpi_fac)}; - UI_block_bounds_set_popup(block, 6 * U.dpi_fac, bounds_offset); + const int bounds_offset[2] = {int(-100 * UI_SCALE_FAC), int(36 * UI_SCALE_FAC)}; + UI_block_bounds_set_popup(block, 6 * UI_SCALE_FAC, bounds_offset); shortcut_free_operator_property(prop); @@ -241,8 +241,8 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *region, void *arg) uiItemL(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Shortcut"), ICON_HAND); uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); - const int bounds_offset[2] = {int(-100 * U.dpi_fac), int(36 * U.dpi_fac)}; - UI_block_bounds_set_popup(block, 6 * U.dpi_fac, bounds_offset); + const int bounds_offset[2] = {int(-100 * UI_SCALE_FAC), int(36 * UI_SCALE_FAC)}; + UI_block_bounds_set_popup(block, 6 * UI_SCALE_FAC, bounds_offset); #ifdef USE_KEYMAP_ADD_HACK g_kmi_id_hack = kmi_id; diff --git a/source/blender/editors/interface/interface_draw.cc b/source/blender/editors/interface/interface_draw.cc index 79cfb2c50c9..74761daa430 100644 --- a/source/blender/editors/interface/interface_draw.cc +++ b/source/blender/editors/interface/interface_draw.cc @@ -1098,7 +1098,8 @@ static void ui_draw_colorband_handle(uint shdr_pos, float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f( + "viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 2); /* "advanced" mode */ immUniform4f("color", 0.8f, 0.8f, 0.8f, 1.0f); @@ -1672,7 +1673,7 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, } cmp = cuma->curve; - GPU_point_size(max_ff(1.0f, min_ff(UI_DPI_FAC / but->block->aspect * 4.0f, 4.0f))); + GPU_point_size(max_ff(1.0f, min_ff(UI_SCALE_FAC / but->block->aspect * 4.0f, 4.0f))); immBegin(GPU_PRIM_POINTS, cuma->totpoint); for (int a = 0; a < cuma->totpoint; a++) { const float fx = rect->xmin + zoomx * (cmp[a].x - offsx); @@ -1931,7 +1932,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, GPU_line_smooth(false); if (path_len > 0) { GPU_blend(GPU_BLEND_NONE); - GPU_point_size(max_ff(3.0f, min_ff(UI_DPI_FAC / but->block->aspect * 5.0f, 5.0f))); + GPU_point_size(max_ff(3.0f, min_ff(UI_SCALE_FAC / but->block->aspect * 5.0f, 5.0f))); immBegin(GPU_PRIM_POINTS, path_len); for (int i = 0; i < path_len; i++) { fx = rect->xmin + zoomx * (pts[i].x - offsx); @@ -1946,7 +1947,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, if (selected_free_points > 0) { GPU_line_smooth(false); GPU_blend(GPU_BLEND_NONE); - GPU_point_size(max_ff(2.0f, min_ff(UI_DPI_FAC / but->block->aspect * 4.0f, 4.0f))); + GPU_point_size(max_ff(2.0f, min_ff(UI_SCALE_FAC / but->block->aspect * 4.0f, 4.0f))); immBegin(GPU_PRIM_POINTS, selected_free_points * 2); for (int i = 0; i < path_len; i++) { if (point_draw_handles(&pts[i])) { @@ -1968,7 +1969,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, pts = profile->segments; const int segments_len = uint(profile->segments_len); if (segments_len > 0 && pts) { - GPU_point_size(max_ff(2.0f, min_ff(UI_DPI_FAC / but->block->aspect * 3.0f, 3.0f))); + GPU_point_size(max_ff(2.0f, min_ff(UI_SCALE_FAC / but->block->aspect * 3.0f, 3.0f))); immBegin(GPU_PRIM_POINTS, segments_len); for (int i = 0; i < segments_len; i++) { fx = rect->xmin + zoomx * (pts[i].x - offsx); diff --git a/source/blender/editors/interface/interface_handlers.cc b/source/blender/editors/interface/interface_handlers.cc index 19b711f9266..05ccda5649c 100644 --- a/source/blender/editors/interface/interface_handlers.cc +++ b/source/blender/editors/interface/interface_handlers.cc @@ -3050,7 +3050,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con if (ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { if (but->flag & UI_HAS_ICON) { - startx += UI_DPI_ICON_SIZE / aspect; + startx += UI_ICON_SIZE / aspect; } } startx += (UI_TEXT_MARGIN_X * U.widget_unit - U.pixelsize) / aspect; @@ -4048,7 +4048,7 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data) const double value_step = is_float ? double(number_but->step_size * UI_PRECISION_FLOAT_SCALE) : int(number_but->step_size); - const float drag_map_softrange_max = UI_DRAG_MAP_SOFT_RANGE_PIXEL_MAX * UI_DPI_FAC; + const float drag_map_softrange_max = UI_DRAG_MAP_SOFT_RANGE_PIXEL_MAX * UI_SCALE_FAC; const float softrange_max = min_ff( softrange, 2 * (is_float ? min_ff(value_step, value_step_float_min) * @@ -5156,7 +5156,7 @@ static bool ui_numedit_but_NUM(uiButNumber *but, if (is_float == false) { /* at minimum, moving cursor 2 pixels should change an int button. */ - CLAMP_MIN(non_linear_scale, 0.5f * UI_DPI_FAC); + CLAMP_MIN(non_linear_scale, 0.5f * UI_SCALE_FAC); } data->dragf += (float(mx - data->draglastx) / deler) * non_linear_scale; @@ -7027,7 +7027,7 @@ static int ui_do_but_COLORBAND( else { CBData *cbd; /* ignore zoom-level for mindist */ - int mindist = (50 * UI_DPI_FAC) * block->aspect; + int mindist = (50 * UI_SCALE_FAC) * block->aspect; int xco; data->dragstartx = mx; data->dragstarty = my; @@ -7215,7 +7215,7 @@ static int ui_do_but_CURVE( CurveMapping *cumap = (CurveMapping *)but->poin; CurveMap *cuma = cumap->cm + cumap->cur; const float m_xy[2] = {float(mx), float(my)}; - float dist_min_sq = square_f(U.dpi_fac * 14.0f); /* 14 pixels radius */ + float dist_min_sq = square_f(UI_SCALE_FAC * 14.0f); /* 14 pixels radius */ int sel = -1; if (event->modifier & KM_CTRL) { @@ -7249,7 +7249,7 @@ static int ui_do_but_CURVE( BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[0].x); /* with 160px height 8px should translate to the old 0.05 coefficient at no zoom */ - dist_min_sq = square_f(U.dpi_fac * 8.0f); + dist_min_sq = square_f(UI_SCALE_FAC * 8.0f); /* loop through the curve segment table and find what's near the mouse. */ for (int i = 1; i <= CM_TABLE; i++) { @@ -7383,7 +7383,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, if (snap) { const float d[2] = {float(mx - data->dragstartx), float(data->dragstarty)}; - if (len_squared_v2(d) < (9.0f * U.dpi_fac)) { + if (len_squared_v2(d) < (9.0f * UI_SCALE_FAC)) { snap = false; } } @@ -7529,7 +7529,8 @@ static int ui_do_but_CURVEPROFILE( /* Check for selecting of a point by finding closest point in radius. */ CurveProfilePoint *pts = profile->path; - float dist_min_sq = square_f(U.dpi_fac * 14.0f); /* 14 pixels radius for selecting points. */ + float dist_min_sq = square_f(UI_SCALE_FAC * + 14.0f); /* 14 pixels radius for selecting points. */ int i_selected = -1; short selection_type = 0; /* For handle selection. */ for (int i = 0; i < profile->path_len; i++) { @@ -7571,7 +7572,7 @@ static int ui_do_but_CURVEPROFILE( CurveProfilePoint *table = profile->table; BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &table[0].x); - dist_min_sq = square_f(U.dpi_fac * 8.0f); /* 8 pixel radius from each table point. */ + dist_min_sq = square_f(UI_SCALE_FAC * 8.0f); /* 8 pixel radius from each table point. */ /* Loop through the path's high resolution table and find what's near the click. */ for (int i = 1; i <= BKE_curveprofile_table_size(profile); i++) { @@ -10150,7 +10151,7 @@ float ui_block_calc_pie_segment(uiBlock *block, const float event_xy[2]) const float len = normalize_v2_v2(block->pie_data.pie_dir, seg2); - if (len < U.pie_menu_threshold * U.dpi_fac) { + if (len < U.pie_menu_threshold * UI_SCALE_FAC) { block->pie_data.flags |= UI_PIE_INVALID_DIR; } else { @@ -10960,7 +10961,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) { const double final_time = 0.01 * U.pie_animation_timeout; float fac = duration / final_time; - const float pie_radius = U.pie_menu_radius * UI_DPI_FAC; + const float pie_radius = U.pie_menu_radius * UI_SCALE_FAC; if (fac > 1.0f) { fac = 1.0f; @@ -11035,7 +11036,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle uiBut *but = ui_region_find_active_but(menu->region); if (but && (U.pie_menu_confirm > 0) && - (dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm))) { + (dist >= UI_SCALE_FAC * (U.pie_menu_threshold + U.pie_menu_confirm))) { return ui_but_pie_menu_apply(C, menu, but, true); } @@ -11060,7 +11061,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle /* here instead, we use the offset location to account for the initial * direction timeout */ if ((U.pie_menu_confirm > 0) && - (dist >= U.dpi_fac * (U.pie_menu_threshold + U.pie_menu_confirm))) { + (dist >= UI_SCALE_FAC * (U.pie_menu_threshold + U.pie_menu_confirm))) { block->pie_data.flags |= UI_PIE_GESTURE_END_WAIT; copy_v2_v2(block->pie_data.last_pos, event_xy); block->pie_data.duration_gesture = duration; diff --git a/source/blender/editors/interface/interface_icons.cc b/source/blender/editors/interface/interface_icons.cc index 0e0363751fa..dd0e505576a 100644 --- a/source/blender/editors/interface/interface_icons.cc +++ b/source/blender/editors/interface/interface_icons.cc @@ -1741,7 +1741,7 @@ static void icon_draw_texture(float x, bool with_border, const IconTextOverlay *text_overlay) { - const float zoom_factor = w / UI_DPI_ICON_SIZE; + const float zoom_factor = w / UI_ICON_SIZE; float text_width = 0.0f; /* No need to show if too zoomed out, otherwise it just adds noise. */ @@ -2492,13 +2492,13 @@ int UI_icon_color_from_collection(const Collection *collection) void UI_icon_draw(float x, float y, int icon_id) { UI_icon_draw_ex( - x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, nullptr, false, UI_NO_ICON_OVERLAY_TEXT); + x, y, icon_id, UI_INV_SCALE_FAC, 1.0f, 0.0f, nullptr, false, UI_NO_ICON_OVERLAY_TEXT); } void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha) { UI_icon_draw_ex( - x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, nullptr, false, UI_NO_ICON_OVERLAY_TEXT); + x, y, icon_id, UI_INV_SCALE_FAC, alpha, 0.0f, nullptr, false, UI_NO_ICON_OVERLAY_TEXT); } void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size) diff --git a/source/blender/editors/interface/interface_icons_event.cc b/source/blender/editors/interface/interface_icons_event.cc index 5d8af37c55f..68a47a8aef6 100644 --- a/source/blender/editors/interface/interface_icons_event.cc +++ b/source/blender/editors/interface/interface_icons_event.cc @@ -26,12 +26,12 @@ static void icon_draw_rect_input_text( BLF_batch_draw_flush(); const int font_id = BLF_default(); BLF_color4fv(font_id, color); - BLF_size(font_id, font_size * U.dpi_fac); + BLF_size(font_id, font_size * UI_SCALE_FAC); float width, height; BLF_width_and_height(font_id, str, BLF_DRAW_STR_DUMMY_MAX, &width, &height); const float x = trunc(rect->xmin + (((rect->xmax - rect->xmin) - width) / 2.0f)); const float y = rect->ymin + (((rect->ymax - rect->ymin) - height) / 2.0f) + - (v_offset * U.dpi_fac); + (v_offset * UI_SCALE_FAC); BLF_position(font_id, x, y, 0.0f); BLF_draw(font_id, str, BLF_DRAW_STR_DUMMY_MAX); BLF_batch_draw_flush(); diff --git a/source/blender/editors/interface/interface_intern.hh b/source/blender/editors/interface/interface_intern.hh index 331e489ce05..830cc977d49 100644 --- a/source/blender/editors/interface/interface_intern.hh +++ b/source/blender/editors/interface/interface_intern.hh @@ -50,12 +50,12 @@ struct wmTimer; #define UI_MENU_WIDTH_MIN (UI_UNIT_Y * 9) /** Some extra padding added to menus containing sub-menu icons. */ -#define UI_MENU_SUBMENU_PADDING (6 * UI_DPI_FAC) +#define UI_MENU_SUBMENU_PADDING (6 * UI_SCALE_FAC) /* menu scrolling */ -#define UI_MENU_SCROLL_ARROW (12 * UI_DPI_FAC) -#define UI_MENU_SCROLL_MOUSE (UI_MENU_SCROLL_ARROW + 2 * UI_DPI_FAC) -#define UI_MENU_SCROLL_PAD (4 * UI_DPI_FAC) +#define UI_MENU_SCROLL_ARROW (12 * UI_SCALE_FAC) +#define UI_MENU_SCROLL_MOUSE (UI_MENU_SCROLL_ARROW + 2 * UI_SCALE_FAC) +#define UI_MENU_SCROLL_PAD (4 * UI_SCALE_FAC) /** Popover width (multiplied by #U.widget_unit) */ #define UI_POPOVER_WIDTH_UNITS 10 @@ -1181,12 +1181,12 @@ void ui_draw_preview_item_stateless(const uiFontStyle *fstyle, eFontStyle_Align text_align); #define UI_TEXT_MARGIN_X 0.4f -#define UI_POPUP_MARGIN (UI_DPI_FAC * 12) +#define UI_POPUP_MARGIN (UI_SCALE_FAC * 12) /** * Margin at top of screen for popups. * Note this value must be sufficient to draw a popover arrow to avoid cropping it. */ -#define UI_POPUP_MENU_TOP (int)(10 * UI_DPI_FAC) +#define UI_POPUP_MENU_TOP (int)(10 * UI_SCALE_FAC) #define UI_PIXEL_AA_JITTER 8 extern const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2]; diff --git a/source/blender/editors/interface/interface_layout.cc b/source/blender/editors/interface/interface_layout.cc index 1a4def7bed7..1cab840f100 100644 --- a/source/blender/editors/interface/interface_layout.cc +++ b/source/blender/editors/interface/interface_layout.cc @@ -3962,7 +3962,7 @@ static void ui_litem_layout_radial(uiLayout *litem) * for radiation, see http://mattebb.com/weblog/radiation/ * also the old code at #5103. */ - const int pie_radius = U.pie_menu_radius * UI_DPI_FAC; + const int pie_radius = U.pie_menu_radius * UI_SCALE_FAC; const int x = litem->x; const int y = litem->y; @@ -4046,7 +4046,7 @@ static void ui_litem_layout_root_radial(uiLayout *litem) ui_item_size(item, &itemw, &itemh); ui_item_position( - item, x - itemw / 2, y + U.dpi_fac * (U.pie_menu_threshold + 9.0f), itemw, itemh); + item, x - itemw / 2, y + UI_SCALE_FAC * (U.pie_menu_threshold + 9.0f), itemw, itemh); } } @@ -6125,13 +6125,13 @@ const char *UI_layout_introspect(uiLayout *layout) uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon) { const uiStyle *style = UI_style_get_dpi(); - const short icon_size = 64 * U.dpi_fac; + const short icon_size = 64 * UI_SCALE_FAC; const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points); - const int dialog_width = icon_size + (text_points_max * size * U.dpi_fac); + const int dialog_width = icon_size + (text_points_max * size * UI_SCALE_FAC); /* By default, the space between icon and text/buttons will be equal to the 'columnspace', * this extra padding will add some space by increasing the left column width, * making the icon placement more symmetrical, between the block edge and the text. */ - const float icon_padding = 5.0f * U.dpi_fac; + const float icon_padding = 5.0f * UI_SCALE_FAC; /* Calculate the factor of the fixed icon column depending on the block width. */ const float split_factor = (float(icon_size) + icon_padding) / float(dialog_width - style->columnspace); diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc index 7a7987540b2..fd3ead60ae2 100644 --- a/source/blender/editors/interface/interface_panel.cc +++ b/source/blender/editors/interface/interface_panel.cc @@ -1099,7 +1099,7 @@ static void panel_draw_aligned_widgets(const uiStyle *style, UI_icon_draw_ex(widget_rect.xmin + size_y * 0.2f, widget_rect.ymin + size_y * 0.2f, UI_panel_is_closed(panel) ? ICON_RIGHTARROW : ICON_DOWNARROW_HLT, - aspect * U.inv_dpi_fac, + aspect * UI_INV_SCALE_FAC, 0.7f, 0.0f, title_color, @@ -1128,7 +1128,7 @@ static void panel_draw_aligned_widgets(const uiStyle *style, UI_icon_draw_ex(widget_rect.xmax - scaled_unit * 2.2f, widget_rect.ymin + 5.0f / aspect, ICON_PINNED, - aspect * U.inv_dpi_fac, + aspect * UI_INV_SCALE_FAC, 1.0f, 0.0f, title_color, @@ -1288,7 +1288,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) const float zoom = 1.0f / aspect; const int px = U.pixelsize; const int category_tabs_width = round_fl_to_int(UI_PANEL_CATEGORY_MARGIN_WIDTH * zoom); - const float dpi_fac = UI_DPI_FAC; + const float dpi_fac = UI_SCALE_FAC; /* Padding of tabs around text. */ const int tab_v_pad_text = round_fl_to_int(TABS_PADDING_TEXT_FACTOR * dpi_fac * zoom) + 2 * px; /* Padding between tabs. */ @@ -1332,9 +1332,9 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) is_alpha = (region->overlap && (theme_col_back[3] != 255)); BLF_enable(fontid, BLF_ROTATION); - BLF_rotation(fontid, M_PI_2); + BLF_rotation(fontid, is_left ? M_PI_2 : -M_PI_2); ui_fontscale(&fstyle_points, aspect); - BLF_size(fontid, fstyle_points * U.dpi_fac); + BLF_size(fontid, fstyle_points * UI_SCALE_FAC); /* Check the region type supports categories to avoid an assert * for showing 3D view panels in the properties space. */ @@ -1467,7 +1467,10 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) /* Tab titles. */ - BLF_position(fontid, rct->xmax - text_v_ofs, rct->ymin + tab_v_pad_text, 0.0f); + BLF_position(fontid, + is_left ? rct->xmax - text_v_ofs : rct->xmin + text_v_ofs, + is_left ? rct->ymin + tab_v_pad_text : rct->ymax - tab_v_pad_text, + 0.0f); BLF_color3ubv(fontid, is_active ? theme_col_text_hi : theme_col_text); BLF_draw(fontid, category_id_draw, category_draw_len); diff --git a/source/blender/editors/interface/interface_region_hud.cc b/source/blender/editors/interface/interface_region_hud.cc index 0aa3bcbdd8c..f0a31c9e739 100644 --- a/source/blender/editors/interface/interface_region_hud.cc +++ b/source/blender/editors/interface/interface_region_hud.cc @@ -173,8 +173,8 @@ static void hud_region_layout(const bContext *C, ARegion *region) if (region->panels.first && ((area->flag & AREA_FLAG_REGION_SIZE_UPDATE) || (region->sizey != size_y))) { - int winx_new = UI_DPI_FAC * (region->sizex + 0.5f); - int winy_new = UI_DPI_FAC * (region->sizey + 0.5f); + int winx_new = UI_SCALE_FAC * (region->sizex + 0.5f); + int winy_new = UI_SCALE_FAC * (region->sizey + 0.5f); View2D *v2d = ®ion->v2d; if (region->flag & RGN_FLAG_SIZE_CLAMP_X) { diff --git a/source/blender/editors/interface/interface_region_popup.cc b/source/blender/editors/interface/interface_region_popup.cc index 7943e7dc6fa..edc6d94c250 100644 --- a/source/blender/editors/interface/interface_region_popup.cc +++ b/source/blender/editors/interface/interface_region_popup.cc @@ -288,8 +288,8 @@ static void ui_popup_block_position(wmWindow *window, /* when you are outside parent button, safety there should be smaller */ - const int s1 = 40 * U.dpi_fac; - const int s2 = 3 * U.dpi_fac; + const int s1 = 40 * UI_SCALE_FAC; + const int s2 = 3 * UI_SCALE_FAC; /* parent button to left */ if (midx < block->rect.xmin) { diff --git a/source/blender/editors/interface/interface_region_search.cc b/source/blender/editors/interface/interface_region_search.cc index 1b63cbe4c97..ccc8586d9fe 100644 --- a/source/blender/editors/interface/interface_region_search.cc +++ b/source/blender/editors/interface/interface_region_search.cc @@ -651,7 +651,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region) if (icon == ICON_BLANK1) { icon = ICON_NONE; - rect.xmin -= UI_DPI_ICON_SIZE / 4; + rect.xmin -= UI_ICON_SIZE / 4; } /* The previous menu item draws the active selection. */ @@ -762,7 +762,7 @@ static void ui_searchbox_region_layout_fn(const struct bContext *C, struct ARegi /* We should make this wider if there is a path or hint on the right. */ if (ui_searchbox_item_separator(data) != UI_MENU_ITEM_SEPARATOR_NONE) { - searchbox_width += 12 * data->fstyle.points * U.dpi_fac; + searchbox_width += 12 * data->fstyle.points * UI_SCALE_FAC; } rctf rect_fl; diff --git a/source/blender/editors/interface/interface_region_tooltip.cc b/source/blender/editors/interface/interface_region_tooltip.cc index fb87d940506..1216359a345 100644 --- a/source/blender/editors/interface/interface_region_tooltip.cc +++ b/source/blender/editors/interface/interface_region_tooltip.cc @@ -253,7 +253,7 @@ static void ui_tooltip_region_draw_cb(const bContext * /*C*/, ARegion *region) UI_fontstyle_set(&fstyle_mono); /* XXX: needed because we don't have mono in 'U.uifonts'. */ - BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.dpi_fac); + BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * UI_SCALE_FAC); rgb_float_to_uchar(drawcol, tip_colors[int(field->format.color_id)]); UI_fontstyle_draw(&fstyle_mono, &bbox, field->text, UI_TIP_STR_MAX, drawcol, &fs_params); } @@ -1132,7 +1132,7 @@ static ARegion *ui_tooltip_create_with_data(bContext *C, int font_id; if (field->format.style == uiTooltipFormat::Style::Mono) { - BLF_size(blf_mono_font, data->fstyle.points * U.dpi_fac); + BLF_size(blf_mono_font, data->fstyle.points * UI_SCALE_FAC); font_id = blf_mono_font; } else { diff --git a/source/blender/editors/interface/interface_style.cc b/source/blender/editors/interface/interface_style.cc index 96eef4fdb60..38301599930 100644 --- a/source/blender/editors/interface/interface_style.cc +++ b/source/blender/editors/interface/interface_style.cc @@ -321,20 +321,20 @@ const uiStyle *UI_style_get_dpi(void) _style = *style; - _style.paneltitle.shadx = short(UI_DPI_FAC * _style.paneltitle.shadx); - _style.paneltitle.shady = short(UI_DPI_FAC * _style.paneltitle.shady); - _style.grouplabel.shadx = short(UI_DPI_FAC * _style.grouplabel.shadx); - _style.grouplabel.shady = short(UI_DPI_FAC * _style.grouplabel.shady); - _style.widgetlabel.shadx = short(UI_DPI_FAC * _style.widgetlabel.shadx); - _style.widgetlabel.shady = short(UI_DPI_FAC * _style.widgetlabel.shady); + _style.paneltitle.shadx = short(UI_SCALE_FAC * _style.paneltitle.shadx); + _style.paneltitle.shady = short(UI_SCALE_FAC * _style.paneltitle.shady); + _style.grouplabel.shadx = short(UI_SCALE_FAC * _style.grouplabel.shadx); + _style.grouplabel.shady = short(UI_SCALE_FAC * _style.grouplabel.shady); + _style.widgetlabel.shadx = short(UI_SCALE_FAC * _style.widgetlabel.shadx); + _style.widgetlabel.shady = short(UI_SCALE_FAC * _style.widgetlabel.shady); - _style.columnspace = short(UI_DPI_FAC * _style.columnspace); - _style.templatespace = short(UI_DPI_FAC * _style.templatespace); - _style.boxspace = short(UI_DPI_FAC * _style.boxspace); - _style.buttonspacex = short(UI_DPI_FAC * _style.buttonspacex); - _style.buttonspacey = short(UI_DPI_FAC * _style.buttonspacey); - _style.panelspace = short(UI_DPI_FAC * _style.panelspace); - _style.panelouter = short(UI_DPI_FAC * _style.panelouter); + _style.columnspace = short(UI_SCALE_FAC * _style.columnspace); + _style.templatespace = short(UI_SCALE_FAC * _style.templatespace); + _style.boxspace = short(UI_SCALE_FAC * _style.boxspace); + _style.buttonspacex = short(UI_SCALE_FAC * _style.buttonspacex); + _style.buttonspacey = short(UI_SCALE_FAC * _style.buttonspacey); + _style.panelspace = short(UI_SCALE_FAC * _style.panelspace); + _style.panelouter = short(UI_SCALE_FAC * _style.panelouter); return &_style; } @@ -351,7 +351,7 @@ int UI_fontstyle_string_width_with_block_aspect(const uiFontStyle *fs, { /* FIXME(@ideasman42): the final scale of the font is rounded which should be accounted for. * Failing to do so causes bad alignment when zoomed out very far in the node-editor. */ - fontstyle_set_ex(fs, U.dpi_fac / aspect); + fontstyle_set_ex(fs, UI_SCALE_FAC / aspect); return int(BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) * aspect); } @@ -492,5 +492,5 @@ static void fontstyle_set_ex(const uiFontStyle *fs, const float dpi_fac) void UI_fontstyle_set(const uiFontStyle *fs) { - fontstyle_set_ex(fs, U.dpi_fac); + fontstyle_set_ex(fs, UI_SCALE_FAC); } diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc index 55b2e780a9e..71bd66ff651 100644 --- a/source/blender/editors/interface/interface_template_asset_view.cc +++ b/source/blender/editors/interface/interface_template_asset_view.cc @@ -24,6 +24,7 @@ #include "RNA_prototypes.h" #include "UI_interface.h" +#include "UI_interface.hh" #include "WM_api.h" #include "WM_types.h" @@ -32,6 +33,7 @@ struct AssetViewListData { AssetLibraryReference asset_library_ref; + AssetFilterSettings filter_settings; bScreen *screen; bool show_names; }; @@ -45,8 +47,6 @@ static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle) } char blend_path[FILE_MAX_LIBEXTRA]; - /* Context can be null here, it's only needed for a File Browser specific hack that should go - * away before too long. */ ED_asset_handle_get_full_library_path(asset_handle, blend_path); const eAssetImportMethod import_method = @@ -68,19 +68,23 @@ static void asset_view_draw_item(uiList *ui_list, const bContext * /*C*/, uiLayout *layout, PointerRNA * /*dataptr*/, - PointerRNA *itemptr, + PointerRNA * /*itemptr*/, int /*icon*/, PointerRNA * /*active_dataptr*/, const char * /*active_propname*/, - int /*index*/, + int index, int /*flt_flag*/) { AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata; - BLI_assert(RNA_struct_is_a(itemptr->type, &RNA_AssetHandle)); - AssetHandle *asset_handle = (AssetHandle *)itemptr->data; + AssetHandle asset_handle = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index); - uiLayoutSetContextPointer(layout, "asset_handle", itemptr); + PointerRNA file_ptr; + RNA_pointer_create(&list_data->screen->id, + &RNA_FileSelectEntry, + const_cast(asset_handle.file_data), + &file_ptr); + uiLayoutSetContextPointer(layout, "active_file", &file_ptr); uiBlock *block = uiLayoutGetBlock(layout); const bool show_names = list_data->show_names; @@ -90,8 +94,8 @@ static void asset_view_draw_item(uiList *ui_list, uiBut *but = uiDefIconTextBut(block, UI_BTYPE_PREVIEW_TILE, 0, - ED_asset_handle_get_preview_icon_id(asset_handle), - show_names ? ED_asset_handle_get_name(asset_handle) : "", + ED_asset_handle_get_preview_icon_id(&asset_handle), + show_names ? ED_asset_handle_get_name(&asset_handle) : "", 0, 0, size_x, @@ -103,14 +107,43 @@ static void asset_view_draw_item(uiList *ui_list, 0, ""); ui_def_but_icon(but, - ED_asset_handle_get_preview_icon_id(asset_handle), + ED_asset_handle_get_preview_icon_id(&asset_handle), /* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */ UI_HAS_ICON | UI_BUT_ICON_PREVIEW); if (!ui_list->dyn_data->custom_drag_optype) { - asset_view_item_but_drag_set(but, asset_handle); + asset_view_item_but_drag_set(but, &asset_handle); } } +static void asset_view_filter_items(uiList *ui_list, + const bContext *C, + PointerRNA *dataptr, + const char *propname) +{ + AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata; + AssetFilterSettings &filter_settings = list_data->filter_settings; + + uiListNameFilter name_filter(*ui_list); + + UI_list_filter_and_sort_items( + ui_list, + C, + [&name_filter, list_data, &filter_settings]( + const PointerRNA &itemptr, blender::StringRefNull name, int index) { + AssetHandle asset = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index); + if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) { + return UI_LIST_ITEM_NEVER_SHOW; + } + return name_filter(itemptr, name, index); + }, + dataptr, + propname, + [list_data](const PointerRNA & /*itemptr*/, int index) -> std::string { + AssetHandle asset = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index); + return ED_asset_handle_get_name(&asset); + }); +} + static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params) { AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata; @@ -136,16 +169,15 @@ uiListType *UI_UL_asset_view() BLI_strncpy(list_type->idname, "UI_UL_asset_view", sizeof(list_type->idname)); list_type->draw_item = asset_view_draw_item; + list_type->filter_items = asset_view_filter_items; list_type->listener = asset_view_listener; return list_type; } -static void asset_view_template_refresh_asset_collection( - const AssetLibraryReference &asset_library_ref, - const AssetFilterSettings &filter_settings, - PointerRNA &assets_dataptr, - const char *assets_propname) +static void populate_asset_collection(const AssetLibraryReference &asset_library_ref, + PointerRNA &assets_dataptr, + const char *assets_propname) { PropertyRNA *assets_prop = RNA_struct_find_property(&assets_dataptr, assets_propname); if (!assets_prop) { @@ -164,17 +196,15 @@ static void asset_view_template_refresh_asset_collection( RNA_property_collection_clear(&assets_dataptr, assets_prop); - ED_assetlist_iterate(asset_library_ref, [&](AssetHandle asset) { - if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) { - /* Don't do anything else, but return true to continue iterating. */ - return true; - } + ED_assetlist_iterate(asset_library_ref, [&](AssetHandle /*asset*/) { + /* XXX creating a dummy #RNA_AssetHandle collection item. It's #file_data will be null. This is + * because the #FileDirEntry may be freed while iterating, there's a cache for them with a + * maximum size. Further code will query as needed it using the collection index. */ PointerRNA itemptr, fileptr; RNA_property_collection_add(&assets_dataptr, assets_prop, &itemptr); - RNA_pointer_create( - nullptr, &RNA_FileSelectEntry, const_cast(asset.file_data), &fileptr); + RNA_pointer_create(nullptr, &RNA_FileSelectEntry, nullptr, &fileptr); RNA_pointer_set(&itemptr, "file_data", fileptr); return true; @@ -221,12 +251,12 @@ void uiTemplateAssetView(uiLayout *layout, ED_assetlist_ensure_previews_job(&asset_library_ref, C); const int tot_items = ED_assetlist_size(&asset_library_ref); - asset_view_template_refresh_asset_collection( - asset_library_ref, *filter_settings, *assets_dataptr, assets_propname); + populate_asset_collection(asset_library_ref, *assets_dataptr, assets_propname); AssetViewListData *list_data = (AssetViewListData *)MEM_mallocN(sizeof(*list_data), "AssetViewListData"); list_data->asset_library_ref = asset_library_ref; + list_data->filter_settings = *filter_settings; list_data->screen = CTX_wm_screen(C); list_data->show_names = (display_flags & UI_TEMPLATE_ASSET_DRAW_NO_NAMES) == 0; diff --git a/source/blender/editors/interface/interface_template_list.cc b/source/blender/editors/interface/interface_template_list.cc index d5803e603f1..28ffee73ca3 100644 --- a/source/blender/editors/interface/interface_template_list.cc +++ b/source/blender/editors/interface/interface_template_list.cc @@ -8,9 +8,11 @@ #include #include "BLI_fnmatch.h" +#include "BLI_function_ref.hh" #include "BLI_listbase.h" #include "BLI_math_base.h" #include "BLI_string.h" +#include "BLI_string_ref.hh" #include "BLI_utildefines.h" #include "BKE_screen.h" @@ -26,12 +28,15 @@ #include "RNA_prototypes.h" #include "UI_interface.h" +#include "UI_interface.hh" #include "UI_view2d.h" #include "WM_api.h" #include "interface_intern.hh" +using namespace blender; + /** * The validated data that was passed to #uiTemplateList (typically through Python). * Populated through #ui_template_list_data_retrieve(). @@ -148,6 +153,45 @@ static void uilist_draw_filter_default(struct uiList *ui_list, } } +uiListNameFilter::uiListNameFilter(uiList &list) +{ + const char *filter_raw = list.filter_byname; + + if (filter_raw[0]) { + const size_t slen = strlen(filter_raw); + + /* Implicitly add heading/trailing wildcards if needed. */ + if (slen + 3 <= sizeof(storage_.filter_buff)) { + filter_ = storage_.filter_buff; + } + else { + filter_ = storage_.filter_dyn = static_cast( + MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn")); + } + BLI_strncpy_ensure_pad(filter_, filter_raw, '*', slen + 3); + } +} + +uiListNameFilter::~uiListNameFilter() +{ + MEM_SAFE_FREE(storage_.filter_dyn); +} + +eUIListFilterResult uiListNameFilter::operator()(const PointerRNA & /* itemptr */, + StringRefNull name, + int /* index */) +{ + if (!filter_) { + return UI_LIST_ITEM_FILTER_MATCHES; + } + + /* Case-insensitive! */ + if (fnmatch(filter_, name.c_str(), FNM_CASEFOLD) == 0) { + return UI_LIST_ITEM_FILTER_MATCHES; + } + return UI_LIST_ITEM_FILTER_MISMATCHES; +} + struct StringCmp { char name[MAX_IDPROP_NAME]; int org_idx; @@ -159,16 +203,16 @@ static int cmpstringp(const void *p1, const void *p2) return BLI_strcasecmp(((StringCmp *)p1)->name, ((StringCmp *)p2)->name); } -static void uilist_filter_items_default(struct uiList *ui_list, - const struct bContext * /*C*/, - struct PointerRNA *dataptr, - const char *propname) +void UI_list_filter_and_sort_items(uiList *ui_list, + const bContext * /*C*/, + uiListItemFilterFn item_filter_fn, + PointerRNA *dataptr, + const char *propname, + uiListItemGetNameFn get_name_fn) { uiListDyn *dyn_data = ui_list->dyn_data; PropertyRNA *prop = RNA_struct_find_property(dataptr, propname); - const char *filter_raw = ui_list->filter_byname; - char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = nullptr; const bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0; const bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_MASK) == UILST_FLT_SORT_ALPHA; @@ -176,41 +220,26 @@ static void uilist_filter_items_default(struct uiList *ui_list, dyn_data->items_shown = dyn_data->items_len = len; - if (len && (order_by_name || filter_raw[0])) { + if (len && (order_by_name || item_filter_fn)) { StringCmp *names = nullptr; int order_idx = 0, i = 0; if (order_by_name) { names = static_cast(MEM_callocN(sizeof(StringCmp) * len, "StringCmp")); } - if (filter_raw[0]) { - const size_t slen = strlen(filter_raw); + if (item_filter_fn) { dyn_data->items_filter_flags = static_cast( MEM_callocN(sizeof(int) * len, "items_filter_flags")); dyn_data->items_shown = 0; - - /* Implicitly add heading/trailing wildcards if needed. */ - if (slen + 3 <= sizeof(filter_buff)) { - filter = filter_buff; - } - else { - filter = filter_dyn = static_cast( - MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn")); - } - BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3); } RNA_PROP_BEGIN (dataptr, itemptr, prop) { bool do_order = false; char *namebuf; - if (RNA_struct_is_a(itemptr.type, &RNA_AssetHandle)) { - /* XXX The AssetHandle design is hacky and meant to be temporary. It can't have a proper - * name property, so for now this hardcoded exception is needed. */ - AssetHandle *asset_handle = (AssetHandle *)itemptr.data; - const char *asset_name = ED_asset_handle_get_name(asset_handle); - namebuf = BLI_strdup(asset_name); + if (get_name_fn) { + namebuf = BLI_strdup(get_name_fn(itemptr, i).c_str()); } else { namebuf = RNA_struct_name_get_alloc(&itemptr, nullptr, 0, nullptr); @@ -218,9 +247,13 @@ static void uilist_filter_items_default(struct uiList *ui_list, const char *name = namebuf ? namebuf : ""; - if (filter[0]) { - /* Case-insensitive! */ - if (fnmatch(filter, name, FNM_CASEFOLD) == 0) { + if (item_filter_fn) { + const eUIListFilterResult filter_result = item_filter_fn(itemptr, name, i); + + if (filter_result == UI_LIST_ITEM_NEVER_SHOW) { + /* Pass. */ + } + else if (filter_result == UI_LIST_ITEM_FILTER_MATCHES) { dyn_data->items_filter_flags[i] = UILST_FLT_ITEM; if (!filter_exclude) { dyn_data->items_shown++; @@ -266,15 +299,30 @@ static void uilist_filter_items_default(struct uiList *ui_list, } } - if (filter_dyn) { - MEM_freeN(filter_dyn); - } if (names) { MEM_freeN(names); } } } +/** + * Default UI List filtering: Filter by name. + */ +static void uilist_filter_items_default(struct uiList *ui_list, + const struct bContext *C, + struct PointerRNA *dataptr, + const char *propname) +{ + if (ui_list->filter_byname[0]) { + uiListNameFilter name_filter(*ui_list); + UI_list_filter_and_sort_items(ui_list, C, name_filter, dataptr, propname); + } + /* Optimization: Skip filtering entirely when there is no filter string set. */ + else { + UI_list_filter_and_sort_items(ui_list, C, nullptr, dataptr, propname); + } +} + static void uilist_free_dyn_data(uiList *ui_list) { uiListDyn *dyn_data = ui_list->dyn_data; diff --git a/source/blender/editors/interface/interface_templates.cc b/source/blender/editors/interface/interface_templates.cc index 618b04aa70a..625fe459758 100644 --- a/source/blender/editors/interface/interface_templates.cc +++ b/source/blender/editors/interface/interface_templates.cc @@ -39,6 +39,7 @@ #include "BLT_translation.h" #include "BKE_action.h" +#include "BKE_blendfile.h" #include "BKE_colorband.h" #include "BKE_colortools.h" #include "BKE_constraint.h" @@ -79,8 +80,6 @@ #include "WM_api.h" #include "WM_types.h" -#include "BLO_readfile.h" - #include "UI_interface.h" #include "UI_interface_icons.h" #include "UI_view2d.h" @@ -5688,7 +5687,7 @@ void uiTemplateColorPicker(uiLayout *layout, "", WHEEL_SIZE + 6, 0, - 14 * UI_DPI_FAC, + 14 * UI_SCALE_FAC, WHEEL_SIZE, ptr, prop, @@ -5709,7 +5708,7 @@ void uiTemplateColorPicker(uiLayout *layout, 0, 4, WHEEL_SIZE, - 18 * UI_DPI_FAC, + 18 * UI_SCALE_FAC, ptr, prop, -1, @@ -5729,7 +5728,7 @@ void uiTemplateColorPicker(uiLayout *layout, 0, 4, WHEEL_SIZE, - 18 * UI_DPI_FAC, + 18 * UI_SCALE_FAC, ptr, prop, -1, @@ -5749,7 +5748,7 @@ void uiTemplateColorPicker(uiLayout *layout, 0, 4, WHEEL_SIZE, - 18 * UI_DPI_FAC, + 18 * UI_SCALE_FAC, ptr, prop, -1, @@ -5771,7 +5770,7 @@ void uiTemplateColorPicker(uiLayout *layout, "", WHEEL_SIZE + 6, 0, - 14 * UI_DPI_FAC, + 14 * UI_SCALE_FAC, WHEEL_SIZE, ptr, prop, @@ -6359,7 +6358,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) UI_fontstyle_set(&style->widgetlabel); int width = BLF_width(style->widgetlabel.uifont_id, report->message, report->len); width = min_ii(int(rti->widthfac * width), width); - width = max_ii(width, 10 * UI_DPI_FAC); + width = max_ii(width, 10 * UI_SCALE_FAC); UI_block_align_begin(block); @@ -6370,7 +6369,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) "", 0, 0, - UI_UNIT_X + (6 * UI_DPI_FAC), + UI_UNIT_X + (6 * UI_SCALE_FAC), UI_UNIT_Y, nullptr, 0.0f, @@ -6386,7 +6385,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) UI_BTYPE_ROUNDBOX, 0, "", - UI_UNIT_X + (6 * UI_DPI_FAC), + UI_UNIT_X + (6 * UI_SCALE_FAC), 0, UI_UNIT_X + width, UI_UNIT_Y, @@ -6410,7 +6409,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) "SCREEN_OT_info_log_show", WM_OP_INVOKE_REGION_WIN, UI_icon_from_report_type(report->type), - (3 * UI_DPI_FAC), + (3 * UI_SCALE_FAC), 0, UI_UNIT_X, UI_UNIT_Y, @@ -6997,7 +6996,7 @@ int uiTemplateRecentFiles(uiLayout *layout, int rows) uiItemFullO(layout, "WM_OT_open_mainfile", filename, - BLO_has_bfile_extension(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP, + BKE_blendfile_extension_check(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP, nullptr, WM_OP_INVOKE_DEFAULT, 0, diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index 55ede2eda80..f50f199357d 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -1354,7 +1354,7 @@ static void widget_draw_icon( return; } - const float aspect = but->block->aspect * U.inv_dpi_fac; + const float aspect = but->block->aspect * UI_INV_SCALE_FAC; const float height = ICON_DEFAULT_HEIGHT / aspect; /* calculate blend color */ @@ -1447,7 +1447,7 @@ static void widget_draw_submenu_tria(const uiBut *but, const rcti *rect, const uiWidgetColors *wcol) { - const float aspect = but->block->aspect * U.inv_dpi_fac; + const float aspect = but->block->aspect * UI_INV_SCALE_FAC; const int tria_height = int(ICON_DEFAULT_HEIGHT / aspect); const int tria_width = int(ICON_DEFAULT_WIDTH / aspect) - 2 * U.pixelsize; const int xs = rect->xmax - tria_width; @@ -1641,7 +1641,7 @@ static void ui_text_clip_middle(const uiFontStyle *fstyle, uiBut *but, const rct int(UI_TEXT_CLIP_MARGIN + 0.5f); const float okwidth = float(max_ii(BLI_rcti_size_x(rect) - border, 0)); const size_t max_len = sizeof(but->drawstr); - const float minwidth = float(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f; + const float minwidth = float(UI_ICON_SIZE) / but->block->aspect * 2.0f; but->ofs = 0; but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, '\0'); @@ -1664,7 +1664,7 @@ static void ui_text_clip_middle_protect_right(const uiFontStyle *fstyle, int(UI_TEXT_CLIP_MARGIN + 0.5f); const float okwidth = float(max_ii(BLI_rcti_size_x(rect) - border, 0)); const size_t max_len = sizeof(but->drawstr); - const float minwidth = float(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f; + const float minwidth = float(UI_ICON_SIZE) / but->block->aspect * 2.0f; but->ofs = 0; but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, rsep); @@ -2297,8 +2297,8 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, const BIFIconID icon = BIFIconID(ui_but_icon(but)); const int icon_size_init = is_tool ? ICON_DEFAULT_HEIGHT_TOOLBAR : ICON_DEFAULT_HEIGHT; - const float icon_size = icon_size_init / (but->block->aspect * U.inv_dpi_fac); - const float icon_padding = 2 * UI_DPI_FAC; + const float icon_size = icon_size_init / (but->block->aspect * UI_INV_SCALE_FAC); + const float icon_padding = 2 * UI_SCALE_FAC; #ifdef USE_UI_TOOLBAR_HACK if (is_tool) { @@ -4994,11 +4994,11 @@ static void ui_draw_clip_tri(uiBlock *block, rcti *rect, uiWidgetType *wt) if (block->flag & UI_BLOCK_CLIPTOP) { /* XXX no scaling for UI here yet */ - UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 6 * U.dpi_fac, 't', draw_color); + UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 6 * UI_SCALE_FAC, 't', draw_color); } if (block->flag & UI_BLOCK_CLIPBOTTOM) { /* XXX no scaling for UI here yet */ - UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10 * U.dpi_fac, 'v', draw_color); + UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10 * UI_SCALE_FAC, 'v', draw_color); } } } @@ -5172,8 +5172,8 @@ void ui_draw_pie_center(uiBlock *block) float *pie_dir = block->pie_data.pie_dir; - const float pie_radius_internal = U.dpi_fac * U.pie_menu_threshold; - const float pie_radius_external = U.dpi_fac * (U.pie_menu_threshold + 7.0f); + const float pie_radius_internal = UI_SCALE_FAC * U.pie_menu_threshold; + const float pie_radius_external = UI_SCALE_FAC * (U.pie_menu_threshold + 7.0f); const int subd = 40; @@ -5246,8 +5246,8 @@ void ui_draw_pie_center(uiBlock *block) if (U.pie_menu_confirm > 0 && !(block->pie_data.flags & (UI_PIE_INVALID_DIR | UI_PIE_CLICK_STYLE))) { - const float pie_confirm_radius = U.dpi_fac * (pie_radius_internal + U.pie_menu_confirm); - const float pie_confirm_external = U.dpi_fac * + const float pie_confirm_radius = UI_SCALE_FAC * (pie_radius_internal + U.pie_menu_confirm); + const float pie_confirm_external = UI_SCALE_FAC * (pie_radius_internal + U.pie_menu_confirm + 7.0f); const uchar col[4] = {UNPACK3(btheme->tui.wcol_pie_menu.text_sel), 64}; @@ -5361,7 +5361,7 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, if (separator_type == UI_MENU_ITEM_SEPARATOR_SHORTCUT) { /* Shrink rect to exclude the shortcut string. */ - rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + UI_DPI_ICON_SIZE; + rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + UI_ICON_SIZE; } else if (separator_type == UI_MENU_ITEM_SEPARATOR_HINT) { /* Determine max-width for the hint string to leave the name string un-clipped (if there's @@ -5390,7 +5390,7 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, char drawstr[UI_MAX_DRAW_STR]; const float okwidth = float(BLI_rcti_size_x(rect)); const size_t max_len = sizeof(drawstr); - const float minwidth = float(UI_DPI_ICON_SIZE); + const float minwidth = float(UI_ICON_SIZE); BLI_strncpy(drawstr, name, sizeof(drawstr)); if (drawstr[0]) { @@ -5439,7 +5439,7 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, char hint_drawstr[UI_MAX_DRAW_STR]; { const size_t max_len = sizeof(hint_drawstr); - const float minwidth = float(UI_DPI_ICON_SIZE); + const float minwidth = float(UI_ICON_SIZE); BLI_strncpy(hint_drawstr, cpoin + 1, sizeof(hint_drawstr)); if (hint_drawstr[0] && (max_hint_width < INT_MAX)) { @@ -5494,7 +5494,7 @@ void ui_draw_preview_item_stateless(const uiFontStyle *fstyle, char drawstr[UI_MAX_DRAW_STR]; const float okwidth = float(BLI_rcti_size_x(&trect)); const size_t max_len = sizeof(drawstr); - const float minwidth = float(UI_DPI_ICON_SIZE); + const float minwidth = float(UI_ICON_SIZE); BLI_strncpy(drawstr, name, sizeof(drawstr)); UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0'); diff --git a/source/blender/editors/interface/resources.cc b/source/blender/editors/interface/resources.cc index f5af0c5b95e..a2c81849107 100644 --- a/source/blender/editors/interface/resources.cc +++ b/source/blender/editors/interface/resources.cc @@ -1471,7 +1471,7 @@ void UI_ThemeClearColor(int colorid) int UI_ThemeMenuShadowWidth() { bTheme *btheme = UI_GetTheme(); - return int(btheme->tui.menu_shadow_width * UI_DPI_FAC); + return int(btheme->tui.menu_shadow_width * UI_SCALE_FAC); } void UI_make_axis_color(const uchar src_col[3], uchar dst_col[3], const char axis) diff --git a/source/blender/editors/interface/view2d.cc b/source/blender/editors/interface/view2d.cc index a8d5b1ad22c..ec81711caeb 100644 --- a/source/blender/editors/interface/view2d.cc +++ b/source/blender/editors/interface/view2d.cc @@ -1288,7 +1288,7 @@ void UI_view2d_dot_grid_draw(const View2D *v2d, immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); /* Scaling the dots fully with the zoom looks too busy, but a bit of size variation is nice. */ - const float min_point_size = 2.0f * UI_DPI_FAC; + const float min_point_size = 2.0f * UI_SCALE_FAC; const float point_size_factor = 1.5f; const float max_point_size = point_size_factor * min_point_size; diff --git a/source/blender/editors/interface/view2d_draw.cc b/source/blender/editors/interface/view2d_draw.cc index c20ad465748..30791a84876 100644 --- a/source/blender/editors/interface/view2d_draw.cc +++ b/source/blender/editors/interface/view2d_draw.cc @@ -38,7 +38,7 @@ /* Compute display grid resolution ********************************************************/ -#define MIN_MAJOR_LINE_DISTANCE (U.v2d_min_gridsize * UI_DPI_FAC) +#define MIN_MAJOR_LINE_DISTANCE (U.v2d_min_gridsize * UI_SCALE_FAC) static float select_major_distance(const float *possible_distances, uint amount, @@ -303,7 +303,7 @@ static void draw_horizontal_scale_indicators(const ARegion *region, BLF_batch_draw_begin(); - const float ypos = rect->ymin + 4 * UI_DPI_FAC; + const float ypos = rect->ymin + 4 * UI_SCALE_FAC; const float xmin = rect->xmin; const float xmax = rect->xmax; @@ -383,7 +383,7 @@ static void draw_vertical_scale_indicators(const ARegion *region, BLF_shadow_offset(font_id, 1, -1); const float x_offset = 8.0f; - const float xpos = (rect->xmin + x_offset) * UI_DPI_FAC; + const float xpos = (rect->xmin + x_offset) * UI_SCALE_FAC; const float ymin = rect->ymin; const float ymax = rect->ymax; const float y_offset = (BLF_height(font_id, "0", 1) / 2.0f) - U.pixelsize; diff --git a/source/blender/editors/interface/view2d_edge_pan.cc b/source/blender/editors/interface/view2d_edge_pan.cc index 897a638dfe5..5f1600647b2 100644 --- a/source/blender/editors/interface/view2d_edge_pan.cc +++ b/source/blender/editors/interface/view2d_edge_pan.cc @@ -174,7 +174,7 @@ static float edge_pan_speed(View2DEdgePanData *vpd, const float zoom_factor = 1.0f + CLAMPIS(vpd->zoom_influence, 0.0f, 1.0f) * (zoomx - 1.0f); return distance_factor * delay_factor * zoom_factor * vpd->max_speed * U.widget_unit * - float(U.dpi_fac); + float(UI_SCALE_FAC); } static void edge_pan_apply_delta(bContext *C, View2DEdgePanData *vpd, float dx, float dy) diff --git a/source/blender/editors/interface/view2d_gizmo_navigate.cc b/source/blender/editors/interface/view2d_gizmo_navigate.cc index 05cb955c660..9e7a62e140e 100644 --- a/source/blender/editors/interface/view2d_gizmo_navigate.cc +++ b/source/blender/editors/interface/view2d_gizmo_navigate.cc @@ -221,7 +221,7 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g navgroup->state.rect_visible = *rect_visible; const float icon_size = GIZMO_SIZE; - const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC; + const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_SCALE_FAC; const float co[2] = { roundf(rect_visible->xmax - (icon_offset_mini * 0.75f)), roundf(rect_visible->ymax - (icon_offset_mini * 0.75f)), diff --git a/source/blender/editors/interface/view2d_ops.cc b/source/blender/editors/interface/view2d_ops.cc index 41bc73e4616..7fd898bbff8 100644 --- a/source/blender/editors/interface/view2d_ops.cc +++ b/source/blender/editors/interface/view2d_ops.cc @@ -976,8 +976,8 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) const bool zoom_to_pos = use_cursor_init && vzd->zoom_to_mouse_pos; /* get amount to move view by */ - float dx = RNA_float_get(op->ptr, "deltax") / U.dpi_fac; - float dy = RNA_float_get(op->ptr, "deltay") / U.dpi_fac; + float dx = RNA_float_get(op->ptr, "deltax") / UI_SCALE_FAC; + float dy = RNA_float_get(op->ptr, "deltay") / UI_SCALE_FAC; /* Check if the 'timer' is initialized, as zooming with the trackpad * never uses the "Continuous" zoom method, and the 'timer' is not initialized. */ diff --git a/source/blender/editors/interface/views/grid_view.cc b/source/blender/editors/interface/views/grid_view.cc index a46e42c9ad7..2674af9a5e3 100644 --- a/source/blender/editors/interface/views/grid_view.cc +++ b/source/blender/editors/interface/views/grid_view.cc @@ -314,7 +314,7 @@ class GridViewLayoutBuilder { friend class GridViewBuilder; public: - GridViewLayoutBuilder(uiBlock &block); + GridViewLayoutBuilder(uiLayout &layout); void build_from_view(const AbstractGridView &grid_view, const View2D &v2d) const; @@ -324,7 +324,7 @@ class GridViewLayoutBuilder { uiLayout *current_layout() const; }; -GridViewLayoutBuilder::GridViewLayoutBuilder(uiBlock &block) : block_(block) +GridViewLayoutBuilder::GridViewLayoutBuilder(uiLayout &layout) : block_(*uiLayoutGetBlock(&layout)) { } @@ -340,7 +340,7 @@ void GridViewLayoutBuilder::build_grid_tile(uiLayout &grid_layout, void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view, const View2D &v2d) const { - uiLayout *prev_layout = current_layout(); + uiLayout *parent_layout = current_layout(); uiLayout &layout = *uiLayoutColumn(current_layout(), false); const GridViewStyle &style = grid_view.get_style(); @@ -377,7 +377,7 @@ void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view, } } - UI_block_layout_set_current(&block_, prev_layout); + UI_block_layout_set_current(&block_, parent_layout); build_visible_helper.fill_layout_after_visible(block_); } @@ -393,13 +393,20 @@ GridViewBuilder::GridViewBuilder(uiBlock &block) : block_(block) { } -void GridViewBuilder::build_grid_view(AbstractGridView &grid_view, const View2D &v2d) +void GridViewBuilder::build_grid_view(AbstractGridView &grid_view, + const View2D &v2d, + uiLayout &layout) { + uiBlock &block = *uiLayoutGetBlock(&layout); + grid_view.build_items(); - grid_view.update_from_old(block_); + grid_view.update_from_old(block); grid_view.change_state_delayed(); - GridViewLayoutBuilder builder(block_); + /* Ensure the given layout is actually active. */ + UI_block_layout_set_current(&block, &layout); + + GridViewLayoutBuilder builder(layout); builder.build_from_view(grid_view, v2d); } diff --git a/source/blender/editors/interface/views/tree_view.cc b/source/blender/editors/interface/views/tree_view.cc index 04987fad59b..f3acfe75246 100644 --- a/source/blender/editors/interface/views/tree_view.cc +++ b/source/blender/editors/interface/views/tree_view.cc @@ -145,7 +145,7 @@ void AbstractTreeViewItem::add_indent(uiLayout &row) const uiLayout *subrow = uiLayoutRow(&row, true); uiLayoutSetFixedSize(subrow, true); - const float indent_size = count_parents() * UI_DPI_ICON_SIZE; + const float indent_size = count_parents() * UI_ICON_SIZE; uiDefBut(block, UI_BTYPE_SEPR, 0, "", 0, 0, indent_size, 0, nullptr, 0.0, 0.0, 0, 0, ""); /* Indent items without collapsing icon some more within their parent. Makes it clear that they @@ -405,30 +405,30 @@ class TreeViewLayoutBuilder { void build_row(AbstractTreeViewItem &item) const; uiBlock &block() const; - uiLayout *current_layout() const; + uiLayout ¤t_layout() const; private: - /* Created through #TreeViewBuilder. */ - TreeViewLayoutBuilder(uiBlock &block); + /* Created through #TreeViewBuilder (friend class). */ + TreeViewLayoutBuilder(uiLayout &layout); static void polish_layout(const uiBlock &block); }; -TreeViewLayoutBuilder::TreeViewLayoutBuilder(uiBlock &block) : block_(block) +TreeViewLayoutBuilder::TreeViewLayoutBuilder(uiLayout &layout) : block_(*uiLayoutGetBlock(&layout)) { } void TreeViewLayoutBuilder::build_from_tree(const AbstractTreeView &tree_view) { - uiLayout *prev_layout = current_layout(); + uiLayout &parent_layout = current_layout(); - uiLayout *box = uiLayoutBox(prev_layout); + uiLayout *box = uiLayoutBox(&parent_layout); uiLayoutColumn(box, false); tree_view.foreach_item([this](AbstractTreeViewItem &item) { build_row(item); }, AbstractTreeView::IterOptions::SkipCollapsed); - UI_block_layout_set_current(&block(), prev_layout); + UI_block_layout_set_current(&block(), &parent_layout); } void TreeViewLayoutBuilder::polish_layout(const uiBlock &block) @@ -450,10 +450,10 @@ void TreeViewLayoutBuilder::build_row(AbstractTreeViewItem &item) const { uiBlock &block_ = block(); - uiLayout *prev_layout = current_layout(); + uiLayout &prev_layout = current_layout(); eUIEmbossType previous_emboss = UI_block_emboss_get(&block_); - uiLayout *overlap = uiLayoutOverlap(prev_layout); + uiLayout *overlap = uiLayoutOverlap(&prev_layout); uiLayoutRow(overlap, false); /* Every item gets one! Other buttons can be overlapped on top. */ @@ -475,7 +475,7 @@ void TreeViewLayoutBuilder::build_row(AbstractTreeViewItem &item) const polish_layout(block_); UI_block_emboss_set(&block_, previous_emboss); - UI_block_layout_set_current(&block_, prev_layout); + UI_block_layout_set_current(&block_, &prev_layout); } uiBlock &TreeViewLayoutBuilder::block() const @@ -483,24 +483,25 @@ uiBlock &TreeViewLayoutBuilder::block() const return block_; } -uiLayout *TreeViewLayoutBuilder::current_layout() const +uiLayout &TreeViewLayoutBuilder::current_layout() const { - return block().curlayout; + return *block().curlayout; } /* ---------------------------------------------------------------------- */ -TreeViewBuilder::TreeViewBuilder(uiBlock &block) : block_(block) +void TreeViewBuilder::build_tree_view(AbstractTreeView &tree_view, uiLayout &layout) { -} + uiBlock &block = *uiLayoutGetBlock(&layout); -void TreeViewBuilder::build_tree_view(AbstractTreeView &tree_view) -{ tree_view.build_tree(); - tree_view.update_from_old(block_); + tree_view.update_from_old(block); tree_view.change_state_delayed(); - TreeViewLayoutBuilder builder(block_); + /* Ensure the given layout is actually active. */ + UI_block_layout_set_current(&block, &layout); + + TreeViewLayoutBuilder builder(layout); builder.build_from_tree(tree_view); } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index ea4050d0ba0..8019fee01fb 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -469,7 +469,8 @@ static void mask_draw_curve_type(const bContext *C, float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f( + "viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 2); /* "advanced" mode */ immUniform4fv("color", colors[0]); @@ -806,7 +807,7 @@ void ED_mask_draw_frames( int height = (frame == cfra) ? 22 : 10; int x = (frame - sfra) * framelen; immVertex2i(pos, x, region_bottom); - immVertex2i(pos, x, region_bottom + height * UI_DPI_FAC); + immVertex2i(pos, x, region_bottom + height * UI_SCALE_FAC); } immEnd(); immUnbindProgram(); diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc index 64a4f59a5e7..2c293400d85 100644 --- a/source/blender/editors/mesh/editface.cc +++ b/source/blender/editors/mesh/editface.cc @@ -224,7 +224,7 @@ static void build_poly_connections(blender::AtomicDisjointSet &islands, { using namespace blender; const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); const bke::AttributeAccessor attributes = mesh.attributes(); const VArray uv_seams = attributes.lookup_or_default( @@ -240,23 +240,23 @@ static void build_poly_connections(blender::AtomicDisjointSet &islands, continue; } const MPoly &poly = polys[poly_index]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); + const Span poly_edges = corner_edges.slice(poly.loopstart, poly.totloop); - for (const int poly_loop_index : poly_loops.index_range()) { - const MLoop &outer_mloop = poly_loops[poly_loop_index]; - if (skip_seams && uv_seams[outer_mloop.e]) { + for (const int poly_loop_index : poly_edges.index_range()) { + const int outer_edge = poly_edges[poly_loop_index]; + if (skip_seams && uv_seams[outer_edge]) { continue; } - for (const MLoop &inner_mloop : - poly_loops.slice(poly_loop_index, poly_loops.size() - poly_loop_index)) { - if (&outer_mloop == &inner_mloop) { + for (const int inner_edge : + poly_edges.slice(poly_loop_index, poly_edges.size() - poly_loop_index)) { + if (outer_edge == inner_edge) { continue; } - if (skip_seams && uv_seams[inner_mloop.e]) { + if (skip_seams && uv_seams[inner_edge]) { continue; } - islands.join(inner_mloop.e, outer_mloop.e); + islands.join(inner_edge, outer_edge); } } } @@ -274,7 +274,7 @@ static void paintface_select_linked_faces(Mesh &mesh, build_poly_connections(islands, mesh); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); const VArray uv_seams = attributes.lookup_or_default( @@ -285,11 +285,11 @@ static void paintface_select_linked_faces(Mesh &mesh, Set selected_roots; for (const int i : face_indices) { const MPoly &poly = polys[i]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - if (uv_seams[loop.e]) { + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + if (uv_seams[edge]) { continue; } - const int root = islands.find_root(loop.e); + const int root = islands.find_root(edge); selected_roots.add(root); } } @@ -297,8 +297,8 @@ static void paintface_select_linked_faces(Mesh &mesh, threading::parallel_for(select_poly.span.index_range(), 1024, [&](const IndexRange range) { for (const int poly_index : range) { const MPoly &poly = polys[poly_index]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - const int root = islands.find_root(loop.e); + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + const int root = islands.find_root(edge); if (selected_roots.contains(root)) { select_poly.span[poly_index] = select; break; @@ -424,7 +424,7 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) const Span positions = me->vert_positions(); const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); bke::AttributeAccessor attributes = me->attributes(); const VArray hide_poly = attributes.lookup_or_default( ".hide_poly", ATTR_DOMAIN_FACE, false); @@ -437,9 +437,9 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) } const MPoly &poly = polys[i]; - const MLoop *ml = &loops[poly.loopstart]; - for (int b = 0; b < poly.totloop; b++, ml++) { - mul_v3_m3v3(vec, bmat, positions[ml->v]); + for (int b = 0; b < poly.totloop; b++) { + const int corner = poly.loopstart + b; + mul_v3_m3v3(vec, bmat, positions[corner_verts[corner]]); add_v3_v3v3(vec, vec, ob->object_to_world[3]); minmax_v3v3_v3(r_min, r_max, vec); } diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 736555d678c..a9cc62e6a51 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -66,7 +66,7 @@ /* Detect isolated holes and fill them. */ #define USE_NET_ISLAND_CONNECT -#define KMAXDIST (10 * U.dpi_fac) /* Max mouse distance from edge before not detecting it. */ +#define KMAXDIST (10 * UI_SCALE_FAC) /* Max mouse distance from edge before not detecting it. */ /* WARNING: Knife float precision is fragile: * Be careful before making changes here see: (#43229, #42864, #42459, #41164). @@ -495,7 +495,7 @@ static void knifetool_draw_visible_distances(const KnifeTool_OpData *kcd) char numstr[256]; float numstr_size[2]; float posit[2]; - const float bg_margin = 4.0f * U.dpi_fac; + const float bg_margin = 4.0f * UI_SCALE_FAC; const float font_size = 14.0f; const int distance_precision = 4; @@ -517,7 +517,7 @@ static void knifetool_draw_visible_distances(const KnifeTool_OpData *kcd) } BLF_enable(blf_mono_font, BLF_ROTATION); - BLF_size(blf_mono_font, font_size * U.dpi_fac); + BLF_size(blf_mono_font, font_size * UI_SCALE_FAC); BLF_rotation(blf_mono_font, 0.0f); BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); @@ -563,9 +563,9 @@ static void knifetool_draw_angle(const KnifeTool_OpData *kcd, { const RegionView3D *rv3d = kcd->region->regiondata; const int arc_steps = 24; - const float arc_size = 64.0f * U.dpi_fac; - const float bg_margin = 4.0f * U.dpi_fac; - const float cap_size = 4.0f * U.dpi_fac; + const float arc_size = 64.0f * UI_SCALE_FAC; + const float bg_margin = 4.0f * UI_SCALE_FAC; + const float cap_size = 4.0f * UI_SCALE_FAC; const float font_size = 14.0f; const int angle_precision = 3; @@ -647,7 +647,7 @@ static void knifetool_draw_angle(const KnifeTool_OpData *kcd, } BLF_enable(blf_mono_font, BLF_ROTATION); - BLF_size(blf_mono_font, font_size * U.dpi_fac); + BLF_size(blf_mono_font, font_size * UI_SCALE_FAC); BLF_rotation(blf_mono_font, 0.0f); BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); @@ -907,7 +907,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v if (kcd->prev.vert) { immUniformColor3ubv(kcd->colors.point); - GPU_point_size(11 * UI_DPI_FAC); + GPU_point_size(11 * UI_SCALE_FAC); immBegin(GPU_PRIM_POINTS, 1); immVertex3fv(pos, kcd->prev.cage); @@ -916,7 +916,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v if (kcd->prev.bmface || kcd->prev.edge) { immUniformColor3ubv(kcd->colors.curpoint); - GPU_point_size(9 * UI_DPI_FAC); + GPU_point_size(9 * UI_SCALE_FAC); immBegin(GPU_PRIM_POINTS, 1); immVertex3fv(pos, kcd->prev.cage); @@ -925,7 +925,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v if (kcd->curr.vert) { immUniformColor3ubv(kcd->colors.point); - GPU_point_size(11 * UI_DPI_FAC); + GPU_point_size(11 * UI_SCALE_FAC); immBegin(GPU_PRIM_POINTS, 1); immVertex3fv(pos, kcd->curr.cage); @@ -943,7 +943,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v if (kcd->curr.bmface || kcd->curr.edge) { immUniformColor3ubv(kcd->colors.curpoint); - GPU_point_size(9 * UI_DPI_FAC); + GPU_point_size(9 * UI_SCALE_FAC); immBegin(GPU_PRIM_POINTS, 1); immVertex3fv(pos, kcd->curr.cage); @@ -984,7 +984,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v KnifeVert *kfv; immUniformColor3ubv(kcd->colors.point); - GPU_point_size(5.0 * UI_DPI_FAC); + GPU_point_size(5.0 * UI_SCALE_FAC); GPUBatch *batch = immBeginBatchAtMost(GPU_PRIM_POINTS, BLI_mempool_len(kcd->kverts)); @@ -1040,7 +1040,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v /* Draw any snapped verts first. */ rgba_uchar_to_float(fcol, kcd->colors.point_a); GPU_batch_uniform_4fv(batch, "color", fcol); - GPU_point_size(11 * UI_DPI_FAC); + GPU_point_size(11 * UI_SCALE_FAC); if (snapped_verts_count > 0) { GPU_batch_draw_range(batch, 0, snapped_verts_count); } @@ -1048,7 +1048,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v /* Now draw the rest. */ rgba_uchar_to_float(fcol, kcd->colors.curpoint_a); GPU_batch_uniform_4fv(batch, "color", fcol); - GPU_point_size(7 * UI_DPI_FAC); + GPU_point_size(7 * UI_SCALE_FAC); if (other_verts_count > 0) { GPU_batch_draw_range(batch, snapped_verts_count, other_verts_count); } diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 9627d88f258..856f021f529 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -800,7 +800,8 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator const bool *sharp_faces = static_cast( CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, "sharp_face")); bke::mesh::edges_sharp_from_angle_set(me->polys(), - me->loops(), + me->corner_verts(), + me->corner_edges(), me->poly_normals(), sharp_faces, me->smoothresh, @@ -1209,8 +1210,11 @@ static void mesh_add_loops(Mesh *mesh, int len) CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop); CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop); - if (!CustomData_has_layer(&ldata, CD_MLOOP)) { - CustomData_add_layer(&ldata, CD_MLOOP, CD_SET_DEFAULT, totloop); + if (!CustomData_get_layer_named(&ldata, CD_PROP_INT32, ".corner_vert")) { + CustomData_add_layer_named(&ldata, CD_PROP_INT32, CD_SET_DEFAULT, totloop, ".corner_vert"); + } + if (!CustomData_get_layer_named(&ldata, CD_PROP_INT32, ".corner_edge")) { + CustomData_add_layer_named(&ldata, CD_PROP_INT32, CD_SET_DEFAULT, totloop, ".corner_edge"); } BKE_mesh_runtime_clear_cache(mesh); @@ -1459,7 +1463,8 @@ void ED_mesh_split_faces(Mesh *mesh) { using namespace blender; const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); + const Span corner_edges = mesh->corner_edges(); const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI); const bke::AttributeAccessor attributes = mesh->attributes(); const VArray mesh_sharp_edges = attributes.lookup_or_default( @@ -1470,15 +1475,20 @@ void ED_mesh_split_faces(Mesh *mesh) Array sharp_edges(mesh->totedge); mesh_sharp_edges.materialize(sharp_edges); - bke::mesh::edges_sharp_from_angle_set( - polys, loops, mesh->poly_normals(), sharp_faces, split_angle, sharp_edges); + bke::mesh::edges_sharp_from_angle_set(polys, + corner_verts, + corner_edges, + mesh->poly_normals(), + sharp_faces, + split_angle, + sharp_edges); threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int poly_i : range) { const MPoly &poly = polys[poly_i]; if (sharp_faces && sharp_faces[poly_i]) { - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - sharp_edges[loop.e] = true; + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + sharp_edges[edge] = true; } } } diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc index 0949361ddea..fef735387b7 100644 --- a/source/blender/editors/mesh/meshtools.cc +++ b/source/blender/editors/mesh/meshtools.cc @@ -74,7 +74,8 @@ static void join_mesh_single(Depsgraph *depsgraph, const float imat[4][4], float3 **vert_positions_pp, MEdge **medge_pp, - MLoop **mloop_pp, + int **corner_verts_pp, + int **corner_edges_pp, MPoly **mpoly_pp, CustomData *vdata, CustomData *edata, @@ -99,7 +100,8 @@ static void join_mesh_single(Depsgraph *depsgraph, Mesh *me = static_cast(ob_src->data); float3 *vert_positions = *vert_positions_pp; MEdge *edge = *medge_pp; - MLoop *mloop = *mloop_pp; + int *corner_verts = *corner_verts_pp; + int *corner_edges = *corner_edges_pp; if (me->totvert) { /* standard data */ @@ -227,9 +229,9 @@ static void join_mesh_single(Depsgraph *depsgraph, CustomData_merge(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop); CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop); - for (a = 0; a < me->totloop; a++, mloop++) { - mloop->v += *vertofs; - mloop->e += *edgeofs; + for (a = 0; a < me->totloop; a++) { + corner_verts[a] += *vertofs; + corner_edges[a] += *edgeofs; } } @@ -293,7 +295,8 @@ static void join_mesh_single(Depsgraph *depsgraph, *edgeofs += me->totedge; *medge_pp += me->totedge; *loopofs += me->totloop; - *mloop_pp += me->totloop; + *corner_verts_pp += me->totloop; + *corner_edges_pp += me->totloop; *polyofs += me->totpoly; *mpoly_pp += me->totpoly; } @@ -334,7 +337,6 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) Mesh *me; MEdge *edge = nullptr; MPoly *polys = nullptr; - MLoop *mloop = nullptr; Key *key, *nkey = nullptr; float imat[4][4]; int a, b, totcol, totmat = 0, totedge = 0, totvert = 0; @@ -585,7 +587,10 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) float3 *vert_positions = (float3 *)CustomData_add_layer_named( &vdata, CD_PROP_FLOAT3, CD_SET_DEFAULT, totvert, "position"); edge = (MEdge *)CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, totedge); - mloop = (MLoop *)CustomData_add_layer(&ldata, CD_MLOOP, CD_SET_DEFAULT, totloop); + int *corner_verts = (int *)CustomData_add_layer_named( + &ldata, CD_PROP_INT32, CD_CONSTRUCT, totloop, ".corner_vert"); + int *corner_edges = (int *)CustomData_add_layer_named( + &ldata, CD_PROP_INT32, CD_CONSTRUCT, totloop, ".corner_edge"); polys = (MPoly *)CustomData_add_layer(&pdata, CD_MPOLY, CD_SET_DEFAULT, totpoly); vertofs = 0; @@ -610,7 +615,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) imat, &vert_positions, &edge, - &mloop, + &corner_verts, + &corner_edges, &polys, &vdata, &edata, @@ -644,7 +650,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) imat, &vert_positions, &edge, - &mloop, + &corner_verts, + &corner_edges, &polys, &vdata, &edata, @@ -1225,16 +1232,14 @@ static void ed_mesh_pick_face_vert__mpoly_find( /* mesh data (evaluated) */ const MPoly *poly, const Span vert_positions, - const MLoop *mloop, + const int *corner_verts, /* return values */ float *r_len_best, int *r_v_idx_best) { - const MLoop *ml; - int j = poly->totloop; - for (ml = &mloop[poly->loopstart]; j--; ml++) { + for (int j = poly->totloop; j--;) { float sco[2]; - const int v_idx = ml->v; + const int v_idx = corner_verts[poly->loopstart + j]; if (ED_view3d_project_float_object(region, vert_positions[v_idx], sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { const float len_test = len_manhattan_v2v2(mval, sco); @@ -1271,7 +1276,7 @@ bool ED_mesh_pick_face_vert( const Span vert_positions = me_eval->vert_positions(); const Span polys = me_eval->polys(); - const Span loops = me_eval->loops(); + const Span corner_verts = me_eval->corner_verts(); const int *index_mp_to_orig = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); @@ -1279,8 +1284,13 @@ bool ED_mesh_pick_face_vert( if (index_mp_to_orig) { for (const int i : polys.index_range()) { if (index_mp_to_orig[i] == poly_index) { - ed_mesh_pick_face_vert__mpoly_find( - region, mval_f, &polys[i], vert_positions, loops.data(), &len_best, &v_idx_best); + ed_mesh_pick_face_vert__mpoly_find(region, + mval_f, + &polys[i], + vert_positions, + corner_verts.data(), + &len_best, + &v_idx_best); } } } @@ -1290,7 +1300,7 @@ bool ED_mesh_pick_face_vert( mval_f, &polys[poly_index], vert_positions, - loops.data(), + corner_verts.data(), &len_best, &v_idx_best); } diff --git a/source/blender/editors/object/object_bake_api.cc b/source/blender/editors/object/object_bake_api.cc index 2b689adc9d0..8f571f03e7e 100644 --- a/source/blender/editors/object/object_bake_api.cc +++ b/source/blender/editors/object/object_bake_api.cc @@ -979,7 +979,7 @@ static bool bake_targets_init_vertex_colors(Main *bmain, } static int find_original_loop(const blender::Span orig_polys, - const blender::Span orig_loops, + const blender::Span orig_corner_verts, const int *vert_origindex, const int *poly_origindex, const int poly_eval, @@ -996,9 +996,9 @@ static int find_original_loop(const blender::Span orig_polys, /* Find matching loop with original vertex in original polygon. */ const MPoly &poly_orig = orig_polys[poly_orig_i]; - const MLoop *mloop_orig = &orig_loops[poly_orig.loopstart]; - for (int j = 0; j < poly_orig.totloop; ++j, ++mloop_orig) { - if (mloop_orig->v == vert_orig) { + const int *poly_verts_orig = &orig_corner_verts[poly_orig.loopstart]; + for (int j = 0; j < poly_orig.totloop; ++j) { + if (poly_verts_orig[j] == vert_orig) { return poly_orig.loopstart + j; } } @@ -1033,9 +1033,9 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, const int tottri = poly_to_tri_count(me_eval->totpoly, me_eval->totloop); MLoopTri *looptri = static_cast(MEM_mallocN(sizeof(*looptri) * tottri, __func__)); - const blender::Span loops = me_eval->loops(); + const blender::Span corner_verts = me_eval->corner_verts(); blender::bke::mesh::looptris_calc( - me_eval->vert_positions(), me_eval->polys(), loops, {looptri, tottri}); + me_eval->vert_positions(), me_eval->polys(), corner_verts, {looptri, tottri}); /* For mapping back to original mesh in case there are modifiers. */ const int *vert_origindex = static_cast( @@ -1043,19 +1043,19 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, const int *poly_origindex = static_cast( CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX)); const blender::Span orig_polys = me->polys(); - const blender::Span orig_loops = me->loops(); + const blender::Span orig_corner_verts = me->corner_verts(); for (int i = 0; i < tottri; i++) { const MLoopTri *lt = &looptri[i]; for (int j = 0; j < 3; j++) { uint l = lt->tri[j]; - uint v = loops[l].v; + const int v = corner_verts[l]; /* Map back to original loop if there are modifiers. */ if (vert_origindex != nullptr && poly_origindex != nullptr) { l = find_original_loop( - orig_polys, orig_loops, vert_origindex, poly_origindex, lt->poly, v); + orig_polys, orig_corner_verts, vert_origindex, poly_origindex, lt->poly, v); if (l == ORIGINDEX_NONE || l >= me->totloop) { continue; } @@ -1152,9 +1152,9 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) MEM_callocN(sizeof(int) * me->totvert, "num_loops_for_vertex")); memset(mcol, 0, sizeof(MPropCol) * me->totvert); - const blender::Span loops = me->loops(); + const blender::Span corner_verts = me->corner_verts(); for (int i = 0; i < totloop; i++) { - const int v = loops[i].v; + const int v = corner_verts[i]; bake_result_add_to_rgba(mcol[v].color, &result[i * channels_num], channels_num); num_loops_for_vertex[v]++; } diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index 987f652dc84..d6181d28de9 100644 --- a/source/blender/editors/object/object_remesh.cc +++ b/source/blender/editors/object/object_remesh.cc @@ -354,7 +354,7 @@ static void voxel_size_edit_draw(const bContext *C, ARegion * /*region*/, void * GPU_matrix_push(); GPU_matrix_mul(cd->text_mat); - BLF_size(fontid, 10.0f * fstyle_points * U.dpi_fac); + BLF_size(fontid, 10.0f * fstyle_points * UI_SCALE_FAC); BLF_color3f(fontid, 1.0f, 1.0f, 1.0f); BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight); BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f); @@ -680,7 +680,8 @@ static bool mesh_is_manifold_consistent(Mesh *mesh) */ const Span positions = mesh->vert_positions(); const Span edges = mesh->edges(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); + const Span corner_edges = mesh->corner_edges(); bool is_manifold_consistent = true; char *edge_faces = (char *)MEM_callocN(mesh->totedge * sizeof(char), "remesh_manifold_check"); @@ -691,17 +692,19 @@ static bool mesh_is_manifold_consistent(Mesh *mesh) edge_vert[i] = -1; } - for (const MLoop &loop : loops) { - edge_faces[loop.e] += 1; - if (edge_faces[loop.e] > 2) { + for (const int corner_i : corner_verts.index_range()) { + const int vert = corner_verts[corner_i]; + const int edge = corner_edges[corner_i]; + edge_faces[edge] += 1; + if (edge_faces[edge] > 2) { is_manifold_consistent = false; break; } - if (edge_vert[loop.e] == -1) { - edge_vert[loop.e] = loop.v; + if (edge_vert[edge] == -1) { + edge_vert[edge] = vert; } - else if (edge_vert[loop.e] == loop.v) { + else if (edge_vert[edge] == vert) { /* Mesh has flips in the surface so it is non consistent */ is_manifold_consistent = false; break; diff --git a/source/blender/editors/render/render_view.cc b/source/blender/editors/render/render_view.cc index f0427bf8683..7f212f03731 100644 --- a/source/blender/editors/render/render_view.cc +++ b/source/blender/editors/render/render_view.cc @@ -134,8 +134,8 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports) int sizex, sizey; BKE_render_resolution(&scene->r, false, &sizex, &sizey); - sizex += 30 * UI_DPI_FAC; - sizey += 60 * UI_DPI_FAC; + sizex += 30 * UI_SCALE_FAC; + sizey += 60 * UI_SCALE_FAC; /* arbitrary... miniature image window views don't make much sense */ if (sizex < 320) { diff --git a/source/blender/editors/screen/area.cc b/source/blender/editors/screen/area.cc index 89c7dd7cf65..bfbea031fdd 100644 --- a/source/blender/editors/screen/area.cc +++ b/source/blender/editors/screen/area.cc @@ -183,7 +183,7 @@ static void area_draw_azone_fullscreen(short /*x1*/, short /*y1*/, short x2, sho UI_icon_draw_ex(x2 - U.widget_unit, y2 - U.widget_unit, ICON_FULLSCREEN_EXIT, - U.inv_dpi_fac, + UI_INV_SCALE_FAC, min_ff(alpha, 0.75f), 0.0f, nullptr, @@ -359,7 +359,7 @@ static void region_draw_status_text(ScrArea *area, ARegion *region) const float y = 0.4f * UI_UNIT_Y; if (overlap) { - const float pad = 2.0f * UI_DPI_FAC; + const float pad = 2.0f * UI_SCALE_FAC; const float x1 = x - (UI_UNIT_X - pad); const float x2 = x + width + (UI_UNIT_X - pad); const float y1 = pad; @@ -1301,13 +1301,13 @@ static void region_rect_recursive( } /* `prefsizex/y`, taking into account DPI. */ - int prefsizex = UI_DPI_FAC * + int prefsizex = UI_SCALE_FAC * ((region->sizex > 1) ? region->sizex + 0.5f : region->type->prefsizex); int prefsizey; if (region->flag & RGN_FLAG_PREFSIZE_OR_HIDDEN) { - prefsizex = UI_DPI_FAC * region->type->prefsizex; - prefsizey = UI_DPI_FAC * region->type->prefsizey; + prefsizex = UI_SCALE_FAC * region->type->prefsizex; + prefsizey = UI_SCALE_FAC * region->type->prefsizey; } else if (region->regiontype == RGN_TYPE_HEADER) { prefsizey = ED_area_headersize(); @@ -1322,7 +1322,8 @@ static void region_rect_recursive( prefsizey = ED_region_global_size_y(); } else { - prefsizey = UI_DPI_FAC * (region->sizey > 1 ? region->sizey + 0.5f : region->type->prefsizey); + prefsizey = UI_SCALE_FAC * + (region->sizey > 1 ? region->sizey + 0.5f : region->type->prefsizey); } if (region->flag & RGN_FLAG_HIDDEN) { @@ -1510,12 +1511,12 @@ static void region_rect_recursive( region->winy = BLI_rcti_size_y(®ion->winrct) + 1; /* If region opened normally, we store this for hide/reveal usage. */ - /* Prevent rounding errors for UI_DPI_FAC multiply and divide. */ + /* Prevent rounding errors for UI_SCALE_FAC multiply and divide. */ if (region->winx > 1) { - region->sizex = (region->winx + 0.5f) / UI_DPI_FAC; + region->sizex = (region->winx + 0.5f) / UI_SCALE_FAC; } if (region->winy > 1) { - region->sizey = (region->winy + 0.5f) / UI_DPI_FAC; + region->sizey = (region->winy + 0.5f) / UI_SCALE_FAC; } /* exception for multiple overlapping regions on same spot */ @@ -3024,8 +3025,8 @@ void ED_region_panels_layout_ex(const bContext *C, Panel *panel = static_cast(region->panels.last); if (panel != nullptr) { const int size_dyn[2] = { - int(UI_UNIT_X * (UI_panel_is_closed(panel) ? 8 : 14) / UI_DPI_FAC), - int(UI_panel_size_y(panel) / UI_DPI_FAC), + int(UI_UNIT_X * (UI_panel_is_closed(panel) ? 8 : 14) / UI_SCALE_FAC), + int(UI_panel_size_y(panel) / UI_SCALE_FAC), }; /* region size is layout based and needs to be updated */ if ((region->sizex != size_dyn[0]) || (region->sizey != size_dyn[1])) { @@ -3033,7 +3034,7 @@ void ED_region_panels_layout_ex(const bContext *C, region->sizey = size_dyn[1]; area->flag |= AREA_FLAG_REGION_SIZE_UPDATE; } - y = fabsf(region->sizey * UI_DPI_FAC - 1); + y = fabsf(region->sizey * UI_SCALE_FAC - 1); } } else { @@ -3288,7 +3289,7 @@ void ED_region_header_layout(const bContext *C, ARegion *region) bool region_layout_based = region->flag & RGN_FLAG_DYNAMIC_SIZE; /* Height of buttons and scaling needed to achieve it. */ - const int buttony = min_ii(UI_UNIT_Y, region->winy - 2 * UI_DPI_FAC); + const int buttony = min_ii(UI_UNIT_Y, region->winy - 2 * UI_SCALE_FAC); const float buttony_scale = buttony / float(UI_UNIT_Y); /* Vertically center buttons. */ @@ -3342,7 +3343,7 @@ void ED_region_header_layout(const bContext *C, ARegion *region) maxco = xco; } - int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_DPI_FAC; + int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_SCALE_FAC; if (region_layout_based && (region->sizex != new_sizex)) { /* region size is layout based and needs to be updated */ @@ -3402,7 +3403,7 @@ void ED_region_header_init(ARegion *region) int ED_area_headersize(void) { /* Accommodate widget and padding. */ - return U.widget_unit + int(UI_DPI_FAC * HEADER_PADDING_Y); + return U.widget_unit + int(UI_SCALE_FAC * HEADER_PADDING_Y); } int ED_area_footersize(void) @@ -3413,17 +3414,17 @@ int ED_area_footersize(void) int ED_area_global_size_y(const ScrArea *area) { BLI_assert(ED_area_is_global(area)); - return round_fl_to_int(area->global->cur_fixed_height * UI_DPI_FAC); + return round_fl_to_int(area->global->cur_fixed_height * UI_SCALE_FAC); } int ED_area_global_min_size_y(const ScrArea *area) { BLI_assert(ED_area_is_global(area)); - return round_fl_to_int(area->global->size_min * UI_DPI_FAC); + return round_fl_to_int(area->global->size_min * UI_SCALE_FAC); } int ED_area_global_max_size_y(const ScrArea *area) { BLI_assert(ED_area_is_global(area)); - return round_fl_to_int(area->global->size_max * UI_DPI_FAC); + return round_fl_to_int(area->global->size_max * UI_SCALE_FAC); } bool ED_area_is_global(const ScrArea *area) @@ -3510,7 +3511,7 @@ void ED_region_info_draw_multiline(ARegion *region, rcti rect = *ED_region_visible_rect(region); /* Needed in case scripts leave the font size at an unexpected value, see: #102213. */ - BLF_size(fontid, style->widget.points * U.dpi_fac); + BLF_size(fontid, style->widget.points * UI_SCALE_FAC); /* Box fill entire width or just around text. */ if (!full_redraw) { @@ -3764,7 +3765,7 @@ void ED_region_cache_draw_background(ARegion *region) immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(128, 128, 255, 64); - immRecti(pos, 0, region_bottom, region->winx, region_bottom + 8 * UI_DPI_FAC); + immRecti(pos, 0, region_bottom, region->winx, region_bottom + 8 * UI_SCALE_FAC); immUnbindProgram(); } @@ -3776,7 +3777,7 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f float font_dims[2] = {0.0f, 0.0f}; /* frame number */ - BLF_size(fontid, 11.0f * U.dpi_fac); + BLF_size(fontid, 11.0f * UI_SCALE_FAC); BLI_snprintf(numstr, sizeof(numstr), "%d", framenr); BLF_width_and_height(fontid, numstr, sizeof(numstr), &font_dims[0], &font_dims[1]); @@ -3810,7 +3811,7 @@ void ED_region_cache_draw_cached_segments( float x1 = float(points[a * 2] - sfra) / (efra - sfra + 1) * region->winx; float x2 = float(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * region->winx; - immRecti(pos, x1, region_bottom, x2, region_bottom + 8 * UI_DPI_FAC); + immRecti(pos, x1, region_bottom, x2, region_bottom + 8 * UI_SCALE_FAC); /* TODO(merwin): use primitive restart to draw multiple rects more efficiently */ } diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 58473219cde..25034dd835b 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -629,8 +629,8 @@ int ED_draw_imbuf_method(ImBuf *ibuf) void immDrawBorderCorners(uint pos, const rcti *border, float zoomx, float zoomy) { - float delta_x = 4.0f * UI_DPI_FAC / zoomx; - float delta_y = 4.0f * UI_DPI_FAC / zoomy; + float delta_x = 4.0f * UI_SCALE_FAC / zoomx; + float delta_y = 4.0f * UI_SCALE_FAC / zoomy; delta_x = min_ff(delta_x, border->xmax - border->xmin); delta_y = min_ff(delta_y, border->ymax - border->ymin); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index cb96d2b6bdf..e0969b444eb 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1064,7 +1064,7 @@ static void screen_global_area_refresh(wmWindow *win, static int screen_global_header_size(void) { - return (int)ceilf(ED_area_headersize() / UI_DPI_FAC); + return (int)ceilf(ED_area_headersize() / UI_SCALE_FAC); } static void screen_global_topbar_area_refresh(wmWindow *win, bScreen *screen) diff --git a/source/blender/editors/screen/screen_geometry.c b/source/blender/editors/screen/screen_geometry.c index 3ad3fa7892c..309bedda4fd 100644 --- a/source/blender/editors/screen/screen_geometry.c +++ b/source/blender/editors/screen/screen_geometry.c @@ -284,7 +284,7 @@ short screen_geom_find_area_split_point(const ScrArea *area, { const int cur_area_width = screen_geom_area_width(area); const int cur_area_height = screen_geom_area_height(area); - const short area_min_x = AREAMINX * U.dpi_fac; + const short area_min_x = AREAMINX * UI_SCALE_FAC; const short area_min_y = ED_area_headersize(); /* area big enough? */ diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index d1fe516b406..1d8bb7cb0bc 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -46,13 +46,13 @@ typedef enum eScreenAxis { #define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the #AZone */ /* Edges must be within these to allow joining. */ -#define AREAJOINTOLERANCEX (AREAMINX * U.dpi_fac) -#define AREAJOINTOLERANCEY (HEADERY * U.dpi_fac) +#define AREAJOINTOLERANCEX (AREAMINX * UI_SCALE_FAC) +#define AREAJOINTOLERANCEY (HEADERY * UI_SCALE_FAC) /** * Expanded interaction influence of area borders. */ -#define BORDERPADDING ((2.0f * U.dpi_fac) + U.pixelsize) +#define BORDERPADDING ((2.0f * UI_SCALE_FAC) + U.pixelsize) /* area.cc */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index a9c6ff11a53..ca1f190001b 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1207,7 +1207,7 @@ static ScrEdge *screen_area_edge_from_cursor(const bContext *C, if (actedge == NULL) { return NULL; } - int borderwidth = (4 * UI_DPI_FAC); + int borderwidth = (4 * UI_SCALE_FAC); ScrArea *sa1, *sa2; if (screen_geom_edge_is_horizontal(actedge)) { sa1 = BKE_screen_find_area_xy( @@ -1638,7 +1638,7 @@ static void area_move_set_limits(wmWindow *win, } } else { - int areamin = AREAMINX * U.dpi_fac; + int areamin = AREAMINX * UI_SCALE_FAC; if (area->v1->vec.x > window_rect.xmin) { areamin += U.pixelsize; @@ -1847,7 +1847,7 @@ static void area_move_apply_do(const bContext *C, if (area->v1->editflag || area->v2->editflag || area->v3->editflag || area->v4->editflag) { if (ED_area_is_global(area)) { /* Snap to minimum or maximum for global areas. */ - int height = round_fl_to_int(screen_geom_area_height(area) / UI_DPI_FAC); + int height = round_fl_to_int(screen_geom_area_height(area) / UI_SCALE_FAC); if (abs(height - area->global->size_min) < abs(height - area->global->size_max)) { area->global->cur_fixed_height = area->global->size_min; } @@ -2061,7 +2061,7 @@ static bool area_split_allowed(const ScrArea *area, const eScreenAxis dir_axis) return false; } - if ((dir_axis == SCREEN_AXIS_V && area->winx <= 2 * AREAMINX * U.dpi_fac) || + if ((dir_axis == SCREEN_AXIS_V && area->winx <= 2 * AREAMINX * UI_SCALE_FAC) || (dir_axis == SCREEN_AXIS_H && area->winy <= 2 * ED_area_headersize())) { /* Must be at least double minimum sizes to split into two. */ return false; @@ -2639,7 +2639,7 @@ static int area_max_regionsize(ScrArea *area, ARegion *scale_region, AZEdge edge } } - dist /= UI_DPI_FAC; + dist /= UI_SCALE_FAC; return dist; } @@ -2731,7 +2731,7 @@ static void region_scale_validate_size(RegionMoveData *rmd) size = &rmd->region->sizey; } - maxsize = rmd->maxsize - (UI_UNIT_Y / UI_DPI_FAC); + maxsize = rmd->maxsize - (UI_UNIT_Y / UI_SCALE_FAC); if (*size > maxsize && maxsize > 0) { *size = maxsize; @@ -2781,7 +2781,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* region sizes now get multiplied */ - delta /= UI_DPI_FAC; + delta /= UI_SCALE_FAC; const int size_no_snap = rmd->origval + delta; rmd->region->sizex = size_no_snap; @@ -2814,7 +2814,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* region sizes now get multiplied */ - delta /= UI_DPI_FAC; + delta /= UI_SCALE_FAC; const int size_no_snap = rmd->origval + delta; rmd->region->sizey = size_no_snap; @@ -5044,8 +5044,8 @@ static int userpref_show_exec(bContext *C, wmOperator *op) wmWindow *win_cur = CTX_wm_window(C); /* Use eventstate, not event from _invoke, so this can be called through exec(). */ const wmEvent *event = win_cur->eventstate; - int sizex = (500 + UI_NAVIGATION_REGION_WIDTH) * UI_DPI_FAC; - int sizey = 520 * UI_DPI_FAC; + int sizex = (500 + UI_NAVIGATION_REGION_WIDTH) * UI_SCALE_FAC; + int sizey = 520 * UI_SCALE_FAC; PropertyRNA *prop = RNA_struct_find_property(op->ptr, "section"); if (prop && RNA_property_is_set(op->ptr, prop)) { @@ -5124,8 +5124,8 @@ static int drivers_editor_show_exec(bContext *C, wmOperator *op) /* Use eventstate, not event from _invoke, so this can be called through exec(). */ const wmEvent *event = win_cur->eventstate; - int sizex = 900 * UI_DPI_FAC; - int sizey = 580 * UI_DPI_FAC; + int sizex = 900 * UI_SCALE_FAC; + int sizey = 580 * UI_SCALE_FAC; /* Get active property to show driver for * - Need to grab it first, or else this info disappears @@ -5201,8 +5201,8 @@ static int info_log_show_exec(bContext *C, wmOperator *op) wmWindow *win_cur = CTX_wm_window(C); /* Use eventstate, not event from _invoke, so this can be called through exec(). */ const wmEvent *event = win_cur->eventstate; - int sizex = 900 * UI_DPI_FAC; - int sizey = 580 * UI_DPI_FAC; + int sizex = 900 * UI_SCALE_FAC; + int sizey = 580 * UI_SCALE_FAC; int shift_y = 480; /* changes context! */ diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc index bb12782cad5..5f953071804 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc @@ -91,7 +91,7 @@ struct AddOperationExecutor { Object *surface_ob_eval_ = nullptr; Mesh *surface_eval_ = nullptr; Span surface_positions_eval_; - Span surface_loops_eval_; + Span surface_corner_verts_eval_; Span surface_looptris_eval_; VArraySpan surface_uv_map_eval_; BVHTreeFromMesh surface_bvh_eval_; @@ -143,7 +143,7 @@ struct AddOperationExecutor { return; } surface_positions_eval_ = surface_eval_->vert_positions(); - surface_loops_eval_ = surface_eval_->loops(); + surface_corner_verts_eval_ = surface_eval_->corner_verts(); surface_looptris_eval_ = surface_eval_->looptris(); BKE_bvhtree_from_mesh_get(&surface_bvh_eval_, surface_eval_, BVHTREE_FROM_LOOPTRI, 2); BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval_); }); @@ -306,7 +306,7 @@ struct AddOperationExecutor { const MLoopTri &looptri = surface_looptris_eval_[looptri_index]; const float3 brush_pos_su = ray_hit.co; const float3 bary_coords = bke::mesh_surface_sample::compute_bary_coord_in_triangle( - surface_positions_eval_, surface_loops_eval_, looptri, brush_pos_su); + surface_positions_eval_, surface_corner_verts_eval_, looptri, brush_pos_su); const float2 uv = bke::mesh_surface_sample::sample_corner_attrribute_with_bary_coords( bary_coords, looptri, surface_uv_map_eval_); @@ -436,9 +436,12 @@ struct AddOperationExecutor { brush_radius_su, [&](const int index, const float3 & /*co*/, const float /*dist_sq*/) { const MLoopTri &looptri = surface_looptris_eval_[index]; - const float3 &v0_su = surface_positions_eval_[surface_loops_eval_[looptri.tri[0]].v]; - const float3 &v1_su = surface_positions_eval_[surface_loops_eval_[looptri.tri[1]].v]; - const float3 &v2_su = surface_positions_eval_[surface_loops_eval_[looptri.tri[2]].v]; + const float3 &v0_su = + surface_positions_eval_[surface_corner_verts_eval_[looptri.tri[0]]]; + const float3 &v1_su = + surface_positions_eval_[surface_corner_verts_eval_[looptri.tri[1]]]; + const float3 &v2_su = + surface_positions_eval_[surface_corner_verts_eval_[looptri.tri[2]]]; float3 normal_su; normal_tri_v3(normal_su, v0_su, v1_su, v2_su); if (math::dot(normal_su, view_direction_su) >= 0.0f) { diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc index f0745ef3d0d..8e484e4fb70 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc @@ -74,7 +74,7 @@ struct PuffOperationExecutor { Object *surface_ob_ = nullptr; Mesh *surface_ = nullptr; Span surface_positions_; - Span surface_loops_; + Span surface_corner_verts_; Span surface_looptris_; Span corner_normals_su_; BVHTreeFromMesh surface_bvh_; @@ -125,7 +125,7 @@ struct PuffOperationExecutor { surface_->totloop}; surface_positions_ = surface_->vert_positions(); - surface_loops_ = surface_->loops(); + surface_corner_verts_ = surface_->corner_verts(); surface_looptris_ = surface_->looptris(); BKE_bvhtree_from_mesh_get(&surface_bvh_, surface_, BVHTREE_FROM_LOOPTRI, 2); BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_); }); @@ -315,9 +315,9 @@ struct PuffOperationExecutor { const MLoopTri &looptri = surface_looptris_[nearest.index]; const float3 closest_pos_su = nearest.co; - const float3 &v0_su = surface_positions_[surface_loops_[looptri.tri[0]].v]; - const float3 &v1_su = surface_positions_[surface_loops_[looptri.tri[1]].v]; - const float3 &v2_su = surface_positions_[surface_loops_[looptri.tri[2]].v]; + const float3 &v0_su = surface_positions_[surface_corner_verts_[looptri.tri[0]]]; + const float3 &v1_su = surface_positions_[surface_corner_verts_[looptri.tri[1]]]; + const float3 &v2_su = surface_positions_[surface_corner_verts_[looptri.tri[2]]]; float3 bary_coords; interp_weights_tri_v3(bary_coords, v0_su, v1_su, v2_su, closest_pos_su); const float3 normal_su = geometry::compute_surface_point_normal( diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc index b4ce8ebc295..2f198b89da9 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc @@ -105,7 +105,7 @@ struct SlideOperationExecutor { Object *surface_ob_eval_ = nullptr; Mesh *surface_eval_ = nullptr; Span surface_positions_eval_; - Span surface_loops_eval_; + Span surface_corner_verts_eval_; Span surface_looptris_eval_; VArraySpan surface_uv_map_eval_; BVHTreeFromMesh surface_bvh_eval_; @@ -199,7 +199,7 @@ struct SlideOperationExecutor { } surface_looptris_eval_ = surface_eval_->looptris(); surface_positions_eval_ = surface_eval_->vert_positions(); - surface_loops_eval_ = surface_eval_->loops(); + surface_corner_verts_eval_ = surface_eval_->corner_verts(); surface_uv_map_eval_ = surface_eval_->attributes().lookup(uv_map_name, ATTR_DOMAIN_CORNER); if (surface_uv_map_eval_.is_empty()) { @@ -317,7 +317,7 @@ struct SlideOperationExecutor { const float4x4 brush_transform_inv = math::invert(brush_transform); const Span positions_orig_su = surface_orig_->vert_positions(); - const Span loops_orig = surface_orig_->loops(); + const Span corner_verts_orig = surface_orig_->corner_verts(); const OffsetIndices points_by_curve = curves_orig_->points_by_curve(); MutableSpan positions_orig_cu = curves_orig_->positions_for_write(); @@ -383,7 +383,7 @@ struct SlideOperationExecutor { /* Compute the uv of the new surface position on the evaluated mesh. */ const MLoopTri &looptri_eval = surface_looptris_eval_[looptri_index_eval]; const float3 bary_weights_eval = bke::mesh_surface_sample::compute_bary_coord_in_triangle( - surface_positions_eval_, surface_loops_eval_, looptri_eval, hit_pos_eval_su); + surface_positions_eval_, surface_corner_verts_eval_, looptri_eval, hit_pos_eval_su); const float2 uv = attribute_math::mix3(bary_weights_eval, surface_uv_map_eval_[looptri_eval.tri[0]], surface_uv_map_eval_[looptri_eval.tri[1]], @@ -408,9 +408,9 @@ struct SlideOperationExecutor { /* Gather old and new surface position. */ const float3 new_first_pos_orig_su = attribute_math::mix3( bary_weights_orig, - positions_orig_su[loops_orig[looptri_orig.tri[0]].v], - positions_orig_su[loops_orig[looptri_orig.tri[1]].v], - positions_orig_su[loops_orig[looptri_orig.tri[2]].v]); + positions_orig_su[corner_verts_orig[looptri_orig.tri[0]]], + positions_orig_su[corner_verts_orig[looptri_orig.tri[1]]], + positions_orig_su[corner_verts_orig[looptri_orig.tri[2]]]); const float3 old_first_pos_orig_cu = self_->initial_positions_cu_[first_point_i]; const float3 new_first_pos_orig_cu = math::transform_point(transforms_.surface_to_curves, new_first_pos_orig_su); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.cc b/source/blender/editors/sculpt_paint/paint_image_proj.cc index f4838823b35..31f0af2c489 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.cc +++ b/source/blender/editors/sculpt_paint/paint_image_proj.cc @@ -414,7 +414,7 @@ struct ProjPaintState { blender::Span vert_normals; blender::Span edges_eval; blender::Span polys_eval; - blender::Span loops_eval; + blender::Span corner_verts_eval; const bool *select_poly_eval; const int *material_indices; const bool *sharp_faces_eval; @@ -508,8 +508,8 @@ struct VertSeam { * \{ */ #define PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) \ - int(ps->loops_eval[lt->tri[0]].v), int(ps->loops_eval[lt->tri[1]].v), \ - int(ps->loops_eval[lt->tri[2]].v), + ps->corner_verts_eval[lt->tri[0]], ps->corner_verts_eval[lt->tri[1]], \ + ps->corner_verts_eval[lt->tri[2]], #define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \ uvlayer[lt->poly][lt->tri[0]], uvlayer[lt->poly][lt->tri[1]], uvlayer[lt->poly][lt->tri[2]], @@ -674,9 +674,9 @@ static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], f const int tri_index = POINTER_AS_INT(node->link); const MLoopTri *lt = &ps->looptris_eval[tri_index]; const float *vtri_ss[3] = { - ps->screenCoords[ps->loops_eval[lt->tri[0]].v], - ps->screenCoords[ps->loops_eval[lt->tri[1]].v], - ps->screenCoords[ps->loops_eval[lt->tri[2]].v], + ps->screenCoords[ps->corner_verts_eval[lt->tri[0]]], + ps->screenCoords[ps->corner_verts_eval[lt->tri[1]]], + ps->screenCoords[ps->corner_verts_eval[lt->tri[2]]], }; if (isect_point_tri_v2(pt, UNPACK3(vtri_ss))) { @@ -916,17 +916,17 @@ static bool project_bucket_point_occluded(const ProjPaintState *ps, if (orig_face != tri_index) { const MLoopTri *lt = &ps->looptris_eval[tri_index]; const float *vtri_ss[3] = { - ps->screenCoords[ps->loops_eval[lt->tri[0]].v], - ps->screenCoords[ps->loops_eval[lt->tri[1]].v], - ps->screenCoords[ps->loops_eval[lt->tri[2]].v], + ps->screenCoords[ps->corner_verts_eval[lt->tri[0]]], + ps->screenCoords[ps->corner_verts_eval[lt->tri[1]]], + ps->screenCoords[ps->corner_verts_eval[lt->tri[2]]], }; float w[3]; if (do_clip) { const float *vtri_co[3] = { - ps->vert_positions_eval[ps->loops_eval[lt->tri[0]].v], - ps->vert_positions_eval[ps->loops_eval[lt->tri[1]].v], - ps->vert_positions_eval[ps->loops_eval[lt->tri[2]].v], + ps->vert_positions_eval[ps->corner_verts_eval[lt->tri[0]]], + ps->vert_positions_eval[ps->corner_verts_eval[lt->tri[1]]], + ps->vert_positions_eval[ps->corner_verts_eval[lt->tri[2]]], }; isect_ret = project_paint_occlude_ptv_clip( pixelScreenCo, UNPACK3(vtri_ss), UNPACK3(vtri_co), w, ps->is_ortho, ps->rv3d); @@ -1143,8 +1143,8 @@ static bool check_seam(const ProjPaintState *ps, const MLoopTri *orig_lt = &ps->looptris_eval[orig_face]; const float *orig_lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt)}; /* vert indices from face vert order indices */ - const uint i1 = ps->loops_eval[orig_lt->tri[orig_i1_fidx]].v; - const uint i2 = ps->loops_eval[orig_lt->tri[orig_i2_fidx]].v; + const uint i1 = ps->corner_verts_eval[orig_lt->tri[orig_i1_fidx]]; + const uint i2 = ps->corner_verts_eval[orig_lt->tri[orig_i2_fidx]]; LinkNode *node; /* index in face */ int i1_fidx = -1, i2_fidx = -1; @@ -1329,8 +1329,8 @@ static void uv_image_outset(const ProjPaintState *ps, fidx[1] = (fidx[0] == 2) ? 0 : fidx[0] + 1; - vert[0] = ps->loops_eval[loop_index].v; - vert[1] = ps->loops_eval[ltri->tri[fidx[1]]].v; + vert[0] = ps->corner_verts_eval[loop_index]; + vert[1] = ps->corner_verts_eval[ltri->tri[fidx[1]]]; for (uint i = 0; i < 2; i++) { VertSeam *seam; @@ -1415,7 +1415,7 @@ static void insert_seam_vert_array(const ProjPaintState *ps, copy_v2_v2(vseam[1].uv, lt_tri_uv[fidx[1]]); for (uint i = 0; i < 2; i++) { - uint vert = ps->loops_eval[lt->tri[fidx[i]]].v; + const int vert = ps->corner_verts_eval[lt->tri[fidx[i]]]; ListBase *list = &ps->vertSeams[vert]; VertSeam *item = static_cast(list->first); @@ -1454,8 +1454,8 @@ static void project_face_seams_init(const ProjPaintState *ps, } do { - if (init_all || (ps->loops_eval[lt->tri[fidx[0]]].v == vert_index) || - (ps->loops_eval[lt->tri[fidx[1]]].v == vert_index)) { + if (init_all || (ps->corner_verts_eval[lt->tri[fidx[0]]] == vert_index) || + (ps->corner_verts_eval[lt->tri[fidx[1]]] == vert_index)) { if ((ps->faceSeamFlags[tri_index] & (PROJ_FACE_SEAM0 << fidx[0] | PROJ_FACE_NOSEAM0 << fidx[0])) == 0) { if (check_seam(ps, tri_index, fidx[0], fidx[1], &other_face, &other_fidx)) { @@ -1502,7 +1502,7 @@ static void project_face_seams_init(const ProjPaintState *ps, continue; } - vert = ps->loops_eval[lt->tri[fidx[i]]].v; + vert = ps->corner_verts_eval[lt->tri[fidx[i]]]; for (node = ps->vertFaces[vert]; node; node = node->next) { const int tri = POINTER_AS_INT(node->link); @@ -4072,7 +4072,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p ps->vert_normals = ps->me_eval->vert_normals(); ps->edges_eval = ps->me_eval->edges(); ps->polys_eval = ps->me_eval->polys(); - ps->loops_eval = ps->me_eval->loops(); + ps->corner_verts_eval = ps->me_eval->corner_verts(); ps->select_poly_eval = (const bool *)CustomData_get_layer_named( &ps->me_eval->pdata, CD_PROP_BOOL, ".select_poly"); ps->material_indices = (const int *)CustomData_get_layer_named( @@ -4391,7 +4391,8 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, int poly_loops = poly.totloop; prev_poly = looptris[tri_index].poly; for (iloop = 0; iloop < poly_loops; iloop++) { - if (!(ps->vertFlags[ps->loops_eval[poly.loopstart + iloop].v] & PROJ_VERT_CULL)) { + if (!(ps->vertFlags[ps->corner_verts_eval[poly.loopstart + iloop]] & + PROJ_VERT_CULL)) { culled = false; break; } diff --git a/source/blender/editors/sculpt_paint/paint_mask.cc b/source/blender/editors/sculpt_paint/paint_mask.cc index a81838af5a4..64aa82cb20a 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_mask.cc @@ -1243,15 +1243,15 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex /* Write the front face triangle indices. */ blender::MutableSpan polys = trim_operation->mesh->polys_for_write(); - blender::MutableSpan loops = trim_operation->mesh->loops_for_write(); + blender::MutableSpan corner_verts = trim_operation->mesh->corner_verts_for_write(); int poly_index = 0; int loop_index = 0; for (int i = 0; i < tot_tris_face; i++) { polys[poly_index].loopstart = loop_index; polys[poly_index].totloop = 3; - loops[loop_index + 0].v = r_tris[i][0]; - loops[loop_index + 1].v = r_tris[i][1]; - loops[loop_index + 2].v = r_tris[i][2]; + corner_verts[loop_index + 0] = r_tris[i][0]; + corner_verts[loop_index + 1] = r_tris[i][1]; + corner_verts[loop_index + 2] = r_tris[i][2]; poly_index++; loop_index += 3; } @@ -1260,9 +1260,9 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex for (int i = 0; i < tot_tris_face; i++) { polys[poly_index].loopstart = loop_index; polys[poly_index].totloop = 3; - loops[loop_index + 0].v = r_tris[i][0] + tot_screen_points; - loops[loop_index + 1].v = r_tris[i][1] + tot_screen_points; - loops[loop_index + 2].v = r_tris[i][2] + tot_screen_points; + corner_verts[loop_index + 0] = r_tris[i][0] + tot_screen_points; + corner_verts[loop_index + 1] = r_tris[i][1] + tot_screen_points; + corner_verts[loop_index + 2] = r_tris[i][2] + tot_screen_points; poly_index++; loop_index += 3; } @@ -1278,9 +1278,9 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex if (next_index >= tot_screen_points) { next_index = 0; } - loops[loop_index + 0].v = next_index + tot_screen_points; - loops[loop_index + 1].v = next_index; - loops[loop_index + 2].v = current_index; + corner_verts[loop_index + 0] = next_index + tot_screen_points; + corner_verts[loop_index + 1] = next_index; + corner_verts[loop_index + 2] = current_index; poly_index++; loop_index += 3; } @@ -1293,9 +1293,9 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex if (next_index >= tot_screen_points) { next_index = 0; } - loops[loop_index + 0].v = current_index; - loops[loop_index + 1].v = current_index + tot_screen_points; - loops[loop_index + 2].v = next_index + tot_screen_points; + corner_verts[loop_index + 0] = current_index; + corner_verts[loop_index + 1] = current_index + tot_screen_points; + corner_verts[loop_index + 2] = next_index + tot_screen_points; poly_index++; loop_index += 3; } diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 4953ab84687..ba9a1c75446 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -274,7 +274,7 @@ static void imapaint_pick_uv( const int tottri = BKE_mesh_runtime_looptri_len(me_eval); const float(*positions)[3] = BKE_mesh_vert_positions(me_eval); - const MLoop *mloop = BKE_mesh_loops(me_eval); + const int *corner_verts = BKE_mesh_corner_verts(me_eval); const int *index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); /* get the needed opengl matrices */ @@ -302,7 +302,7 @@ static void imapaint_pick_uv( float tri_co[3][3]; for (int j = 3; j--;) { - copy_v3_v3(tri_co[j], positions[mloop[lt->tri[j]].v]); + copy_v3_v3(tri_co[j], positions[corner_verts[lt->tri[j]]]); } if (mode == PAINT_CANVAS_SOURCE_MATERIAL) { diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index 70ebd7fc077..36074b9c0e5 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -1241,7 +1241,7 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) Mesh *me = (Mesh *)ob->data; const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); if (gmap->vert_to_loop == nullptr) { gmap->vert_map_mem = nullptr; @@ -1251,14 +1251,14 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) BKE_mesh_vert_loop_map_create(&gmap->vert_to_loop, &gmap->vert_map_mem, polys.data(), - loops.data(), + corner_verts.data(), me->totvert, me->totpoly, me->totloop); BKE_mesh_vert_poly_map_create(&gmap->vert_to_poly, &gmap->poly_map_mem, polys.data(), - loops.data(), + corner_verts.data(), me->totvert, me->totpoly, me->totloop); @@ -1972,7 +1972,8 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->corner_verts[vd.grid_indices[vd.g]] : + vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; /* If the vertex is selected */ if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { @@ -1986,8 +1987,8 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, total_hit_loops += poly.totloop; for (int k = 0; k < poly.totloop; k++) { const int l_index = poly.loopstart + k; - const MLoop *ml = &ss->mloop[l_index]; - weight_final += data->wpd->precomputed_weight[ml->v]; + const int vert_i = ss->corner_verts[l_index]; + weight_final += data->wpd->precomputed_weight[vert_i]; } } @@ -2070,7 +2071,8 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->corner_verts[vd.grid_indices[vd.g]] : + vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; const float3 &mv_curr = ss->vert_positions[v_index]; @@ -2095,9 +2097,9 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const MPoly &poly = ss->polys[p_index]; - const MLoop *ml_other = &ss->mloop[poly.loopstart]; - for (int k = 0; k < poly.totloop; k++, ml_other++) { - const uint v_other_index = ml_other->v; + for (int k = 0; k < poly.totloop; k++) { + const int other_corner_i = poly.loopstart + k; + const int v_other_index = ss->corner_verts[other_corner_i]; if (v_other_index != v_index) { const float3 &mv_other = ss->vert_positions[v_other_index]; @@ -2180,7 +2182,8 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, /* NOTE: grids are 1:1 with corners (aka loops). * For multires, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->corner_verts[vd.grid_indices[vd.g]] : + vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; /* If the vertex is selected */ @@ -2251,7 +2254,8 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(void *__restrict userdata, 1.0f; if (angle_cos > 0.0 && BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) { - const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->corner_verts[vd.grid_indices[vd.g]] : + vd.vert_indices[vd.i]; /* If the vertex is selected. */ if (!(use_face_sel || use_vert_sel) || select_vert[v_index]) { @@ -3005,7 +3009,7 @@ static void do_vpaint_brush_blur_loops(bContext *C, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->corner_verts[vd.grid_indices[vd.g]] : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; @@ -3064,7 +3068,7 @@ static void do_vpaint_brush_blur_loops(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; - BLI_assert(ss->mloop[l_index].v == v_index); + BLI_assert(ss->corner_verts[l_index] == v_index); if (!use_face_sel || select_poly[p_index]) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3150,7 +3154,7 @@ static void do_vpaint_brush_blur_verts(bContext *C, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->corner_verts[vd.grid_indices[vd.g]] : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; @@ -3180,7 +3184,7 @@ static void do_vpaint_brush_blur_verts(bContext *C, total_hit_loops += poly.totloop; for (int k = 0; k < poly.totloop; k++) { const uint l_index = poly.loopstart + k; - const uint v_index = ss->mloop[l_index].v; + const uint v_index = ss->corner_verts[l_index]; Color *col = lcol + v_index; @@ -3211,7 +3215,7 @@ static void do_vpaint_brush_blur_verts(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; - BLI_assert(ss->mloop[gmap->vert_to_loop[v_index].indices[j]].v == v_index); + BLI_assert(ss->corner_verts[gmap->vert_to_loop[v_index].indices[j]] == v_index); if (!use_face_sel || select_poly[p_index]) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3304,7 +3308,7 @@ static void do_vpaint_brush_smear(bContext *C, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->corner_verts[vd.grid_indices[vd.g]] : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; const float3 &mv_curr = &ss->vert_positions[v_index]; @@ -3336,13 +3340,13 @@ static void do_vpaint_brush_smear(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; - BLI_assert(ss->mloop[l_index].v == v_index); + BLI_assert(ss->corner_verts[l_index] == v_index); UNUSED_VARS_NDEBUG(l_index); const MPoly &poly = ss->polys[p_index]; if (!use_face_sel || select_poly[p_index]) { - const MLoop *ml_other = &ss->mloop[poly.loopstart]; - for (int k = 0; k < poly.totloop; k++, ml_other++) { - const uint v_other_index = ml_other->v; + for (int k = 0; k < poly.totloop; k++) { + const int other_corner_i = poly.loopstart + k; + const int v_other_index = ss->corner_verts[other_corner_i]; if (v_other_index != v_index) { const float3 &mv_other = &ss->vert_positions[v_other_index]; @@ -3358,7 +3362,7 @@ static void do_vpaint_brush_smear(bContext *C, int elem_index; if constexpr (domain == ATTR_DOMAIN_POINT) { - elem_index = ml_other->v; + elem_index = v_other_index; } else { elem_index = poly.loopstart + k; @@ -3390,7 +3394,7 @@ static void do_vpaint_brush_smear(bContext *C, else { const int l_index = gmap->vert_to_loop[v_index].indices[j]; elem_index = l_index; - BLI_assert(ss->mloop[l_index].v == v_index); + BLI_assert(ss->corner_verts[l_index] == v_index); } if (!use_face_sel || select_poly[p_index]) { @@ -3468,7 +3472,7 @@ static void calculate_average_color(VPaintData *vpd, BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->corner_verts[vd.grid_indices[vd.g]] : vd.vert_indices[vd.i]; if (BKE_brush_curve_strength(brush, 0.0, cache->radius) > 0.0) { /* If the vertex is selected for painting. */ @@ -3592,7 +3596,7 @@ static void vpaint_do_draw(bContext *C, /* NOTE: Grids are 1:1 with corners (aka loops). * For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->corner_verts[vd.grid_indices[vd.g]] : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; @@ -3648,7 +3652,7 @@ static void vpaint_do_draw(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; - BLI_assert(ss->mloop[l_index].v == v_index); + BLI_assert(ss->corner_verts[l_index] == v_index); if (!use_face_sel || select_poly[p_index]) { Color color_orig = Color(0, 0, 0, 0); /* unused when array is nullptr */ @@ -4120,7 +4124,7 @@ static void fill_mesh_face_or_corner_attribute(Mesh &mesh, ".select_poly", ATTR_DOMAIN_FACE, false); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); for (const int i : polys.index_range()) { if (use_face_sel && !select_poly[i]) { @@ -4130,7 +4134,7 @@ static void fill_mesh_face_or_corner_attribute(Mesh &mesh, int j = 0; do { - uint vidx = loops[poly.loopstart + j].v; + const int vidx = corner_verts[poly.loopstart + j]; if (!(use_vert_sel && !(select_vert[vidx]))) { if (domain == ATTR_DOMAIN_CORNER) { diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.cc index e0a0b8a5be8..46540486600 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.cc @@ -318,7 +318,7 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, ED_view3d_viewcontext_init(C, &vc, depsgraph); me = BKE_mesh_from_object(vc.obact); const blender::Span polys = me->polys(); - const blender::Span loops = me->loops(); + const blender::Span corner_verts = me->corner_verts(); const MDeformVert *dverts = BKE_mesh_deform_verts(me); if (me && dverts && vc.v3d && vc.rv3d && me->vertex_group_names.first) { @@ -348,7 +348,7 @@ static const EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, uint fidx = poly.totloop - 1; do { - const MDeformVert *dvert = &dverts[loops[poly.loopstart + fidx].v]; + const MDeformVert *dvert = &dverts[corner_verts[poly.loopstart + fidx]]; found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups); } while (fidx--); } @@ -446,7 +446,7 @@ static bool weight_paint_set(Object *ob, float paintweight) const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me); const blender::Span polys = me->polys(); - const blender::Span loops = me->loops(); + const blender::Span corner_verts = me->corner_verts(); MDeformVert *dvert = BKE_mesh_deform_verts_for_write(me); if (me->totpoly == 0 || dvert == nullptr) { @@ -477,7 +477,7 @@ static bool weight_paint_set(Object *ob, float paintweight) } do { - uint vidx = loops[poly.loopstart + fidx].v; + const int vidx = corner_verts[poly.loopstart + fidx]; if (!dvert[vidx].flag) { if ((paint_selmode == SCE_SELECT_VERTEX) && !(select_vert && select_vert[vidx])) { diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 668fc4312ff..65dc800e1f6 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -727,8 +727,7 @@ static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(SculptSession *ss for (int i = 0; i < vert_map->count; i++) { const MPoly &poly = ss->polys[vert_map->indices[i]]; for (int l = 0; l < poly.totloop; l++) { - const MLoop *loop = &ss->mloop[poly.loopstart + l]; - if (loop->v == v2) { + if (ss->corner_verts[poly.loopstart + l] == v2) { if (p1 == -1) { p1 = vert_map->indices[i]; break; @@ -769,7 +768,7 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex) coord.y = vertex_index / key->grid_size; int v1, v2; const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get( - ss->subdiv_ccg, &coord, ss->mloop, ss->polys, &v1, &v2); + ss->subdiv_ccg, &coord, ss->corner_verts, ss->polys, &v1, &v2); switch (adjacency) { case SUBDIV_CCG_ADJACENT_VERTEX: return sculpt_check_unique_face_set_in_base_mesh(ss, v1); @@ -890,7 +889,7 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, } const MPoly &poly = ss->polys[vert_map->indices[i]]; int f_adj_v[2]; - if (poly_get_adj_loops_from_vert(&poly, ss->mloop, vertex.i, f_adj_v) != -1) { + if (poly_get_adj_loops_from_vert(&poly, ss->corner_verts, vertex.i, f_adj_v) != -1) { for (int j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) { if (f_adj_v[j] != vertex.i) { sculpt_vertex_neighbor_add(iter, BKE_pbvh_make_vref(f_adj_v[j]), f_adj_v[j]); @@ -1004,7 +1003,7 @@ bool SCULPT_vertex_is_boundary(const SculptSession *ss, const PBVHVertRef vertex coord.y = vertex_index / key->grid_size; int v1, v2; const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get( - ss->subdiv_ccg, &coord, ss->mloop, ss->polys, &v1, &v2); + ss->subdiv_ccg, &coord, ss->corner_verts, ss->polys, &v1, &v2); switch (adjacency) { case SUBDIV_CCG_ADJACENT_VERTEX: return sculpt_check_boundary_vertex_in_base_mesh(ss, v1); @@ -6196,6 +6195,7 @@ struct SculptTopologyIDFloodFillData { void SCULPT_boundary_info_ensure(Object *object) { + using namespace blender; SculptSession *ss = object->sculpt; if (ss->vertex_info.boundary) { return; @@ -6204,7 +6204,7 @@ void SCULPT_boundary_info_ensure(Object *object) Mesh *base_mesh = BKE_mesh_from_object(object); const blender::Span edges = base_mesh->edges(); const blender::Span polys = base_mesh->polys(); - const blender::Span loops = base_mesh->loops(); + const Span corner_edges = base_mesh->corner_edges(); ss->vertex_info.boundary = BLI_BITMAP_NEW(base_mesh->totvert, "Boundary info"); int *adjacent_faces_edge_count = static_cast( @@ -6213,8 +6213,8 @@ void SCULPT_boundary_info_ensure(Object *object) for (const int p : polys.index_range()) { const MPoly &poly = polys[p]; for (int l = 0; l < poly.totloop; l++) { - const MLoop *loop = &loops[l + poly.loopstart]; - adjacent_faces_edge_count[loop->e]++; + const int edge_i = corner_edges[poly.loopstart + l]; + adjacent_faces_edge_count[edge_i]++; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.cc b/source/blender/editors/sculpt_paint/sculpt_automasking.cc index c7df5d6d92b..b526460f642 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.cc +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc @@ -179,6 +179,10 @@ static float sculpt_automasking_normal_calc(SculptSession *ss, static bool sculpt_automasking_is_constrained_by_radius(const Brush *br) { + if (br == nullptr) { + return false; + } + /* 2D falloff is not constrained by radius. */ if (br->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { return false; diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.cc b/source/blender/editors/sculpt_paint/sculpt_cloth.cc index 6db4fe5b718..79ba11e6db3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.cc @@ -1508,7 +1508,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent } const float len = event->prev_press_xy[0] - event->xy[0]; - filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC; + filter_strength = filter_strength * -len * 0.001f * UI_SCALE_FAC; SCULPT_vertex_random_access_ensure(ss); diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc index ca7684fce6d..3e914f0fa76 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc @@ -326,7 +326,7 @@ static bool dyntopo_supports_layer(const CustomDataLayer &layer, const int elem_ return BM_attribute_stored_in_bmesh_builtin(layer.name); } /* Some layers just encode #Mesh topology or are handled as special cases for dyntopo. */ - return ELEM(layer.type, CD_MEDGE, CD_MPOLY, CD_MLOOP, CD_PAINT_MASK, CD_ORIGINDEX); + return ELEM(layer.type, CD_MEDGE, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX); } static bool dyntopo_supports_customdata_layers(const blender::Span layers, diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.cc b/source/blender/editors/sculpt_paint/sculpt_expand.cc index a8f2634151f..c575fe71551 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_expand.cc @@ -148,8 +148,8 @@ static bool sculpt_expand_is_face_in_active_component(SculptSession *ss, ExpandCache *expand_cache, const int f) { - const MLoop *loop = &ss->mloop[ss->polys[f].loopstart]; - return sculpt_expand_is_vert_in_active_component(ss, expand_cache, BKE_pbvh_make_vref(loop->v)); + const int vert = ss->corner_verts[ss->polys[f].loopstart]; + return sculpt_expand_is_vert_in_active_component(ss, expand_cache, BKE_pbvh_make_vref(vert)); } /** @@ -714,7 +714,7 @@ static float *sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertR for (int j = 0; j < ss->pmap[v_next_i].count; j++) { const MPoly &poly = ss->polys[ss->pmap[v_next_i].indices[j]]; for (int l = 0; l < poly.totloop; l++) { - const PBVHVertRef neighbor_v = BKE_pbvh_make_vref(ss->mloop[poly.loopstart + l].v); + const PBVHVertRef neighbor_v = BKE_pbvh_make_vref(ss->corner_verts[poly.loopstart + l]); if (BLI_BITMAP_TEST(visited_verts, neighbor_v.i)) { continue; } @@ -810,14 +810,14 @@ static void sculpt_expand_grids_to_faces_falloff(SculptSession *ss, static void sculpt_expand_vertex_to_faces_falloff(Mesh *mesh, ExpandCache *expand_cache) { const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); for (const int p : polys.index_range()) { const MPoly &poly = polys[p]; float accum = 0.0f; for (int l = 0; l < poly.totloop; l++) { - const MLoop *loop = &loops[l + poly.loopstart]; - accum += expand_cache->vert_falloff[loop->v]; + const int vert = corner_verts[poly.loopstart + l]; + accum += expand_cache->vert_falloff[vert]; } expand_cache->face_falloff[p] = accum / poly.totloop; } @@ -1119,8 +1119,8 @@ static void sculpt_expand_snap_initialize_from_enabled(SculptSession *ss, const MPoly &poly = ss->polys[p]; bool any_disabled = false; for (int l = 0; l < poly.totloop; l++) { - const MLoop *loop = &ss->mloop[l + poly.loopstart]; - if (!BLI_BITMAP_TEST(enabled_verts, loop->v)) { + const int vert = ss->corner_verts[l + poly.loopstart]; + if (!BLI_BITMAP_TEST(enabled_verts, vert)) { any_disabled = true; break; } @@ -1988,7 +1988,7 @@ static void sculpt_expand_delete_face_set_id(int *r_face_sets, const int totface = ss->totfaces; MeshElemMap *pmap = ss->pmap; const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); /* Check that all the face sets IDs in the mesh are not equal to `delete_id` * before attempting to delete it. */ @@ -2025,8 +2025,8 @@ static void sculpt_expand_delete_face_set_id(int *r_face_sets, int other_id = delete_id; const MPoly &c_poly = polys[f_index]; for (int l = 0; l < c_poly.totloop; l++) { - const MLoop *c_loop = &loops[c_poly.loopstart + l]; - const MeshElemMap *vert_map = &pmap[c_loop->v]; + const int vert = corner_verts[c_poly.loopstart + l]; + const MeshElemMap *vert_map = &pmap[vert]; for (int i = 0; i < vert_map->count; i++) { const int neighbor_face_index = vert_map->indices[i]; diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index 374d8e6f7d9..f0e51122d63 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -129,7 +129,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, const Span positions( reinterpret_cast(SCULPT_mesh_deformed_positions_get(ss)), SCULPT_vertex_count_get(ss)); - const Span loops(ss->mloop, data->me->totloop); + const Span corner_verts(ss->corner_verts, data->me->totloop); AutomaskingNodeData automask_data; SCULPT_automasking_node_begin( data->ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); @@ -144,7 +144,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, const MPoly &poly = ss->polys[vert_map->indices[j]]; const float3 poly_center = bke::mesh::poly_center_calc( - positions, loops.slice(poly.loopstart, poly.totloop)); + positions, corner_verts.slice(poly.loopstart, poly.totloop)); if (!sculpt_brush_test_sq_fn(&test, poly_center)) { continue; @@ -552,7 +552,7 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFill const Span edges = mesh->edges(); const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_edges = mesh->corner_edges(); if (!ss->epmap) { BKE_mesh_edge_poly_map_create(&ss->epmap, @@ -560,8 +560,8 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFill edges.size(), polys.data(), polys.size(), - loops.data(), - loops.size()); + corner_edges.data(), + corner_edges.size()); } int next_face_set = 1; @@ -581,8 +581,7 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFill const MPoly &poly = polys[poly_i]; queue.pop(); - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - const int edge_i = loop.e; + for (const int edge_i : corner_edges.slice(poly.loopstart, poly.totloop)) { const Span neighbor_polys(ss->epmap[edge_i].indices, ss->epmap[edge_i].count); for (const int neighbor_i : neighbor_polys) { if (neighbor_i == poly_i) { @@ -1110,18 +1109,18 @@ static void sculpt_face_set_grow(Object *ob, const int active_face_set_id, const bool modify_hidden) { + using namespace blender; Mesh *mesh = BKE_mesh_from_object(ob); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); for (const int p : polys.index_range()) { if (!modify_hidden && prev_face_sets[p] <= 0) { continue; } const MPoly &c_poly = polys[p]; - for (int l = 0; l < c_poly.totloop; l++) { - const MLoop *c_loop = &loops[c_poly.loopstart + l]; - const MeshElemMap *vert_map = &ss->pmap[c_loop->v]; + for (const int vert : corner_verts.slice(c_poly.loopstart, c_poly.totloop)) { + const MeshElemMap *vert_map = &ss->pmap[vert]; for (int i = 0; i < vert_map->count; i++) { const int neighbor_face_index = vert_map->indices[i]; if (neighbor_face_index == p) { @@ -1141,18 +1140,18 @@ static void sculpt_face_set_shrink(Object *ob, const int active_face_set_id, const bool modify_hidden) { + using namespace blender; Mesh *mesh = BKE_mesh_from_object(ob); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); for (const int p : polys.index_range()) { if (!modify_hidden && prev_face_sets[p] <= 0) { continue; } if (abs(prev_face_sets[p]) == active_face_set_id) { const MPoly &c_poly = polys[p]; - for (int l = 0; l < c_poly.totloop; l++) { - const MLoop *c_loop = &loops[c_poly.loopstart + l]; - const MeshElemMap *vert_map = &ss->pmap[c_loop->v]; + for (const int vert_i : corner_verts.slice(c_poly.loopstart, c_poly.totloop)) { + const MeshElemMap *vert_map = &ss->pmap[vert_i]; for (int i = 0; i < vert_map->count; i++) { const int neighbor_face_index = vert_map->indices[i]; if (neighbor_face_index == p) { diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc index 27bb4f11569..f9912aa4402 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc @@ -810,7 +810,7 @@ static void sculpt_mesh_update_strength(wmOperator *op, { const float len = prev_press_mouse[0] - mouse[0]; - float filter_strength = ss->filter_cache->start_filter_strength * -len * 0.001f * UI_DPI_FAC; + float filter_strength = ss->filter_cache->start_filter_strength * -len * 0.001f * UI_SCALE_FAC; RNA_float_set(op->ptr, "strength", filter_strength); } static void sculpt_mesh_filter_apply_with_history(bContext *C, wmOperator *op) diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc index 33fc931fca8..7a6f08f5f86 100644 --- a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc +++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc @@ -89,7 +89,8 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, float(*vert_positions)[3] = SCULPT_mesh_deformed_positions_get(ss); const blender::Span edges = mesh->edges(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); + const blender::Span corner_edges = mesh->corner_edges(); float *dists = static_cast(MEM_malloc_arrayN(totvert, sizeof(float), __func__)); BLI_bitmap *edge_tag = BLI_BITMAP_NEW(totedge, "edge tag"); @@ -100,8 +101,8 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, edges.size(), polys.data(), polys.size(), - loops.data(), - loops.size()); + corner_edges.data(), + corner_edges.size()); } if (!ss->vemap) { BKE_mesh_vert_edge_map_create( @@ -183,8 +184,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, } for (int loop_index = 0; loop_index < polys[poly].totloop; loop_index++) { - const MLoop *mloop = &loops[loop_index + polys[poly].loopstart]; - const int v_other = mloop->v; + const int v_other = corner_verts[loop_index + polys[poly].loopstart]; if (ELEM(v_other, v1, v2)) { continue; } diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index bd84ff23bde..2831e5d8454 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -645,7 +645,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene) /* Iterate over pointcaches on the active object, and draw each one's range. */ float y_offset = 0.0f; - const float cache_draw_height = 4.0f * UI_DPI_FAC * U.pixelsize; + const float cache_draw_height = 4.0f * UI_SCALE_FAC * U.pixelsize; LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) { if (timeline_cache_is_hidden_by_setting(saction, pid)) { continue; diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.cc b/source/blender/editors/space_clip/clip_dopesheet_draw.cc index 87dd61ce1e1..e39316e8dc5 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.cc +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.cc @@ -340,7 +340,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *region) /* second pass: text */ y = float(CHANNEL_FIRST); - BLF_size(fontid, 11.0f * U.dpi_fac); + BLF_size(fontid, 11.0f * UI_SCALE_FAC); LISTBASE_FOREACH (MovieTrackingDopesheetChannel *, channel, &dopesheet->channels) { float yminc = float(y - CHANNEL_HEIGHT_HALF); diff --git a/source/blender/editors/space_clip/clip_draw.cc b/source/blender/editors/space_clip/clip_draw.cc index 6f95132d123..c6b730bfaf1 100644 --- a/source/blender/editors/space_clip/clip_draw.cc +++ b/source/blender/editors/space_clip/clip_draw.cc @@ -59,11 +59,11 @@ static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int wid if (width == 1) { immBegin(GPU_PRIM_LINES, 2); immVertex2i(pos, x, 0); - immVertex2i(pos, x, height * UI_DPI_FAC); + immVertex2i(pos, x, height * UI_SCALE_FAC); immEnd(); } else { - immRecti(pos, x, 0, x + width, height * UI_DPI_FAC); + immRecti(pos, x, 0, x + width, height * UI_SCALE_FAC); } } @@ -191,7 +191,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *region, MovieClip *clip (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, - 4 * UI_DPI_FAC); + 4 * UI_SCALE_FAC); } } } @@ -223,7 +223,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *region, MovieClip *clip (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, - 8 * UI_DPI_FAC); + 8 * UI_SCALE_FAC); } } } @@ -234,11 +234,11 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *region, MovieClip *clip x = (sc->user.framenr - sfra) / (efra - sfra + 1) * region->winx; immUniformThemeColor(TH_CFRAME); - immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC); + immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_SCALE_FAC); immUnbindProgram(); - ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC); + ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_SCALE_FAC); pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); @@ -368,7 +368,8 @@ static void draw_stabilization_border( float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f( + "viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* "simple" mode */ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.0f); @@ -743,7 +744,7 @@ static void draw_marker_areas(SpaceClip *sc, float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* "simple" mode */ @@ -954,11 +955,11 @@ static void draw_marker_slide_zones(SpaceClip *sc, dy = 6.0f / height / sc->zoom; side = get_shortest_pattern_side(marker); - patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f) * UI_DPI_FAC; - patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f) * UI_DPI_FAC; + patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f) * UI_SCALE_FAC; + patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f) * UI_SCALE_FAC; - searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f) * UI_DPI_FAC; - searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f) * UI_DPI_FAC; + searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f) * UI_SCALE_FAC; + searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f) * UI_SCALE_FAC; px[0] = 1.0f / sc->zoom / width / sc->scale; px[1] = 1.0f / sc->zoom / height / sc->scale; @@ -1035,7 +1036,7 @@ static void draw_marker_texts(SpaceClip *sc, return; } - BLF_size(fontid, 11.0f * U.dpi_fac); + BLF_size(fontid, 11.0f * UI_SCALE_FAC); fontsize = BLF_height_max(fontid); if (marker->flag & MARKER_DISABLED) { @@ -1288,7 +1289,8 @@ static void draw_plane_marker_ex(SpaceClip *sc, float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f( + "viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* "simple" mode */ diff --git a/source/blender/editors/space_clip/clip_ops.cc b/source/blender/editors/space_clip/clip_ops.cc index 3ace6605487..78466926e05 100644 --- a/source/blender/editors/space_clip/clip_ops.cc +++ b/source/blender/editors/space_clip/clip_ops.cc @@ -1104,7 +1104,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event ARegion *region = CTX_wm_region(C); if (region->regiontype == RGN_TYPE_WINDOW) { - if (event->mval[1] > 16 * UI_DPI_FAC) { + if (event->mval[1] > 16 * UI_SCALE_FAC) { return OPERATOR_PASS_THROUGH; } } diff --git a/source/blender/editors/space_clip/space_clip.cc b/source/blender/editors/space_clip/space_clip.cc index b30a1d6f305..f6680ed8069 100644 --- a/source/blender/editors/space_clip/space_clip.cc +++ b/source/blender/editors/space_clip/space_clip.cc @@ -997,7 +997,7 @@ static void graph_region_draw(const bContext *C, ARegion *region) { rcti rect; BLI_rcti_init( - &rect, 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, region->winy - UI_TIME_SCRUB_MARGIN_Y); + &rect, 0, 15 * UI_SCALE_FAC, 15 * UI_SCALE_FAC, region->winy - UI_TIME_SCRUB_MARGIN_Y); UI_view2d_draw_scale_y__values(region, v2d, &rect, TH_TEXT); } } diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index 6710d4ce0e7..8f037c3bcd8 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -167,7 +167,7 @@ static void console_textview_draw_rect_calc(const ARegion *region, rcti *r_draw_rect, rcti *r_draw_rect_outer) { - const int margin = 4 * UI_DPI_FAC; + const int margin = 4 * UI_SCALE_FAC; r_draw_rect->xmin = margin; r_draw_rect->xmax = region->winx - V2D_SCROLL_WIDTH; r_draw_rect->ymin = margin; @@ -209,7 +209,7 @@ static int console_textview_main__internal(SpaceConsole *sc, /* view */ tvc.sel_start = sc->sel_start; tvc.sel_end = sc->sel_end; - tvc.lheight = sc->lheight * UI_DPI_FAC; + tvc.lheight = sc->lheight * UI_SCALE_FAC; tvc.scroll_ymin = v2d->cur.ymin; tvc.scroll_ymax = v2d->cur.ymax; diff --git a/source/blender/editors/space_file/asset_catalog_tree_view.cc b/source/blender/editors/space_file/asset_catalog_tree_view.cc index 8b7b19387c2..535121ab252 100644 --- a/source/blender/editors/space_file/asset_catalog_tree_view.cc +++ b/source/blender/editors/space_file/asset_catalog_tree_view.cc @@ -782,6 +782,5 @@ void file_create_asset_catalog_tree_view_in_layout(::AssetLibrary *asset_library std::make_unique( asset_library, params, *space_file)); - ui::TreeViewBuilder builder(*block); - builder.build_tree_view(*tree_view); + ui::TreeViewBuilder::build_tree_view(*tree_view, *layout); } diff --git a/source/blender/editors/space_file/file_draw.cc b/source/blender/editors/space_file/file_draw.cc index 6e54e7ac3e2..4ecb9a52c6a 100644 --- a/source/blender/editors/space_file/file_draw.cc +++ b/source/blender/editors/space_file/file_draw.cc @@ -21,10 +21,9 @@ #include "BIF_glutil.h" +#include "BKE_blendfile.h" #include "BKE_context.h" -#include "BLO_readfile.h" - #include "BLT_translation.h" #include "BLF_api.h" @@ -142,7 +141,7 @@ static void file_but_enable_drag(uiBut *but, else if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS && (file->typeflag & FILE_TYPE_ASSET) != 0) { char blend_path[FILE_MAX_LIBEXTRA]; - if (BLO_library_path_explode(path, blend_path, nullptr, nullptr)) { + if (BKE_blendfile_library_path_explode(path, blend_path, nullptr, nullptr)) { const int import_method = ED_fileselect_asset_import_method_get(sfile, file); BLI_assert(import_method > -1); @@ -206,7 +205,7 @@ static void file_draw_string(int sx, fs = style->widget; BLI_strncpy(fname, string, FILE_MAXFILE); - UI_text_clip_middle_ex(&fs, fname, width, UI_DPI_ICON_SIZE, sizeof(fname), '\0'); + UI_text_clip_middle_ex(&fs, fname, width, UI_ICON_SIZE, sizeof(fname), '\0'); /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict * (for buttons it works) */ @@ -341,8 +340,8 @@ static void file_draw_preview(const FileDirEntry *file, BLI_assert(imb != nullptr); - ui_imbx = imb->x * UI_DPI_FAC; - ui_imby = imb->y * UI_DPI_FAC; + ui_imbx = imb->x * UI_SCALE_FAC; + ui_imby = imb->y * UI_SCALE_FAC; /* Unlike thumbnails, icons are not scaled up. */ if (((ui_imbx > layout->prv_w) || (ui_imby > layout->prv_h)) || (!is_icon && ((ui_imbx < layout->prv_w) || (ui_imby < layout->prv_h)))) { @@ -360,7 +359,7 @@ static void file_draw_preview(const FileDirEntry *file, else { scaledx = ui_imbx; scaledy = ui_imby; - scale = UI_DPI_FAC; + scale = UI_SCALE_FAC; } ex = int(scaledx); @@ -418,7 +417,7 @@ static void file_draw_preview(const FileDirEntry *file, if (icon && is_icon) { /* Small icon in the middle of large image, scaled to fit container and UI scale */ float icon_x, icon_y; - const float icon_size = 16.0f / icon_aspect * U.dpi_fac; + const float icon_size = 16.0f / icon_aspect * UI_SCALE_FAC; float icon_opacity = 0.3f; uchar icon_color[4] = {0, 0, 0, 255}; float bgcolor[4]; @@ -433,7 +432,7 @@ static void file_draw_preview(const FileDirEntry *file, UI_icon_draw_ex(icon_x, icon_y, icon, - icon_aspect / U.dpi_fac, + icon_aspect / UI_SCALE_FAC, icon_opacity, 0.0f, icon_color, @@ -444,8 +443,8 @@ static void file_draw_preview(const FileDirEntry *file, if (is_link || is_offline) { /* Icon at bottom to indicate it is a shortcut, link, alias, or offline. */ float icon_x, icon_y; - icon_x = xco + (2.0f * UI_DPI_FAC); - icon_y = yco + (2.0f * UI_DPI_FAC); + icon_x = xco + (2.0f * UI_SCALE_FAC); + icon_y = yco + (2.0f * UI_SCALE_FAC); const int arrow = is_link ? ICON_LOOP_FORWARDS : ICON_URL; if (!is_icon) { /* At very bottom-left if preview style. */ @@ -454,7 +453,7 @@ static void file_draw_preview(const FileDirEntry *file, UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, - 1.0f / U.dpi_fac, + 1.0f / UI_SCALE_FAC, 0.2f, 0.0f, dark, @@ -463,7 +462,7 @@ static void file_draw_preview(const FileDirEntry *file, UI_icon_draw_ex(icon_x, icon_y, arrow, - 1.0f / U.dpi_fac, + 1.0f / UI_SCALE_FAC, 0.6f, 0.0f, light, @@ -479,7 +478,7 @@ static void file_draw_preview(const FileDirEntry *file, UI_icon_draw_ex(icon_x, icon_y, arrow, - icon_aspect / U.dpi_fac * 1.8, + icon_aspect / UI_SCALE_FAC * 1.8f, 0.3f, 0.0f, icon_color, @@ -492,19 +491,26 @@ static void file_draw_preview(const FileDirEntry *file, float icon_x, icon_y; const uchar dark[4] = {0, 0, 0, 255}; const uchar light[4] = {255, 255, 255, 255}; - icon_x = xco + (2.0f * UI_DPI_FAC); - icon_y = yco + (2.0f * UI_DPI_FAC); + icon_x = xco + (2.0f * UI_SCALE_FAC); + icon_y = yco + (2.0f * UI_SCALE_FAC); UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, - 1.0f / U.dpi_fac, + 1.0f / UI_SCALE_FAC, 0.2f, 0.0f, dark, false, UI_NO_ICON_OVERLAY_TEXT); - UI_icon_draw_ex( - icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false, UI_NO_ICON_OVERLAY_TEXT); + UI_icon_draw_ex(icon_x, + icon_y, + icon, + 1.0f / UI_SCALE_FAC, + 0.6f, + 0.0f, + light, + false, + UI_NO_ICON_OVERLAY_TEXT); } const bool is_current_main_data = filelist_file_get_id(file) != nullptr; @@ -518,7 +524,7 @@ static void file_draw_preview(const FileDirEntry *file, UI_icon_draw_ex(icon_x, icon_y, ICON_CURRENT_FILE, - 1.0f / U.dpi_fac, + 1.0f / UI_SCALE_FAC, 0.6f, 0.0f, light, @@ -980,7 +986,7 @@ void file_draw_list(const bContext *C, ARegion *region) rcti tile_bg_rect = tile_draw_rect; /* One pixel downwards, places it more in the center. */ - BLI_rcti_translate(&tile_bg_rect, 0, -1); + BLI_rcti_translate(&tile_bg_rect, 0, -U.pixelsize); draw_tile_background(&tile_bg_rect, colorid, shade); } } @@ -1042,7 +1048,7 @@ void file_draw_list(const bContext *C, ARegion *region) 0, 0); UI_but_dragflag_enable(drag_but, UI_BUT_DRAG_FULL_BUT); - file_but_enable_drag(drag_but, sfile, file, path, nullptr, icon, UI_DPI_FAC); + file_but_enable_drag(drag_but, sfile, file, path, nullptr, icon, UI_SCALE_FAC); } /* Add this after the fake draggable button, so the icon button tooltip is displayed. */ @@ -1057,7 +1063,7 @@ void file_draw_list(const bContext *C, ARegion *region) if (do_drag) { /* For some reason the dragging is unreliable for the icon button if we don't explicitly * enable dragging, even though the dummy drag button above covers the same area. */ - file_but_enable_drag(icon_but, sfile, file, path, nullptr, icon, UI_DPI_FAC); + file_but_enable_drag(icon_but, sfile, file, path, nullptr, icon, UI_SCALE_FAC); } } diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 8616707e42e..c3fef65c5ff 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -11,9 +11,8 @@ #include "BLI_linklist.h" #include "BLI_math.h" -#include "BLO_readfile.h" - #include "BKE_appdir.h" +#include "BKE_blendfile.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" @@ -2539,7 +2538,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN BLI_split_dirfile( path, params->dir, params->file, sizeof(params->dir), sizeof(params->file)); } - else if (BLO_library_path_explode(params->dir, tdir, &group, &name)) { + else if (BKE_blendfile_library_path_explode(params->dir, tdir, &group, &name)) { if (group) { BLI_path_append(tdir, sizeof(tdir), group); } @@ -2578,7 +2577,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN char tdir[FILE_MAX_LIBEXTRA]; /* If we are 'inside' a blend library, we cannot do anything... */ - if (lastdir && BLO_library_path_explode(lastdir, tdir, NULL, NULL)) { + if (lastdir && BKE_blendfile_library_path_explode(lastdir, tdir, NULL, NULL)) { BLI_strncpy(params->dir, lastdir, sizeof(params->dir)); } else { diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c index 455cbf0da2f..97c228a7795 100644 --- a/source/blender/editors/space_file/file_utils.c +++ b/source/blender/editors/space_file/file_utils.c @@ -9,8 +9,8 @@ #include "BLI_rect.h" #include "BLI_string.h" +#include "BKE_blendfile.h" #include "BKE_context.h" -#include "BLO_readfile.h" #include "ED_fileselect.h" #include "ED_screen.h" @@ -37,5 +37,5 @@ void file_path_to_ui_path(const char *path, char *r_path, int max_size) char tmp_path[PATH_MAX]; BLI_strncpy(tmp_path, path, sizeof(tmp_path)); BLI_path_slash_rstrip(tmp_path); - BLI_strncpy(r_path, BLO_has_bfile_extension(tmp_path) ? tmp_path : path, max_size); + BLI_strncpy(r_path, BKE_blendfile_extension_check(tmp_path) ? tmp_path : path, max_size); } diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index b20e07f94af..f27238f4fe3 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -48,6 +48,7 @@ #endif #include "BKE_asset.h" +#include "BKE_blendfile.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_icons.h" @@ -56,7 +57,6 @@ #include "BKE_main.h" #include "BKE_main_idmap.h" #include "BKE_preferences.h" -#include "BLO_readfile.h" #include "DNA_asset_types.h" #include "DNA_space_types.h" @@ -1353,7 +1353,7 @@ static bool filelist_checkdir_lib(FileList * /*filelist*/, char *r_dir, const bo char *name; const bool is_valid = (BLI_is_dir(r_dir) || - (BLO_library_path_explode(r_dir, tdir, nullptr, &name) && + (BKE_blendfile_library_path_explode(r_dir, tdir, nullptr, &name) && BLI_is_file(tdir) && !name)); if (do_change && !is_valid) { @@ -1950,7 +1950,7 @@ static const char *fileentry_uiname(const char *root, FileListInternEntry *entry char *group; BLI_path_join(abspath, sizeof(abspath), root, relpath); - BLO_library_path_explode(abspath, buff, &group, &name); + BKE_blendfile_library_path_explode(abspath, buff, &group, &name); if (!name) { name = group; } @@ -2623,7 +2623,7 @@ int ED_path_extension_type(const char *path) /* ATTENTION: Never return OR'ed bit-flags here, always return a single enum value! Some code * using this may do `ELEM()`-like checks. */ - if (BLO_has_bfile_extension(path)) { + if (BKE_blendfile_extension_check(path)) { return FILE_TYPE_BLENDER; } if (file_is_blend_backup(path)) { @@ -2885,7 +2885,7 @@ bool filelist_islibrary(FileList *filelist, char *dir, char **r_group) if (filelist->asset_library) { return true; } - return BLO_library_path_explode(filelist->filelist.root, dir, r_group, nullptr); + return BKE_blendfile_library_path_explode(filelist->filelist.root, dir, r_group, nullptr); } static int groupname_to_code(const char *group) @@ -3041,7 +3041,7 @@ static int filelist_readjob_list_dir(FileListReadJob *job_params, } if (!(entry->typeflag & FILE_TYPE_DIR)) { - if (do_lib && BLO_has_bfile_extension(target)) { + if (do_lib && BKE_blendfile_extension_check(target)) { /* If we are considering .blend files as libraries, promote them to directory status. */ entry->typeflag = FILE_TYPE_BLENDER; /* prevent current file being used as acceptable dir */ @@ -3234,7 +3234,7 @@ static std::optional filelist_readjob_list_lib(FileListReadJob *job_params, * will do a dir listing only when this function does not return any entries. */ /* TODO(jbakker): We should consider introducing its own function to detect if it is a lib and * call it directly from `filelist_readjob_do` to increase readability. */ - const bool is_lib = BLO_library_path_explode(root, dir, &group, nullptr); + const bool is_lib = BKE_blendfile_library_path_explode(root, dir, &group, nullptr); if (!is_lib) { return std::nullopt; } diff --git a/source/blender/editors/space_file/filesel.cc b/source/blender/editors/space_file/filesel.cc index 45bbb25a4de..bc9fd0140cf 100644 --- a/source/blender/editors/space_file/filesel.cc +++ b/source/blender/editors/space_file/filesel.cc @@ -630,8 +630,8 @@ void ED_fileselect_window_params_get(const wmWindow *win, int win_size[2], bool /* Get DPI/pixel-size independent size to be stored in preferences. */ WM_window_set_dpi(win); /* Ensure the DPI is taken from the right window. */ - win_size[0] = WM_window_pixels_x(win) / UI_DPI_FAC; - win_size[1] = WM_window_pixels_y(win) / UI_DPI_FAC; + win_size[0] = WM_window_pixels_x(win) / UI_SCALE_FAC; + win_size[1] = WM_window_pixels_y(win) / UI_SCALE_FAC; *is_maximized = WM_window_is_maximized(win); } @@ -967,7 +967,7 @@ float file_font_pointsize(void) #else const uiStyle *style = UI_style_get(); UI_fontstyle_set(&style->widget); - return style->widget.points * UI_DPI_FAC; + return style->widget.points * UI_SCALE_FAC; #endif } diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index ff4cc11885c..4ce7d4286df 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -84,7 +84,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* Simple dashes. */ immUniformColor3f(0.0f, 0.0f, 0.0f); @@ -235,7 +235,7 @@ static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, u { immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); - immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.dpi_fac); + immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * UI_SCALE_FAC); draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos); draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos); @@ -332,8 +332,8 @@ static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handl immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); /* set handle size */ - immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.dpi_fac); - immUniform1f("outlineWidth", 1.5f * U.dpi_fac); + immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * UI_SCALE_FAC); + immUniform1f("outlineWidth", 1.5f * UI_SCALE_FAC); draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos); draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos); @@ -1043,7 +1043,8 @@ static void draw_fcurve(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, bAn if (BKE_fcurve_is_protected(fcu)) { /* Protected curves (non editable) are drawn with dotted lines. */ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f( + "viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* Simple dashes. */ immUniform1f("dash_width", 4.0f); immUniform1f("udash_factor", 0.5f); @@ -1192,7 +1193,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* Simple dashes. */ @@ -1312,7 +1313,7 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* Simple dashes. */ immUniform1f("dash_width", 20.0f); diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 53d75665bbd..812143d3a40 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -314,7 +314,7 @@ static void graph_main_region_draw_overlay(const bContext *C, ARegion *region) { rcti rect; BLI_rcti_init( - &rect, 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, region->winy - UI_TIME_SCRUB_MARGIN_Y); + &rect, 0, 15 * UI_SCALE_FAC, 15 * UI_SCALE_FAC, region->winy - UI_TIME_SCRUB_MARGIN_Y); UI_view2d_draw_scale_y__values(region, v2d, &rect, TH_SCROLL_TEXT); } } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index d323a7162d7..786fcd4075a 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -789,7 +789,7 @@ void uiTemplateImage(uiLayout *layout, else if (ima->type == IMA_TYPE_R_RESULT) { /* browse layer/passes */ RenderResult *rr; - const float dpi_fac = UI_DPI_FAC; + const float dpi_fac = UI_SCALE_FAC; const int menus_width = 230 * dpi_fac; /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ @@ -880,7 +880,7 @@ void uiTemplateImage(uiLayout *layout, if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) { uiItemS(layout); - const float dpi_fac = UI_DPI_FAC; + const float dpi_fac = UI_SCALE_FAC; uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL); } @@ -1162,7 +1162,7 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser /* render layers and passes */ if (ima && iuser) { RenderResult *rr; - const float dpi_fac = UI_DPI_FAC; + const float dpi_fac = UI_SCALE_FAC; const int menus_width = 160 * dpi_fac; const bool is_render_result = (ima->type == IMA_TYPE_R_RESULT); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 9bf23ff4538..6460e6ebd7b 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -168,7 +168,7 @@ void ED_image_draw_info(Scene *scene, GPU_blend(GPU_BLEND_NONE); - BLF_size(blf_mono_font, 11.0f * U.dpi_fac); + BLF_size(blf_mono_font, 11.0f * UI_SCALE_FAC); BLF_color3ub(blf_mono_font, 255, 255, 255); SNPRINTF(str, "X:%-4d Y:%-4d |", x, y); @@ -452,7 +452,8 @@ void draw_image_sample_line(SpaceImage *sima) float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f( + "viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 2); /* Advanced dashes. */ immUniform4f("color", 1.0f, 1.0f, 1.0f, 1.0f); @@ -504,7 +505,7 @@ bool ED_space_image_show_cache_and_mval_over(const SpaceImage *sima, const int mval[2]) { const rcti *rect_visible = ED_region_visible_rect(region); - if (mval[1] > rect_visible->ymin + (16 * UI_DPI_FAC)) { + if (mval[1] > rect_visible->ymin + (16 * UI_SCALE_FAC)) { return false; } return ED_space_image_show_cache(sima); @@ -559,10 +560,10 @@ void draw_image_cache(const bContext *C, ARegion *region) immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColor(TH_CFRAME); - immRecti(pos, x, region_bottom, x + ceilf(framelen), region_bottom + 8 * UI_DPI_FAC); + immRecti(pos, x, region_bottom, x + ceilf(framelen), region_bottom + 8 * UI_SCALE_FAC); immUnbindProgram(); - ED_region_cache_draw_curfra_label(cfra, x, region_bottom + 8.0f * UI_DPI_FAC); + ED_region_cache_draw_curfra_label(cfra, x, region_bottom + 8.0f * UI_SCALE_FAC); if (mask != NULL) { ED_mask_draw_frames(mask, region, cfra, sfra, efra); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 13d3681b10e..31eea8c7558 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -3008,6 +3008,7 @@ static int image_scale_exec(bContext *C, wmOperator *op) ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; IMB_scaleImBuf(ibuf, size[0], size[1]); + BKE_image_mark_dirty(ima, ibuf); BKE_image_release_ibuf(ima, ibuf, NULL); ED_image_undo_push_end(); diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c index 812df2fc6cc..695d13f9425 100644 --- a/source/blender/editors/space_info/info_draw.c +++ b/source/blender/editors/space_info/info_draw.c @@ -190,7 +190,7 @@ static int info_textview_main__internal(const SpaceInfo *sinfo, /* view */ tvc.sel_start = 0; tvc.sel_end = 0; - tvc.lheight = 17 * UI_DPI_FAC; + tvc.lheight = 17 * UI_SCALE_FAC; tvc.row_vpadding = 0.4 * tvc.lheight; tvc.scroll_ymin = v2d->cur.ymin; tvc.scroll_ymax = v2d->cur.ymax; diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index 12ee6f45991..c1c21bebf2b 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -15,7 +15,7 @@ #include "GPU_immediate.h" #include "GPU_state.h" -#include "DNA_userdef_types.h" /* For 'U.dpi_fac' */ +#include "DNA_userdef_types.h" /* For 'UI_SCALE_FAC' */ #include "UI_interface.h" #include "UI_interface_icons.h" @@ -205,7 +205,7 @@ static bool textview_draw_string(TextViewDrawState *tds, if (icon_bg) { float col[4]; - int bg_size = UI_DPI_ICON_SIZE * 1.2; + int bg_size = UI_ICON_SIZE * 1.2; float vpadding = (tds->lheight + (tds->row_vpadding * 2) - bg_size) / 2; float hpadding = tds->draw_rect->xmin - (bg_size * 1.2f); @@ -219,19 +219,19 @@ static bool textview_draw_string(TextViewDrawState *tds, .ymax = line_top - vpadding, }, true, - 4 * UI_DPI_FAC, + 4 * UI_SCALE_FAC, col); } if (icon) { - int vpadding = (tds->lheight + (tds->row_vpadding * 2) - UI_DPI_ICON_SIZE) / 2; - int hpadding = tds->draw_rect->xmin - (UI_DPI_ICON_SIZE * 1.3f); + int vpadding = (tds->lheight + (tds->row_vpadding * 2) - UI_ICON_SIZE) / 2; + int hpadding = tds->draw_rect->xmin - (UI_ICON_SIZE * 1.3f); GPU_blend(GPU_BLEND_ALPHA); UI_icon_draw_ex(hpadding, - line_top - UI_DPI_ICON_SIZE - vpadding, + line_top - UI_ICON_SIZE - vpadding, icon, - (16 / UI_DPI_ICON_SIZE), + (16 / UI_ICON_SIZE), 1.0f, 0.0f, icon_fg, diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 058cf3c49b4..83d0d1c205b 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -183,7 +183,8 @@ static void nla_actionclip_draw_markers( float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f( + "viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* "simple" mode */ immUniform1f("dash_width", 6.0f); @@ -382,7 +383,7 @@ static uint nla_draw_use_dashed_outlines(const float color[4], bool muted) float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* Simple dashes. */ immUniformColor3fv(color); @@ -789,7 +790,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region) { View2D *v2d = ®ion->v2d; const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); - const float text_margin_x = (8 * UI_DPI_FAC) * pixelx; + const float text_margin_x = (8 * UI_SCALE_FAC) * pixelx; /* build list of channels to draw */ ListBase anim_data = {NULL, NULL}; diff --git a/source/blender/editors/space_node/add_menu_assets.cc b/source/blender/editors/space_node/add_menu_assets.cc index 060e8914194..710eac2be0f 100644 --- a/source/blender/editors/space_node/add_menu_assets.cc +++ b/source/blender/editors/space_node/add_menu_assets.cc @@ -3,6 +3,7 @@ #include "AS_asset_catalog.hh" #include "AS_asset_catalog_tree.hh" #include "AS_asset_library.hh" +#include "AS_asset_representation.h" #include "BLI_multi_value_map.hh" @@ -46,7 +47,7 @@ static void node_add_menu_assets_listen_fn(const wmRegionListenerParams *params) struct LibraryAsset { AssetLibraryReference library_ref; - AssetHandle handle; + AssetRepresentation &asset; }; struct AssetItemTree { @@ -93,11 +94,11 @@ static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node return {}; } - ED_assetlist_iterate(all_library_ref, [&](AssetHandle asset) { - if (!ED_asset_filter_matches_asset(&type_filter, &asset)) { + ED_assetlist_iterate(all_library_ref, [&](AssetHandle asset_handle) { + if (!ED_asset_filter_matches_asset(&type_filter, &asset_handle)) { return true; } - const AssetMetaData &meta_data = *ED_asset_handle_get_metadata(&asset); + const AssetMetaData &meta_data = *ED_asset_handle_get_metadata(&asset_handle); const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type"); if (tree_type == nullptr || IDP_Int(tree_type) != node_tree->type) { return true; @@ -111,7 +112,8 @@ static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node if (catalog == nullptr) { return true; } - assets_per_path.add(catalog->path, LibraryAsset{all_library_ref, asset}); + AssetRepresentation *asset = ED_asset_handle_get_representation(&asset_handle); + assets_per_path.add(catalog->path, LibraryAsset{all_library_ref, *asset}); return true; }); @@ -178,16 +180,17 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu) for (const LibraryAsset &item : asset_items) { uiLayout *col = uiLayoutColumn(layout, false); - PointerRNA file{ - &screen.id, &RNA_FileSelectEntry, const_cast(item.handle.file_data)}; - uiLayoutSetContextPointer(col, "active_file", &file); + + PointerRNA asset_ptr{NULL, &RNA_AssetRepresentation, &item.asset}; + uiLayoutSetContextPointer(col, "asset", &asset_ptr); PointerRNA library_ptr{&screen.id, &RNA_AssetLibraryReference, const_cast(&item.library_ref)}; uiLayoutSetContextPointer(col, "asset_library_ref", &library_ptr); - uiItemO(col, ED_asset_handle_get_name(&item.handle), ICON_NONE, "NODE_OT_add_group_asset"); + uiItemO( + col, AS_asset_representation_name_get(&item.asset), ICON_NONE, "NODE_OT_add_group_asset"); } catalog_item->foreach_child([&](asset_system::AssetCatalogTreeItem &child_item) { diff --git a/source/blender/editors/space_node/add_node_search.cc b/source/blender/editors/space_node/add_node_search.cc index 281995f59bc..c0ba8cd998e 100644 --- a/source/blender/editors/space_node/add_node_search.cc +++ b/source/blender/editors/space_node/add_node_search.cc @@ -40,7 +40,7 @@ namespace blender::ed::space_node { struct AddNodeItem { nodes::AddNodeInfo info; std::string identifier; - std::optional asset; + const AssetRepresentation *asset; }; struct AddNodeSearchStorage { @@ -66,24 +66,25 @@ static void add_node_search_listen_fn(const wmRegionListenerParams *params, void } static void search_items_for_asset_metadata(const bNodeTree &node_tree, - const AssetHandle asset, + const AssetHandle asset_handle, Vector &search_items) { - const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset); + const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset_handle); const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type"); if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) { return; } + const AssetRepresentation *asset = ED_asset_handle_get_representation(&asset_handle); AddNodeItem item{}; - item.info.ui_name = ED_asset_handle_get_name(&asset); + item.info.ui_name = ED_asset_handle_get_name(&asset_handle); item.identifier = node_tree.typeinfo->group_idname; item.info.description = asset_data.description == nullptr ? "" : asset_data.description; item.asset = asset; item.info.after_add_fn = [asset](const bContext &C, bNodeTree &node_tree, bNode &node) { Main &bmain = *CTX_data_main(&C); node.flag &= ~NODE_OPTIONS; - node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset); + node.id = ED_asset_get_local_id_from_asset_or_append_and_reuse(&bmain, asset, ID_NT); id_us_plus(node.id); BKE_ntree_update_tag_node_property(&node_tree, &node); DEG_relations_tag_update(&bmain); @@ -236,8 +237,8 @@ static void add_node_search_exec_fn(bContext *C, void *arg1, void *arg2) item->info.after_add_fn(*C, node_tree, *new_node); } - new_node->locx = storage.cursor.x / UI_DPI_FAC; - new_node->locy = storage.cursor.y / UI_DPI_FAC + 20; + new_node->locx = storage.cursor.x / UI_SCALE_FAC; + new_node->locy = storage.cursor.y / UI_SCALE_FAC + 20; nodeSetSelected(new_node, true); nodeSetActive(&node_tree, new_node); diff --git a/source/blender/editors/space_node/clipboard.cc b/source/blender/editors/space_node/clipboard.cc index d08e0b0b682..0a5c2233d18 100644 --- a/source/blender/editors/space_node/clipboard.cc +++ b/source/blender/editors/space_node/clipboard.cc @@ -264,7 +264,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) float2 mouse_location; RNA_property_float_get_array(op->ptr, offset_prop, mouse_location); - const float2 offset = (mouse_location - center) / UI_DPI_FAC; + const float2 offset = (mouse_location - center) / UI_SCALE_FAC; for (bNode *new_node : node_map.values()) { new_node->locx += offset.x; diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index b64e0bb6116..1fdccc72913 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -1589,12 +1589,11 @@ void draw_nodespace_back_pix(const bContext &C, GPU_matrix_pop(); } -static float2 socket_link_connection_location(const Span socket_locations, - const bNode &node, +static float2 socket_link_connection_location(const bNode &node, const bNodeSocket &socket, const bNodeLink &link) { - const float2 socket_location = socket_locations[socket.index_in_tree()]; + const float2 socket_location = socket.runtime->location; if (socket.is_multi_input() && socket.is_input() && !(node.flag & NODE_HIDDEN)) { return node_link_calculate_multi_input_position( socket_location, link.multi_input_socket_index, socket.runtime->total_inputs); @@ -1628,13 +1627,11 @@ static void calculate_inner_link_bezier_points(std::array &points) } } -static std::array node_link_bezier_points(const Span socket_locations, - const bNodeLink &link) +static std::array node_link_bezier_points(const bNodeLink &link) { std::array points; - points[0] = socket_link_connection_location( - socket_locations, *link.fromnode, *link.fromsock, link); - points[3] = socket_link_connection_location(socket_locations, *link.tonode, *link.tosock, link); + points[0] = socket_link_connection_location(*link.fromnode, *link.fromsock, link); + points[3] = socket_link_connection_location(*link.tonode, *link.tosock, link); calculate_inner_link_bezier_points(points); return points; } @@ -1650,11 +1647,10 @@ static bool node_link_draw_is_visible(const View2D &v2d, const std::array socket_locations, - const bNodeLink &link, +void node_link_bezier_points_evaluated(const bNodeLink &link, std::array &coords) { - const std::array points = node_link_bezier_points(socket_locations, link); + const std::array points = node_link_bezier_points(link); /* The extra +1 in size is required by these functions and would be removed ideally. */ BKE_curve_forward_diff_bezier(points[0].x, @@ -1675,8 +1671,8 @@ void node_link_bezier_points_evaluated(const Span socket_locations, #define NODELINK_GROUP_SIZE 256 #define LINK_RESOL 24 -#define LINK_WIDTH (2.5f * UI_DPI_FAC) -#define ARROW_SIZE (7 * UI_DPI_FAC) +#define LINK_WIDTH (2.5f * UI_SCALE_FAC) +#define ARROW_SIZE (7 * UI_SCALE_FAC) /* Reroute arrow shape and mute bar. These are expanded here and shrunk in the glsl code. * See: gpu_shader_2D_nodelink_vert.glsl */ @@ -2041,9 +2037,7 @@ static NodeLinkDrawConfig nodelink_get_draw_config(const bContext &C, const bNodeTree &node_tree = *snode.edittree; - draw_config.dim_factor = selected ? 1.0f : - node_link_dim_factor( - node_tree.runtime->all_socket_locations, v2d, link); + draw_config.dim_factor = selected ? 1.0f : node_link_dim_factor(v2d, link); bTheme *btheme = UI_GetTheme(); draw_config.dash_alpha = btheme->space_node.dash_alpha; @@ -2166,9 +2160,7 @@ void node_draw_link_bezier(const bContext &C, const int th_col3, const bool selected) { - const bNodeTree &node_tree = *snode.edittree; - const std::array points = node_link_bezier_points( - node_tree.runtime->all_socket_locations, link); + const std::array points = node_link_bezier_points(link); if (!node_link_draw_is_visible(v2d, points)) { return; } @@ -2227,19 +2219,13 @@ void node_draw_link(const bContext &C, std::array node_link_bezier_points_dragged(const SpaceNode &snode, const bNodeLink &link) { - const bNodeTree &node_tree = *snode.edittree; - const float2 cursor = snode.runtime->cursor * UI_DPI_FAC; + const float2 cursor = snode.runtime->cursor * UI_SCALE_FAC; std::array points; points[0] = link.fromsock ? - socket_link_connection_location(node_tree.runtime->all_socket_locations, - *link.fromnode, - *link.fromsock, - link) : - cursor; - points[3] = link.tosock ? - socket_link_connection_location( - node_tree.runtime->all_socket_locations, *link.tonode, *link.tosock, link) : + socket_link_connection_location(*link.fromnode, *link.fromsock, link) : cursor; + points[3] = link.tosock ? socket_link_connection_location(*link.tonode, *link.tosock, link) : + cursor; calculate_inner_link_bezier_points(points); return points; } diff --git a/source/blender/editors/space_node/link_drag_search.cc b/source/blender/editors/space_node/link_drag_search.cc index b0244f599b6..58f6dc18447 100644 --- a/source/blender/editors/space_node/link_drag_search.cc +++ b/source/blender/editors/space_node/link_drag_search.cc @@ -143,10 +143,10 @@ static void add_existing_group_input_fn(nodes::LinkSearchOpParams ¶ms, */ static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree, const bNodeSocket &socket, - const AssetHandle asset, + const AssetHandle asset_handle, Vector &search_link_ops) { - const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset); + const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset_handle); const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type"); if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) { return; @@ -182,7 +182,8 @@ static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree, continue; } - const StringRef asset_name = ED_asset_handle_get_name(&asset); + AssetRepresentation *asset = ED_asset_handle_get_representation(&asset_handle); + const StringRef asset_name = ED_asset_handle_get_name(&asset_handle); const StringRef socket_name = socket_property->name; search_link_ops.append( @@ -193,7 +194,7 @@ static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree, bNode &node = params.add_node(params.node_tree.typeinfo->group_idname); node.flag &= ~NODE_OPTIONS; - node.id = asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset); + node.id = ED_asset_get_local_id_from_asset_or_append_and_reuse(&bmain, asset, ID_NT); id_us_plus(node.id); BKE_ntree_update_tag_node_property(¶ms.node_tree, &node); DEG_relations_tag_update(&bmain); @@ -380,8 +381,8 @@ static void link_drag_search_exec_fn(bContext *C, void *arg1, void *arg2) BLI_assert(new_nodes.size() == 1); bNode *new_node = new_nodes.first(); - new_node->locx = storage.cursor.x / UI_DPI_FAC; - new_node->locy = storage.cursor.y / UI_DPI_FAC + 20; + new_node->locx = storage.cursor.x / UI_SCALE_FAC; + new_node->locy = storage.cursor.y / UI_SCALE_FAC + 20; if (storage.in_out() == SOCK_IN) { new_node->locx -= new_node->width; } diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc index 473ae4a6f83..60a7ed590e6 100644 --- a/source/blender/editors/space_node/node_add.cc +++ b/source/blender/editors/space_node/node_add.cc @@ -7,6 +7,8 @@ #include +#include "AS_asset_representation.h" + #include "MEM_guardedalloc.h" #include "DNA_collection_types.h" @@ -55,8 +57,8 @@ namespace blender::ed::space_node { static void position_node_based_on_mouse(bNode &node, const float2 &location) { - node.locx = location.x - NODE_DY * 1.5f / UI_DPI_FAC; - node.locy = location.y + NODE_DY * 0.5f / UI_DPI_FAC; + node.locx = location.x - NODE_DY * 1.5f / UI_SCALE_FAC; + node.locy = location.y + NODE_DY * 0.5f / UI_SCALE_FAC; } bNode *add_node(const bContext &C, const StringRef idname, const float2 &location) @@ -107,12 +109,10 @@ bNode *add_static_node(const bContext &C, int type, const float2 &location) /** \name Add Reroute Operator * \{ */ -std::optional link_path_intersection(const Span socket_locations, - const bNodeLink &link, - const Span path) +std::optional link_path_intersection(const bNodeLink &link, const Span path) { std::array coords; - node_link_bezier_points_evaluated(socket_locations, link, coords); + node_link_bezier_points_evaluated(link, coords); for (const int i : path.index_range().drop_back(1)) { for (const int j : IndexRange(NODE_LINK_RESOL)) { @@ -138,7 +138,6 @@ static int add_reroute_exec(bContext *C, wmOperator *op) const ARegion ®ion = *CTX_wm_region(C); SpaceNode &snode = *CTX_wm_space_node(C); bNodeTree &ntree = *snode.edittree; - const Span socket_locations = ntree.runtime->all_socket_locations; Vector path; RNA_BEGIN (op->ptr, itemptr, "path") { @@ -170,10 +169,10 @@ static int add_reroute_exec(bContext *C, wmOperator *op) Map cuts_per_socket; LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { - if (node_link_is_hidden_or_dimmed(socket_locations, region.v2d, *link)) { + if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { continue; } - const std::optional cut = link_path_intersection(socket_locations, *link, path); + const std::optional cut = link_path_intersection(*link, path); if (!cut) { continue; } @@ -204,8 +203,8 @@ static int add_reroute_exec(bContext *C, wmOperator *op) const float2 insert_point = std::accumulate( cuts.values().begin(), cuts.values().end(), float2(0)) / cuts.size(); - reroute->locx = insert_point.x / UI_DPI_FAC; - reroute->locy = insert_point.y / UI_DPI_FAC; + reroute->locx = insert_point.x / UI_SCALE_FAC; + reroute->locy = insert_point.y / UI_SCALE_FAC; /* Attach the reroute node to frame nodes behind it. */ for (const int i : frame_nodes.index_range()) { @@ -348,8 +347,8 @@ static int node_add_group_invoke(bContext *C, wmOperator *op, const wmEvent *eve &snode->runtime->cursor[0], &snode->runtime->cursor[1]); - snode->runtime->cursor[0] /= UI_DPI_FAC; - snode->runtime->cursor[1] /= UI_DPI_FAC; + snode->runtime->cursor[0] /= UI_SCALE_FAC; + snode->runtime->cursor[1] /= UI_SCALE_FAC; return node_add_group_exec(C, op); } @@ -378,14 +377,16 @@ void NODE_OT_add_group(wmOperatorType *ot) /** \name Add Node Group Asset Operator * \{ */ -static bool add_node_group_asset(const bContext &C, const AssetHandle asset, ReportList &reports) +static bool add_node_group_asset(const bContext &C, + const AssetRepresentation *asset, + ReportList &reports) { Main &bmain = *CTX_data_main(&C); SpaceNode &snode = *CTX_wm_space_node(&C); bNodeTree &edit_tree = *snode.edittree; bNodeTree *node_group = reinterpret_cast( - asset::get_local_id_from_asset_or_append_and_reuse(bmain, asset)); + ED_asset_get_local_id_from_asset_or_append_and_reuse(&bmain, asset, ID_NT)); if (!node_group) { return false; } @@ -427,9 +428,8 @@ static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEven if (!library_ref) { return OPERATOR_CANCELLED; } - bool is_valid; - const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid); - if (!is_valid) { + const AssetRepresentation *asset = CTX_wm_asset(C); + if (!asset) { return OPERATOR_CANCELLED; } @@ -440,9 +440,9 @@ static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEven &snode.runtime->cursor[0], &snode.runtime->cursor[1]); - snode.runtime->cursor /= UI_DPI_FAC; + snode.runtime->cursor /= UI_SCALE_FAC; - if (!add_node_group_asset(*C, handle, *op->reports)) { + if (!add_node_group_asset(*C, asset, *op->reports)) { return OPERATOR_CANCELLED; } @@ -460,12 +460,11 @@ static char *node_add_group_asset_get_description(struct bContext *C, struct wmOperatorType * /*op*/, struct PointerRNA * /*values*/) { - bool is_valid; - const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid); - if (!is_valid) { + const AssetRepresentation *asset = CTX_wm_asset(C); + if (!asset) { return nullptr; } - const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&handle); + const AssetMetaData &asset_data = *AS_asset_representation_metadata_get(asset); if (!asset_data.description) { return nullptr; } @@ -541,8 +540,8 @@ static int node_add_object_invoke(bContext *C, wmOperator *op, const wmEvent *ev &snode->runtime->cursor[0], &snode->runtime->cursor[1]); - snode->runtime->cursor[0] /= UI_DPI_FAC; - snode->runtime->cursor[1] /= UI_DPI_FAC; + snode->runtime->cursor[0] /= UI_SCALE_FAC; + snode->runtime->cursor[1] /= UI_SCALE_FAC; return node_add_object_exec(C, op); } @@ -628,8 +627,8 @@ static int node_add_collection_invoke(bContext *C, wmOperator *op, const wmEvent &snode->runtime->cursor[0], &snode->runtime->cursor[1]); - snode->runtime->cursor[0] /= UI_DPI_FAC; - snode->runtime->cursor[1] /= UI_DPI_FAC; + snode->runtime->cursor[0] /= UI_SCALE_FAC; + snode->runtime->cursor[1] /= UI_SCALE_FAC; return node_add_collection_exec(C, op); } @@ -743,8 +742,8 @@ static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *even &snode->runtime->cursor[0], &snode->runtime->cursor[1]); - snode->runtime->cursor[0] /= UI_DPI_FAC; - snode->runtime->cursor[1] /= UI_DPI_FAC; + snode->runtime->cursor[0] /= UI_SCALE_FAC; + snode->runtime->cursor[1] /= UI_SCALE_FAC; if (WM_operator_properties_id_lookup_is_set(op->ptr) || RNA_struct_property_is_set(op->ptr, "filepath")) { diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 1ad86b5d8db..faca5438979 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -300,9 +300,6 @@ void node_sort(bNodeTree &ntree) ntree.runtime->nodes_by_id.add_new(sort_nodes[i]); sort_nodes[i]->runtime->index_in_tree = i; } - - /* Nodes have been reordered; the socket locations are invalid until the node tree is redrawn. */ - ntree.runtime->all_socket_locations.clear(); } static Array node_uiblocks_init(const bContext &C, const Span nodes) @@ -323,7 +320,7 @@ float2 node_to_view(const bNode &node, const float2 &co) { float2 result; nodeToView(&node, co.x, co.y, &result.x, &result.y); - return result * UI_DPI_FAC; + return result * UI_SCALE_FAC; } void node_to_updated_rect(const bNode &node, rctf &r_rect) @@ -339,8 +336,8 @@ void node_to_updated_rect(const bNode &node, rctf &r_rect) float2 node_from_view(const bNode &node, const float2 &co) { - const float x = co.x / UI_DPI_FAC; - const float y = co.y / UI_DPI_FAC; + const float x = co.x / UI_SCALE_FAC; + const float y = co.y / UI_SCALE_FAC; float2 result; nodeFromView(&node, x, y, &result.x, &result.y); return result; @@ -353,8 +350,7 @@ static void node_update_basis(const bContext &C, const TreeDrawContext & /*tree_draw_ctx*/, bNodeTree &ntree, bNode &node, - uiBlock &block, - MutableSpan socket_locations) + uiBlock &block) { PointerRNA nodeptr; RNA_pointer_create(&ntree.id, &RNA_Node, &node, &nodeptr); @@ -430,8 +426,7 @@ static void node_update_basis(const bContext &C, buty = min_ii(buty, dy - NODE_DY); /* Round the socket location to stop it from jiggling. */ - socket_locations[socket->index_in_tree()] = float2(round(loc.x + NODE_WIDTH(node)), - round(dy - NODE_DYS)); + socket->runtime->location = float2(round(loc.x + NODE_WIDTH(node)), round(dy - NODE_DYS)); dy = buty; if (socket->next) { @@ -568,7 +563,7 @@ static void node_update_basis(const bContext &C, buty = min_ii(buty, dy - NODE_DY); /* Round the socket vertical position to stop it from jiggling. */ - socket_locations[socket->index_in_tree()] = float2(loc.x, round(dy - NODE_DYS)); + socket->runtime->location = float2(loc.x, round(dy - NODE_DYS)); dy = buty - multi_input_socket_offset * 0.5; if (socket->next) { @@ -598,7 +593,7 @@ static void node_update_basis(const bContext &C, /** * Based on settings in node, sets drawing rect info. */ -static void node_update_hidden(bNode &node, uiBlock &block, MutableSpan socket_locations) +static void node_update_hidden(bNode &node, uiBlock &block) { int totin = 0, totout = 0; @@ -638,7 +633,7 @@ static void node_update_hidden(bNode &node, uiBlock &block, MutableSpan for (bNodeSocket *socket : node.output_sockets()) { if (socket->is_visible()) { /* Round the socket location to stop it from jiggling. */ - socket_locations[socket->index_in_tree()] = { + socket->runtime->location = { round(node.runtime->totr.xmax - hiddenrad + sinf(rad) * hiddenrad), round(node.runtime->totr.ymin + hiddenrad + cosf(rad) * hiddenrad)}; rad += drad; @@ -651,7 +646,7 @@ static void node_update_hidden(bNode &node, uiBlock &block, MutableSpan for (bNodeSocket *socket : node.input_sockets()) { if (socket->is_visible()) { /* Round the socket location to stop it from jiggling. */ - socket_locations[socket->index_in_tree()] = { + socket->runtime->location = { round(node.runtime->totr.xmin + hiddenrad + sinf(rad) * hiddenrad), round(node.runtime->totr.ymin + hiddenrad + cosf(rad) * hiddenrad)}; rad += drad; @@ -783,10 +778,10 @@ static void node_socket_draw_multi_input(const float color[4], const float2 location) { /* The other sockets are drawn with the keyframe shader. There, the outline has a base thickness - * that can be varied but always scales with the size the socket is drawn at. Using `U.dpi_fac` - * has the same effect here. It scales the outline correctly across different screen DPI's - * and UI scales without being affected by the 'line-width'. */ - const float outline_width = NODE_SOCK_OUTLINE_SCALE * U.dpi_fac; + * that can be varied but always scales with the size the socket is drawn at. Using + * `UI_SCALE_FAC` has the same effect here. It scales the outline correctly across different + * screen DPI's and UI scales without being affected by the 'line-width'. */ + const float outline_width = NODE_SOCK_OUTLINE_SCALE * UI_SCALE_FAC; /* UI_draw_roundbox draws the outline on the outer side, so compensate for the outline width. */ const rctf rect = { @@ -1231,7 +1226,6 @@ void node_socket_add_tooltip(const bNodeTree &ntree, const bNodeSocket &sock, ui static void node_socket_draw_nested(const bContext &C, const bNodeTree &ntree, - const Span socket_locations, PointerRNA &node_ptr, uiBlock &block, const bNodeSocket &sock, @@ -1243,7 +1237,7 @@ static void node_socket_draw_nested(const bContext &C, const float size, const bool selected) { - const float2 location = socket_locations[sock.index_in_tree()]; + const float2 location = sock.runtime->location; float color[4]; float outline_color[4]; @@ -1445,7 +1439,6 @@ static void node_draw_shadow(const SpaceNode &snode, static void node_draw_sockets(const View2D &v2d, const bContext &C, const bNodeTree &ntree, - const Span socket_locations, const bNode &node, uiBlock &block, const bool draw_outputs, @@ -1505,7 +1498,6 @@ static void node_draw_sockets(const View2D &v2d, node_socket_draw_nested(C, ntree, - socket_locations, node_ptr, block, *sock, @@ -1532,7 +1524,6 @@ static void node_draw_sockets(const View2D &v2d, node_socket_draw_nested(C, ntree, - socket_locations, node_ptr, block, *sock, @@ -1571,7 +1562,6 @@ static void node_draw_sockets(const View2D &v2d, if (select_all || (sock->flag & SELECT)) { node_socket_draw_nested(C, ntree, - socket_locations, node_ptr, block, *sock, @@ -1599,7 +1589,6 @@ static void node_draw_sockets(const View2D &v2d, if (select_all || (sock->flag & SELECT)) { node_socket_draw_nested(C, ntree, - socket_locations, node_ptr, block, *sock, @@ -1645,7 +1634,7 @@ static void node_draw_sockets(const View2D &v2d, node_socket_color_get(C, ntree, node_ptr, *socket, color); node_socket_outline_color_get(socket->flag & SELECT, socket->type, outline_color); - const float2 location = socket_locations[socket->index_in_tree()]; + const float2 location = socket->runtime->location; node_socket_draw_multi_input(color, outline_color, width, height, location); } } @@ -2036,7 +2025,7 @@ static void node_draw_extra_info_row(const bNode &node, const int row, const NodeExtraInfoRow &extra_info_row) { - const float but_icon_left = rect.xmin + 6.0f * U.dpi_fac; + const float but_icon_left = rect.xmin + 6.0f * UI_SCALE_FAC; const float but_icon_width = NODE_HEADER_ICON_SIZE * 0.8f; const float but_icon_right = but_icon_left + but_icon_width; @@ -2046,7 +2035,7 @@ static void node_draw_extra_info_row(const bNode &node, 0, extra_info_row.icon, int(but_icon_left), - int(rect.ymin + row * (20.0f * U.dpi_fac)), + int(rect.ymin + row * (20.0f * UI_SCALE_FAC)), but_icon_width, UI_UNIT_Y, nullptr, @@ -2063,7 +2052,7 @@ static void node_draw_extra_info_row(const bNode &node, } UI_block_emboss_set(&block, UI_EMBOSS); - const float but_text_left = but_icon_right + 6.0f * U.dpi_fac; + const float but_text_left = but_icon_right + 6.0f * UI_SCALE_FAC; const float but_text_right = rect.xmax; const float but_text_width = but_text_right - but_text_left; @@ -2072,7 +2061,7 @@ static void node_draw_extra_info_row(const bNode &node, 0, extra_info_row.text.c_str(), int(but_text_left), - int(rect.ymin + row * (20.0f * U.dpi_fac)), + int(rect.ymin + row * (20.0f * UI_SCALE_FAC)), short(but_text_width), short(NODE_DY), nullptr, @@ -2102,19 +2091,19 @@ static void node_draw_extra_info_panel(TreeDrawContext &tree_draw_ctx, float color[4]; rctf extra_info_rect; - const float width = (node.width - 6.0f) * U.dpi_fac; + const float width = (node.width - 6.0f) * UI_SCALE_FAC; if (node.is_frame()) { extra_info_rect.xmin = rct.xmin; - extra_info_rect.xmax = rct.xmin + 95.0f * U.dpi_fac; - extra_info_rect.ymin = rct.ymin + 2.0f * U.dpi_fac; - extra_info_rect.ymax = rct.ymin + 2.0f * U.dpi_fac; + extra_info_rect.xmax = rct.xmin + 95.0f * UI_SCALE_FAC; + extra_info_rect.ymin = rct.ymin + 2.0f * UI_SCALE_FAC; + extra_info_rect.ymax = rct.ymin + 2.0f * UI_SCALE_FAC; } else { - extra_info_rect.xmin = rct.xmin + 3.0f * U.dpi_fac; + extra_info_rect.xmin = rct.xmin + 3.0f * UI_SCALE_FAC; extra_info_rect.xmax = rct.xmin + width; extra_info_rect.ymin = rct.ymax; - extra_info_rect.ymax = rct.ymax + extra_info_rows.size() * (20.0f * U.dpi_fac); + extra_info_rect.ymax = rct.ymax + extra_info_rows.size() * (20.0f * UI_SCALE_FAC); if (node.flag & NODE_MUTED) { UI_GetThemeColorBlend4f(TH_BACK, TH_NODE, 0.2f, color); @@ -2130,10 +2119,11 @@ static void node_draw_extra_info_panel(TreeDrawContext &tree_draw_ctx, /* Draw outline. */ const float outline_width = 1.0f; - extra_info_rect.xmin = rct.xmin + 3.0f * U.dpi_fac - outline_width; + extra_info_rect.xmin = rct.xmin + 3.0f * UI_SCALE_FAC - outline_width; extra_info_rect.xmax = rct.xmin + width + outline_width; extra_info_rect.ymin = rct.ymax - outline_width; - extra_info_rect.ymax = rct.ymax + outline_width + extra_info_rows.size() * (20.0f * U.dpi_fac); + extra_info_rect.ymax = rct.ymax + outline_width + + extra_info_rows.size() * (20.0f * UI_SCALE_FAC); UI_GetThemeColorBlendShade4fv(TH_BACK, TH_NODE, 0.4f, -20, color); UI_draw_roundbox_corner_set( @@ -2152,7 +2142,6 @@ static void node_draw_basis(const bContext &C, const View2D &v2d, const SpaceNode &snode, bNodeTree &ntree, - const Span socket_locations, const bNode &node, uiBlock &block, bNodeInstanceKey key) @@ -2345,7 +2334,7 @@ static void node_draw_basis(const bContext &C, showname, int(rct.xmin + NODE_MARGIN_X + 0.4f), int(rct.ymax - NODE_DY), - short(iconofs - rct.xmin - (18.0f * U.dpi_fac)), + short(iconofs - rct.xmin - (18.0f * UI_SCALE_FAC)), short(NODE_DY), nullptr, 0, @@ -2472,7 +2461,7 @@ static void node_draw_basis(const bContext &C, /* Skip slow socket drawing if zoom is small. */ if (scale > 0.2f) { - node_draw_sockets(v2d, C, ntree, socket_locations, node, block, true, false); + node_draw_sockets(v2d, C, ntree, node, block, true, false); } /* Preview. */ @@ -2496,7 +2485,6 @@ static void node_draw_hidden(const bContext &C, const View2D &v2d, const SpaceNode &snode, bNodeTree &ntree, - const Span socket_locations, bNode &node, uiBlock &block) { @@ -2594,7 +2582,7 @@ static void node_draw_hidden(const bContext &C, showname, round_fl_to_int(rct.xmin + NODE_MARGIN_X), round_fl_to_int(centy - NODE_DY * 0.5f), - short(BLI_rctf_size_x(&rct) - ((18.0f + 12.0f) * U.dpi_fac)), + short(BLI_rctf_size_x(&rct) - ((18.0f + 12.0f) * UI_SCALE_FAC)), short(NODE_DY), nullptr, 0, @@ -2666,7 +2654,7 @@ static void node_draw_hidden(const bContext &C, immUnbindProgram(); GPU_blend(GPU_BLEND_NONE); - node_draw_sockets(v2d, C, ntree, socket_locations, node, block, true, false); + node_draw_sockets(v2d, C, ntree, node, block, true, false); UI_block_end(&C, &block); UI_block_draw(&C, &block); @@ -2752,7 +2740,7 @@ static void count_multi_input_socket_links(bNodeTree &ntree, SpaceNode &snode) static float frame_node_label_height(const NodeFrame &frame_data) { - return frame_data.label_size * U.dpi_fac; + return frame_data.label_size * UI_SCALE_FAC; } #define NODE_FRAME_MARGIN (1.5f * U.widget_unit) @@ -2814,13 +2802,13 @@ static void frame_node_prepare_for_draw(bNode &node, Span nodes) node.runtime->totr = rect; } -static void reroute_node_prepare_for_draw(bNode &node, MutableSpan socket_locations) +static void reroute_node_prepare_for_draw(bNode &node) { const float2 loc = node_to_view(node, float2(0)); /* Reroute node has exactly one input and one output, both in the same place. */ - socket_locations[node.input_socket(0).index_in_tree()] = loc; - socket_locations[node.output_socket(0).index_in_tree()] = loc; + node.input_socket(0).runtime->location = loc; + node.output_socket(0).runtime->location = loc; const float size = 8.0f; node.width = size * 2; @@ -2834,8 +2822,7 @@ static void node_update_nodetree(const bContext &C, TreeDrawContext &tree_draw_ctx, bNodeTree &ntree, Span nodes, - Span blocks, - MutableSpan socket_locations) + Span blocks) { /* Make sure socket "used" tags are correct, for displaying value buttons. */ SpaceNode *snode = CTX_wm_space_node(&C); @@ -2851,14 +2838,14 @@ static void node_update_nodetree(const bContext &C, } if (node.is_reroute()) { - reroute_node_prepare_for_draw(node, socket_locations); + reroute_node_prepare_for_draw(node); } else { if (node.flag & NODE_HIDDEN) { - node_update_hidden(node, block, socket_locations); + node_update_hidden(node, block); } else { - node_update_basis(C, tree_draw_ctx, ntree, node, block, socket_locations); + node_update_basis(C, tree_draw_ctx, ntree, node, block); } } } @@ -2888,7 +2875,7 @@ static void frame_node_draw_label(TreeDrawContext &tree_draw_ctx, BLF_enable(fontid, BLF_ASPECT); BLF_aspect(fontid, aspect, aspect, 1.0f); - BLF_size(fontid, font_size * U.dpi_fac); + BLF_size(fontid, font_size * UI_SCALE_FAC); /* Title color. */ int color_id = node_get_colorid(tree_draw_ctx, node); @@ -3001,12 +2988,8 @@ static void frame_node_draw(const bContext &C, UI_block_draw(&C, &block); } -static void reroute_node_draw(const bContext &C, - ARegion ®ion, - bNodeTree &ntree, - const Span socket_locations, - const bNode &node, - uiBlock &block) +static void reroute_node_draw( + const bContext &C, ARegion ®ion, bNodeTree &ntree, const bNode &node, uiBlock &block) { /* Skip if out of view. */ const rctf &rct = node.runtime->totr; @@ -3044,8 +3027,7 @@ static void reroute_node_draw(const bContext &C, /* Only draw input socket as they all are placed on the same position highlight * if node itself is selected, since we don't display the node body separately. */ - node_draw_sockets( - region.v2d, C, ntree, socket_locations, node, block, false, node.flag & SELECT); + node_draw_sockets(region.v2d, C, ntree, node, block, false, node.flag & SELECT); UI_block_end(&C, &block); UI_block_draw(&C, &block); @@ -3056,7 +3038,6 @@ static void node_draw(const bContext &C, ARegion ®ion, const SpaceNode &snode, bNodeTree &ntree, - const Span socket_locations, bNode &node, uiBlock &block, bNodeInstanceKey key) @@ -3065,15 +3046,15 @@ static void node_draw(const bContext &C, frame_node_draw(C, tree_draw_ctx, region, snode, ntree, node, block); } else if (node.is_reroute()) { - reroute_node_draw(C, region, ntree, socket_locations, node, block); + reroute_node_draw(C, region, ntree, node, block); } else { const View2D &v2d = region.v2d; if (node.flag & NODE_HIDDEN) { - node_draw_hidden(C, tree_draw_ctx, v2d, snode, ntree, socket_locations, node, block); + node_draw_hidden(C, tree_draw_ctx, v2d, snode, ntree, node, block); } else { - node_draw_basis(C, tree_draw_ctx, v2d, snode, ntree, socket_locations, node, block, key); + node_draw_basis(C, tree_draw_ctx, v2d, snode, ntree, node, block, key); } } } @@ -3235,7 +3216,6 @@ static void node_draw_nodetree(const bContext &C, ARegion ®ion, SpaceNode &snode, bNodeTree &ntree, - const Span socket_locations, Span nodes, Span blocks, bNodeInstanceKey parent_key) @@ -3257,8 +3237,7 @@ static void node_draw_nodetree(const bContext &C, } const bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]); - node_draw( - C, tree_draw_ctx, region, snode, ntree, socket_locations, *nodes[i], *blocks[i], key); + node_draw(C, tree_draw_ctx, region, snode, ntree, *nodes[i], *blocks[i], key); } /* Node lines. */ @@ -3288,8 +3267,7 @@ static void node_draw_nodetree(const bContext &C, } const bNodeInstanceKey key = BKE_node_instance_key(parent_key, &ntree, nodes[i]); - node_draw( - C, tree_draw_ctx, region, snode, ntree, socket_locations, *nodes[i], *blocks[i], key); + node_draw(C, tree_draw_ctx, region, snode, ntree, *nodes[i], *blocks[i], key); } } @@ -3302,7 +3280,7 @@ static void draw_tree_path(const bContext &C, ARegion ®ion) const rcti *rect = ED_region_visible_rect(®ion); const uiStyle *style = UI_style_get_dpi(); - const float padding_x = 16 * UI_DPI_FAC; + const float padding_x = 16 * UI_SCALE_FAC; const int x = rect->xmin + padding_x; const int y = region.winy - UI_UNIT_Y * 0.6f; const int width = BLI_rcti_size_x(rect) - 2 * padding_x; @@ -3396,20 +3374,10 @@ static void draw_nodetree(const bContext &C, else if (ntree.type == NTREE_COMPOSIT) { tree_draw_ctx.used_by_realtime_compositor = realtime_compositor_is_in_use(C); } - ntree.runtime->all_socket_locations.reinitialize(ntree.all_sockets().size()); - node_update_nodetree( - C, tree_draw_ctx, ntree, nodes, blocks, ntree.runtime->all_socket_locations); + node_update_nodetree(C, tree_draw_ctx, ntree, nodes, blocks); node_draw_sub_context_frames(tree_draw_ctx, *snode, ntree); - node_draw_nodetree(C, - tree_draw_ctx, - region, - *snode, - ntree, - ntree.runtime->all_socket_locations, - nodes, - blocks, - parent_key); + node_draw_nodetree(C, tree_draw_ctx, region, *snode, ntree, nodes, blocks, parent_key); } /** @@ -3457,8 +3425,8 @@ void node_draw_space(const bContext &C, ARegion ®ion) win->eventstate->xy[1] - region.winrct.ymin, &snode.runtime->cursor[0], &snode.runtime->cursor[1]); - snode.runtime->cursor[0] /= UI_DPI_FAC; - snode.runtime->cursor[1] /= UI_DPI_FAC; + snode.runtime->cursor[0] /= UI_SCALE_FAC; + snode.runtime->cursor[1] /= UI_SCALE_FAC; ED_region_draw_cb_draw(&C, ®ion, REGION_DRAW_PRE_VIEW); diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 123ea7d7149..89e4ab12db8 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -916,8 +916,8 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) WM_event_drag_start_mval(event, region, mval); float mx, my; UI_view2d_region_to_view(®ion->v2d, mval.x, mval.y, &mx, &my); - const float dx = (mx - nsw->mxstart) / UI_DPI_FAC; - const float dy = (my - nsw->mystart) / UI_DPI_FAC; + const float dx = (mx - nsw->mxstart) / UI_SCALE_FAC; + const float dy = (my - nsw->mystart) / UI_SCALE_FAC; if (node) { float *pwidth = &node->width; @@ -941,8 +941,8 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Height works the other way round. */ { - float heightmin = UI_DPI_FAC * node->typeinfo->minheight; - float heightmax = UI_DPI_FAC * node->typeinfo->maxheight; + float heightmin = UI_SCALE_FAC * node->typeinfo->minheight; + float heightmax = UI_SCALE_FAC * node->typeinfo->maxheight; if (nsw->directions & NODE_RESIZE_TOP) { float locmin = nsw->oldlocy - nsw->oldheight; @@ -1099,12 +1099,10 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) } } -static bool cursor_isect_multi_input_socket(const Span socket_locations, - const float2 &cursor, - const bNodeSocket &socket) +static bool cursor_isect_multi_input_socket(const float2 &cursor, const bNodeSocket &socket) { const float node_socket_height = node_socket_calculate_height(socket); - const float2 location = socket_locations[socket.index_in_tree()]; + const float2 location = socket.runtime->location; /* `.xmax = socket->locx + NODE_SOCKSIZE * 5.5f` * would be the same behavior as for regular sockets. * But keep it smaller because for multi-input socket you @@ -1131,11 +1129,6 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode, bNodeTree &node_tree = *snode.edittree; node_tree.ensure_topology_cache(); - const Span socket_locations = node_tree.runtime->all_socket_locations; - if (socket_locations.size() != node_tree.all_sockets().size()) { - /* Sockets haven't been drawn yet, e.g. when the file is currently opening. */ - return nullptr; - } const Span nodes = node_tree.all_nodes(); if (nodes.is_empty()) { return nullptr; @@ -1160,9 +1153,9 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode, if (in_out & SOCK_IN) { for (bNodeSocket *sock : node.input_sockets()) { if (sock->is_visible()) { - const float2 location = socket_locations[sock->index_in_tree()]; + const float2 location = sock->runtime->location; if (sock->flag & SOCK_MULTI_INPUT && !(node.flag & NODE_HIDDEN)) { - if (cursor_isect_multi_input_socket(socket_locations, cursor, *sock)) { + if (cursor_isect_multi_input_socket(cursor, *sock)) { if (!socket_is_occluded(location, node, snode)) { return sock; } @@ -1179,7 +1172,7 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode, if (in_out & SOCK_OUT) { for (bNodeSocket *sock : node.output_sockets()) { if (sock->is_visible()) { - const float2 location = socket_locations[sock->index_in_tree()]; + const float2 location = sock->runtime->location; if (BLI_rctf_isect_pt(&rect, location.x, location.y)) { if (!socket_is_occluded(location, node, snode)) { return sock; @@ -1199,16 +1192,14 @@ bNodeSocket *node_find_indicated_socket(SpaceNode &snode, /** \name Node Link Dimming * \{ */ -float node_link_dim_factor(const Span socket_locations, - const View2D &v2d, - const bNodeLink &link) +float node_link_dim_factor(const View2D &v2d, const bNodeLink &link) { if (link.fromsock == nullptr || link.tosock == nullptr) { return 1.0f; } - const float2 from = socket_locations[link.fromsock->index_in_tree()]; - const float2 to = socket_locations[link.tosock->index_in_tree()]; + const float2 from = link.fromsock->runtime->location; + const float2 to = link.tosock->runtime->location; const float min_endpoint_distance = std::min( std::max(BLI_rctf_length_x(&v2d.cur, from.x), BLI_rctf_length_y(&v2d.cur, from.y)), @@ -1221,11 +1212,9 @@ float node_link_dim_factor(const Span socket_locations, return std::clamp(1.0f - min_endpoint_distance / viewport_width * 10.0f, 0.05f, 1.0f); } -bool node_link_is_hidden_or_dimmed(const Span socket_locations, - const View2D &v2d, - const bNodeLink &link) +bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link) { - return nodeLinkIsHidden(&link) || node_link_dim_factor(socket_locations, v2d, link) < 0.5f; + return nodeLinkIsHidden(&link) || node_link_dim_factor(v2d, link) < 0.5f; } /** \} */ diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index 11e64bb2f4c..a18d1d19240 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -129,8 +129,8 @@ ENUM_OPERATORS(NodeResizeDirection, NODE_RESIZE_LEFT); #define NODE_DYS (U.widget_unit / 2) #define NODE_DY U.widget_unit #define NODE_SOCKDY (0.1f * U.widget_unit) -#define NODE_WIDTH(node) (node.width * UI_DPI_FAC) -#define NODE_HEIGHT(node) (node.height * UI_DPI_FAC) +#define NODE_WIDTH(node) (node.width * UI_SCALE_FAC) +#define NODE_HEIGHT(node) (node.height * UI_SCALE_FAC) #define NODE_MARGIN_X (1.2f * U.widget_unit) #define NODE_SOCKSIZE (0.25f * U.widget_unit) #define NODE_SOCKSIZE_DRAW_MULIPLIER 2.25f @@ -247,13 +247,10 @@ void node_draw_link_bezier(const bContext &C, int th_col3, bool selected); -void node_link_bezier_points_evaluated(Span all_socket_locations, - const bNodeLink &link, +void node_link_bezier_points_evaluated(const bNodeLink &link, std::array &coords); -std::optional link_path_intersection(Span socket_locations, - const bNodeLink &link, - Span path); +std::optional link_path_intersection(const bNodeLink &link, Span path); void draw_nodespace_back_pix(const bContext &C, ARegion ®ion, @@ -325,12 +322,8 @@ int node_render_changed_exec(bContext *, wmOperator *); bNodeSocket *node_find_indicated_socket(SpaceNode &snode, const float2 &cursor, eNodeSocketInOut in_out); -float node_link_dim_factor(Span socket_locations, - const View2D &v2d, - const bNodeLink &link); -bool node_link_is_hidden_or_dimmed(Span socket_locations, - const View2D &v2d, - const bNodeLink &link); +float node_link_dim_factor(const View2D &v2d, const bNodeLink &link); +bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link); void NODE_OT_duplicate(wmOperatorType *ot); void NODE_OT_delete(wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index c41a62dfa39..48893551c46 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -122,10 +122,6 @@ static void pick_input_link_by_link_intersect(const bContext &C, { SpaceNode *snode = CTX_wm_space_node(&C); bNodeTree &node_tree = *snode->edittree; - const Span socket_locations = node_tree.runtime->all_socket_locations; - if (socket_locations.is_empty()) { - return; - } float2 drag_start; RNA_float_get_array(op.ptr, "drag_start", drag_start); @@ -133,14 +129,14 @@ static void pick_input_link_by_link_intersect(const bContext &C, bNode &node = socket->owner_node(); /* Distance to test overlapping of cursor on link. */ - const float cursor_link_touch_distance = 12.5f * UI_DPI_FAC; + const float cursor_link_touch_distance = 12.5f * UI_SCALE_FAC; bNodeLink *link_to_pick = nullptr; clear_picking_highlight(&node_tree.links); for (bNodeLink *link : socket->directly_linked_links()) { /* Test if the cursor is near a link. */ std::array coords; - node_link_bezier_points_evaluated(socket_locations, *link, coords); + node_link_bezier_points_evaluated(*link, coords); for (const int i : IndexRange(coords.size() - 1)) { const float distance = dist_squared_to_line_segment_v2(cursor, coords[i], coords[i + 1]); @@ -293,12 +289,11 @@ struct LinkAndPosition { float2 multi_socket_position; }; -static void sort_multi_input_socket_links_with_drag(const Span socket_locations, - bNodeSocket &socket, +static void sort_multi_input_socket_links_with_drag(bNodeSocket &socket, bNodeLink &drag_link, const float2 &cursor) { - const float2 &socket_location = socket_locations[socket.index_in_tree()]; + const float2 &socket_location = socket.runtime->location; Vector links; for (bNodeLink *link : socket.directly_linked_links()) { @@ -530,6 +525,7 @@ static void remove_links_to_unavailable_viewer_sockets(bNodeTree &btree, bNode & static bNodeSocket *determine_socket_to_view(bNode &node_to_view) { int last_linked_socket_index = -1; + bool has_linked_geometry_socket = false; for (bNodeSocket *socket : node_to_view.output_sockets()) { if (!socket_can_be_viewed(*socket)) { continue; @@ -542,10 +538,8 @@ static bNodeSocket *determine_socket_to_view(bNode &node_to_view) /* This socket is linked to a deactivated viewer, the viewer should be activated. */ return socket; } - if (socket->type == SOCK_GEOMETRY && (target_node.flag & NODE_DO_OUTPUT)) { - /* Skip geometry sockets connected to viewer nodes when deciding whether to cycle through - * outputs. */ - continue; + if (socket->type == SOCK_GEOMETRY) { + has_linked_geometry_socket = true; } last_linked_socket_index = socket->index(); } @@ -570,6 +564,11 @@ static bNodeSocket *determine_socket_to_view(bNode &node_to_view) if (!socket_can_be_viewed(output_socket)) { continue; } + if (has_linked_geometry_socket && output_socket.type == SOCK_GEOMETRY) { + /* Skip geometry sockets when cycling if one is already viewed. */ + continue; + } + bool is_currently_viewed = false; for (const bNodeLink *link : output_socket.directly_linked_links()) { bNodeSocket &target_socket = *link->tosock; @@ -646,10 +645,10 @@ static int view_socket(const bContext &C, } } if (viewer_node == nullptr) { - const float2 socket_location = - btree.runtime->all_socket_locations[bsocket_to_view.index_in_tree()]; + const float2 socket_location = bsocket_to_view.runtime->location; const int viewer_type = get_default_viewer_type(&C); - const float2 location{socket_location.x / UI_DPI_FAC + 100, socket_location.y / UI_DPI_FAC}; + const float2 location{socket_location.x / UI_SCALE_FAC + 100, + socket_location.y / UI_SCALE_FAC}; viewer_node = add_static_node(C, viewer_type, location); } @@ -823,17 +822,18 @@ static void draw_draglink_tooltip(const bContext * /*C*/, ARegion * /*region*/, uchar text_col[4]; UI_GetThemeColor4ubv(TH_TEXT, text_col); - const int padding = 4 * UI_DPI_FAC; + const int padding = 4 * UI_SCALE_FAC; const float x = nldrag->in_out == SOCK_IN ? nldrag->cursor[0] - 3.3f * padding : nldrag->cursor[0]; - const float y = nldrag->cursor[1] - 2.0f * UI_DPI_FAC; + const float y = nldrag->cursor[1] - 2.0f * UI_SCALE_FAC; const bool new_link = nldrag->in_out == nldrag->start_socket->in_out; const bool swap_links = nldrag->swap_links; const int icon = !swap_links ? ICON_ADD : (new_link ? ICON_ANIM : ICON_UV_SYNC_SELECT); - UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT); + UI_icon_draw_ex( + x, y, icon, UI_INV_SCALE_FAC, 1.0f, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT); } static void draw_draglink_tooltip_activate(const ARegion ®ion, bNodeLinkDrag &nldrag) @@ -900,7 +900,11 @@ static void displace_links(bNodeTree *ntree, const bNode *node, bNodeLink *inser if (linked_socket->is_input()) { BLI_assert(!linked_socket->is_multi_input()); ntree->ensure_topology_cache(); - bNodeLink *displaced_link = linked_socket->runtime->directly_linked_links.first(); + + if (linked_socket->directly_linked_links().is_empty()) { + return; + } + bNodeLink *displaced_link = linked_socket->directly_linked_links().first(); if (!replacement_socket) { nodeRemLink(ntree, displaced_link); @@ -958,18 +962,31 @@ static void node_swap_links(bNodeLinkDrag &nldrag, bNodeTree &ntree) if (linked_socket.is_input()) { LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { - if (link->tosock == &linked_socket) { - link->tosock = start_socket; - link->tonode = start_node; + if (link->tosock != &linked_socket) { + continue; } + if (link->fromnode == start_node) { + /* Don't link a node to itself. */ + nodeRemLink(&ntree, link); + continue; + } + + link->tosock = start_socket; + link->tonode = start_node; } } else { LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { - if (link->fromsock == &linked_socket) { - link->fromsock = start_socket; - link->fromnode = start_node; + if (link->fromsock != &linked_socket) { + continue; } + if (link->tonode == start_node) { + /* Don't link a node to itself. */ + nodeRemLink(&ntree, link); + continue; + } + link->fromsock = start_socket; + link->fromnode = start_node; } } @@ -1097,12 +1114,7 @@ static void node_link_cancel(bContext *C, wmOperator *op) static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cursor) { SpaceNode &snode = *CTX_wm_space_node(&C); - bNodeTree &node_tree = *snode.edittree; bNodeLinkDrag &nldrag = *static_cast(op.customdata); - const Span socket_locations = node_tree.runtime->all_socket_locations; - if (socket_locations.is_empty()) { - return; - } if (nldrag.in_out == SOCK_OUT) { if (bNodeSocket *tsock = node_find_indicated_socket(snode, cursor, SOCK_IN)) { @@ -1133,7 +1145,7 @@ static void node_link_find_socket(bContext &C, wmOperator &op, const float2 &cur continue; } if (tsock && tsock->is_multi_input()) { - sort_multi_input_socket_links_with_drag(socket_locations, *tsock, link, cursor); + sort_multi_input_socket_links_with_drag(*tsock, link, cursor); } } } @@ -1506,15 +1518,14 @@ static int cut_links_exec(bContext *C, wmOperator *op) bNodeTree &node_tree = *snode.edittree; node_tree.ensure_topology_cache(); - const Span socket_locations = node_tree.runtime->all_socket_locations; Set links_to_remove; LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { - if (node_link_is_hidden_or_dimmed(socket_locations, region.v2d, *link)) { + if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { continue; } - if (link_path_intersection(socket_locations, *link, path)) { + if (link_path_intersection(*link, path)) { if (!found) { /* TODO(sergey): Why did we kill jobs twice? */ @@ -1592,7 +1603,6 @@ static int mute_links_exec(bContext *C, wmOperator *op) SpaceNode &snode = *CTX_wm_space_node(C); const ARegion ®ion = *CTX_wm_region(C); bNodeTree &ntree = *snode.edittree; - const Span socket_locations = ntree.runtime->all_socket_locations; Vector path; RNA_BEGIN (op->ptr, itemptr, "path") { @@ -1617,10 +1627,10 @@ static int mute_links_exec(bContext *C, wmOperator *op) Set affected_links; LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) { - if (node_link_is_hidden_or_dimmed(socket_locations, region.v2d, *link)) { + if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { continue; } - if (!link_path_intersection(socket_locations, *link, path)) { + if (!link_path_intersection(*link, path)) { continue; } affected_links.add(link); @@ -2069,10 +2079,6 @@ void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion ®ion) { bNodeTree &node_tree = *snode.edittree; node_tree.ensure_topology_cache(); - const Span socket_locations = node_tree.runtime->all_socket_locations; - if (socket_locations.is_empty()) { - return; - } node_insert_on_link_flags_clear(node_tree); @@ -2085,12 +2091,12 @@ void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion ®ion) bNodeLink *selink = nullptr; float dist_best = FLT_MAX; LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) { - if (node_link_is_hidden_or_dimmed(socket_locations, region.v2d, *link)) { + if (node_link_is_hidden_or_dimmed(region.v2d, *link)) { continue; } std::array coords; - node_link_bezier_points_evaluated(socket_locations, *link, coords); + node_link_bezier_points_evaluated(*link, coords); float dist = FLT_MAX; /* Loop over link coords to find shortest dist to upper left node edge of a intersected line @@ -2308,7 +2314,7 @@ static void node_offset_apply(bNode &node, const float offset_x) /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */ if ((node.flag & NODE_TEST) == 0) { node.runtime->anim_init_locx = node.locx; - node.runtime->anim_ofsx = (offset_x / UI_DPI_FAC); + node.runtime->anim_ofsx = (offset_x / UI_SCALE_FAC); node.flag |= NODE_TEST; } } @@ -2412,7 +2418,7 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd, bNode *prev = iofsd->prev, *next = iofsd->next; bNode *init_parent = insert.parent; /* store old insert.parent for restoring later */ - const float min_margin = U.node_margin * UI_DPI_FAC; + const float min_margin = U.node_margin * UI_SCALE_FAC; const float width = NODE_WIDTH(insert); const bool needs_alignment = (next->runtime->totr.xmin - prev->runtime->totr.xmax) < (width + (min_margin * 2.0f)); diff --git a/source/blender/editors/space_node/node_view.cc b/source/blender/editors/space_node/node_view.cc index b11997ba1b6..eafc963e433 100644 --- a/source/blender/editors/space_node/node_view.cc +++ b/source/blender/editors/space_node/node_view.cc @@ -370,7 +370,7 @@ static int backimage_fit_exec(bContext *C, wmOperator * /*op*/) BKE_image_release_ibuf(ima, ibuf, lock); - snode->zoom *= min_ff(facx, facy) * U.dpi_fac; + snode->zoom *= min_ff(facx, facy) * UI_SCALE_FAC; snode->xof = 0; snode->yof = 0; diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index a922d31829d..cc71df93963 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -616,8 +616,8 @@ static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region) node_set_cursor(*win, *snode, snode->runtime->cursor); /* XXX snode->runtime->cursor is in placing new nodes space */ - snode->runtime->cursor[0] /= UI_DPI_FAC; - snode->runtime->cursor[1] /= UI_DPI_FAC; + snode->runtime->cursor[0] /= UI_SCALE_FAC; + snode->runtime->cursor[1] /= UI_SCALE_FAC; } /* Initialize main region, setting handlers. */ diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index 20cca386fcc..b91e5adbb30 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -1803,7 +1803,7 @@ static void outliner_draw_overrides_rna_buts(uiBlock *block, const ListBase *lb, const int x) { - const float pad_x = 2.0f * UI_DPI_FAC; + const float pad_x = 2.0f * UI_SCALE_FAC; const float pad_y = 0.5f * U.pixelsize; const float item_max_width = round_fl_to_int(OL_RNA_COL_SIZEX - 2 * pad_x); const float item_height = round_fl_to_int(UI_UNIT_Y - 2.0f * pad_y); @@ -2903,7 +2903,7 @@ static bool tselem_draw_icon(uiBlock *block, UI_icon_draw_ex(x, y, data.icon, - U.inv_dpi_fac, + UI_INV_SCALE_FAC, alpha, 0.0f, btheme->collection_color[collection->color_tag].color, @@ -2919,10 +2919,11 @@ static bool tselem_draw_icon(uiBlock *block, /* Restrict column clip. it has been coded by simply overdrawing, doesn't work for buttons. */ uchar color[4]; if (UI_icon_get_theme_color(data.icon, color)) { - UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true, &text_overlay); + UI_icon_draw_ex(x, y, data.icon, UI_INV_SCALE_FAC, alpha, 0.0f, color, true, &text_overlay); } else { - UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false, &text_overlay); + UI_icon_draw_ex( + x, y, data.icon, UI_INV_SCALE_FAC, alpha, 0.0f, nullptr, false, &text_overlay); } } else { @@ -3529,7 +3530,7 @@ static void outliner_draw_hierarchy_lines(SpaceOutliner *space_outliner, float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* "simple" mode */ immUniform1f("dash_width", 8.0f); UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col); @@ -3813,7 +3814,8 @@ static int outliner_width(SpaceOutliner *space_outliner, float right_column_width) { if (space_outliner->outlinevis == SO_DATA_API) { - return outliner_data_api_buttons_start_x(max_tree_width) + OL_RNA_COL_SIZEX + 10 * UI_DPI_FAC; + return outliner_data_api_buttons_start_x(max_tree_width) + OL_RNA_COL_SIZEX + + 10 * UI_SCALE_FAC; } return max_tree_width + right_column_width; } diff --git a/source/blender/editors/space_outliner/space_outliner.cc b/source/blender/editors/space_outliner/space_outliner.cc index ba9aa719b93..2308db83177 100644 --- a/source/blender/editors/space_outliner/space_outliner.cc +++ b/source/blender/editors/space_outliner/space_outliner.cc @@ -195,6 +195,11 @@ static void outliner_main_region_listener(const wmRegionListenerParams *params) ED_region_tag_redraw(region); } break; + case NC_ASSET: + if (ELEM(wmn->action, NA_ADDED, NA_REMOVED)) { + ED_region_tag_redraw_no_rebuild(region); + } + break; case NC_MATERIAL: switch (wmn->data) { case ND_SHADING_LINKS: diff --git a/source/blender/editors/space_sequencer/sequencer_drag_drop.c b/source/blender/editors/space_sequencer/sequencer_drag_drop.c index 49c2f48666b..797145fb57d 100644 --- a/source/blender/editors/space_sequencer/sequencer_drag_drop.c +++ b/source/blender/editors/space_sequencer/sequencer_drag_drop.c @@ -429,7 +429,7 @@ static void draw_seq_in_view(bContext *C, wmWindow *UNUSED(win), wmDrag *drag, c float handle_size = 8.0f; /* SEQ_HANDLE_SIZE */ /* Calculate height needed for drawing text on strip. */ - float text_margin_y = y2 - min_ff(0.40f, 20 * U.dpi_fac * pixely); + float text_margin_y = y2 - min_ff(0.40f, 20 * UI_SCALE_FAC * pixely); float text_margin_x = 2.0f * (pixelx * handle_size) * U.pixelsize; rctf rect; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 5276914346d..debdb677d63 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1330,10 +1330,10 @@ static void draw_seq_strip(const bContext *C, (sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_DURATION)) { /* Calculate height needed for drawing text on strip. */ - text_margin_y = y2 - min_ff(0.40f, 20 * U.dpi_fac * pixely); + text_margin_y = y2 - min_ff(0.40f, 20 * UI_SCALE_FAC * pixely); /* Is there enough space for drawing something else than text? */ - y_threshold = ((y2 - y1) / pixely) > 20 * U.dpi_fac; + y_threshold = ((y2 - y1) / pixely) > 20 * UI_SCALE_FAC; } else { text_margin_y = y2; @@ -1423,7 +1423,7 @@ static void draw_seq_strip(const bContext *C, if (sseq->flag & SEQ_SHOW_OVERLAY) { /* Don't draw strip if there is not enough vertical or horizontal space. */ - if (((x2 - x1) > 32 * pixelx * U.dpi_fac) && ((y2 - y1) > 8 * pixely * U.dpi_fac)) { + if (((x2 - x1) > 32 * pixelx * UI_SCALE_FAC) && ((y2 - y1) > 8 * pixely * UI_SCALE_FAC)) { /* Depending on the vertical space, draw text on top or in the center of strip. */ draw_seq_text_overlay( scene, v2d, seq, sseq, x1, x2, y_threshold ? text_margin_y : y1, y2, seq_active); @@ -1650,7 +1650,7 @@ static void sequencer_draw_borders_overlay(const SpaceSeq *sseq, float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniformThemeColor(TH_BACK); immUniform1i("colors_len", 0); /* Simple dashes. */ @@ -2470,7 +2470,7 @@ static bool draw_cache_view_iter_fn(void *userdata, if ((cache_type & SEQ_CACHE_STORE_FINAL_OUT) && (drawdata->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT)) { - stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) - v2d->cur.ymin; + stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_SCALE_FAC * U.pixelsize) - v2d->cur.ymin; stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HANDLE_HEIGHT); stripe_top = stripe_bot + stripe_ht; vbo = drawdata->final_out_vbo; @@ -2551,7 +2551,7 @@ static void draw_cache_view(const bContext *C) float stripe_bot, stripe_top; float stripe_ofs_y = UI_view2d_region_to_view_y(v2d, 1.0f) - v2d->cur.ymin; - float stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) - + float stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_SCALE_FAC * U.pixelsize) - v2d->cur.ymin; CLAMP_MAX(stripe_ht, 0.2f); diff --git a/source/blender/editors/space_sequencer/sequencer_gizmo_retime_type.cc b/source/blender/editors/space_sequencer/sequencer_gizmo_retime_type.cc index 1b61c7d7987..ba122b32b54 100644 --- a/source/blender/editors/space_sequencer/sequencer_gizmo_retime_type.cc +++ b/source/blender/editors/space_sequencer/sequencer_gizmo_retime_type.cc @@ -54,15 +54,17 @@ using blender::MutableSpan; -/** Pixels from bottom of strip. */ -#define REMOVE_GIZMO_HEIGHT (14.0f * U.dpi_fac) /** Size in pixels. */ -#define RETIME_HANDLE_TRIANGLE_SIZE (14.0f * U.dpi_fac) -/** Size in pixels. */ -#define RETIME_HANDLE_MOUSEOVER_THRESHOLD (16.0f * U.dpi_fac) +#define RETIME_HANDLE_MOUSEOVER_THRESHOLD (16.0f * UI_SCALE_FAC) /** Factor based on icon size. */ #define RETIME_BUTTON_SIZE 0.6f +static float remove_gizmo_height_get(const View2D *v2d) +{ + const float max_size = (SEQ_STRIP_OFSTOP - SEQ_STRIP_OFSBOTTOM) * UI_view2d_scale_get_y(v2d); + return min_ff(14.0f * UI_SCALE_FAC, max_size * 0.4f); +} + static float strip_y_rescale(const Sequence *seq, const float y_value) { const float y_range = SEQ_STRIP_OFSTOP - SEQ_STRIP_OFSBOTTOM; @@ -147,8 +149,9 @@ static rctf strip_box_get(const bContext *C, const Sequence *seq) static rctf remove_box_get(const bContext *C, const Sequence *seq) { + const View2D *v2d = UI_view2d_fromcontext(C); rctf rect = strip_box_get(C, seq); - rect.ymax = rect.ymin + REMOVE_GIZMO_HEIGHT; + rect.ymax = rect.ymin + remove_gizmo_height_get(v2d); return rect; } @@ -182,8 +185,8 @@ static ButtonDimensions button_dimensions_get(const bContext *C, const RetimeBut const View2D *v2d = UI_view2d_fromcontext(C); const Sequence *seq = active_seq_from_context(C); - const float icon_height = UI_icon_get_height(gizmo->icon_id) * U.dpi_fac; - const float icon_width = UI_icon_get_width(gizmo->icon_id) * U.dpi_fac; + const float icon_height = UI_icon_get_height(gizmo->icon_id) * UI_SCALE_FAC; + const float icon_width = UI_icon_get_width(gizmo->icon_id) * UI_SCALE_FAC; const float icon_x = UI_view2d_view_to_region_x(v2d, BKE_scene_frame_get(scene)) + icon_width / 2; const float icon_y = UI_view2d_view_to_region_y(v2d, strip_y_rescale(seq, 0.5)) - @@ -336,7 +339,7 @@ static void retime_handle_draw(const bContext *C, return; /* Handle out of strip bounds. */ } - const int ui_triangle_size = RETIME_HANDLE_TRIANGLE_SIZE; + const int ui_triangle_size = remove_gizmo_height_get(v2d); const float bottom = UI_view2d_view_to_region_y(v2d, strip_y_rescale(seq, 0.0f)) + 2; const float top = UI_view2d_view_to_region_y(v2d, strip_y_rescale(seq, 1.0f)) - 2; const float handle_position = UI_view2d_view_to_region_x(v2d, handle_x); @@ -457,8 +460,9 @@ static int gizmo_retime_handle_test_select(bContext *C, wmGizmo *gz, const int m return -1; } + const View2D *v2d = UI_view2d_fromcontext(C); rctf strip_box = strip_box_get(C, seq); - BLI_rctf_resize_x(&strip_box, BLI_rctf_size_x(&strip_box) + 2 * RETIME_HANDLE_TRIANGLE_SIZE); + BLI_rctf_resize_x(&strip_box, BLI_rctf_size_x(&strip_box) + 2 * remove_gizmo_height_get(v2d)); if (!mouse_is_inside_box(&strip_box, mval)) { return -1; } @@ -537,9 +541,9 @@ static int gizmo_retime_remove_test_select(bContext *C, wmGizmo *gz, const int m return -1; /* Last handle can not be removed. */ } + const View2D *v2d = UI_view2d_fromcontext(C); rctf box = remove_box_get(C, seq); - - BLI_rctf_resize_x(&box, BLI_rctf_size_x(&box) + 2 * RETIME_HANDLE_TRIANGLE_SIZE); + BLI_rctf_resize_x(&box, BLI_rctf_size_x(&box) + 2 * remove_gizmo_height_get(v2d)); if (!mouse_is_inside_box(&box, mval)) { return -1; } diff --git a/source/blender/editors/space_sequencer/sequencer_retiming.cc b/source/blender/editors/space_sequencer/sequencer_retiming.cc index 51f0e87b7f3..89fbba42ea1 100644 --- a/source/blender/editors/space_sequencer/sequencer_retiming.cc +++ b/source/blender/editors/space_sequencer/sequencer_retiming.cc @@ -229,15 +229,16 @@ void SEQUENCER_OT_retiming_handle_move(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, - "handle_index", - 0, - 0, - INT_MAX, - "Handle Index", - "Index of handle to be moved", - 0, - INT_MAX); + PropertyRNA *prop = RNA_def_int(ot->srna, + "handle_index", + 0, + 0, + INT_MAX, + "Handle Index", + "Index of handle to be moved", + 0, + INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); } /** \} */ @@ -367,15 +368,16 @@ void SEQUENCER_OT_retiming_handle_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_int(ot->srna, - "handle_index", - 0, - 0, - INT_MAX, - "Handle Index", - "Index of handle to be removed", - 0, - INT_MAX); + PropertyRNA *prop = RNA_def_int(ot->srna, + "handle_index", + 0, + 0, + INT_MAX, + "Handle Index", + "Index of handle to be removed", + 0, + INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); } /** \} */ diff --git a/source/blender/editors/space_sequencer/sequencer_thumbnails.c b/source/blender/editors/space_sequencer/sequencer_thumbnails.c index d1606b14152..13e8f109598 100644 --- a/source/blender/editors/space_sequencer/sequencer_thumbnails.c +++ b/source/blender/editors/space_sequencer/sequencer_thumbnails.c @@ -439,7 +439,7 @@ void draw_seq_strip_thumbnail(View2D *v2d, } /* If width of the strip too small ignore drawing thumbnails. */ - if ((y2 - y1) / pixely <= 20 * U.dpi_fac) { + if ((y2 - y1) / pixely <= 20 * UI_SCALE_FAC) { return; } diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 5661208dc15..b345cac7836 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -292,7 +292,7 @@ static void sequencer_refresh(const bContext *C, ScrArea *area) case SEQ_VIEW_SEQUENCE_PREVIEW: if (region_main && region_preview) { /* Get available height (without DPI correction). */ - const float height = (area->winy - ED_area_headersize()) / UI_DPI_FAC; + const float height = (area->winy - ED_area_headersize()) / UI_SCALE_FAC; /* We reuse hidden region's size, allows to find same layout as before if we just switch * between one 'full window' view and the combined one. This gets lost if we switch to both diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index b35facd020b..30d15d46106 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -356,7 +356,7 @@ static float get_column_width(const ColumnValues &values) { float data_width = get_default_column_width(values); const int fontid = UI_style_get()->widget.uifont_id; - BLF_size(fontid, UI_DEFAULT_TEXT_POINTS * U.dpi_fac); + BLF_size(fontid, UI_DEFAULT_TEXT_POINTS * UI_SCALE_FAC); const StringRefNull name = values.name(); const float name_width = BLF_width(fontid, name.data(), name.size()); return std::max(name_width / UI_UNIT_X + 1.0f, data_width); @@ -370,7 +370,7 @@ static float get_column_width_in_pixels(const ColumnValues &values) static int get_index_column_width(const int tot_rows) { const int fontid = UI_style_get()->widget.uifont_id; - BLF_size(fontid, UI_style_get_dpi()->widget.points * U.dpi_fac); + BLF_size(fontid, UI_style_get_dpi()->widget.points * UI_SCALE_FAC); return std::to_string(std::max(0, tot_rows - 1)).size() * BLF_width(fontid, "0", 1) + UI_UNIT_X * 0.75; } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index e0c2a6852af..0673a5acced 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -165,16 +165,11 @@ static std::unique_ptr build_mesh_debug_columns(const Mesh &mesh, return {}; } case ATTR_DOMAIN_CORNER: { - const Span loops = mesh.loops(); if (name == "Vertex") { - return std::make_unique( - name, - VArray::ForFunc(loops.size(), [loops](int64_t index) { return loops[index].v; })); + return std::make_unique(name, VArray::ForSpan(mesh.corner_verts())); } if (name == "Edge") { - return std::make_unique( - name, - VArray::ForFunc(loops.size(), [loops](int64_t index) { return loops[index].e; })); + return std::make_unique(name, VArray::ForSpan(mesh.corner_edges())); } return {}; } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc index 301f73d6be2..ba0b118302f 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_dataset_draw.cc @@ -219,8 +219,7 @@ void spreadsheet_data_set_panel_draw(const bContext *C, Panel *panel) std::make_unique( spreadsheet_get_display_geometry_set(sspreadsheet, object), *C)); - ui::TreeViewBuilder builder(*block); - builder.build_tree_view(*tree_view); + ui::TreeViewBuilder::build_tree_view(*tree_view, *layout); } } // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_draw.cc b/source/blender/editors/space_spreadsheet/spreadsheet_draw.cc index e50e655853f..c199e20f9ca 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_draw.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_draw.cc @@ -13,7 +13,7 @@ #include "spreadsheet_draw.hh" -#define CELL_RIGHT_PADDING (2.0f * UI_DPI_FAC) +#define CELL_RIGHT_PADDING (2.0f * UI_SCALE_FAC) namespace blender::ed::spreadsheet { diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index aa5689bd047..d527688c3b1 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -13,9 +13,9 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BLO_readfile.h" #include "BLT_translation.h" +#include "BKE_blendfile.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_screen.h" @@ -202,7 +202,7 @@ static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu) if (!BLI_listbase_is_empty(&G.recent_files)) { for (recent = G.recent_files.first; (recent); recent = recent->next) { const char *file = BLI_path_basename(recent->filepath); - const int icon = BLO_has_bfile_extension(file) ? ICON_FILE_BLEND : ICON_FILE_BACKUP; + const int icon = BKE_blendfile_extension_check(file) ? ICON_FILE_BLEND : ICON_FILE_BACKUP; PointerRNA ptr; uiItemFullO(layout, "WM_OT_open_mainfile", file, icon, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr); RNA_string_set(&ptr, "filepath", recent->filepath); diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index 1516435c6fc..45107547b8f 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -55,7 +55,7 @@ static SpaceLink *userpref_create(const ScrArea *area, const Scene *UNUSED(scene region->alignment = RGN_ALIGN_LEFT; /* Use smaller size when opened in area like properties editor. */ - if (area->winx && area->winx < 3.0f * UI_NAVIGATION_REGION_WIDTH * UI_DPI_FAC) { + if (area->winx && area->winx < 3.0f * UI_NAVIGATION_REGION_WIDTH * UI_SCALE_FAC) { region->sizex = UI_NARROW_NAVIGATION_REGION_WIDTH; } diff --git a/source/blender/editors/space_view3d/drawobject.cc b/source/blender/editors/space_view3d/drawobject.cc index 835b2d6d0d0..2754ffa7651 100644 --- a/source/blender/editors/space_view3d/drawobject.cc +++ b/source/blender/editors/space_view3d/drawobject.cc @@ -71,13 +71,13 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, const float(*positions)[3] = BKE_mesh_vert_positions(me); const blender::Span polys = me->polys(); - const blender::Span loops = me->loops(); + const blender::Span corner_verts = me->corner_verts(); const blender::Span looptris = me->looptris(); facemap_data = static_cast(CustomData_get_layer(&me->pdata, CD_FACEMAP)); /* Make a batch and free it each time for now. */ - const int looptris_len = poly_to_tri_count(polys.size(), loops.size()); + const int looptris_len = poly_to_tri_count(polys.size(), corner_verts.size()); const int vbo_len_capacity = looptris_len * 3; int vbo_len_used = 0; @@ -97,11 +97,11 @@ void ED_draw_object_facemap(Depsgraph *depsgraph, if (facemap_data[i] == facemap) { for (int j = 2; j < poly.totloop; j++) { copy_v3_v3(static_cast(GPU_vertbuf_raw_step(&pos_step)), - positions[loops[looptris[tri_index].tri[0]].v]); + positions[corner_verts[looptris[tri_index].tri[0]]]); copy_v3_v3(static_cast(GPU_vertbuf_raw_step(&pos_step)), - positions[loops[looptris[tri_index].tri[1]].v]); + positions[corner_verts[looptris[tri_index].tri[1]]]); copy_v3_v3(static_cast(GPU_vertbuf_raw_step(&pos_step)), - positions[loops[looptris[tri_index].tri[2]].v]); + positions[corner_verts[looptris[tri_index].tri[2]]]); vbo_len_used += 3; tri_index++; } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 380a0c47b3e..492282f1433 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -511,7 +511,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float int yi = 200; const float tilt_limit = DEG2RADF(21600.0f); const int butw = 200; - const int buth = 20 * UI_DPI_FAC; + const int buth = 20 * UI_SCALE_FAC; const int but_margin = 2; const char *c; @@ -1210,7 +1210,7 @@ static void v3d_object_dimension_buts(bContext *C, uiLayout *layout, View3D *v3d BLI_assert(C == NULL); int yi = 200; const int butw = 200; - const int buth = 20 * UI_DPI_FAC; + const int buth = 20 * UI_SCALE_FAC; BKE_object_dimensions_get(ob, tfp->ob_dims); copy_v3_v3(tfp->ob_dims_orig, tfp->ob_dims); diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.c b/source/blender/editors/space_view3d/view3d_cursor_snap.c index 875097b4827..bf32a509dd9 100644 --- a/source/blender/editors/space_view3d/view3d_cursor_snap.c +++ b/source/blender/editors/space_view3d/view3d_cursor_snap.c @@ -320,7 +320,7 @@ static void v3d_cursor_plane_draw(const RegionView3D *rv3d, color_alpha *= max_ff(0.3f, 1.0f - square_f(square_f(1.0f - view_dot))); } - const float scale_mod = U.gizmo_size * 2 * U.dpi_fac / U.pixelsize; + const float scale_mod = U.gizmo_size * 2 * UI_SCALE_FAC / U.pixelsize; float final_scale = (scale_mod * pixel_size); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c index 35ae745bab3..f58f39d87a2 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c @@ -250,8 +250,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g const bool show_navigate = (U.uiflag & USER_SHOW_GIZMO_NAVIGATE) != 0; const bool show_rotate_gizmo = (U.mini_axis_type == USER_MINI_AXIS_TYPE_GIZMO); - const float icon_offset = ((GIZMO_SIZE / 2.0f) + GIZMO_OFFSET) * UI_DPI_FAC; - const float icon_offset_mini = (GIZMO_MINI_SIZE + GIZMO_MINI_OFFSET) * UI_DPI_FAC; + const float icon_offset = ((GIZMO_SIZE / 2.0f) + GIZMO_OFFSET) * UI_SCALE_FAC; + const float icon_offset_mini = (GIZMO_MINI_SIZE + GIZMO_MINI_OFFSET) * UI_SCALE_FAC; const float co_rotate[2] = { rect_visible->xmax - icon_offset, rect_visible->ymax - icon_offset, diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c index 70afb0eaff1..7b811594cb5 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c @@ -42,7 +42,7 @@ #include "view3d_intern.h" /* Radius of the entire background. */ -#define WIDGET_RADIUS ((U.gizmo_size_navigate_v3d / 2.0f) * UI_DPI_FAC) +#define WIDGET_RADIUS ((U.gizmo_size_navigate_v3d / 2.0f) * UI_SCALE_FAC) /* Sizes of axis spheres containing XYZ characters in relation to above. */ #define AXIS_HANDLE_SIZE 0.20f diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index 765a3d01405..fd940470cc1 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -621,9 +621,9 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz) RulerItem *ruler_item = (RulerItem *)gz; ARegion *region = ruler_info->region; RegionView3D *rv3d = region->regiondata; - const float cap_size = 4.0f * U.dpi_fac; - const float bg_margin = 4.0f * U.dpi_fac; - const float arc_size = 64.0f * U.dpi_fac; + const float cap_size = 4.0f * UI_SCALE_FAC; + const float bg_margin = 4.0f * UI_SCALE_FAC; + const float arc_size = 64.0f * UI_SCALE_FAC; #define ARC_STEPS 24 const int arc_steps = ARC_STEPS; const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f}; @@ -643,7 +643,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz) GPU_line_width(1.0f); BLF_enable(blf_mono_font, BLF_ROTATION); - BLF_size(blf_mono_font, 14.0f * U.dpi_fac); + BLF_size(blf_mono_font, 14.0f * UI_SCALE_FAC); BLF_rotation(blf_mono_font, 0.0f); UI_GetThemeColor3ubv(TH_TEXT, color_text); diff --git a/source/blender/editors/space_view3d/view3d_navigate.c b/source/blender/editors/space_view3d/view3d_navigate.c index 116293cdfd7..e46778adb05 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.c +++ b/source/blender/editors/space_view3d/view3d_navigate.c @@ -274,16 +274,29 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp /* we need the depth info before changing any viewport options */ if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) { - float fallback_depth_pt[3]; + wmWindow *win = CTX_wm_window(C); + const bool use_depth_last = ED_view3d_autodist_last_check(win, event); - view3d_operator_needs_opengl(C); /* Needed for Z-buffer drawing. */ + if (use_depth_last) { + vod->use_dyn_ofs = ED_view3d_autodist_last_get(win, vod->dyn_ofs); + } + else { + float fallback_depth_pt[3]; - negate_v3_v3(fallback_depth_pt, rv3d->ofs); + view3d_operator_needs_opengl(C); /* Needed for Z-buffer drawing. */ - vod->use_dyn_ofs = ED_view3d_autodist( - depsgraph, vod->region, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt); + negate_v3_v3(fallback_depth_pt, rv3d->ofs); + + vod->use_dyn_ofs = ED_view3d_autodist( + depsgraph, vod->region, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt); + + ED_view3d_autodist_last_set(win, event, vod->dyn_ofs, vod->use_dyn_ofs); + } } else { + wmWindow *win = CTX_wm_window(C); + ED_view3d_autodist_last_clear(win); + vod->use_dyn_ofs = false; } vod->init.persp = rv3d->persp; diff --git a/source/blender/editors/space_view3d/view3d_navigate_rotate.c b/source/blender/editors/space_view3d/view3d_navigate_rotate.c index 446a1e929c1..b1971dda4e8 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_rotate.c +++ b/source/blender/editors/space_view3d/view3d_navigate_rotate.c @@ -234,7 +234,7 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2]) float xaxis[3]; /* Radians per-pixel. */ - const float sensitivity = U.view_rotate_sensitivity_turntable / U.dpi_fac; + const float sensitivity = U.view_rotate_sensitivity_turntable / UI_SCALE_FAC; /* Get the 3x3 matrix and its inverse from the quaternion */ quat_to_mat3(m, vod->curr.viewquat); diff --git a/source/blender/editors/space_view3d/view3d_navigate_zoom.c b/source/blender/editors/space_view3d/view3d_navigate_zoom.c index 51aab367959..f766e4a454f 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_zoom.c +++ b/source/blender/editors/space_view3d/view3d_navigate_zoom.c @@ -199,7 +199,7 @@ static float viewzoom_scale_value(const rcti *winrct, fac = (float)(xy_init[1] - xy_curr[1]); } - fac /= U.dpi_fac; + fac /= UI_SCALE_FAC; if (zoom_invert != zoom_invert_force) { fac = -fac; @@ -215,8 +215,8 @@ static float viewzoom_scale_value(const rcti *winrct, BLI_rcti_cent_x(winrct), BLI_rcti_cent_y(winrct), }; - float len_new = (5 * U.dpi_fac) + ((float)len_v2v2_int(ctr, xy_curr) / U.dpi_fac); - float len_old = (5 * U.dpi_fac) + ((float)len_v2v2_int(ctr, xy_init) / U.dpi_fac); + float len_new = (5 * UI_SCALE_FAC) + ((float)len_v2v2_int(ctr, xy_curr) / UI_SCALE_FAC); + float len_old = (5 * UI_SCALE_FAC) + ((float)len_v2v2_int(ctr, xy_init) / UI_SCALE_FAC); /* intentionally ignore 'zoom_invert' for scale */ if (zoom_invert_force) { @@ -226,16 +226,16 @@ static float viewzoom_scale_value(const rcti *winrct, zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val; } else { /* USER_ZOOM_DOLLY */ - float len_new = 5 * U.dpi_fac; - float len_old = 5 * U.dpi_fac; + float len_new = 5 * UI_SCALE_FAC; + float len_old = 5 * UI_SCALE_FAC; if (U.uiflag & USER_ZOOM_HORIZ) { - len_new += (winrct->xmax - (xy_curr[0])) / U.dpi_fac; - len_old += (winrct->xmax - (xy_init[0])) / U.dpi_fac; + len_new += (winrct->xmax - (xy_curr[0])) / UI_SCALE_FAC; + len_old += (winrct->xmax - (xy_init[0])) / UI_SCALE_FAC; } else { - len_new += (winrct->ymax - (xy_curr[1])) / U.dpi_fac; - len_old += (winrct->ymax - (xy_init[1])) / U.dpi_fac; + len_new += (winrct->ymax - (xy_curr[1])) / UI_SCALE_FAC; + len_old += (winrct->ymax - (xy_init[1])) / UI_SCALE_FAC; } if (zoom_invert != zoom_invert_force) { diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 0044a325ed8..1a17d44255a 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -2316,7 +2316,7 @@ static Base *mouse_select_object_center(ViewContext *vc, Base *startbase, const Base *basact = nullptr; /* Put the active object at a disadvantage to cycle through other objects. */ - const float penalty_dist = 10.0f * UI_DPI_FAC; + const float penalty_dist = 10.0f * UI_SCALE_FAC; Base *base = startbase; while (base) { if (BASE_SELECTABLE(v3d, base)) { diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index d87a2730c7b..385ab423155 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -1005,6 +1005,77 @@ void ED_view3d_quadview_update(ScrArea *area, ARegion *region, bool do_clip) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name View Auto-Depth Last State Access + * + * Calling consecutive track-pad gestures reuses the previous offset to prevent + * each track-pad event using a different offset, see: #103263. + * \{ */ + +static const char *view3d_autodepth_last_id = "view3d_autodist_last"; + +/** + * Auto-depth values for #ED_view3d_autodist_last_check and related functions. + */ +typedef struct View3D_AutoDistLast { + float ofs[3]; + bool has_depth; +} View3D_AutoDistLast; + +bool ED_view3d_autodist_last_check(wmWindow *win, const wmEvent *event) +{ + if (event->flag & WM_EVENT_IS_CONSECUTIVE) { + const View3D_AutoDistLast *autodepth_last = WM_event_consecutive_data_get( + win, view3d_autodepth_last_id); + if (autodepth_last) { + return true; + } + } + return false; +} + +void ED_view3d_autodist_last_clear(wmWindow *win) +{ + WM_event_consecutive_data_free(win); +} + +void ED_view3d_autodist_last_set(wmWindow *win, + const wmEvent *event, + const float ofs[3], + const bool has_depth) +{ + ED_view3d_autodist_last_clear(win); + + if (WM_event_consecutive_gesture_test(event)) { + View3D_AutoDistLast *autodepth_last = MEM_callocN(sizeof(*autodepth_last), __func__); + + autodepth_last->has_depth = has_depth; + copy_v3_v3(autodepth_last->ofs, ofs); + + WM_event_consecutive_data_set(win, view3d_autodepth_last_id, autodepth_last); + } +} + +bool ED_view3d_autodist_last_get(wmWindow *win, float r_ofs[3]) +{ + const View3D_AutoDistLast *autodepth_last = WM_event_consecutive_data_get( + win, view3d_autodepth_last_id); + /* #ED_view3d_autodist_last_check should be called first. */ + BLI_assert(autodepth_last); + if (autodepth_last == NULL) { + return false; + } + + if (autodepth_last->has_depth == false) { + zero_v3(r_ofs); + return false; + } + copy_v3_v3(r_ofs, autodepth_last->ofs); + return true; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name View Auto-Depth Utilities * \{ */ diff --git a/source/blender/editors/transform/transform_convert_node.cc b/source/blender/editors/transform/transform_convert_node.cc index 13095ff6f5a..8e14b900394 100644 --- a/source/blender/editors/transform/transform_convert_node.cc +++ b/source/blender/editors/transform/transform_convert_node.cc @@ -48,11 +48,11 @@ static void create_transform_data_for_node(TransData &td, /* account for parents (nested nodes) */ if (node.parent) { - nodeToView(node.parent, node.locx, node.locy, &locx, &locy); + nodeToView(node.parent, node.locx + node.offsetx, node.locy + node.offsety, &locx, &locy); } else { - locx = node.locx; - locy = node.locy; + locx = node.locx + node.offsetx; + locy = node.locy + node.offsety; } /* use top-left corner as the transform origin for nodes */ @@ -142,7 +142,7 @@ static void createTransNodeData(bContext * /*C*/, TransInfo *t) tc->data_2d = MEM_cnew_array(tc->data_len, __func__); for (const int i : nodes.index_range()) { - create_transform_data_for_node(tc->data[i], tc->data_2d[i], *nodes[i], UI_DPI_FAC); + create_transform_data_for_node(tc->data[i], tc->data_2d[i], *nodes[i], UI_SCALE_FAC); } } @@ -197,7 +197,7 @@ static void node_snap_grid_apply(TransInfo *t) static void flushTransNodes(TransInfo *t) { using namespace blender::ed; - const float dpi_fac = UI_DPI_FAC; + const float dpi_fac = UI_SCALE_FAC; SpaceNode *snode = static_cast(t->area->spacedata.first); TransCustomDataNode *customdata = (TransCustomDataNode *)t->custom.type.data; @@ -244,11 +244,16 @@ static void flushTransNodes(TransInfo *t) /* account for parents (nested nodes) */ if (node->parent) { - nodeFromView(node->parent, loc[0], loc[1], &loc[0], &loc[1]); + nodeFromView(node->parent, + loc[0] - node->offsetx, + loc[1] - node->offsety, + &node->locx, + &node->locy); + } + else { + node->locx = loc[0] - node->offsetx; + node->locy = loc[1] - node->offsety; } - - node->locx = loc[0]; - node->locy = loc[1]; } /* handle intersection with noodles */ diff --git a/source/blender/editors/transform/transform_draw_cursors.c b/source/blender/editors/transform/transform_draw_cursors.c index 0cec6e7943b..b76cfce7e96 100644 --- a/source/blender/editors/transform/transform_draw_cursors.c +++ b/source/blender/editors/transform/transform_draw_cursors.c @@ -35,9 +35,9 @@ enum eArrowDirection { static void drawArrow(const uint pos_id, const enum eArrowDirection dir) { - int offset = 5.0f * UI_DPI_FAC; - int length = (6.0f * UI_DPI_FAC) + (4.0f * U.pixelsize); - int size = (3.0f * UI_DPI_FAC) + (2.0f * U.pixelsize); + int offset = 5.0f * UI_SCALE_FAC; + int length = (6.0f * UI_SCALE_FAC) + (4.0f * U.pixelsize); + int size = (3.0f * UI_SCALE_FAC) + (2.0f * U.pixelsize); /* To line up the arrow point nicely, one end has to be extended by half its width. But * being on a 45 degree angle, Pythagoras says a movement of sqrt(2)/2 * (line width /2) */ diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 394779865f3..0c64183be15 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -243,7 +243,7 @@ static void snap_object_data_mesh_get(SnapObjectContext *sctx, { const Span vert_positions = me_eval->vert_positions(); const Span polys = me_eval->polys(); - const Span loops = me_eval->loops(); + const Span corner_verts = me_eval->corner_verts(); if (ob_eval->type == OB_MESH) { /* Any existing #SnapData_EditMesh is now invalid. */ @@ -256,11 +256,11 @@ static void snap_object_data_mesh_get(SnapObjectContext *sctx, BLI_assert(reinterpret_cast(r_treedata->vert_positions) == vert_positions.data()); - BLI_assert(r_treedata->loop == loops.data()); + BLI_assert(r_treedata->corner_verts == corner_verts.data()); BLI_assert(!polys.data() || r_treedata->looptri); BLI_assert(!r_treedata->tree || r_treedata->looptri); - UNUSED_VARS_NDEBUG(vert_positions, polys, loops); + UNUSED_VARS_NDEBUG(vert_positions, polys, corner_verts); } /* Searches for the #Mesh_Runtime associated with the object that is most likely to be updated due @@ -624,9 +624,9 @@ static void mesh_looptri_raycast_backface_culling_cb(void *userdata, const float(*vert_positions)[3] = data->vert_positions; const MLoopTri *lt = &data->looptri[index]; const float *vtri_co[3] = { - vert_positions[data->loop[lt->tri[0]].v], - vert_positions[data->loop[lt->tri[1]].v], - vert_positions[data->loop[lt->tri[2]].v], + vert_positions[data->corner_verts[lt->tri[0]]], + vert_positions[data->corner_verts[lt->tri[1]]], + vert_positions[data->corner_verts[lt->tri[2]]], }; float dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co)); @@ -1429,7 +1429,8 @@ struct Nearest2dUserData { const float (*vert_positions)[3]; const blender::float3 *vert_normals; const MEdge *edges; /* only used for #BVHTreeFromMeshEdges */ - const MLoop *loop; + const int *corner_verts; + const int *corner_edges; const MLoopTri *looptris; }; }; @@ -1480,14 +1481,15 @@ static void cb_bedge_verts_get(const int index, const Nearest2dUserData *data, i static void cb_mlooptri_edges_get(const int index, const Nearest2dUserData *data, int r_v_index[3]) { const MEdge *edges = data->edges; - const MLoop *mloop = data->loop; + const int *corner_verts = data->corner_verts; + const int *corner_edges = data->corner_edges; const MLoopTri *lt = &data->looptris[index]; for (int j = 2, j_next = 0; j_next < 3; j = j_next++) { - const MEdge *edge = &edges[mloop[lt->tri[j]].e]; - const uint tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v}; + const MEdge *edge = &edges[corner_edges[lt->tri[j]]]; + const int tri_edge[2] = {corner_verts[lt->tri[j]], corner_verts[lt->tri[j_next]]}; if (ELEM(edge->v1, tri_edge[0], tri_edge[1]) && ELEM(edge->v2, tri_edge[0], tri_edge[1])) { // printf("real edge found\n"); - r_v_index[j] = mloop[lt->tri[j]].e; + r_v_index[j] = corner_edges[lt->tri[j]]; } else { r_v_index[j] = -1; @@ -1497,12 +1499,12 @@ static void cb_mlooptri_edges_get(const int index, const Nearest2dUserData *data static void cb_mlooptri_verts_get(const int index, const Nearest2dUserData *data, int r_v_index[3]) { - const MLoop *loop = data->loop; + const int *corner_verts = data->corner_verts; const MLoopTri *looptri = &data->looptris[index]; - r_v_index[0] = loop[looptri->tri[0]].v; - r_v_index[1] = loop[looptri->tri[1]].v; - r_v_index[2] = loop[looptri->tri[2]].v; + r_v_index[0] = corner_verts[looptri->tri[0]]; + r_v_index[1] = corner_verts[looptri->tri[1]]; + r_v_index[2] = corner_verts[looptri->tri[2]]; } static bool test_projected_vert_dist(const DistProjectedAABBPrecalc *precalc, @@ -1718,7 +1720,8 @@ static void nearest2d_data_init_mesh(const Mesh *mesh, r_nearest2d->vert_positions = BKE_mesh_vert_positions(mesh); r_nearest2d->vert_normals = mesh->vert_normals().data(); r_nearest2d->edges = mesh->edges().data(); - r_nearest2d->loop = mesh->loops().data(); + r_nearest2d->corner_verts = mesh->corner_verts().data(); + r_nearest2d->corner_edges = mesh->corner_edges().data(); r_nearest2d->looptris = mesh->looptris().data(); r_nearest2d->is_persp = is_persp; @@ -1783,13 +1786,14 @@ static eSnapMode snap_mesh_polygon(SnapObjectContext *sctx, &nearest2d); const MPoly &poly = mesh->polys()[sctx->ret.index]; - const MLoop *ml = &nearest2d.loop[poly.loopstart]; + if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { elem = SCE_SNAP_MODE_EDGE; BLI_assert(nearest2d.edges != nullptr); - for (int i = poly.totloop; i--; ml++) { + const int *poly_edges = &nearest2d.corner_edges[poly.loopstart]; + for (int i = poly.totloop; i--;) { cb_snap_edge(&nearest2d, - int(ml->e), + poly_edges[i], &neasrest_precalc, clip_planes_local, sctx->runtime.clip_plane_len, @@ -1798,9 +1802,10 @@ static eSnapMode snap_mesh_polygon(SnapObjectContext *sctx, } else { elem = SCE_SNAP_MODE_VERTEX; - for (int i = poly.totloop; i--; ml++) { + const int *poly_verts = &nearest2d.corner_verts[poly.loopstart]; + for (int i = poly.totloop; i--;) { cb_snap_vert(&nearest2d, - int(ml->v), + poly_verts[i], &neasrest_precalc, clip_planes_local, sctx->runtime.clip_plane_len, diff --git a/source/blender/editors/util/ed_draw.c b/source/blender/editors/util/ed_draw.c index 1eacb7a2045..bc091a77aa1 100644 --- a/source/blender/editors/util/ed_draw.c +++ b/source/blender/editors/util/ed_draw.c @@ -53,7 +53,7 @@ * #ED_slider_destroy. * \{ */ -#define SLIDE_PIXEL_DISTANCE (300.0f * U.dpi_fac) +#define SLIDE_PIXEL_DISTANCE (300.0f * UI_SCALE_FAC) #define OVERSHOOT_RANGE_DELTA 0.2f typedef struct tSlider { @@ -571,7 +571,7 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_ float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 0); /* "simple" mode */ immUniformThemeColor3(TH_VIEW_OVERLAY); @@ -819,7 +819,7 @@ void ED_region_image_metadata_draw( GPU_matrix_translate_2f(x, y); GPU_matrix_scale_2f(zoomx, zoomy); - BLF_size(blf_mono_font, style->widgetlabel.points * U.dpi_fac); + BLF_size(blf_mono_font, style->widgetlabel.points * UI_SCALE_FAC); /* *** upper box*** */ diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index be569aa02fa..6f67d92681b 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -50,10 +50,11 @@ static void viewer_path_for_geometry_node(const SpaceNode &snode, modifier = nmd; } } - - ModifierViewerPathElem *modifier_elem = BKE_viewer_path_elem_new_modifier(); - modifier_elem->modifier_name = BLI_strdup(modifier->modifier.name); - BLI_addtail(&r_dst.path, modifier_elem); + if (modifier != nullptr) { + ModifierViewerPathElem *modifier_elem = BKE_viewer_path_elem_new_modifier(); + modifier_elem->modifier_name = BLI_strdup(modifier->modifier.name); + BLI_addtail(&r_dst.path, modifier_elem); + } Vector tree_path = snode.treepath; for (const int i : tree_path.index_range().drop_back(1)) { diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 7c59c6b5a45..ea8aa543f23 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -28,7 +28,7 @@ void ED_image_draw_cursor(ARegion *region, const float cursor[2]) UI_view2d_scale_get_inverse(®ion->v2d, &zoom[0], &zoom[1]); - mul_v2_fl(zoom, 256.0f * UI_DPI_FAC); + mul_v2_fl(zoom, 256.0f * UI_SCALE_FAC); x_fac = zoom[0]; y_fac = zoom[1]; @@ -43,7 +43,7 @@ void ED_image_draw_cursor(ARegion *region, const float cursor[2]) float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); + immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC); immUniform1i("colors_len", 2); /* "advanced" mode */ immUniform4f("color", 1.0f, 0.0f, 0.0f, 1.0f); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc index 6f9276c94ed..9666deeba74 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc @@ -639,7 +639,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, const float(*subsurfedPositions)[3] = BKE_mesh_vert_positions(subdiv_mesh); const blender::Span subsurf_edges = subdiv_mesh->edges(); const blender::Span subsurf_polys = subdiv_mesh->polys(); - const blender::Span subsurf_loops = subdiv_mesh->loops(); + const blender::Span subsurf_corner_verts = subdiv_mesh->corner_verts(); const int *origVertIndices = static_cast( CustomData_get_layer(&subdiv_mesh->vdata, CD_ORIGINDEX)); @@ -691,32 +691,52 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, } } - const MLoop *mloop = &subsurf_loops[poly.loopstart]; + const int *poly_corner_verts = &subsurf_corner_verts[poly.loopstart]; /* We will not check for v4 here. Sub-surface faces always have 4 vertices. */ BLI_assert(poly.totloop == 4); key = (ParamKey)i; - vkeys[0] = (ParamKey)mloop[0].v; - vkeys[1] = (ParamKey)mloop[1].v; - vkeys[2] = (ParamKey)mloop[2].v; - vkeys[3] = (ParamKey)mloop[3].v; + vkeys[0] = (ParamKey)poly_corner_verts[0]; + vkeys[1] = (ParamKey)poly_corner_verts[1]; + vkeys[2] = (ParamKey)poly_corner_verts[2]; + vkeys[3] = (ParamKey)poly_corner_verts[3]; - co[0] = subsurfedPositions[mloop[0].v]; - co[1] = subsurfedPositions[mloop[1].v]; - co[2] = subsurfedPositions[mloop[2].v]; - co[3] = subsurfedPositions[mloop[3].v]; + co[0] = subsurfedPositions[poly_corner_verts[0]]; + co[1] = subsurfedPositions[poly_corner_verts[1]]; + co[2] = subsurfedPositions[poly_corner_verts[2]]; + co[3] = subsurfedPositions[poly_corner_verts[3]]; /* This is where all the magic is done. * If the vertex exists in the, we pass the original uv pointer to the solver, thus * flushing the solution to the edit mesh. */ - texface_from_original_index( - scene, offsets, origFace, origVertIndices[mloop[0].v], &uv[0], &pin[0], &select[0]); - texface_from_original_index( - scene, offsets, origFace, origVertIndices[mloop[1].v], &uv[1], &pin[1], &select[1]); - texface_from_original_index( - scene, offsets, origFace, origVertIndices[mloop[2].v], &uv[2], &pin[2], &select[2]); - texface_from_original_index( - scene, offsets, origFace, origVertIndices[mloop[3].v], &uv[3], &pin[3], &select[3]); + texface_from_original_index(scene, + offsets, + origFace, + origVertIndices[poly_corner_verts[0]], + &uv[0], + &pin[0], + &select[0]); + texface_from_original_index(scene, + offsets, + origFace, + origVertIndices[poly_corner_verts[1]], + &uv[1], + &pin[1], + &select[1]); + texface_from_original_index(scene, + offsets, + origFace, + origVertIndices[poly_corner_verts[2]], + &uv[2], + &pin[2], + &select[2]); + texface_from_original_index(scene, + offsets, + origFace, + origVertIndices[poly_corner_verts[3]], + &uv[3], + &pin[3], + &select[3]); blender::geometry::uv_parametrizer_face_add(handle, key, 4, vkeys, co, uv, pin, select); } diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 3b9670a9d9b..c9c65150a13 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -385,18 +385,19 @@ int BlenderFileLoader::testDegenerateTriangle(float v1[3], float v2[3], float v3 static bool testEdgeMark(Mesh *me, const FreestyleEdge *fed, const MLoopTri *lt, int i) { const Span edges = me->edges(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); + const Span corner_edges = me->corner_edges(); - const MLoop *mloop = &loops[lt->tri[i]]; - const MLoop *mloop_next = &loops[lt->tri[(i + 1) % 3]]; - const MEdge *edge = &edges[mloop->e]; + const int corner = lt->tri[i]; + const int corner_next = lt->tri[(i + 1) % 3]; + const MEdge *edge = &edges[corner_edges[corner]]; - if (!ELEM(mloop_next->v, edge->v1, edge->v2)) { + if (!ELEM(corner_verts[corner_next], edge->v1, edge->v2)) { /* Not an edge in the original mesh before triangulation. */ return false; } - return (fed[mloop->e].flag & FREESTYLE_EDGE_MARK) != 0; + return (fed[corner_edges[corner]].flag & FREESTYLE_EDGE_MARK) != 0; } void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) @@ -406,12 +407,12 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) const Span vert_positions = me->vert_positions(); const Span mesh_polys = me->polys(); - const Span mesh_loops = me->loops(); + const Span corner_verts = me->corner_verts(); // Compute loop triangles int tottri = poly_to_tri_count(me->totpoly, me->totloop); MLoopTri *mlooptri = (MLoopTri *)MEM_malloc_arrayN(tottri, sizeof(*mlooptri), __func__); - blender::bke::mesh::looptris_calc(vert_positions, mesh_polys, mesh_loops, {mlooptri, tottri}); + blender::bke::mesh::looptris_calc(vert_positions, mesh_polys, corner_verts, {mlooptri, tottri}); // Compute loop normals BKE_mesh_calc_normals_split(me); @@ -448,9 +449,9 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) for (int a = 0; a < tottri; a++) { const MLoopTri *lt = &mlooptri[a]; - copy_v3_v3(v1, vert_positions[mesh_loops[lt->tri[0]].v]); - copy_v3_v3(v2, vert_positions[mesh_loops[lt->tri[1]].v]); - copy_v3_v3(v3, vert_positions[mesh_loops[lt->tri[2]].v]); + copy_v3_v3(v1, vert_positions[corner_verts[lt->tri[0]]]); + copy_v3_v3(v2, vert_positions[corner_verts[lt->tri[1]]]); + copy_v3_v3(v3, vert_positions[corner_verts[lt->tri[2]]]); mul_m4_v3(obmat, v1); mul_m4_v3(obmat, v2); @@ -523,9 +524,9 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) const MLoopTri *lt = &mlooptri[a]; Material *mat = BKE_object_material_get(ob, material_indices[lt->poly] + 1); - copy_v3_v3(v1, vert_positions[mesh_loops[lt->tri[0]].v]); - copy_v3_v3(v2, vert_positions[mesh_loops[lt->tri[1]].v]); - copy_v3_v3(v3, vert_positions[mesh_loops[lt->tri[2]].v]); + copy_v3_v3(v1, vert_positions[corner_verts[lt->tri[0]]]); + copy_v3_v3(v2, vert_positions[corner_verts[lt->tri[1]]]); + copy_v3_v3(v3, vert_positions[corner_verts[lt->tri[2]]]); mul_m4_v3(obmat, v1); mul_m4_v3(obmat, v2); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 9cad3c1eb72..5c3d527d2bc 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -587,8 +587,10 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) &mesh->edata, CD_MEDGE, CD_SET_DEFAULT, mesh->totedge); MPoly *polys = (MPoly *)CustomData_add_layer( &mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly); - MLoop *loops = (MLoop *)CustomData_add_layer( - &mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, mesh->totloop); + int *corner_verts = (int *)CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_vert"); + int *corner_edges = (int *)CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_vert"); int *material_indices = (int *)CustomData_add_layer_named( &mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totpoly, "material_index"); blender::float2 *loopsuv[2] = {nullptr}; @@ -718,26 +720,27 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex) bool is_odd = n % 2; // loops if (is_odd) { - loops[0].v = vertex_index - 1; - loops[0].e = edge_index - 2; + corner_verts[0] = vertex_index - 1; + corner_edges[0] = edge_index - 2; - loops[1].v = vertex_index - 3; - loops[1].e = edge_index - 3; + corner_verts[1] = vertex_index - 3; + corner_edges[1] = edge_index - 3; - loops[2].v = vertex_index - 2; - loops[2].e = edge_index - 1; + corner_verts[2] = vertex_index - 2; + corner_edges[2] = edge_index - 1; } else { - loops[0].v = vertex_index - 1; - loops[0].e = edge_index - 1; + corner_verts[0] = vertex_index - 1; + corner_edges[0] = edge_index - 1; - loops[1].v = vertex_index - 2; - loops[1].e = edge_index - 3; + corner_verts[1] = vertex_index - 2; + corner_edges[1] = edge_index - 3; - loops[2].v = vertex_index - 3; - loops[2].e = edge_index - 2; + corner_verts[2] = vertex_index - 3; + corner_edges[2] = edge_index - 2; } - loops += 3; + corner_verts += 3; + corner_edges += 3; loop_index += 3; // UV diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt index 9b8d66232eb..615e6f11b39 100644 --- a/source/blender/geometry/CMakeLists.txt +++ b/source/blender/geometry/CMakeLists.txt @@ -24,6 +24,7 @@ set(SRC intern/mesh_to_curve_convert.cc intern/mesh_to_volume.cc intern/point_merge_by_distance.cc + intern/points_to_volume.cc intern/realize_instances.cc intern/resample_curves.cc intern/reverse_uv_sampler.cc @@ -42,6 +43,7 @@ set(SRC GEO_mesh_to_curve.hh GEO_mesh_to_volume.hh GEO_point_merge_by_distance.hh + GEO_points_to_volume.hh GEO_realize_instances.hh GEO_resample_curves.hh GEO_reverse_uv_sampler.hh diff --git a/source/blender/geometry/GEO_mesh_to_volume.hh b/source/blender/geometry/GEO_mesh_to_volume.hh index 3c2f882891d..393a9cc68fb 100644 --- a/source/blender/geometry/GEO_mesh_to_volume.hh +++ b/source/blender/geometry/GEO_mesh_to_volume.hh @@ -36,20 +36,25 @@ struct MeshToVolumeResolution { */ float volume_compute_voxel_size(const Depsgraph *depsgraph, FunctionRef bounds_fn, - const MeshToVolumeResolution resolution, + MeshToVolumeResolution resolution, float exterior_band_width, const float4x4 &transform); /** - * Add a new VolumeGrid to the Volume by converting the supplied mesh + * Add a new fog VolumeGrid to the Volume by converting the supplied mesh. */ -VolumeGrid *volume_grid_add_from_mesh(Volume *volume, - const StringRefNull name, - const Mesh *mesh, - const float4x4 &mesh_to_volume_space_transform, - float voxel_size, - bool fill_volume, - float exterior_band_width, - float interior_band_width, - float density); +VolumeGrid *fog_volume_grid_add_from_mesh(Volume *volume, + StringRefNull name, + const Mesh *mesh, + const float4x4 &mesh_to_volume_space_transform, + float voxel_size, + bool fill_volume, + float exterior_band_width, + float interior_band_width, + float density); +/** + * Add a new SDF VolumeGrid to the Volume by converting the supplied mesh. + */ +VolumeGrid *sdf_volume_grid_add_from_mesh( + Volume *volume, StringRefNull name, const Mesh &mesh, float voxel_size, float half_band_width); #endif } // namespace blender::geometry diff --git a/source/blender/geometry/GEO_points_to_volume.hh b/source/blender/geometry/GEO_points_to_volume.hh new file mode 100644 index 00000000000..329e3067049 --- /dev/null +++ b/source/blender/geometry/GEO_points_to_volume.hh @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_function_ref.hh" +#include "BLI_math_matrix_types.hh" +#include "BLI_string_ref.hh" + +#include "DNA_modifier_types.h" + +#pragma once + +struct Volume; +struct VolumeGrid; + +/** \file + * \ingroup geo + */ + +namespace blender::geometry { + +#ifdef WITH_OPENVDB + +/** + * Add a new fog VolumeGrid to the Volume by converting the supplied points. + */ +VolumeGrid *fog_volume_grid_add_from_points(Volume *volume, + StringRefNull name, + Span positions, + Span radii, + float voxel_size, + float density); +/** + * Add a new SDF VolumeGrid to the Volume by converting the supplied points. + */ +VolumeGrid *sdf_volume_grid_add_from_points(Volume *volume, + StringRefNull name, + Span positions, + Span radii, + float voxel_size); +#endif +} // namespace blender::geometry diff --git a/source/blender/geometry/intern/add_curves_on_mesh.cc b/source/blender/geometry/intern/add_curves_on_mesh.cc index ec066307f76..fe9f4d15056 100644 --- a/source/blender/geometry/intern/add_curves_on_mesh.cc +++ b/source/blender/geometry/intern/add_curves_on_mesh.cc @@ -252,7 +252,7 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves, /* Find faces that the passed in uvs belong to. */ const Span surface_positions = inputs.surface->vert_positions(); - const Span surface_loops = inputs.surface->loops(); + const Span surface_corner_verts = inputs.surface->corner_verts(); for (const int i : inputs.uvs.index_range()) { const float2 &uv = inputs.uvs[i]; const ReverseUVSampler::Result result = inputs.reverse_uv_sampler->sample(uv); @@ -265,9 +265,9 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves, looptris.append(&looptri); const float3 root_position_su = attribute_math::mix3( result.bary_weights, - surface_positions[surface_loops[looptri.tri[0]].v], - surface_positions[surface_loops[looptri.tri[1]].v], - surface_positions[surface_loops[looptri.tri[2]].v]); + surface_positions[surface_corner_verts[looptri.tri[0]]], + surface_positions[surface_corner_verts[looptri.tri[1]]], + surface_positions[surface_corner_verts[looptri.tri[2]]]); root_positions_cu.append( math::transform_point(inputs.transforms->surface_to_curves, root_position_su)); used_uvs.append(uv); diff --git a/source/blender/geometry/intern/mesh_merge_by_distance.cc b/source/blender/geometry/intern/mesh_merge_by_distance.cc index ebd2883abdc..6a494da82f5 100644 --- a/source/blender/geometry/intern/mesh_merge_by_distance.cc +++ b/source/blender/geometry/intern/mesh_merge_by_distance.cc @@ -115,7 +115,8 @@ struct WeldLoopOfPolyIter { int loop_start; int loop_end; Span wloop; - Span mloop; + Span corner_verts; + Span corner_edges; Span loop_map; /* Weld group. */ int *group; @@ -138,7 +139,8 @@ struct WeldLoopOfPolyIter { static bool weld_iter_loop_of_poly_begin(WeldLoopOfPolyIter &iter, const WeldPoly &wp, Span wloop, - Span mloop, + const Span corner_verts, + const Span corner_edges, Span loop_map, int *group_buffer); @@ -159,21 +161,27 @@ static void weld_assert_edge_kill_len(Span wedge, const int supposed_k } static void weld_assert_poly_and_loop_kill_len(WeldMesh *weld_mesh, - Span mloop, + const Span corner_verts, + const Span corner_edges, Span polys, const int supposed_poly_kill_len, const int supposed_loop_kill_len) { int poly_kills = 0; - int loop_kills = mloop.size(); + int loop_kills = corner_verts.size(); for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; int poly_ctx = weld_mesh->poly_map[i]; if (poly_ctx != OUT_OF_CONTEXT) { const WeldPoly *wp = &weld_mesh->wpoly[poly_ctx]; WeldLoopOfPolyIter iter; - if (!weld_iter_loop_of_poly_begin( - iter, *wp, weld_mesh->wloop, mloop, weld_mesh->loop_map, nullptr)) { + if (!weld_iter_loop_of_poly_begin(iter, + *wp, + weld_mesh->wloop, + corner_verts, + corner_edges, + weld_mesh->loop_map, + nullptr)) { poly_kills++; continue; } @@ -245,13 +253,15 @@ static void weld_assert_poly_and_loop_kill_len(WeldMesh *weld_mesh, static void weld_assert_poly_no_vert_repetition(const WeldPoly &wp, Span wloop, - Span mloop, + const Span corner_verts, + const Span corner_edges, Span loop_map) { const int loop_len = wp.loop_len; Array verts(loop_len); WeldLoopOfPolyIter iter; - if (!weld_iter_loop_of_poly_begin(iter, wp, wloop, mloop, loop_map, nullptr)) { + if (!weld_iter_loop_of_poly_begin( + iter, wp, wloop, corner_verts, corner_edges, loop_map, nullptr)) { return; } else { @@ -672,7 +682,8 @@ static void weld_edge_groups_setup(const int edges_len, static bool weld_iter_loop_of_poly_begin(WeldLoopOfPolyIter &iter, const WeldPoly &wp, Span wloop, - Span mloop, + const Span corner_verts, + const Span corner_edges, Span loop_map, int *group_buffer) { @@ -683,7 +694,8 @@ static bool weld_iter_loop_of_poly_begin(WeldLoopOfPolyIter &iter, iter.loop_start = wp.loop_start; iter.loop_end = wp.loop_end; iter.wloop = wloop; - iter.mloop = mloop; + iter.corner_verts = corner_verts; + iter.corner_edges = corner_edges; iter.loop_map = loop_map; iter.group = group_buffer; @@ -756,12 +768,11 @@ static bool weld_iter_loop_of_poly_next(WeldLoopOfPolyIter &iter) iter.type = 1; } else { - const MLoop &ml = iter.mloop[l]; #ifdef USE_WELD_DEBUG - BLI_assert(uint(iter.v) != ml.v); + BLI_assert(iter.v != iter.corner_verts[l]); #endif - iter.v = ml.v; - iter.e = ml.e; + iter.v = iter.corner_verts[l]; + iter.e = iter.corner_edges[l]; iter.type = 0; } if (iter.group) { @@ -780,20 +791,21 @@ static bool weld_iter_loop_of_poly_next(WeldLoopOfPolyIter &iter) * \return r_weld_mesh: Loop and poly members will be allocated here. */ static void weld_poly_loop_ctx_alloc(Span polys, - Span mloop, + const Span corner_verts, + const Span corner_edges, Span vert_dest_map, Span edge_dest_map, WeldMesh *r_weld_mesh) { /* Loop/Poly Context. */ - Array loop_map(mloop.size()); + Array loop_map(corner_verts.size()); Array poly_map(polys.size()); int wloop_len = 0; int wpoly_len = 0; int max_ctx_poly_len = 4; Vector wloop; - wloop.reserve(mloop.size()); + wloop.reserve(corner_verts.size()); Vector wpoly; wpoly.reserve(polys.size()); @@ -806,9 +818,9 @@ static void weld_poly_loop_ctx_alloc(Span polys, const int totloop = poly.totloop; int prev_wloop_len = wloop_len; - for (const int i_loop : mloop.index_range().slice(loopstart, totloop)) { - int v = mloop[i_loop].v; - int e = mloop[i_loop].e; + for (const int i_loop : IndexRange(loopstart, totloop)) { + int v = corner_verts[i_loop]; + int e = corner_edges[i_loop]; int v_dest = vert_dest_map[v]; int e_dest = edge_dest_map[e]; bool is_vert_ctx = v_dest != OUT_OF_CONTEXT; @@ -866,7 +878,8 @@ static void weld_poly_loop_ctx_alloc(Span polys, static void weld_poly_split_recursive(Span vert_dest_map, #ifdef USE_WELD_DEBUG - const Span mloop, + const Span corner_verts, + const Span corner_edges, #endif int ctx_verts_len, WeldPoly *r_wp, @@ -966,7 +979,8 @@ static void weld_poly_split_recursive(Span vert_dest_map, r_weld_mesh->wpoly_new_len++; weld_poly_split_recursive(vert_dest_map, #ifdef USE_WELD_DEBUG - mloop, + corner_verts, + corner_edges, #endif ctx_verts_len, new_wp, @@ -1003,7 +1017,8 @@ static void weld_poly_split_recursive(Span vert_dest_map, *r_loop_kill += loop_kill; #ifdef USE_WELD_DEBUG - weld_assert_poly_no_vert_repetition(*r_wp, wloop, mloop, r_weld_mesh->loop_map); + weld_assert_poly_no_vert_repetition( + *r_wp, wloop, corner_verts, corner_edges, r_weld_mesh->loop_map); #endif } @@ -1018,7 +1033,8 @@ static void weld_poly_split_recursive(Span vert_dest_map, */ static void weld_poly_loop_ctx_setup_collapsed_and_split( #ifdef USE_WELD_DEBUG - Span mloop, + const Span corner_verts, + const Span corner_edges, Span polys, #endif Span vert_dest_map, @@ -1271,7 +1287,8 @@ static int poly_find_doubles(const OffsetIndices poly_corners_offsets, return doubles_buffer_num - (r_doubles_offsets.size() - 1); } -static void weld_poly_find_doubles(Span mloop, +static void weld_poly_find_doubles(const Span corner_verts, + const Span corner_edges, #ifdef USE_WELD_DEBUG const Span polys, #endif @@ -1289,14 +1306,15 @@ static void weld_poly_find_doubles(Span mloop, const int poly_len = r_weld_mesh->wpoly.size(); Array poly_offs(poly_len + 1); - Vector corner_edges; - corner_edges.reserve(mloop.size() - r_weld_mesh->loop_kill_len); + Vector new_corner_edges; + new_corner_edges.reserve(corner_verts.size() - r_weld_mesh->loop_kill_len); for (const WeldPoly &wp : r_weld_mesh->wpoly) { - poly_offs[poly_index++] = corner_edges.size(); + poly_offs[poly_index++] = new_corner_edges.size(); WeldLoopOfPolyIter iter; - if (!weld_iter_loop_of_poly_begin(iter, wp, wloop, mloop, loop_map, nullptr)) { + if (!weld_iter_loop_of_poly_begin( + iter, wp, wloop, corner_verts, corner_edges, loop_map, nullptr)) { continue; } @@ -1305,17 +1323,17 @@ static void weld_poly_find_doubles(Span mloop, } while (weld_iter_loop_of_poly_next(iter)) { - corner_edges.append(iter.e); + new_corner_edges.append(iter.e); } } - poly_offs[poly_len] = corner_edges.size(); + poly_offs[poly_len] = new_corner_edges.size(); Vector doubles_offsets; Array doubles_buffer; const int doubles_num = poly_find_doubles(OffsetIndices(poly_offs), poly_len, - corner_edges, + new_corner_edges, medge_len, doubles_offsets, doubles_buffer); @@ -1361,7 +1379,8 @@ static void weld_mesh_context_create(const Mesh &mesh, { const Span edges = mesh.edges(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); + const Span corner_edges = mesh.corner_edges(); Vector wvert = weld_vert_ctx_alloc_and_setup(vert_dest_map, vert_kill_len); r_weld_mesh->vert_kill_len = vert_kill_len; @@ -1377,18 +1396,21 @@ static void weld_mesh_context_create(const Mesh &mesh, wedge, &r_weld_mesh->edge_kill_len); - weld_poly_loop_ctx_alloc(polys, loops, vert_dest_map, edge_dest_map, r_weld_mesh); + weld_poly_loop_ctx_alloc( + polys, corner_verts, corner_edges, vert_dest_map, edge_dest_map, r_weld_mesh); weld_poly_loop_ctx_setup_collapsed_and_split( #ifdef USE_WELD_DEBUG - loops, + corner_verts, + corner_edges, polys, #endif vert_dest_map, wedge.size() - r_weld_mesh->edge_kill_len, r_weld_mesh); - weld_poly_find_doubles(loops, + weld_poly_find_doubles(corner_verts, + corner_edges, #ifdef USE_WELD_DEBUG polys, #endif @@ -1512,7 +1534,8 @@ static Mesh *create_merged_mesh(const Mesh &mesh, const int removed_vertex_count) { const Span src_polys = mesh.polys(); - const Span src_loops = mesh.loops(); + const Span src_corner_verts = mesh.corner_verts(); + const Span src_corner_edges = mesh.corner_edges(); const int totvert = mesh.totvert; const int totedge = mesh.totedge; @@ -1525,14 +1548,15 @@ static Mesh *create_merged_mesh(const Mesh &mesh, const int result_nverts = totvert - weld_mesh.vert_kill_len; const int result_nedges = totedge - weld_mesh.edge_kill_len; - const int result_nloops = src_loops.size() - weld_mesh.loop_kill_len; + const int result_nloops = src_corner_verts.size() - weld_mesh.loop_kill_len; const int result_npolys = src_polys.size() - weld_mesh.poly_kill_len + weld_mesh.wpoly_new_len; Mesh *result = BKE_mesh_new_nomain_from_template( &mesh, result_nverts, result_nedges, result_nloops, result_npolys); MutableSpan dst_edges = result->edges_for_write(); MutableSpan dst_polys = result->polys_for_write(); - MutableSpan dst_loops = result->loops_for_write(); + MutableSpan dst_corner_verts = result->corner_verts_for_write(); + MutableSpan dst_corner_edges = result->corner_edges_for_write(); /* Vertices. */ @@ -1620,7 +1644,6 @@ static Mesh *create_merged_mesh(const Mesh &mesh, /* Polys/Loops. */ - MLoop *r_ml = dst_loops.data(); int r_i = 0; int loop_cur = 0; Array group_buffer(weld_mesh.max_poly_len); @@ -1631,17 +1654,21 @@ static Mesh *create_merged_mesh(const Mesh &mesh, if (poly_ctx == OUT_OF_CONTEXT) { int mp_loop_len = poly.totloop; CustomData_copy_data(&mesh.ldata, &result->ldata, poly.loopstart, loop_cur, mp_loop_len); - loop_cur += mp_loop_len; - for (; mp_loop_len--; r_ml++) { - r_ml->v = vert_final_map[r_ml->v]; - r_ml->e = edge_final_map[r_ml->e]; + for (; mp_loop_len--; loop_cur++) { + dst_corner_verts[loop_cur] = vert_final_map[dst_corner_verts[loop_cur]]; + dst_corner_edges[loop_cur] = edge_final_map[dst_corner_edges[loop_cur]]; } } else { const WeldPoly &wp = weld_mesh.wpoly[poly_ctx]; WeldLoopOfPolyIter iter; - if (!weld_iter_loop_of_poly_begin( - iter, wp, weld_mesh.wloop, src_loops, weld_mesh.loop_map, group_buffer.data())) { + if (!weld_iter_loop_of_poly_begin(iter, + wp, + weld_mesh.wloop, + src_corner_verts, + src_corner_edges, + weld_mesh.loop_map, + group_buffer.data())) { continue; } @@ -1651,11 +1678,8 @@ static Mesh *create_merged_mesh(const Mesh &mesh, while (weld_iter_loop_of_poly_next(iter)) { customdata_weld( &mesh.ldata, &result->ldata, group_buffer.data(), iter.group_len, loop_cur); - int v = vert_final_map[iter.v]; - int e = edge_final_map[iter.e]; - r_ml->v = v; - r_ml->e = e; - r_ml++; + dst_corner_verts[loop_cur] = vert_final_map[iter.v]; + dst_corner_edges[loop_cur] = edge_final_map[iter.e]; loop_cur++; } } @@ -1671,8 +1695,13 @@ static Mesh *create_merged_mesh(const Mesh &mesh, const WeldPoly &wp = weld_mesh.wpoly[i]; const int loop_start = loop_cur; WeldLoopOfPolyIter iter; - if (!weld_iter_loop_of_poly_begin( - iter, wp, weld_mesh.wloop, src_loops, weld_mesh.loop_map, group_buffer.data())) { + if (!weld_iter_loop_of_poly_begin(iter, + wp, + weld_mesh.wloop, + src_corner_verts, + src_corner_edges, + weld_mesh.loop_map, + group_buffer.data())) { continue; } @@ -1681,11 +1710,8 @@ static Mesh *create_merged_mesh(const Mesh &mesh, } while (weld_iter_loop_of_poly_next(iter)) { customdata_weld(&mesh.ldata, &result->ldata, group_buffer.data(), iter.group_len, loop_cur); - int v = vert_final_map[iter.v]; - int e = edge_final_map[iter.e]; - r_ml->v = v; - r_ml->e = e; - r_ml++; + dst_corner_verts[loop_cur] = vert_final_map[iter.v]; + dst_corner_edges[loop_cur] = edge_final_map[iter.e]; loop_cur++; } diff --git a/source/blender/geometry/intern/mesh_primitive_cuboid.cc b/source/blender/geometry/intern/mesh_primitive_cuboid.cc index 6032b19ac25..cf87607338f 100644 --- a/source/blender/geometry/intern/mesh_primitive_cuboid.cc +++ b/source/blender/geometry/intern/mesh_primitive_cuboid.cc @@ -109,7 +109,7 @@ static void calculate_positions(const CuboidConfig &config, MutableSpan * anti-clockwise. */ static void define_quad(MutableSpan polys, - MutableSpan loops, + MutableSpan corner_verts, const int poly_index, const int loop_index, const int vert_1, @@ -121,19 +121,15 @@ static void define_quad(MutableSpan polys, poly.loopstart = loop_index; poly.totloop = 4; - MLoop &loop_1 = loops[loop_index]; - loop_1.v = vert_1; - MLoop &loop_2 = loops[loop_index + 1]; - loop_2.v = vert_2; - MLoop &loop_3 = loops[loop_index + 2]; - loop_3.v = vert_3; - MLoop &loop_4 = loops[loop_index + 3]; - loop_4.v = vert_4; + corner_verts[loop_index] = vert_1; + corner_verts[loop_index + 1] = vert_2; + corner_verts[loop_index + 2] = vert_3; + corner_verts[loop_index + 3] = vert_4; } static void calculate_polys(const CuboidConfig &config, MutableSpan polys, - MutableSpan loops) + MutableSpan corner_verts) { int loop_index = 0; int poly_index = 0; @@ -152,7 +148,7 @@ static void calculate_polys(const CuboidConfig &config, const int vert_3 = vert_2 + 1; const int vert_4 = vert_1 + 1; - define_quad(polys, loops, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4); + define_quad(polys, corner_verts, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4); loop_index += 4; poly_index++; } @@ -166,7 +162,7 @@ static void calculate_polys(const CuboidConfig &config, for ([[maybe_unused]] const int z : IndexRange(config.edges_z)) { for (const int x : IndexRange(config.edges_x)) { define_quad(polys, - loops, + corner_verts, poly_index, loop_index, vert_1_start + x, @@ -189,7 +185,7 @@ static void calculate_polys(const CuboidConfig &config, for ([[maybe_unused]] const int y : IndexRange(config.edges_y)) { for (const int x : IndexRange(config.edges_x)) { define_quad(polys, - loops, + corner_verts, poly_index, loop_index, vert_1_start + x, @@ -213,7 +209,7 @@ static void calculate_polys(const CuboidConfig &config, } for (const int x : IndexRange(config.edges_x)) { define_quad(polys, - loops, + corner_verts, poly_index, loop_index, vert_1_start + x, @@ -258,7 +254,7 @@ static void calculate_polys(const CuboidConfig &config, vert_3 = vert_2 + 2; } - define_quad(polys, loops, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4); + define_quad(polys, corner_verts, poly_index, loop_index, vert_1, vert_2, vert_3, vert_4); loop_index += 4; poly_index++; } @@ -305,7 +301,7 @@ static void calculate_polys(const CuboidConfig &config, vert_4 = vert_1 + config.verts_x; } - define_quad(polys, loops, poly_index, loop_index, vert_1, vert_4, vert_3, vert_2); + define_quad(polys, corner_verts, poly_index, loop_index, vert_1, vert_4, vert_3, vert_2); loop_index += 4; poly_index++; } @@ -406,12 +402,12 @@ Mesh *create_cuboid_mesh(const float3 &size, Mesh *mesh = BKE_mesh_new_nomain(config.vertex_count, 0, config.loop_count, config.poly_count); MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); BKE_mesh_smooth_flag_set(mesh, false); calculate_positions(config, positions); - calculate_polys(config, polys, loops); + calculate_polys(config, polys, corner_verts); BKE_mesh_calc_edges(mesh, false, false); if (uv_id) { diff --git a/source/blender/geometry/intern/mesh_split_edges.cc b/source/blender/geometry/intern/mesh_split_edges.cc index 506f7355111..8148f9a7fc5 100644 --- a/source/blender/geometry/intern/mesh_split_edges.cc +++ b/source/blender/geometry/intern/mesh_split_edges.cc @@ -157,7 +157,7 @@ static void add_new_edges(Mesh &mesh, */ static void merge_edges(const int orig_edge_i, const int new_edge_i, - MutableSpan new_loops, + MutableSpan new_corner_edges, Vector> &edge_to_loop_map, Vector &new_edges, Vector &new_to_old_edges_map) @@ -165,7 +165,7 @@ static void merge_edges(const int orig_edge_i, /* Merge back into the original edge by undoing the topology changes. */ BLI_assert(edge_to_loop_map[new_edge_i].size() == 1); const int loop_i = edge_to_loop_map[new_edge_i][0]; - new_loops[loop_i].e = orig_edge_i; + new_corner_edges[loop_i] = orig_edge_i; /* We are putting the last edge in the location of new_edge in all the maps, to remove * new_edge efficiently. We have to update the topology information for this last edge @@ -174,7 +174,7 @@ static void merge_edges(const int orig_edge_i, if (last_edge_i != new_edge_i) { BLI_assert(edge_to_loop_map[last_edge_i].size() == 1); const int last_edge_loop_i = edge_to_loop_map[last_edge_i][0]; - new_loops[last_edge_loop_i].e = new_edge_i; + new_corner_edges[last_edge_loop_i] = new_edge_i; } /* We can now safely swap-remove. */ @@ -192,7 +192,7 @@ static void merge_edges(const int orig_edge_i, static void swap_vertex_of_edge(MEdge &edge, const int old_vert, const int new_vert, - MutableSpan loops, + MutableSpan corner_verts, const Span connected_loops) { if (edge.v1 == old_vert) { @@ -206,8 +206,8 @@ static void swap_vertex_of_edge(MEdge &edge, } for (const int loop_i : connected_loops) { - if (loops[loop_i].v == old_vert) { - loops[loop_i].v = new_vert; + if (corner_verts[loop_i] == old_vert) { + corner_verts[loop_i] = new_vert; } /* The old vertex is on the loop containing the adjacent edge. Since this function is also * called on the adjacent edge, we don't replace it here. */ @@ -222,7 +222,7 @@ static void split_vertex_per_fan(const int vertex, const Span fan_sizes, const Span> edge_to_loop_map, MutableSpan new_edges, - MutableSpan new_loops, + MutableSpan corner_verts, MutableSpan new_to_old_verts_map) { int fan_start = 0; @@ -234,7 +234,7 @@ static void split_vertex_per_fan(const int vertex, for (const int edge_i : fans.slice(fan_start, fan_sizes[i])) { swap_vertex_of_edge( - new_edges[edge_i], vertex, new_vert_i, new_loops, edge_to_loop_map[edge_i]); + new_edges[edge_i], vertex, new_vert_i, corner_verts, edge_to_loop_map[edge_i]); } fan_start += fan_sizes[i]; } @@ -244,12 +244,16 @@ static void split_vertex_per_fan(const int vertex, * Get the index of the adjacent edge to a loop connected to a vertex. In other words, for the * given polygon return the unique edge connected to the given vertex and not on the given loop. */ -static int adjacent_edge(Span loops, const int loop_i, const MPoly &poly, const int vertex) +static int adjacent_edge(const Span corner_verts, + const Span corner_edges, + const int loop_i, + const MPoly &poly, + const int vertex) { - const int adjacent_loop_i = (loops[loop_i].v == vertex) ? + const int adjacent_loop_i = (corner_verts[loop_i] == vertex) ? bke::mesh_topology::poly_loop_prev(poly, loop_i) : bke::mesh_topology::poly_loop_next(poly, loop_i); - return loops[adjacent_loop_i].e; + return corner_edges[adjacent_loop_i]; } /** @@ -259,7 +263,8 @@ static int adjacent_edge(Span loops, const int loop_i, const MPoly &poly, * be used to retrieve the fans from connected_edges. */ static void calc_vertex_fans(const int vertex, - const Span new_loops, + const Span new_corner_verts, + const Span new_corner_edges, const Span polys, const Span> edge_to_loop_map, const Span loop_to_poly_map, @@ -289,7 +294,7 @@ static void calc_vertex_fans(const int vertex, /* Add adjacent edges to search stack. */ for (const int loop_i : edge_to_loop_map[curr_edge_i]) { const int adjacent_edge_i = adjacent_edge( - new_loops, loop_i, polys[loop_to_poly_map[loop_i]], vertex); + new_corner_verts, new_corner_edges, loop_i, polys[loop_to_poly_map[loop_i]], vertex); /* Find out if this edge was visited already. */ int i = curr_i + 1; @@ -331,7 +336,7 @@ static void calc_vertex_fans(const int vertex, static void split_edge_per_poly(const int edge_i, const int new_edge_start, MutableSpan> edge_to_loop_map, - MutableSpan new_loops, + MutableSpan corner_edges, MutableSpan new_edges, MutableSpan new_to_old_edges_map) { @@ -344,7 +349,7 @@ static void split_edge_per_poly(const int edge_i, new_edges[new_edge_index] = new_edge; new_to_old_edges_map[new_edge_index] = edge_i; edge_to_loop_map[new_edge_index].append({loop_i}); - new_loops[loop_i].e = new_edge_index; + corner_edges[loop_i] = new_edge_index; new_edge_index++; } /* Only the first loop is now connected to this edge. */ @@ -368,7 +373,7 @@ void split_edges(Mesh &mesh, Array> vert_to_edge_map = bke::mesh_topology::build_vert_to_edge_map(edges, mesh.totvert); Vector> edge_to_loop_map = bke::mesh_topology::build_edge_to_loop_map_resizable( - mesh.loops(), mesh.totedge); + mesh.corner_edges(), mesh.totedge); Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(mesh.polys(), mesh.totloop); @@ -387,7 +392,8 @@ void split_edges(Mesh &mesh, const Span polys = mesh.polys(); - MutableSpan loops = mesh.loops_for_write(); + MutableSpan corner_verts = mesh.corner_verts_for_write(); + MutableSpan corner_edges = mesh.corner_edges_for_write(); Vector new_edges(new_edges_size); new_edges.as_mutable_span().take_front(edges.size()).copy_from(edges); @@ -400,8 +406,12 @@ void split_edges(Mesh &mesh, threading::parallel_for(mask.index_range(), 512, [&](IndexRange range) { for (const int mask_i : range) { const int edge_i = mask[mask_i]; - split_edge_per_poly( - edge_i, edge_offsets[edge_i], edge_to_loop_map, loops, new_edges, new_to_old_edges_map); + split_edge_per_poly(edge_i, + edge_offsets[edge_i], + edge_to_loop_map, + corner_edges, + new_edges, + new_to_old_edges_map); } }); @@ -422,7 +432,8 @@ void split_edges(Mesh &mesh, continue; } calc_vertex_fans(vert, - loops, + corner_verts, + corner_edges, polys, edge_to_loop_map, loop_to_poly_map, @@ -459,7 +470,7 @@ void split_edges(Mesh &mesh, vertex_fan_sizes[vert], edge_to_loop_map, new_edges, - loops, + corner_verts, new_to_old_verts_map); } }); @@ -474,12 +485,14 @@ void split_edges(Mesh &mesh, int end_of_duplicates = start_of_duplicates + num_edge_duplicates[edge] - 1; for (int duplicate = end_of_duplicates; duplicate >= start_of_duplicates; duplicate--) { if (naive_edges_equal(new_edges[edge], new_edges[duplicate])) { - merge_edges(edge, duplicate, loops, edge_to_loop_map, new_edges, new_to_old_edges_map); + merge_edges( + edge, duplicate, corner_edges, edge_to_loop_map, new_edges, new_to_old_edges_map); break; } for (int other = start_of_duplicates; other < duplicate; other++) { if (naive_edges_equal(new_edges[other], new_edges[duplicate])) { - merge_edges(other, duplicate, loops, edge_to_loop_map, new_edges, new_to_old_edges_map); + merge_edges( + other, duplicate, corner_edges, edge_to_loop_map, new_edges, new_to_old_edges_map); break; } } diff --git a/source/blender/geometry/intern/mesh_to_volume.cc b/source/blender/geometry/intern/mesh_to_volume.cc index d098f6ce584..dd6fd27d6c5 100644 --- a/source/blender/geometry/intern/mesh_to_volume.cc +++ b/source/blender/geometry/intern/mesh_to_volume.cc @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_math_matrix.hh" +#include "BLI_task.hh" #include "BKE_mesh.hh" #include "BKE_mesh_runtime.h" @@ -19,7 +20,7 @@ namespace blender::geometry { class OpenVDBMeshAdapter { private: Span positions_; - Span loops_; + Span corner_verts_; Span looptris_; float4x4 transform_; @@ -33,7 +34,7 @@ class OpenVDBMeshAdapter { OpenVDBMeshAdapter::OpenVDBMeshAdapter(const Mesh &mesh, float4x4 transform) : positions_(mesh.vert_positions()), - loops_(mesh.loops()), + corner_verts_(mesh.corner_verts()), looptris_(mesh.looptris()), transform_(transform) { @@ -61,7 +62,7 @@ void OpenVDBMeshAdapter::getIndexSpacePoint(size_t polygon_index, { const MLoopTri &looptri = looptris_[polygon_index]; const float3 transformed_co = math::transform_point( - transform_, positions_[loops_[looptri.tri[vertex_index]].v]); + transform_, positions_[corner_verts_[looptri.tri[vertex_index]]]); pos = &transformed_co.x; } @@ -97,13 +98,14 @@ float volume_compute_voxel_size(const Depsgraph *depsgraph, return voxel_size; } -static openvdb::FloatGrid::Ptr mesh_to_volume_grid(const Mesh *mesh, - const float4x4 &mesh_to_volume_space_transform, - const float voxel_size, - const bool fill_volume, - const float exterior_band_width, - const float interior_band_width, - const float density) +static openvdb::FloatGrid::Ptr mesh_to_fog_volume_grid( + const Mesh *mesh, + const float4x4 &mesh_to_volume_space_transform, + const float voxel_size, + const bool fill_volume, + const float exterior_band_width, + const float interior_band_width, + const float density) { if (voxel_size == 0.0f) { return nullptr; @@ -120,47 +122,81 @@ static openvdb::FloatGrid::Ptr mesh_to_volume_grid(const Mesh *mesh, const float exterior = MAX2(0.001f, exterior_band_width / voxel_size); const float interior = MAX2(0.001f, interior_band_width / voxel_size); - openvdb::FloatGrid::Ptr new_grid; - if (fill_volume) { - /* Setting the interior bandwidth to FLT_MAX, will make it fill the entire volume. */ - new_grid = openvdb::tools::meshToVolume( - mesh_adapter, {}, exterior, FLT_MAX); - } - else { - new_grid = openvdb::tools::meshToVolume( - mesh_adapter, {}, exterior, interior); - } + /* Setting the interior bandwidth to FLT_MAX, will make it fill the entire volume. */ + openvdb::FloatGrid::Ptr new_grid = openvdb::tools::meshToVolume( + mesh_adapter, {}, exterior, fill_volume ? FLT_MAX : interior); /* Give each grid cell a fixed density for now. */ openvdb::tools::foreach ( new_grid->beginValueOn(), [density](const openvdb::FloatGrid::ValueOnIter &iter) { iter.setValue(density); }); + new_grid->setGridClass(openvdb::GRID_FOG_VOLUME); + return new_grid; } -VolumeGrid *volume_grid_add_from_mesh(Volume *volume, - const StringRefNull name, - const Mesh *mesh, - const float4x4 &mesh_to_volume_space_transform, - const float voxel_size, - const bool fill_volume, - const float exterior_band_width, - const float interior_band_width, - const float density) +static openvdb::FloatGrid::Ptr mesh_to_sdf_volume_grid(const Mesh &mesh, + const float voxel_size, + const float half_band_width) +{ + if (voxel_size <= 0.0f || half_band_width <= 0.0f) { + return nullptr; + } + + const Span positions = mesh.vert_positions(); + const Span corner_verts = mesh.corner_verts(); + const Span looptris = mesh.looptris(); + + std::vector points(positions.size()); + std::vector triangles(looptris.size()); + + threading::parallel_for(positions.index_range(), 2048, [&](const IndexRange range) { + for (const int i : range) { + const float3 &co = positions[i]; + points[i] = openvdb::Vec3s(co.x, co.y, co.z) - 0.5f * voxel_size; + } + }); + + threading::parallel_for(looptris.index_range(), 2048, [&](const IndexRange range) { + for (const int i : range) { + const MLoopTri &loop_tri = looptris[i]; + triangles[i] = openvdb::Vec3I(corner_verts[loop_tri.tri[0]], + corner_verts[loop_tri.tri[1]], + corner_verts[loop_tri.tri[2]]); + } + }); + + openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform( + voxel_size); + openvdb::FloatGrid::Ptr new_grid = openvdb::tools::meshToLevelSet( + *transform, points, triangles, half_band_width); + + return new_grid; +} + +VolumeGrid *fog_volume_grid_add_from_mesh(Volume *volume, + const StringRefNull name, + const Mesh *mesh, + const float4x4 &mesh_to_volume_space_transform, + const float voxel_size, + const bool fill_volume, + const float exterior_band_width, + const float interior_band_width, + const float density) { VolumeGrid *c_grid = BKE_volume_grid_add(volume, name.c_str(), VOLUME_GRID_FLOAT); openvdb::FloatGrid::Ptr grid = openvdb::gridPtrCast( BKE_volume_grid_openvdb_for_write(volume, c_grid, false)); /* Generate grid from mesh */ - openvdb::FloatGrid::Ptr mesh_grid = mesh_to_volume_grid(mesh, - mesh_to_volume_space_transform, - voxel_size, - fill_volume, - exterior_band_width, - interior_band_width, - density); + openvdb::FloatGrid::Ptr mesh_grid = mesh_to_fog_volume_grid(mesh, + mesh_to_volume_space_transform, + voxel_size, + fill_volume, + exterior_band_width, + interior_band_width, + density); if (mesh_grid != nullptr) { /* Merge the generated grid. Should be cheap because grid has just been created. */ @@ -168,9 +204,17 @@ VolumeGrid *volume_grid_add_from_mesh(Volume *volume, /* Change transform so that the index space is correctly transformed to object space. */ grid->transform().postScale(voxel_size); } - /* Set class to "Fog Volume". */ - grid->setGridClass(openvdb::GRID_FOG_VOLUME); return c_grid; } + +VolumeGrid *sdf_volume_grid_add_from_mesh(Volume *volume, + const StringRefNull name, + const Mesh &mesh, + const float voxel_size, + const float half_band_width) +{ + openvdb::FloatGrid::Ptr mesh_grid = mesh_to_sdf_volume_grid(mesh, voxel_size, half_band_width); + return mesh_grid ? BKE_volume_grid_add_vdb(*volume, name, std::move(mesh_grid)) : nullptr; +} } // namespace blender::geometry #endif diff --git a/source/blender/geometry/intern/points_to_volume.cc b/source/blender/geometry/intern/points_to_volume.cc new file mode 100644 index 00000000000..ec0afc3a990 --- /dev/null +++ b/source/blender/geometry/intern/points_to_volume.cc @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_math_matrix.hh" + +#include "BKE_volume.h" + +#include "GEO_points_to_volume.hh" + +#ifdef WITH_OPENVDB +# include +# include +# include + +namespace blender::geometry { + +/* Implements the interface required by #openvdb::tools::ParticlesToLevelSet. */ +struct OpenVDBParticleList { + using PosType = openvdb::Vec3R; + + Span positions; + Span radii; + + size_t size() const + { + return size_t(positions.size()); + } + + void getPos(size_t n, openvdb::Vec3R &xyz) const + { + xyz = &positions[n].x; + } + + void getPosRad(size_t n, openvdb::Vec3R &xyz, openvdb::Real &radius) const + { + xyz = &positions[n].x; + radius = radii[n]; + } +}; + +static openvdb::FloatGrid::Ptr points_to_sdf_grid(const Span positions, + const Span radii) +{ + /* Create a new grid that will be filled. #ParticlesToLevelSet requires + * the background value to be positive */ + openvdb::FloatGrid::Ptr new_grid = openvdb::FloatGrid::create(1.0f); + + /* Create a narrow-band level set grid based on the positions and radii. */ + openvdb::tools::ParticlesToLevelSet op{*new_grid}; + /* Don't ignore particles based on their radius. */ + op.setRmin(0.0f); + op.setRmax(FLT_MAX); + OpenVDBParticleList particles{positions, radii}; + op.rasterizeSpheres(particles); + op.finalize(); + + return new_grid; +} + +VolumeGrid *fog_volume_grid_add_from_points(Volume *volume, + const StringRefNull name, + const Span positions, + const Span radii, + const float voxel_size, + const float density) +{ + openvdb::FloatGrid::Ptr new_grid = points_to_sdf_grid(positions, radii); + new_grid->transform().postScale(voxel_size); + new_grid->setGridClass(openvdb::GRID_FOG_VOLUME); + + /* Convert the level set to a fog volume. This also sets the background value to zero. Inside the + * fog there will be a density of 1. */ + openvdb::tools::sdfToFogVolume(*new_grid); + + /* Take the desired density into account. */ + openvdb::tools::foreach (new_grid->beginValueOn(), + [&](const openvdb::FloatGrid::ValueOnIter &iter) { + iter.modifyValue([&](float &value) { value *= density; }); + }); + + return BKE_volume_grid_add_vdb(*volume, name, std::move(new_grid)); +} + +VolumeGrid *sdf_volume_grid_add_from_points(Volume *volume, + const StringRefNull name, + const Span positions, + const Span radii, + const float voxel_size) +{ + openvdb::FloatGrid::Ptr new_grid = points_to_sdf_grid(positions, radii); + new_grid->transform().postScale(voxel_size); + new_grid->setGridClass(openvdb::GRID_LEVEL_SET); + + return BKE_volume_grid_add_vdb(*volume, name, std::move(new_grid)); +} +} // namespace blender::geometry +#endif diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 3a6b92c6e93..9ff6eacd1cb 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -104,7 +104,8 @@ struct MeshRealizeInfo { Span positions; Span edges; Span polys; - Span loops; + Span corner_verts; + Span corner_edges; /** Maps old material indices to new material indices. */ Array material_index_map; @@ -846,6 +847,8 @@ static OrderedAttributes gather_generic_mesh_attributes_to_propagate( options.propagation_info, attributes_to_propagate); attributes_to_propagate.remove("position"); + attributes_to_propagate.remove(".corner_vert"); + attributes_to_propagate.remove(".corner_edge"); r_create_id = attributes_to_propagate.pop_try("id").has_value(); r_create_material_index = attributes_to_propagate.pop_try("material_index").has_value(); OrderedAttributes ordered_attributes; @@ -900,7 +903,8 @@ static AllMeshesInfo preprocess_meshes(const GeometrySet &geometry_set, mesh_info.positions = mesh->vert_positions(); mesh_info.edges = mesh->edges(); mesh_info.polys = mesh->polys(); - mesh_info.loops = mesh->loops(); + mesh_info.corner_verts = mesh->corner_verts(); + mesh_info.corner_edges = mesh->corner_edges(); /* Create material index mapping. */ mesh_info.material_index_map.reinitialize(std::max(mesh->totcol, 1)); @@ -946,7 +950,8 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, MutableSpan all_dst_positions, MutableSpan all_dst_edges, MutableSpan all_dst_polys, - MutableSpan all_dst_loops, + MutableSpan all_dst_corner_verts, + MutableSpan all_dst_corner_edges, MutableSpan all_dst_vertex_ids, MutableSpan all_dst_material_indices) { @@ -956,17 +961,19 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, const Span src_positions = mesh_info.positions; const Span src_edges = mesh_info.edges; const Span src_polys = mesh_info.polys; - const Span src_loops = mesh_info.loops; + const Span src_corner_verts = mesh_info.corner_verts; + const Span src_corner_edges = mesh_info.corner_edges; const IndexRange dst_vert_range(task.start_indices.vertex, src_positions.size()); const IndexRange dst_edge_range(task.start_indices.edge, src_edges.size()); const IndexRange dst_poly_range(task.start_indices.poly, src_polys.size()); - const IndexRange dst_loop_range(task.start_indices.loop, src_loops.size()); + const IndexRange dst_loop_range(task.start_indices.loop, src_corner_verts.size()); MutableSpan dst_positions = all_dst_positions.slice(dst_vert_range); MutableSpan dst_edges = all_dst_edges.slice(dst_edge_range); MutableSpan dst_polys = all_dst_polys.slice(dst_poly_range); - MutableSpan dst_loops = all_dst_loops.slice(dst_loop_range); + MutableSpan dst_corner_verts = all_dst_corner_verts.slice(dst_loop_range); + MutableSpan dst_corner_edges = all_dst_corner_edges.slice(dst_loop_range); threading::parallel_for(src_positions.index_range(), 1024, [&](const IndexRange vert_range) { for (const int i : vert_range) { @@ -982,13 +989,14 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, dst_edge.v2 += task.start_indices.vertex; } }); - threading::parallel_for(src_loops.index_range(), 1024, [&](const IndexRange loop_range) { + threading::parallel_for(src_corner_verts.index_range(), 1024, [&](const IndexRange loop_range) { for (const int i : loop_range) { - const MLoop &src_loop = src_loops[i]; - MLoop &dst_loop = dst_loops[i]; - dst_loop = src_loop; - dst_loop.v += task.start_indices.vertex; - dst_loop.e += task.start_indices.edge; + dst_corner_verts[i] = src_corner_verts[i] + task.start_indices.vertex; + } + }); + threading::parallel_for(src_corner_edges.index_range(), 1024, [&](const IndexRange loop_range) { + for (const int i : loop_range) { + dst_corner_edges[i] = src_corner_edges[i] + task.start_indices.edge; } }); threading::parallel_for(src_polys.index_range(), 1024, [&](const IndexRange poly_range) { @@ -1079,7 +1087,8 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, MutableSpan dst_positions = dst_mesh->vert_positions_for_write(); MutableSpan dst_edges = dst_mesh->edges_for_write(); MutableSpan dst_polys = dst_mesh->polys_for_write(); - MutableSpan dst_loops = dst_mesh->loops_for_write(); + MutableSpan dst_corner_verts = dst_mesh->corner_verts_for_write(); + MutableSpan dst_corner_edges = dst_mesh->corner_edges_for_write(); /* Copy settings from the first input geometry set with a mesh. */ const RealizeMeshTask &first_task = tasks.first(); @@ -1128,7 +1137,8 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, dst_positions, dst_edges, dst_polys, - dst_loops, + dst_corner_verts, + dst_corner_edges, vertex_ids.span, material_indices.span); } diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc index b9b6b5c2eb5..00c0c06f438 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc @@ -1477,7 +1477,8 @@ struct EdgeFeatData { const int *material_indices; blender::Span edges; blender::Span polys; - blender::Span loops; + blender::Span corner_verts; + blender::Span corner_edges; blender::Span looptris; LineartTriangle *tri_array; blender::VArray sharp_edges; @@ -1683,8 +1684,11 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata, } int real_edges[3]; - BKE_mesh_looptri_get_real_edges( - e_feat_data->edges.data(), e_feat_data->loops.data(), &looptris[i / 3], real_edges); + BKE_mesh_looptri_get_real_edges(e_feat_data->edges.data(), + e_feat_data->corner_verts.data(), + e_feat_data->corner_edges.data(), + &looptris[i / 3], + real_edges); if (real_edges[i % 3] >= 0) { if (ld->conf.use_crease && ld->conf.sharp_as_crease && @@ -1789,7 +1793,7 @@ static void lineart_triangle_adjacent_assign(LineartTriangle *tri, struct TriData { LineartObjectInfo *ob_info; blender::Span positions; - blender::Span loops; + blender::Span corner_verts; blender::Span looptris; const int *material_indices; LineartVert *vert_arr; @@ -1805,7 +1809,7 @@ static void lineart_load_tri_task(void *__restrict userdata, TriData *tri_task_data = (TriData *)userdata; LineartObjectInfo *ob_info = tri_task_data->ob_info; const blender::Span positions = tri_task_data->positions; - const blender::Span loops = tri_task_data->loops; + const blender::Span corner_verts = tri_task_data->corner_verts; const MLoopTri *looptri = &tri_task_data->looptris[i]; const int *material_indices = tri_task_data->material_indices; LineartVert *vert_arr = tri_task_data->vert_arr; @@ -1813,9 +1817,9 @@ static void lineart_load_tri_task(void *__restrict userdata, tri = (LineartTriangle *)(((uchar *)tri) + tri_task_data->lineart_triangle_size * i); - int v1 = loops[looptri->tri[0]].v; - int v2 = loops[looptri->tri[1]].v; - int v3 = loops[looptri->tri[2]].v; + int v1 = corner_verts[looptri->tri[0]]; + int v2 = corner_verts[looptri->tri[1]]; + int v3 = corner_verts[looptri->tri[2]]; tri->v[0] = &vert_arr[v1]; tri->v[1] = &vert_arr[v2]; @@ -1863,7 +1867,7 @@ static void lineart_load_tri_task(void *__restrict userdata, struct EdgeNeighborData { LineartEdgeNeighbor *edge_nabr; LineartAdjacentEdge *adj_e; - blender::Span loops; + blender::Span corner_verts; blender::Span looptris; }; @@ -1875,11 +1879,11 @@ static void lineart_edge_neighbor_init_task(void *__restrict userdata, LineartAdjacentEdge *adj_e = &en_data->adj_e[i]; const MLoopTri *looptri = &en_data->looptris[i / 3]; LineartEdgeNeighbor *edge_nabr = &en_data->edge_nabr[i]; - const blender::Span loops = en_data->loops; + const blender::Span corner_verts = en_data->corner_verts; adj_e->e = i; - adj_e->v1 = loops[looptri->tri[i % 3]].v; - adj_e->v2 = loops[looptri->tri[(i + 1) % 3]].v; + adj_e->v1 = corner_verts[looptri->tri[i % 3]]; + adj_e->v2 = corner_verts[looptri->tri[(i + 1) % 3]]; if (adj_e->v1 > adj_e->v2) { std::swap(adj_e->v1, adj_e->v2); } @@ -1925,7 +1929,7 @@ static LineartEdgeNeighbor *lineart_build_edge_neighbor(Mesh *me, int total_edge EdgeNeighborData en_data; en_data.adj_e = adj_e; en_data.edge_nabr = edge_nabr; - en_data.loops = me->loops(); + en_data.corner_verts = me->corner_verts(); en_data.looptris = me->looptris(); BLI_task_parallel_range(0, total_edges, &en_data, lineart_edge_neighbor_init_task, &en_settings); @@ -2066,7 +2070,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, tri_data.ob_info = ob_info; tri_data.positions = me->vert_positions(); tri_data.looptris = looptris; - tri_data.loops = me->loops(); + tri_data.corner_verts = me->corner_verts(); tri_data.material_indices = material_indices; tri_data.vert_arr = la_v_arr; tri_data.tri_arr = la_tri_arr; @@ -2103,7 +2107,8 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, edge_feat_data.material_indices = material_indices; edge_feat_data.edges = me->edges(); edge_feat_data.polys = me->polys(); - edge_feat_data.loops = me->loops(); + edge_feat_data.corner_verts = me->corner_verts(); + edge_feat_data.corner_edges = me->corner_edges(); edge_feat_data.looptris = looptris; edge_feat_data.sharp_edges = sharp_edges; edge_feat_data.sharp_faces = sharp_faces; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 102b1b1a57b..329cb211c3f 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -603,9 +603,11 @@ list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR}) set(SRC_SHADER_CREATE_INFOS ../draw/engines/basic/shaders/infos/basic_depth_info.hh + ../draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_film_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh + ../draw/engines/eevee_next/shaders/infos/eevee_irradiance_cache_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_light_culling_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_material_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_motion_blur_info.hh diff --git a/source/blender/gpu/intern/gpu_debug.cc b/source/blender/gpu/intern/gpu_debug.cc index 79f78c1af5c..d40e5a02a73 100644 --- a/source/blender/gpu/intern/gpu_debug.cc +++ b/source/blender/gpu/intern/gpu_debug.cc @@ -112,12 +112,12 @@ void *GPU_debug_capture_scope_create(const char *name) { /* GPU Frame capture is only enabled when --debug-gpu is specified. */ if (!(G.debug & G_DEBUG_GPU)) { - return NULL; + return nullptr; } Context *ctx = Context::get(); if (!ctx) { - return NULL; + return nullptr; } return ctx->debug_capture_scope_create(name); } diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc index 2c08d0f4061..45a5f1df6a0 100644 --- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc +++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc @@ -147,14 +147,6 @@ bool paint_is_grid_face_hidden(const uint * /*grid_hidden*/, /** \name Stubs of BKE_mesh.h * \{ */ -void BKE_mesh_looptri_get_real_edges(const struct MEdge * /*edges*/, - const struct MLoop * /*loops*/, - const struct MLoopTri * /*looptri*/, - int[3] /*col*/) -{ - BLI_assert_unreachable(); -} - /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/gpu/shaders/common/gpu_shader_common_math_utils.glsl b/source/blender/gpu/shaders/common/gpu_shader_common_math_utils.glsl index ca9c42f2027..ddb014cc045 100644 --- a/source/blender/gpu/shaders/common/gpu_shader_common_math_utils.glsl +++ b/source/blender/gpu/shaders/common/gpu_shader_common_math_utils.glsl @@ -1,18 +1,23 @@ /* Float Math */ +/* WORKAROUND: To be removed once we port all code to use gpu_shader_math_base_lib.glsl. */ +#ifndef GPU_SHADER_MATH_BASE_LIB_GLSL + float safe_divide(float a, float b) { return (b != 0.0) ? a / b : 0.0; } +#endif + /* fmod function compatible with OSL (copy from OSL/dual.h) */ float compatible_fmod(float a, float b) { - if (b != 0.0f) { + if (b != 0.0) { int N = int(a / b); return a - N * b; } - return 0.0f; + return 0.0; } float compatible_pow(float x, float y) @@ -59,11 +64,16 @@ vec3 wrap(vec3 a, vec3 b, vec3 c) return vec3(wrap(a.x, b.x, c.x), wrap(a.y, b.y, c.y), wrap(a.z, b.z, c.z)); } +/* WORKAROUND: To be removed once we port all code to use gpu_shader_math_base_lib.glsl. */ +#ifndef GPU_SHADER_MATH_BASE_LIB_GLSL + float hypot(float x, float y) { return sqrt(x * x + y * y); } +#endif + int floor_to_int(float x) { return int(floor(x)); @@ -76,6 +86,9 @@ int quick_floor(float x) /* Vector Math */ +/* WORKAROUND: To be removed once we port all code to use gpu_shader_math_base_lib.glsl. */ +#ifndef GPU_SHADER_MATH_BASE_LIB_GLSL + vec2 safe_divide(vec2 a, vec2 b) { return vec2(safe_divide(a.x, b.x), safe_divide(a.y, b.y)); @@ -107,6 +120,8 @@ vec4 safe_divide(vec4 a, float b) return (b != 0.0) ? a / b : vec4(0.0); } +#endif + vec3 compatible_fmod(vec3 a, vec3 b) { return vec3(compatible_fmod(a.x, b.x), compatible_fmod(a.y, b.y), compatible_fmod(a.z, b.z)); diff --git a/source/blender/gpu/tests/storage_buffer_test.cc b/source/blender/gpu/tests/storage_buffer_test.cc index 35d0b8f1a1a..3903fade393 100644 --- a/source/blender/gpu/tests/storage_buffer_test.cc +++ b/source/blender/gpu/tests/storage_buffer_test.cc @@ -47,4 +47,52 @@ static void test_storage_buffer_create_update_read() GPU_TEST(storage_buffer_create_update_read); +static void test_storage_buffer_clear_zero() +{ + GPUStorageBuf *ssbo = GPU_storagebuf_create_ex( + SIZE_IN_BYTES, nullptr, GPU_USAGE_STATIC, __func__); + EXPECT_NE(ssbo, nullptr); + + /* Upload some dummy data. */ + const Vector data = test_data(); + GPU_storagebuf_update(ssbo, data.data()); + GPU_storagebuf_clear_to_zero(ssbo); + + /* Read back data from SSBO. */ + Vector read_data; + read_data.resize(SIZE, 0); + GPU_storagebuf_read(ssbo, read_data.data()); + + /* Check if data is the same. */ + for (int i : IndexRange(SIZE)) { + EXPECT_EQ(0, read_data[i]); + } + + GPU_storagebuf_free(ssbo); +} +GPU_TEST(storage_buffer_clear_zero); + +static void test_storage_buffer_clear() +{ + GPUStorageBuf *ssbo = GPU_storagebuf_create_ex( + SIZE_IN_BYTES, nullptr, GPU_USAGE_STATIC, __func__); + EXPECT_NE(ssbo, nullptr); + + GPU_storagebuf_clear(ssbo, 157255); + + /* Read back data from SSBO. */ + Vector read_data; + read_data.resize(SIZE, 0); + GPU_storagebuf_read(ssbo, read_data.data()); + + /* Check if datatest_ is the same. */ + for (int i : IndexRange(SIZE)) { + EXPECT_EQ(157255, read_data[i]); + } + + GPU_storagebuf_free(ssbo); +} + +GPU_TEST(storage_buffer_clear); + } // namespace blender::gpu::tests diff --git a/source/blender/gpu/vulkan/vk_buffer.cc b/source/blender/gpu/vulkan/vk_buffer.cc index a5afcde7162..feb5ca9c9a0 100644 --- a/source/blender/gpu/vulkan/vk_buffer.cc +++ b/source/blender/gpu/vulkan/vk_buffer.cc @@ -84,6 +84,12 @@ void VKBuffer::update(const void *data) const memcpy(mapped_memory_, data, size_in_bytes_); } +void VKBuffer::clear(VKContext &context, uint32_t clear_value) +{ + VKCommandBuffer &command_buffer = context.command_buffer_get(); + command_buffer.fill(*this, clear_value); +} + void VKBuffer::read(void *data) const { BLI_assert_msg(is_mapped(), "Cannot read a non-mapped buffer."); diff --git a/source/blender/gpu/vulkan/vk_buffer.hh b/source/blender/gpu/vulkan/vk_buffer.hh index 917103114a5..dac3519fbb8 100644 --- a/source/blender/gpu/vulkan/vk_buffer.hh +++ b/source/blender/gpu/vulkan/vk_buffer.hh @@ -35,6 +35,7 @@ class VKBuffer { int64_t size, GPUUsageType usage, VkBufferUsageFlagBits buffer_usage); + void clear(VKContext &context, uint32_t clear_value); void update(const void *data) const; void read(void *data) const; bool free(VKContext &context); diff --git a/source/blender/gpu/vulkan/vk_command_buffer.cc b/source/blender/gpu/vulkan/vk_command_buffer.cc index b4526df6aba..af8d39bcf7b 100644 --- a/source/blender/gpu/vulkan/vk_command_buffer.cc +++ b/source/blender/gpu/vulkan/vk_command_buffer.cc @@ -86,6 +86,11 @@ void VKCommandBuffer::push_constants(const VKPushConstants &push_constants, push_constants.data()); } +void VKCommandBuffer::fill(VKBuffer &buffer, uint32_t clear_data) +{ + vkCmdFillBuffer(vk_command_buffer_, buffer.vk_handle(), 0, buffer.size_in_bytes(), clear_data); +} + void VKCommandBuffer::copy(VKBuffer &dst_buffer, VKTexture &src_texture, Span regions) diff --git a/source/blender/gpu/vulkan/vk_command_buffer.hh b/source/blender/gpu/vulkan/vk_command_buffer.hh index 0f5f47a423a..103f4ac2300 100644 --- a/source/blender/gpu/vulkan/vk_command_buffer.hh +++ b/source/blender/gpu/vulkan/vk_command_buffer.hh @@ -51,6 +51,7 @@ class VKCommandBuffer : NonCopyable, NonMovable { void pipeline_barrier(VkPipelineStageFlags source_stages, VkPipelineStageFlags destination_stages); void pipeline_barrier(Span image_memory_barriers); + void fill(VKBuffer &buffer, uint32_t data); /** * Stop recording commands, encode + send the recordings to Vulkan, wait for the until the diff --git a/source/blender/gpu/vulkan/vk_storage_buffer.cc b/source/blender/gpu/vulkan/vk_storage_buffer.cc index 5ab293bef6a..fd89fc38296 100644 --- a/source/blender/gpu/vulkan/vk_storage_buffer.cc +++ b/source/blender/gpu/vulkan/vk_storage_buffer.cc @@ -23,7 +23,11 @@ void VKStorageBuffer::update(const void *data) void VKStorageBuffer::allocate(VKContext &context) { - buffer_.create(context, size_in_bytes_, usage_, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + buffer_.create(context, + size_in_bytes_, + usage_, + static_cast(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT)); } void VKStorageBuffer::bind(int slot) @@ -43,8 +47,13 @@ void VKStorageBuffer::unbind() { } -void VKStorageBuffer::clear(uint32_t /*clear_value*/) +void VKStorageBuffer::clear(uint32_t clear_value) { + VKContext &context = *VKContext::get(); + if (!buffer_.is_allocated()) { + allocate(context); + } + buffer_.clear(context, clear_value); } void VKStorageBuffer::copy_sub(VertBuf * /*src*/, diff --git a/source/blender/imbuf/intern/oiio/openimageio_support.cc b/source/blender/imbuf/intern/oiio/openimageio_support.cc index bda4027c613..cdfe74aa4f9 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_support.cc +++ b/source/blender/imbuf/intern/oiio/openimageio_support.cc @@ -209,7 +209,7 @@ static ImBuf *get_oiio_ibuf(ImageInput *in, const ReadContext &ctx, char colorsp if (x_res > 0.0f && y_res > 0.0f) { double scale = 1.0; auto unit = spec.get_string_attribute("ResolutionUnit", ""); - if (unit == "in" || unit == "inch") { + if (ELEM(unit, "in", "inch")) { scale = 100.0 / 2.54; } else if (unit == "cm") { @@ -234,8 +234,8 @@ static ImBuf *get_oiio_ibuf(ImageInput *in, const ReadContext &ctx, char colorsp } /** - * Returns an ImageInput for the precise `format` requested using the provided IOMemReader. - * If successful, the ImageInput will be opened and ready for operations. Null will be returned if + * Returns an #ImageInput for the precise `format` requested using the provided #IOMemReader. + * If successful, the #ImageInput will be opened and ready for operations. Null will be returned if * the format was not found or if the open call fails. */ static unique_ptr get_oiio_reader(const char *format, @@ -358,10 +358,10 @@ ImageSpec imb_create_write_spec(const WriteContext &ctx, int file_channels, Type /* Populate the spec with all common attributes. * * Care must be taken with the metadata: - * - It should be processed first, before the "Resolution" metadata below, to - * ensure the proper values end up in the ImageSpec - * - It needs to filter format-specific metadata that may no longer apply to - * the current format being written (e.g. metadata for tiff being written to a png) + * - It should be processed first, before the "Resolution" metadata below, to + * ensure the proper values end up in the #ImageSpec + * - It needs to filter format-specific metadata that may no longer apply to + * the current format being written (e.g. metadata for tiff being written to a `PNG`) */ if (ctx.ibuf->metadata) { diff --git a/source/blender/imbuf/intern/oiio/openimageio_support.hh b/source/blender/imbuf/intern/oiio/openimageio_support.hh index 2000e7460bb..f6bf8bda9bc 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_support.hh +++ b/source/blender/imbuf/intern/oiio/openimageio_support.hh @@ -24,13 +24,13 @@ struct ReadContext { const eImbFileType file_type; const int flags; - /* Override the automatic color-role choice with the value specified here. */ + /** Override the automatic color-role choice with the value specified here. */ int use_colorspace_role = -1; - /* Allocate and use all ImBuf image planes even if the image has fewer. */ + /** Allocate and use all #ImBuf image planes even if the image has fewer. */ bool use_all_planes = false; - /* Use the colorspace provided in the image metadata when available. */ + /** Use the `colorspace` provided in the image metadata when available. */ bool use_embedded_colorspace = false; }; @@ -58,7 +58,7 @@ bool imb_oiio_check(const uchar *mem, size_t mem_size, const char *file_format); * The primary method for reading data into an #ImBuf. * * During the `IB_test` phase of loading, the `colorspace` parameter will be populated - * with the appropriate colorspace name. + * with the appropriate `colorspace` name. * * Upon return, the `r_newspec` parameter will contain image format information * which can be inspected afterwards if necessary. @@ -91,7 +91,7 @@ WriteContext imb_create_write_context(const char *file_format, bool prefer_float = true); /** - * Returns an ImageSpec filled in with all common attributes associated with the #ImBuf + * Returns an #ImageSpec filled in with all common attributes associated with the #ImBuf * provided as part of the #WriteContext. * * This includes optional metadata that has been attached to the #ImBuf and which should be diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 29bac03654f..3c4eef83b15 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -10,6 +10,8 @@ #include "MEM_guardedalloc.h" +#include "BKE_blendfile.h" + #include "BLI_fileops.h" #include "BLI_ghash.h" #include "BLI_hash_md5.h" @@ -22,8 +24,6 @@ #include "DNA_space_types.h" /* For FILE_MAX_LIBEXTRA */ -#include "BLO_readfile.h" - #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_metadata.h" @@ -527,7 +527,7 @@ ImBuf *IMB_thumb_manage(const char *filepath, ThumbSize size, ThumbSource source path = file_path = filepath; if (source == THB_SOURCE_BLEND) { - if (BLO_library_path_explode(path, path_buff, &blen_group, &blen_id)) { + if (BKE_blendfile_library_path_explode(path, path_buff, &blen_group, &blen_id)) { if (blen_group) { if (!blen_id) { /* No preview for blen groups */ diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index af619db9417..52fc86fd09d 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -177,7 +177,7 @@ void ABCGenericMeshWriter::do_write(HierarchyContext &context) m_custom_data_config.pack_uvs = args_.export_params->packuv; m_custom_data_config.mesh = mesh; m_custom_data_config.polys = mesh->polys_for_write().data(); - m_custom_data_config.mloop = mesh->loops_for_write().data(); + m_custom_data_config.corner_verts = mesh->corner_verts_for_write().data(); m_custom_data_config.totpoly = mesh->totpoly; m_custom_data_config.totloop = mesh->totloop; m_custom_data_config.totvert = mesh->totvert; @@ -450,7 +450,7 @@ static void get_topology(struct Mesh *mesh, bool &r_has_flat_shaded_poly) { const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); const bke::AttributeAccessor attributes = mesh->attributes(); const VArray sharp_faces = attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); @@ -463,7 +463,7 @@ static void get_topology(struct Mesh *mesh, poly_verts.clear(); loop_counts.clear(); - poly_verts.reserve(loops.size()); + poly_verts.reserve(corner_verts.size()); loop_counts.reserve(polys.size()); /* NOTE: data needs to be written in the reverse order. */ @@ -471,10 +471,9 @@ static void get_topology(struct Mesh *mesh, const MPoly &poly = polys[i]; loop_counts.push_back(poly.totloop); - const MLoop *loop = &loops[poly.loopstart + (poly.totloop - 1)]; - - for (int j = 0; j < poly.totloop; j++, loop--) { - poly_verts.push_back(loop->v); + int corner = poly.loopstart + (poly.totloop - 1); + for (int j = 0; j < poly.totloop; j++, corner--) { + poly_verts.push_back(corner_verts[corner]); } } } diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc index bf7c1fdea06..f9ae257e1ff 100644 --- a/source/blender/io/alembic/intern/abc_customdata.cc +++ b/source/blender/io/alembic/intern/abc_customdata.cc @@ -58,7 +58,7 @@ static void get_uvs(const CDStreamConfig &config, const int num_poly = config.totpoly; MPoly *polys = config.polys; - MLoop *mloop = config.mloop; + int *corner_verts = config.corner_verts; if (!config.pack_uvs) { int count = 0; @@ -86,18 +86,18 @@ static void get_uvs(const CDStreamConfig &config, for (int i = 0; i < num_poly; i++) { MPoly ¤t_poly = polys[i]; - MLoop *looppoly = mloop + current_poly.loopstart + current_poly.totloop; + int *poly_verts = corner_verts + current_poly.loopstart + current_poly.totloop; const float2 *loopuv = mloopuv_array + current_poly.loopstart + current_poly.totloop; for (int j = 0; j < current_poly.totloop; j++) { - looppoly--; + poly_verts--; loopuv--; Imath::V2f uv((*loopuv)[0], (*loopuv)[1]); bool found_same = false; /* Find UV already in uvs array. */ - for (uint32_t uv_idx : idx_map[looppoly->v]) { + for (uint32_t uv_idx : idx_map[*poly_verts]) { if (uvs[uv_idx] == uv) { found_same = true; uvidx.push_back(uv_idx); @@ -108,7 +108,7 @@ static void get_uvs(const CDStreamConfig &config, /* UV doesn't exists for this vertex, add it. */ if (!found_same) { uint32_t uv_idx = idx_count++; - idx_map[looppoly->v].push_back(uv_idx); + idx_map[*poly_verts].push_back(uv_idx); uvidx.push_back(uv_idx); uvs.push_back(uv); } @@ -316,7 +316,7 @@ static void read_uvs(const CDStreamConfig &config, const UInt32ArraySamplePtr &indices) { MPoly *polys = config.polys; - MLoop *mloops = config.mloop; + const int *corner_verts = config.corner_verts; float2 *mloopuvs = static_cast(data); uint uv_index, loop_index, rev_loop_index; @@ -330,7 +330,7 @@ static void read_uvs(const CDStreamConfig &config, for (int f = 0; f < poly.totloop; f++) { rev_loop_index = rev_loop_offset - f; - loop_index = do_uvs_per_loop ? poly.loopstart + f : mloops[rev_loop_index].v; + loop_index = do_uvs_per_loop ? poly.loopstart + f : corner_verts[rev_loop_index]; uv_index = (*indices)[loop_index]; const Imath::V2f &uv = (*uvs)[uv_index]; @@ -412,7 +412,7 @@ static void read_custom_data_mcols(const std::string &iobject_full_name, config.mesh, prop_header.getName().c_str(), CD_PROP_BYTE_COLOR); MCol *cfaces = static_cast(cd_data); const MPoly *polys = config.polys; - MLoop *mloops = config.mloop; + const int *corner_verts = config.corner_verts; size_t face_index = 0; size_t color_index; @@ -427,13 +427,13 @@ static void read_custom_data_mcols(const std::string &iobject_full_name, for (int i = 0; i < config.totpoly; i++) { const MPoly &poly = polys[i]; MCol *cface = &cfaces[poly.loopstart + poly.totloop]; - MLoop *mloop = &mloops[poly.loopstart + poly.totloop]; + const int *poly_verts = &corner_verts[poly.loopstart + poly.totloop]; for (int j = 0; j < poly.totloop; j++, face_index++) { cface--; - mloop--; + poly_verts--; - color_index = is_facevarying ? face_index : mloop->v; + color_index = is_facevarying ? face_index : *poly_verts; if (use_dual_indexing) { color_index = (*indices)[color_index]; } diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h index 17ec872b989..4e011393e36 100644 --- a/source/blender/io/alembic/intern/abc_customdata.h +++ b/source/blender/io/alembic/intern/abc_customdata.h @@ -16,7 +16,6 @@ #include "BLI_math_vector_types.hh" struct CustomData; -struct MLoop; struct MPoly; struct Mesh; @@ -30,7 +29,7 @@ struct UVSample { }; struct CDStreamConfig { - MLoop *mloop; + int *corner_verts; int totloop; MPoly *polys; @@ -73,7 +72,7 @@ struct CDStreamConfig { std::map abc_vertex_colors; CDStreamConfig() - : mloop(NULL), + : corner_verts(NULL), totloop(0), polys(NULL), totpoly(0), diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index ed9de7ea227..f4190f3d40e 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -176,7 +176,7 @@ void read_mverts(Mesh &mesh, const P3fArraySamplePtr positions, const N3fArraySa static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) { MPoly *polys = config.polys; - MLoop *mloops = config.mloop; + int *corner_verts = config.corner_verts; float2 *mloopuvs = config.mloopuv; const Int32ArraySamplePtr &face_indices = mesh_data.face_indices; @@ -209,18 +209,18 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) uint last_vertex_index = 0; for (int f = 0; f < face_size; f++, loop_index++, rev_loop_index--) { - MLoop &loop = mloops[rev_loop_index]; - loop.v = (*face_indices)[loop_index]; + const int vert = (*face_indices)[loop_index]; + corner_verts[rev_loop_index] = vert; - if (f > 0 && loop.v == last_vertex_index) { + if (f > 0 && vert == last_vertex_index) { /* This face is invalid, as it has consecutive loops from the same vertex. This is caused * by invalid geometry in the Alembic file, such as in #76514. */ seen_invalid_geometry = true; } - last_vertex_index = loop.v; + last_vertex_index = vert; if (do_uvs) { - uv_index = (*uvs_indices)[do_uvs_per_loop ? loop_index : loop.v]; + uv_index = (*uvs_indices)[do_uvs_per_loop ? loop_index : last_vertex_index]; /* Some Alembic files are broken (or at least export UVs in a way we don't expect). */ if (uv_index >= uvs_size) { @@ -517,7 +517,7 @@ CDStreamConfig get_config(Mesh *mesh, const bool use_vertex_interpolation) CDStreamConfig config; config.mesh = mesh; config.positions = mesh->vert_positions_for_write().data(); - config.mloop = mesh->loops_for_write().data(); + config.corner_verts = mesh->corner_verts_for_write().data(); config.polys = mesh->polys_for_write().data(); config.totvert = mesh->totvert; config.totloop = mesh->totloop; diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index 59038c41863..04340a04f93 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -328,7 +328,7 @@ void GeometryExporter::create_mesh_primitive_list(short material_index, std::vector &norind) { const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); std::vector vcount_list; @@ -415,11 +415,11 @@ void GeometryExporter::create_mesh_primitive_list(short material_index, int loop_count = poly->totloop; if (material_indices[i] == material_index) { - const MLoop *l = &loops[poly->loopstart]; BCPolygonNormalsIndices normal_indices = norind[i]; for (int j = 0; j < loop_count; j++) { - primitive_list->appendValues(l[j].v); + const int vert = corner_verts[poly->loopstart + j]; + primitive_list->appendValues(vert); primitive_list->appendValues(normal_indices[j]); if (has_uvs) { primitive_list->appendValues(texindex + j); @@ -622,7 +622,7 @@ void GeometryExporter::create_normals(std::vector &normals, const Span positions = me->vert_positions(); const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me); const Span polys = me->polys(); - const Span loops = me->loops(); + const Span corner_verts = me->corner_verts(); const float(*lnors)[3] = nullptr; bool use_custom_normals = false; @@ -644,7 +644,7 @@ void GeometryExporter::create_normals(std::vector &normals, /* For flat faces use face normal as vertex normal: */ const float3 vector = blender::bke::mesh::poly_normal_calc( - positions, loops.slice(poly->loopstart, poly->totloop)); + positions, corner_verts.slice(poly->loopstart, poly->totloop)); Normal n = {vector[0], vector[1], vector[2]}; normals.push_back(n); @@ -661,7 +661,7 @@ void GeometryExporter::create_normals(std::vector &normals, normalize_v3_v3(normalized, lnors[loop_idx]); } else { - copy_v3_v3(normalized, vert_normals[loops[loop_index].v]); + copy_v3_v3(normalized, vert_normals[corner_verts[loop_index]]); normalize_v3(normalized); } Normal n = {normalized[0], normalized[1], normalized[2]}; diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index 5d88c6fd0c0..8c289e55157 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -210,7 +210,7 @@ MeshImporter::MeshImporter(UnitConverter *unitconv, } bool MeshImporter::set_poly_indices( - MPoly *poly, MLoop *mloop, int loop_index, const uint *indices, int loop_count) + MPoly *poly, int *poly_verts, int loop_index, const uint *indices, int loop_count) { poly->loopstart = loop_index; poly->totloop = loop_count; @@ -227,8 +227,8 @@ bool MeshImporter::set_poly_indices( } } - mloop->v = indices[index]; - mloop++; + *poly_verts = indices[index]; + poly_verts++; } return broken_loop; } @@ -456,7 +456,8 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) me->totpoly = total_poly_count; me->totloop = total_loop_count; CustomData_add_layer(&me->pdata, CD_MPOLY, CD_SET_DEFAULT, me->totpoly); - CustomData_add_layer(&me->ldata, CD_MLOOP, CD_SET_DEFAULT, me->totloop); + CustomData_add_layer_named( + &me->ldata, CD_PROP_INT32, CD_SET_DEFAULT, me->totloop, ".corner_vert"); uint totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount(); for (int i = 0; i < totuvset; i++) { @@ -608,8 +609,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, VCOLDataWrapper vcol(collada_mesh->getColors()); MutableSpan polys = me->polys_for_write(); - MutableSpan loops = me->loops_for_write(); - MLoop *mloop = loops.data(); + MutableSpan corner_verts = me->corner_verts_for_write(); int poly_index = 0; int loop_index = 0; @@ -659,7 +659,11 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, /* For each triangle store indices of its 3 vertices */ uint triangle_vertex_indices[3] = { first_vertex, position_indices[1], position_indices[2]}; - set_poly_indices(&polys[poly_index], mloop, loop_index, triangle_vertex_indices, 3); + set_poly_indices(&polys[poly_index], + &corner_verts[loop_index], + loop_index, + triangle_vertex_indices, + 3); if (mp_has_normals) { /* vertex normals, same implementation as for the triangles */ /* The same for vertices normals. */ @@ -668,7 +672,6 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, normal_indices++; } - mloop += 3; poly_index++; loop_index += 3; prim.totpoly++; @@ -703,7 +706,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, } bool broken_loop = set_poly_indices( - &polys[poly_index], mloop, loop_index, position_indices, vcount); + &polys[poly_index], &corner_verts[loop_index], loop_index, position_indices, vcount); if (broken_loop) { invalid_loop_holes += 1; } @@ -768,7 +771,6 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, } poly_index++; - mloop += vcount; loop_index += vcount; start_index += vcount; prim.totpoly++; @@ -890,8 +892,8 @@ std::string *MeshImporter::get_geometry_name(const std::string &mesh_name) static bool bc_has_out_of_bound_indices(Mesh *me) { - for (const MLoop &loop : me->loops()) { - if (loop.v >= me->totvert) { + for (const int vert_i : me->corner_verts()) { + if (vert_i >= me->totvert) { return true; } } @@ -1154,7 +1156,7 @@ bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom) * BKE_mesh_set_custom_normals()'s internals expect me->medge to be populated * and for the MLoops to have correct edge indices. */ if (use_custom_normals && !loop_normals.is_empty()) { - /* BKE_mesh_set_custom_normals()'s internals also expect that each MLoop + /* BKE_mesh_set_custom_normals()'s internals also expect that each corner * has a valid vertex index, which may not be the case due to the existing * logic in read_polys(). This check isn't necessary in the no-custom-normals * case because the invalid MLoops get stripped in a later step. */ diff --git a/source/blender/io/collada/MeshImporter.h b/source/blender/io/collada/MeshImporter.h index 3d815a025ec..e34a9e322fb 100644 --- a/source/blender/io/collada/MeshImporter.h +++ b/source/blender/io/collada/MeshImporter.h @@ -93,7 +93,7 @@ class MeshImporter : public MeshImporterBase { std::multimap materials_mapped_to_geom; bool set_poly_indices( - MPoly *poly, MLoop *mloop, int loop_index, const unsigned int *indices, int loop_count); + MPoly *poly, int *poly_verts, int loop_index, const unsigned int *indices, int loop_count); void set_face_uv(blender::float2 *mloopuv, UVDataWrapper &uvs, diff --git a/source/blender/io/ply/CMakeLists.txt b/source/blender/io/ply/CMakeLists.txt index 980a2c0b4cb..76d73d6772a 100644 --- a/source/blender/io/ply/CMakeLists.txt +++ b/source/blender/io/ply/CMakeLists.txt @@ -14,6 +14,7 @@ set(INC ../../makesdna ../../makesrna ../../windowmanager + ../../../../extern/fast_float ../../../../extern/fmtlib/include ../../../../intern/guardedalloc ) @@ -31,13 +32,11 @@ set(SRC exporter/ply_file_buffer_ascii.cc exporter/ply_file_buffer_binary.cc importer/ply_import.cc - importer/ply_import_ascii.cc - importer/ply_import_binary.cc + importer/ply_import_buffer.cc + importer/ply_import_data.cc importer/ply_import_mesh.cc IO_ply.cc - - exporter/ply_export.hh exporter/ply_export_data.hh exporter/ply_export_header.hh @@ -46,14 +45,12 @@ set(SRC exporter/ply_file_buffer_ascii.hh exporter/ply_file_buffer_binary.hh importer/ply_import.hh - importer/ply_import_ascii.hh - importer/ply_import_binary.hh + importer/ply_import_buffer.hh + importer/ply_import_data.hh importer/ply_import_mesh.hh IO_ply.h intern/ply_data.hh - intern/ply_functions.cc - intern/ply_functions.hh ) set(LIB @@ -63,12 +60,10 @@ set(LIB blender_add_lib(bf_ply "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") -if (WITH_GTESTS) +if(WITH_GTESTS) set(TEST_SRC - tests/io_ply_importer_test.cc - - tests/io_ply_exporter_test.cc - + tests/io_ply_importer_test.cc + tests/io_ply_exporter_test.cc ) set(TEST_INC ../../blenloader diff --git a/source/blender/io/ply/exporter/ply_export_data.cc b/source/blender/io/ply/exporter/ply_export_data.cc index 1c4379f24ec..28204339eb3 100644 --- a/source/blender/io/ply/exporter/ply_export_data.cc +++ b/source/blender/io/ply/exporter/ply_export_data.cc @@ -39,8 +39,10 @@ void write_vertices(FileBuffer &buffer, const PlyData &ply_data) void write_faces(FileBuffer &buffer, const PlyData &ply_data) { - for (const Array &face : ply_data.faces) { - buffer.write_face(char(face.size()), face); + const uint32_t *indices = ply_data.face_vertices.data(); + for (uint32_t face_size : ply_data.face_sizes) { + buffer.write_face(char(face_size), Span(indices, face_size)); + indices += face_size; } buffer.write_to_file(); } diff --git a/source/blender/io/ply/exporter/ply_export_header.cc b/source/blender/io/ply/exporter/ply_export_header.cc index 014aa9de897..8dac491e298 100644 --- a/source/blender/io/ply/exporter/ply_export_header.cc +++ b/source/blender/io/ply/exporter/ply_export_header.cc @@ -49,13 +49,13 @@ void write_header(FileBuffer &buffer, buffer.write_header_scalar_property("float", "t"); } - if (!ply_data.faces.is_empty()) { - buffer.write_header_element("face", int32_t(ply_data.faces.size())); + if (!ply_data.face_sizes.is_empty()) { + buffer.write_header_element("face", int(ply_data.face_sizes.size())); buffer.write_header_list_property("uchar", "uint", "vertex_indices"); } if (!ply_data.edges.is_empty()) { - buffer.write_header_element("edge", int32_t(ply_data.edges.size())); + buffer.write_header_element("edge", int(ply_data.edges.size())); buffer.write_header_scalar_property("int", "vertex1"); buffer.write_header_scalar_property("int", "vertex2"); } diff --git a/source/blender/io/ply/exporter/ply_export_load_plydata.cc b/source/blender/io/ply/exporter/ply_export_load_plydata.cc index 6cf09474d61..b2139f6d8e3 100644 --- a/source/blender/io/ply/exporter/ply_export_load_plydata.cc +++ b/source/blender/io/ply/exporter/ply_export_load_plydata.cc @@ -114,19 +114,22 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams const float2 *uv_map = static_cast( CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2)); - Map vertex_map = generate_vertex_map(mesh, uv_map, export_params); + Map vertex_map; + generate_vertex_map(mesh, uv_map, export_params, vertex_map); set_world_axes_transform( &export_object_eval_, export_params.forward_axis, export_params.up_axis); /* Load faces into plyData. */ + plyData.face_vertices.reserve(mesh->totloop); + plyData.face_sizes.reserve(mesh->totpoly); int loop_offset = 0; - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); for (const MPoly &poly : mesh->polys()) { - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - Array poly_verts(poly_loops.size()); + const Span mesh_poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + Array poly_verts(mesh_poly_verts.size()); - for (int i = 0; i < poly_loops.size(); ++i) { + for (int i = 0; i < mesh_poly_verts.size(); ++i) { float2 uv; if (export_params.export_uv && uv_map != nullptr) { uv = uv_map[i + loop_offset]; @@ -134,13 +137,12 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams else { uv = {0, 0}; } - UV_vertex_key key = UV_vertex_key(uv, poly_loops[i].v); + UV_vertex_key key = UV_vertex_key(uv, mesh_poly_verts[i]); int ply_vertex_index = vertex_map.lookup(key); - poly_verts[i] = (uint32_t(ply_vertex_index + vertex_offset)); + plyData.face_vertices.append(ply_vertex_index + vertex_offset); } - loop_offset += poly_loops.size(); - - plyData.faces.append(std::move(poly_verts)); + loop_offset += poly.totloop; + plyData.face_sizes.append(poly.totloop); } Array mesh_vertex_index_LUT(vertex_map.size()); @@ -221,32 +223,31 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams DEG_OBJECT_ITER_END; } -Map generate_vertex_map(const Mesh *mesh, - const float2 *uv_map, - const PLYExportParams &export_params) +void generate_vertex_map(const Mesh *mesh, + const float2 *uv_map, + const PLYExportParams &export_params, + Map &r_map) { - Map vertex_map; - const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); const int totvert = mesh->totvert; - vertex_map.reserve(totvert); + r_map.reserve(totvert); if (uv_map == nullptr || !export_params.export_uv) { for (int vertex_index = 0; vertex_index < totvert; ++vertex_index) { UV_vertex_key key = UV_vertex_key({0, 0}, vertex_index); - vertex_map.add_new(key, int(vertex_map.size())); + r_map.add_new(key, int(r_map.size())); } - return vertex_map; + return; } const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT}; UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(polys.data(), nullptr, nullptr, - loops.data(), + corner_verts.data(), reinterpret_cast(uv_map), uint(polys.size()), totvert, @@ -259,7 +260,7 @@ Map generate_vertex_map(const Mesh *mesh, if (uv_vert == nullptr) { UV_vertex_key key = UV_vertex_key({0, 0}, vertex_index); - vertex_map.add_new(key, int(vertex_map.size())); + r_map.add_new(key, int(r_map.size())); } for (; uv_vert; uv_vert = uv_vert->next) { @@ -267,10 +268,10 @@ Map generate_vertex_map(const Mesh *mesh, const int loopstart = polys[uv_vert->poly_index].loopstart; float2 vert_uv_coords(uv_map[loopstart + uv_vert->loop_of_poly_index]); UV_vertex_key key = UV_vertex_key(vert_uv_coords, vertex_index); - vertex_map.add(key, int(vertex_map.size())); + r_map.add(key, int(r_map.size())); } } BKE_mesh_uv_vert_map_free(uv_vert_map); - return vertex_map; } + } // namespace blender::io::ply diff --git a/source/blender/io/ply/exporter/ply_export_load_plydata.hh b/source/blender/io/ply/exporter/ply_export_load_plydata.hh index 4b5e1fb0c09..29332687c9c 100644 --- a/source/blender/io/ply/exporter/ply_export_load_plydata.hh +++ b/source/blender/io/ply/exporter/ply_export_load_plydata.hh @@ -13,6 +13,7 @@ #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_object.h" +#include "BLI_hash.hh" #include "BLI_math.h" #include "RNA_types.h" @@ -45,16 +46,14 @@ struct UV_vertex_key { uint64_t hash() const { - return ((std::hash()(UV.x) ^ (std::hash()(UV.y) << 1)) >> 1) ^ - (std::hash()(mesh_vertex_index) << 1); + return get_default_hash_3(UV.x, UV.y, mesh_vertex_index); } }; -blender::Map generate_vertex_map(const Mesh *mesh, - const float2 *uv_map, - const PLYExportParams &export_params); - -void load_plydata(PlyData &plyData, const bContext *C, const PLYExportParams &export_params); +void generate_vertex_map(const Mesh *mesh, + const float2 *uv_map, + const PLYExportParams &export_params, + Map &r_map); void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams &export_params); } // namespace blender::io::ply diff --git a/source/blender/io/ply/exporter/ply_file_buffer.cc b/source/blender/io/ply/exporter/ply_file_buffer.cc index 2e9f5fe4bb9..11d49599479 100644 --- a/source/blender/io/ply/exporter/ply_file_buffer.cc +++ b/source/blender/io/ply/exporter/ply_file_buffer.cc @@ -64,14 +64,6 @@ void FileBuffer::write_newline() write_fstring("\n"); } -void FileBuffer::ensure_space(size_t at_least) -{ - if (blocks_.is_empty() || (blocks_.last().capacity() - blocks_.last().size() < at_least)) { - blocks_.append(VectorChar()); - blocks_.reserve(std::max(at_least, buffer_chunk_size_)); - } -} - void FileBuffer::write_bytes(Span bytes) { ensure_space(bytes.size()); diff --git a/source/blender/io/ply/exporter/ply_file_buffer.hh b/source/blender/io/ply/exporter/ply_file_buffer.hh index c26f9e56ed1..cf2dda58449 100644 --- a/source/blender/io/ply/exporter/ply_file_buffer.hh +++ b/source/blender/io/ply/exporter/ply_file_buffer.hh @@ -6,11 +6,8 @@ #pragma once -#include #include -#include -#include "BLI_array.hh" #include "BLI_compiler_attrs.h" #include "BLI_fileops.h" #include "BLI_string_ref.hh" @@ -75,7 +72,13 @@ class FileBuffer : private NonMovable { protected: /* Ensure the last block contains at least this amount of free space. * If not, add a new block with max of block size & the amount of space needed. */ - void ensure_space(size_t at_least); + void ensure_space(size_t at_least) + { + if (blocks_.is_empty() || (blocks_.last().capacity() - blocks_.last().size() < at_least)) { + blocks_.append(VectorChar()); + blocks_.last().reserve(std::max(at_least, buffer_chunk_size_)); + } + } template void write_fstring(const char *fmt, T &&...args) { diff --git a/source/blender/io/ply/importer/ply_import.cc b/source/blender/io/ply/importer/ply_import.cc index 6454c021701..1ddb31837d7 100644 --- a/source/blender/io/ply/importer/ply_import.cc +++ b/source/blender/io/ply/importer/ply_import.cc @@ -14,7 +14,6 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BLI_fileops.hh" #include "BLI_math_vector.h" #include "BLI_memory_utils.hh" @@ -22,53 +21,137 @@ #include "DEG_depsgraph_build.h" #include "ply_data.hh" -#include "ply_functions.hh" #include "ply_import.hh" -#include "ply_import_ascii.hh" -#include "ply_import_binary.hh" +#include "ply_import_buffer.hh" +#include "ply_import_data.hh" #include "ply_import_mesh.hh" namespace blender::io::ply { -void splitstr(std::string str, Vector &words, const StringRef &deli) +/* If line starts with keyword, returns true and drops it from the line. */ +static bool parse_keyword(Span &str, StringRef keyword) { - int pos; - - while ((pos = int(str.find(deli))) != std::string::npos) { - words.append(str.substr(0, pos)); - str.erase(0, pos + deli.size()); + const size_t keyword_len = keyword.size(); + if (str.size() < keyword_len) { + return false; } - /* We add the final word to the vector. */ - words.append(str.substr()); + if (memcmp(str.data(), keyword.data(), keyword_len) != 0) { + return false; + } + str = str.drop_front(keyword_len); + return true; } -enum PlyDataTypes from_string(const StringRef &input) +static Span parse_word(Span &str) { - if (input == "uchar") { + size_t len = 0; + while (len < str.size() && str[len] > ' ') { + ++len; + } + Span word(str.begin(), len); + str = str.drop_front(len); + return word; +} + +static void skip_space(Span &str) +{ + while (!str.is_empty() && str[0] <= ' ') + str = str.drop_front(1); +} + +static PlyDataTypes type_from_string(Span word) +{ + StringRef input(word.data(), word.size()); + if (input == "uchar" || input == "uint8") { return PlyDataTypes::UCHAR; } - if (input == "char") { + if (input == "char" || input == "int8") { return PlyDataTypes::CHAR; } - if (input == "ushort") { + if (input == "ushort" || input == "uint16") { return PlyDataTypes::USHORT; } - if (input == "short") { + if (input == "short" || input == "int16") { return PlyDataTypes::SHORT; } - if (input == "uint") { + if (input == "uint" || input == "uint32") { return PlyDataTypes::UINT; } - if (input == "int") { + if (input == "int" || input == "int32") { return PlyDataTypes::INT; } - if (input == "float") { + if (input == "float" || input == "float32") { return PlyDataTypes::FLOAT; } - if (input == "double") { + if (input == "double" || input == "float64") { return PlyDataTypes::DOUBLE; } - return PlyDataTypes::FLOAT; + return PlyDataTypes::NONE; +} + +const char *read_header(PlyReadBuffer &file, PlyHeader &r_header) +{ + Span word, line; + line = file.read_line(); + if (StringRef(line.data(), line.size()) != "ply") { + return "Invalid PLY header."; + } + + while (true) { /* We break when end_header is encountered. */ + line = file.read_line(); + + if (parse_keyword(line, "format")) { + skip_space(line); + if (parse_keyword(line, "ascii")) { + r_header.type = PlyFormatType::ASCII; + } + else if (parse_keyword(line, "binary_big_endian")) { + r_header.type = PlyFormatType::BINARY_BE; + } + else if (parse_keyword(line, "binary_little_endian")) { + r_header.type = PlyFormatType::BINARY_LE; + } + } + else if (parse_keyword(line, "element")) { + PlyElement element; + + skip_space(line); + word = parse_word(line); + element.name = std::string(word.data(), word.size()); + skip_space(line); + word = parse_word(line); + element.count = std::stoi(std::string(word.data(), word.size())); + r_header.elements.append(element); + } + else if (parse_keyword(line, "property")) { + PlyProperty property; + skip_space(line); + if (parse_keyword(line, "list")) { + skip_space(line); + property.count_type = type_from_string(parse_word(line)); + } + skip_space(line); + property.type = type_from_string(parse_word(line)); + skip_space(line); + word = parse_word(line); + property.name = std::string(word.data(), word.size()); + r_header.elements.last().properties.append(property); + } + else if (parse_keyword(line, "end_header")) { + break; + } + else if (line.is_empty() || (line.first() >= '0' && line.first() <= '9') || + line.first() == '-') { + /* A value was found before we broke out of the loop. No end_header. */ + return "No end_header."; + } + } + + file.after_header(r_header.type != PlyFormatType::ASCII); + for (PlyElement &el : r_header.elements) { + el.calc_stride(); + } + return nullptr; } void importer_main(bContext *C, const PLYImportParams &import_params, wmOperator *op) @@ -85,75 +168,42 @@ void importer_main(Main *bmain, const PLYImportParams &import_params, wmOperator *op) { - - std::string line; - fstream infile(import_params.filepath, std::ios::in | std::ios::binary); - - PlyHeader header; - - while (true) { /* We break when end_header is encountered. */ - safe_getline(infile, line); - if (header.header_size == 0 && line != "ply") { - fprintf(stderr, "PLY Importer: failed to read file. Invalid PLY header.\n"); - BKE_report(op->reports, RPT_ERROR, "PLY Importer: Invalid PLY header."); - return; - } - header.header_size++; - Vector words{}; - splitstr(line, words, " "); - - if (strcmp(words[0].c_str(), "format") == 0) { - if (strcmp(words[1].c_str(), "ascii") == 0) { - header.type = PlyFormatType::ASCII; - } - else if (strcmp(words[1].c_str(), "binary_big_endian") == 0) { - header.type = PlyFormatType::BINARY_BE; - } - else if (strcmp(words[1].c_str(), "binary_little_endian") == 0) { - header.type = PlyFormatType::BINARY_LE; - } - } - else if (strcmp(words[0].c_str(), "element") == 0) { - header.elements.append(std::make_pair(words[1], std::stoi(words[2]))); - if (strcmp(words[1].c_str(), "vertex") == 0) { - header.vertex_count = std::stoi(words[2]); - } - else if (strcmp(words[1].c_str(), "face") == 0) { - header.face_count = std::stoi(words[2]); - } - else if (strcmp(words[1].c_str(), "edge") == 0) { - header.edge_count = std::stoi(words[2]); - } - } - else if (strcmp(words[0].c_str(), "property") == 0) { - std::pair property; - property.first = words[2]; - property.second = from_string(words[1]); - - while (header.properties.size() < header.elements.size()) { - Vector> temp; - header.properties.append(temp); - } - header.properties[header.elements.size() - 1].append(property); - } - else if (words[0] == "end_header") { - break; - } - else if ((words[0][0] >= '0' && words[0][0] <= '9') || words[0][0] == '-' || line.empty() || - infile.eof()) { - /* A value was found before we broke out of the loop. No end_header. */ - BKE_report(op->reports, RPT_ERROR, "PLY Importer: No end_header"); - return; - } - } - - /* Name used for both mesh and object. */ + /* File base name used for both mesh and object. */ char ob_name[FILE_MAX]; BLI_strncpy(ob_name, BLI_path_basename(import_params.filepath), FILE_MAX); BLI_path_extension_replace(ob_name, FILE_MAX, ""); - Mesh *mesh = BKE_mesh_add(bmain, ob_name); + /* Parse header. */ + PlyReadBuffer file(import_params.filepath, 64 * 1024); + PlyHeader header; + const char *err = read_header(file, header); + if (err != nullptr) { + fprintf(stderr, "PLY Importer: %s: %s\n", ob_name, err); + BKE_reportf(op->reports, RPT_ERROR, "PLY Importer: %s: %s", ob_name, err); + return; + } + + /* Parse actual file data. */ + std::unique_ptr data = import_ply_data(file, header); + if (data == nullptr) { + fprintf(stderr, "PLY Importer: failed importing %s, unknown error\n", ob_name); + BKE_report(op->reports, RPT_ERROR, "PLY Importer: failed importing, unknown error."); + return; + } + if (!data->error.empty()) { + fprintf(stderr, "PLY Importer: failed importing %s: %s\n", ob_name, data->error.c_str()); + BKE_report(op->reports, RPT_ERROR, "PLY Importer: failed importing, unknown error."); + return; + } + if (data->vertices.is_empty()) { + fprintf(stderr, "PLY Importer: file %s contains no vertices\n", ob_name); + BKE_report(op->reports, RPT_ERROR, "PLY Importer: failed importing, no vertices."); + return; + } + + /* Create mesh and do all prep work. */ + Mesh *mesh = BKE_mesh_add(bmain, ob_name); BKE_view_layer_base_deselect_all(scene, view_layer); LayerCollection *lc = BKE_layer_collection_get_active(view_layer); Object *obj = BKE_object_add_only_object(bmain, OB_MESH, ob_name); @@ -163,26 +213,13 @@ void importer_main(Main *bmain, Base *base = BKE_view_layer_base_find(view_layer, obj); BKE_view_layer_base_select_and_set_active(view_layer, base); - try { - std::unique_ptr data; - if (header.type == PlyFormatType::ASCII) { - data = import_ply_ascii(infile, &header); - } - else { - data = import_ply_binary(infile, &header); - } - - Mesh *temp_val = convert_ply_to_mesh(*data, mesh, import_params); - if (import_params.merge_verts && temp_val != mesh) { - BKE_mesh_nomain_to_mesh(temp_val, mesh, obj); - } - } - catch (std::exception &e) { - fprintf(stderr, "PLY Importer: failed to read file. %s.\n", e.what()); - BKE_report(op->reports, RPT_ERROR, "PLY Importer: failed to parse file."); - return; + /* Stuff ply data into the mesh. */ + Mesh *temp_val = convert_ply_to_mesh(*data, mesh, import_params); + if (import_params.merge_verts && temp_val != mesh) { + BKE_mesh_nomain_to_mesh(temp_val, mesh, obj); } + /* Object matrix and finishing up. */ float global_scale = import_params.global_scale; if ((scene->unit.system != USER_UNIT_NONE) && import_params.use_scene_unit) { global_scale *= scene->unit.scale_length; @@ -205,7 +242,5 @@ void importer_main(Main *bmain, DEG_id_tag_update_ex(bmain, &obj->id, flags); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); DEG_relations_tag_update(bmain); - - infile.close(); } } // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import.hh b/source/blender/io/ply/importer/ply_import.hh index a19f32cc5ad..c10482377e9 100644 --- a/source/blender/io/ply/importer/ply_import.hh +++ b/source/blender/io/ply/importer/ply_import.hh @@ -11,7 +11,7 @@ namespace blender::io::ply { -enum PlyDataTypes from_string(const StringRef &input); +class PlyReadBuffer; void splitstr(std::string str, Vector &words, const StringRef &deli); @@ -25,4 +25,6 @@ void importer_main(Main *bmain, const PLYImportParams &import_params, wmOperator *op); +const char *read_header(PlyReadBuffer &file, PlyHeader &r_header); + } // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import_ascii.cc b/source/blender/io/ply/importer/ply_import_ascii.cc deleted file mode 100644 index 0579255eec7..00000000000 --- a/source/blender/io/ply/importer/ply_import_ascii.cc +++ /dev/null @@ -1,222 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup ply - */ - -#include "ply_import_ascii.hh" -#include "ply_functions.hh" - -#include -#include - -namespace blender::io::ply { - -std::unique_ptr import_ply_ascii(fstream &file, PlyHeader *header) -{ - std::unique_ptr data = std::make_unique(load_ply_ascii(file, header)); - return data; -} - -PlyData load_ply_ascii(fstream &file, const PlyHeader *header) -{ - PlyData data; - /* Check if header contains alpha. */ - std::pair alpha = {"alpha", PlyDataTypes::UCHAR}; - bool has_alpha = std::find(header->properties[0].begin(), header->properties[0].end(), alpha) != - header->properties[0].end(); - - /* Check if header contains colors. */ - std::pair red = {"red", PlyDataTypes::UCHAR}; - bool has_color = std::find(header->properties[0].begin(), header->properties[0].end(), red) != - header->properties[0].end(); - - /* Check if header contains normals. */ - std::pair normalx = {"nx", PlyDataTypes::FLOAT}; - bool has_normals = std::find(header->properties[0].begin(), - header->properties[0].end(), - normalx) != header->properties[0].end(); - - /* Check if header contains uv data. */ - std::pair uv = {"s", PlyDataTypes::FLOAT}; - const bool has_uv = std::find(header->properties[0].begin(), header->properties[0].end(), uv) != - header->properties[0].end(); - - int3 vertex_index = get_vertex_index(header); - int alpha_index; - int3 color_index; - int3 normal_index; - int2 uv_index; - - if (has_alpha) { - alpha_index = get_index(header, "alpha", PlyDataTypes::UCHAR); - } - - if (has_color) { - /* x=red, y=green, z=blue */ - color_index = get_color_index(header); - } - - if (has_normals) { - normal_index = get_normal_index(header); - } - - if (has_uv) { - uv_index = get_uv_index(header); - } - - for (int i = 0; i < header->vertex_count; i++) { - std::string line; - safe_getline(file, line); - Vector value_vec = explode(line, ' '); - - /* Vertex coords */ - float3 vertex3; - vertex3.x = std::stof(value_vec[vertex_index.x]); - vertex3.y = std::stof(value_vec[vertex_index.y]); - vertex3.z = std::stof(value_vec[vertex_index.z]); - - data.vertices.append(vertex3); - - /* Vertex colors */ - if (has_color) { - float4 colors4; - colors4.x = std::stof(value_vec[color_index.x]) / 255.0f; - colors4.y = std::stof(value_vec[color_index.y]) / 255.0f; - colors4.z = std::stof(value_vec[color_index.z]) / 255.0f; - if (has_alpha) { - colors4.w = std::stof(value_vec[alpha_index]) / 255.0f; - } - else { - colors4.w = 1.0f; - } - - data.vertex_colors.append(colors4); - } - - /* If normals */ - if (has_normals) { - float3 normals3; - normals3.x = std::stof(value_vec[normal_index.x]); - normals3.y = std::stof(value_vec[normal_index.y]); - normals3.z = std::stof(value_vec[normal_index.z]); - - data.vertex_normals.append(normals3); - } - - /* If uv */ - if (has_uv) { - float2 uvmap; - uvmap.x = std::stof(value_vec[uv_index.x]); - uvmap.y = std::stof(value_vec[uv_index.y]); - - data.uv_coordinates.append(uvmap); - } - } - for (int i = 0; i < header->face_count; i++) { - std::string line; - getline(file, line); - Vector value_vec = explode(line, ' '); - int count = std::stoi(value_vec[0]); - Array vertex_indices(count); - - for (int j = 1; j <= count; j++) { - int index = std::stoi(value_vec[j]); - /* If the face has a vertex index that is outside the range. */ - if (index >= data.vertices.size()) { - throw std::runtime_error("Vertex index out of bounds"); - } - vertex_indices[j - 1] = index; - } - data.faces.append(vertex_indices); - } - - for (int i = 0; i < header->edge_count; i++) { - std::string line; - getline(file, line); - Vector value_vec = explode(line, ' '); - - std::pair edge = std::make_pair(stoi(value_vec[0]), stoi(value_vec[1])); - data.edges.append(edge); - } - - return data; -} - -int3 get_vertex_index(const PlyHeader *header) -{ - int3 vertex_index; - vertex_index.x = get_index(header, "x", PlyDataTypes::FLOAT); - vertex_index.y = get_index(header, "y", PlyDataTypes::FLOAT); - vertex_index.z = get_index(header, "z", PlyDataTypes::FLOAT); - - return vertex_index; -} - -int3 get_color_index(const PlyHeader *header) -{ - int3 color_index; - color_index.x = get_index(header, "red", PlyDataTypes::UCHAR); - color_index.y = get_index(header, "green", PlyDataTypes::UCHAR); - color_index.z = get_index(header, "blue", PlyDataTypes::UCHAR); - - return color_index; -} - -int3 get_normal_index(const PlyHeader *header) -{ - int3 normal_index; - normal_index.x = get_index(header, "nx", PlyDataTypes::FLOAT); - normal_index.y = get_index(header, "ny", PlyDataTypes::FLOAT); - normal_index.z = get_index(header, "nz", PlyDataTypes::FLOAT); - - return normal_index; -} - -int2 get_uv_index(const PlyHeader *header) -{ - int2 uv_index; - uv_index.x = get_index(header, "s", PlyDataTypes::FLOAT); - uv_index.y = get_index(header, "t", PlyDataTypes::FLOAT); - - return uv_index; -} - -int get_index(const PlyHeader *header, std::string property, PlyDataTypes datatype) -{ - std::pair pair = {property, datatype}; - const std::pair *it = std::find( - header->properties[0].begin(), header->properties[0].end(), pair); - return (int)(it - header->properties[0].begin()); -} - -Vector explode(const StringRef str, const char &ch) -{ - std::string next; - Vector result; - - /* For each character in the string. */ - for (char c : str) { - /* If we've hit the terminal character. */ - if (c == ch) { - /* If we have some characters accumulated. */ - if (!next.empty()) { - /* Add them to the result vector. */ - result.append(next); - next.clear(); - } - } - else { - /* Accumulate the next character into the sequence. */ - next += c; - } - } - - if (!next.empty()) { - result.append(next); - } - - return result; -} - -} // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import_ascii.hh b/source/blender/io/ply/importer/ply_import_ascii.hh deleted file mode 100644 index 3506dd3ed54..00000000000 --- a/source/blender/io/ply/importer/ply_import_ascii.hh +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup ply - */ - -#pragma once - -#include "BLI_fileops.hh" - -#include "DNA_mesh_types.h" - -#include "IO_ply.h" -#include "ply_data.hh" - -namespace blender::io::ply { - -/** - * The function that gets called from the importer. - * \param file: The PLY file that was opened. - * \param header: The information in the PLY header. - */ -std::unique_ptr import_ply_ascii(fstream &file, PlyHeader *header); - -/** - * Loads the information from the PLY file in ASCII format to the #PlyData data-structure. - * \param file: The PLY file that was opened. - * \param header: The information in the PLY header. - * \return The #PlyData data-structure that can be used for conversion to a Mesh. - */ -PlyData load_ply_ascii(fstream &file, const PlyHeader *header); - -int3 get_vertex_index(const PlyHeader *header); -int3 get_color_index(const PlyHeader *header); -int3 get_normal_index(const PlyHeader *header); -int2 get_uv_index(const PlyHeader *header); -int get_index(const PlyHeader *header, std::string property, PlyDataTypes datatype); -Vector explode(const StringRef str, const char &ch); -} // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import_binary.cc b/source/blender/io/ply/importer/ply_import_binary.cc deleted file mode 100644 index 163d3fdbeb7..00000000000 --- a/source/blender/io/ply/importer/ply_import_binary.cc +++ /dev/null @@ -1,215 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup ply - */ -#include "BLI_array.hh" - -#include "ply_import_binary.hh" - -#include - -namespace blender::io::ply { -std::unique_ptr import_ply_binary(fstream &file, const PlyHeader *header) -{ - std::unique_ptr data = std::make_unique(load_ply_binary(file, header)); - return data; -} - -template T read(fstream &file, bool is_big_endian) -{ - T returnVal; - file.read((char *)&returnVal, sizeof(returnVal)); - check_file_errors(file); - if (is_big_endian) { - returnVal = swap_bytes(returnVal); - } - return returnVal; -} - -template uint8_t read(fstream &file, bool is_big_endian); -template int8_t read(fstream &file, bool is_big_endian); -template uint16_t read(fstream &file, bool is_big_endian); -template int16_t read(fstream &file, bool is_big_endian); -template uint32_t read(fstream &file, bool is_big_endian); -template int32_t read(fstream &file, bool is_big_endian); -template float read(fstream &file, bool is_big_endian); -template double read(fstream &file, bool is_big_endian); - -void check_file_errors(const fstream &file) -{ - if (file.bad()) { - throw std::ios_base::failure("Read/Write error on io operation"); - } - if (file.fail()) { - throw std::ios_base::failure("Logical error on io operation"); - } - if (file.eof()) { - throw std::ios_base::failure("Reached end of the file"); - } -} - -void discard_value(fstream &file, const PlyDataTypes type) -{ - switch (type) { - case CHAR: - read(file, false); - break; - case UCHAR: - read(file, false); - break; - case SHORT: - read(file, false); - break; - case USHORT: - read(file, false); - break; - case INT: - read(file, false); - break; - case UINT: - read(file, false); - break; - case FLOAT: - read(file, false); - break; - case DOUBLE: - read(file, false); - break; - } -} - -PlyData load_ply_binary(fstream &file, const PlyHeader *header) -{ - PlyData data; - bool is_big_endian = header->type == PlyFormatType::BINARY_BE; - - for (int i = 0; i < header->elements.size(); i++) { - if (header->elements[i].first == "vertex") { - /* Import vertices. */ - load_vertex_data(file, header, &data, i); - } - else if (header->elements[i].first == "edge") { - /* Import edges. */ - for (int j = 0; j < header->elements[i].second; j++) { - std::pair vertex_indices; - for (auto [name, type] : header->properties[i]) { - if (name == "vertex1") { - vertex_indices.first = int(read(file, is_big_endian)); - } - else if (name == "vertex2") { - vertex_indices.second = int(read(file, is_big_endian)); - } - else { - discard_value(file, type); - } - } - data.edges.append(vertex_indices); - } - } - else if (header->elements[i].first == "face") { - - /* Import faces. */ - for (int j = 0; j < header->elements[i].second; j++) { - /* Assume vertex_index_count_type is uchar. */ - uint8_t count = read(file, is_big_endian); - Array vertex_indices(count); - - /* Loop over the amount of vertex indices in this face. */ - for (uint8_t k = 0; k < count; k++) { - uint32_t index = read(file, is_big_endian); - /* If the face has a vertex index that is outside the range. */ - if (index >= data.vertices.size()) { - throw std::runtime_error("Vertex index out of bounds"); - } - vertex_indices[k] = index; - } - data.faces.append(vertex_indices); - } - } - else { - /* Nothing else is supported. */ - for (int j = 0; j < header->elements[i].second; j++) { - for (auto [name, type] : header->properties[i]) { - discard_value(file, type); - } - } - } - } - - return data; -} - -void load_vertex_data(fstream &file, const PlyHeader *header, PlyData *r_data, int index) -{ - bool hasNormal = false; - bool hasColor = false; - bool hasUv = false; - bool is_big_endian = header->type == PlyFormatType::BINARY_BE; - - for (int i = 0; i < header->vertex_count; i++) { - float3 coord{0}; - float3 normal{0}; - float4 color{1}; - float2 uv{0}; - - for (auto [name, type] : header->properties[index]) { - if (name == "x") { - coord.x = read(file, is_big_endian); - } - else if (name == "y") { - coord.y = read(file, is_big_endian); - } - else if (name == "z") { - coord.z = read(file, is_big_endian); - } - else if (name == "nx") { - normal.x = read(file, is_big_endian); - hasNormal = true; - } - else if (name == "ny") { - normal.y = read(file, is_big_endian); - } - else if (name == "nz") { - normal.z = read(file, is_big_endian); - } - else if (name == "red") { - color.x = read(file, is_big_endian) / 255.0f; - hasColor = true; - } - else if (name == "green") { - color.y = read(file, is_big_endian) / 255.0f; - } - else if (name == "blue") { - color.z = read(file, is_big_endian) / 255.0f; - } - else if (name == "alpha") { - color.w = read(file, is_big_endian) / 255.0f; - } - else if (name == "s") { - uv.x = read(file, is_big_endian); - hasUv = true; - } - else if (name == "t") { - uv.y = read(file, is_big_endian); - } - else { - /* No other properties are supported yet. */ - discard_value(file, type); - } - } - - r_data->vertices.append(coord); - if (hasNormal) { - r_data->vertex_normals.append(normal); - } - if (hasColor) { - r_data->vertex_colors.append(color); - } - if (hasUv) { - r_data->uv_coordinates.append(uv); - } - } -} - -} // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import_binary.hh b/source/blender/io/ply/importer/ply_import_binary.hh deleted file mode 100644 index 91f471e5eb2..00000000000 --- a/source/blender/io/ply/importer/ply_import_binary.hh +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup ply - */ - -#pragma once - -#include "BLI_endian_switch.h" -#include "BLI_fileops.hh" - -#include "ply_data.hh" - -namespace blender::io::ply { - -/** - * The function that gets called from the importer. - * \param file: The PLY file that was opened. - * \param header: The information in the PLY header. - * \return The #PlyData data-structure that can be used for conversion to a #Mesh. - */ -std::unique_ptr import_ply_binary(fstream &file, const PlyHeader *header); - -/** - * Loads the information from the PLY file in binary format to the #PlyData data-structure. - * \param file: The PLY file that was opened. - * \param header: The information in the PLY header. - * \return The #PlyData data-structure that can be used for conversion to a Mesh. - */ -PlyData load_ply_binary(fstream &file, const PlyHeader *header); - -void load_vertex_data(fstream &file, const PlyHeader *header, PlyData *r_data, int index); - -void check_file_errors(const fstream &file); - -void discard_value(fstream &file, const PlyDataTypes type); - -template T swap_bytes(T input) -{ - /* In big endian, the most-significant byte is first. - * So, we need to swap the byte order. */ - - /* 0xAC in LE should become 0xCA in BE. */ - if (sizeof(T) == 1) { - return input; - } - - if constexpr (sizeof(T) == 2) { - uint16_t value = reinterpret_cast(input); - BLI_endian_switch_uint16(&value); - return reinterpret_cast(value); - } - - if constexpr (sizeof(T) == 4) { - /* Reinterpret this data as uint32 for easy rearranging of bytes. */ - uint32_t value = reinterpret_cast(input); - BLI_endian_switch_uint32(&value); - return reinterpret_cast(value); - } - - if constexpr (sizeof(T) == 8) { - /* Reinterpret this data as uint64 for easy rearranging of bytes. */ - uint64_t value = reinterpret_cast(input); - BLI_endian_switch_uint64(&value); - return reinterpret_cast(value); - } -} - -template T read(fstream &file, bool isBigEndian); - -} // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import_buffer.cc b/source/blender/io/ply/importer/ply_import_buffer.cc new file mode 100644 index 00000000000..3b1d5de9eb7 --- /dev/null +++ b/source/blender/io/ply/importer/ply_import_buffer.cc @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "ply_import_buffer.hh" + +#include "BLI_fileops.h" + +#include + +static inline bool is_newline(char ch) +{ + return ch == '\n' || ch == '\r'; +} + +namespace blender::io::ply { + +PlyReadBuffer::PlyReadBuffer(const char *file_path, size_t read_buffer_size) + : buffer_(read_buffer_size), read_buffer_size_(read_buffer_size) +{ + file_ = BLI_fopen(file_path, "rb"); +} + +PlyReadBuffer::~PlyReadBuffer() +{ + if (file_ != nullptr) { + fclose(file_); + } +} + +void PlyReadBuffer::after_header(bool is_binary) +{ + is_binary_ = is_binary; +} + +Span PlyReadBuffer::read_line() +{ + if (is_binary_) { + throw std::runtime_error("PLY read_line should not be used in binary mode"); + } + if (pos_ >= last_newline_) { + refill_buffer(); + } + BLI_assert(last_newline_ <= buffer_.size()); + int res_begin = pos_; + while (pos_ < last_newline_ && !is_newline(buffer_[pos_])) { + pos_++; + } + int res_end = pos_; + /* Move past newlines (possibly multiple for different line endings). */ + while (pos_ < buf_used_ && is_newline(buffer_[pos_])) { + pos_++; + } + return Span(buffer_.data() + res_begin, res_end - res_begin); +} + +bool PlyReadBuffer::read_bytes(void *dst, size_t size) +{ + while (size > 0) { + if (pos_ + size > buf_used_) { + if (!refill_buffer()) { + return false; + } + } + int to_copy = int(size); + if (to_copy > buf_used_) + to_copy = buf_used_; + memcpy(dst, buffer_.data() + pos_, to_copy); + pos_ += to_copy; + dst = (char *)dst + to_copy; + size -= to_copy; + } + return true; +} + +bool PlyReadBuffer::refill_buffer() +{ + BLI_assert(pos_ <= buf_used_); + BLI_assert(pos_ <= buffer_.size()); + BLI_assert(buf_used_ <= buffer_.size()); + + if (file_ == nullptr || at_eof_) { + return false; /* File is fully read. */ + } + + /* Move any leftover to start of buffer. */ + int keep = buf_used_ - pos_; + if (keep > 0) { + memmove(buffer_.data(), buffer_.data() + pos_, keep); + } + /* Read in data from the file. */ + size_t read = fread(buffer_.data() + keep, 1, read_buffer_size_ - keep, file_) + keep; + at_eof_ = read < read_buffer_size_; + pos_ = 0; + buf_used_ = int(read); + + /* Find last newline. */ + if (!is_binary_) { + int last_nl = buf_used_; + if (!at_eof_) { + while (last_nl > 0) { + --last_nl; + if (is_newline(buffer_[last_nl])) { + break; + } + } + if (!is_newline(buffer_[last_nl])) { + /* Whole line did not fit into our read buffer. */ + throw std::runtime_error("PLY text line did not fit into the read buffer"); + } + } + last_newline_ = last_nl; + } + + return true; +} + +} // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import_buffer.hh b/source/blender/io/ply/importer/ply_import_buffer.hh new file mode 100644 index 00000000000..692ca806495 --- /dev/null +++ b/source/blender/io/ply/importer/ply_import_buffer.hh @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup ply + */ + +#pragma once + +#include +#include + +#include "BLI_array.hh" +#include "BLI_span.hh" + +namespace blender::io::ply { + +/** + * Reads underlying PLY file in large chunks, and provides interface for ascii/header + * parsing to read individual lines, and for binary parsing to read chunks of bytes. + */ +class PlyReadBuffer { + public: + PlyReadBuffer(const char *file_path, size_t read_buffer_size = 64 * 1024); + ~PlyReadBuffer(); + + /** After header is parsed, indicate whether the rest of reading will be ascii or binary. */ + void after_header(bool is_binary); + + /** Gets the next line from the file as a Span. The line does not include any newline characters. + */ + Span read_line(); + + /** Reads a number of bytes into provided destination pointer. Returns false if this amount of + * bytes can not be read. */ + bool read_bytes(void *dst, size_t size); + + private: + bool refill_buffer(); + + private: + FILE *file_ = nullptr; + Array buffer_; + int pos_ = 0; + int buf_used_ = 0; + int last_newline_ = 0; + size_t read_buffer_size_ = 0; + bool at_eof_ = false; + bool is_binary_ = false; +}; + +} // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import_data.cc b/source/blender/io/ply/importer/ply_import_data.cc new file mode 100644 index 00000000000..fc396d5aad2 --- /dev/null +++ b/source/blender/io/ply/importer/ply_import_data.cc @@ -0,0 +1,606 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup ply + */ + +#include "ply_import_data.hh" +#include "ply_data.hh" +#include "ply_import_buffer.hh" + +#include "BLI_endian_switch.h" + +#include "fast_float.h" + +#include +#include + +static bool is_whitespace(char c) +{ + return c <= ' '; +} + +static const char *drop_whitespace(const char *p, const char *end) +{ + while (p < end && is_whitespace(*p)) { + ++p; + } + return p; +} + +static const char *drop_non_whitespace(const char *p, const char *end) +{ + while (p < end && !is_whitespace(*p)) { + ++p; + } + return p; +} + +static const char *drop_plus(const char *p, const char *end) +{ + if (p < end && *p == '+') { + ++p; + } + return p; +} + +static const char *parse_float(const char *p, const char *end, float fallback, float &dst) +{ + p = drop_whitespace(p, end); + p = drop_plus(p, end); + fast_float::from_chars_result res = fast_float::from_chars(p, end, dst); + if (ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) { + dst = fallback; + } + return res.ptr; +} + +static const char *parse_int(const char *p, const char *end, int fallback, int &dst) +{ + p = drop_whitespace(p, end); + p = drop_plus(p, end); + std::from_chars_result res = std::from_chars(p, end, dst); + if (ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) { + dst = fallback; + } + return res.ptr; +} + +static void endian_switch(uint8_t *ptr, int type_size) +{ + if (type_size == 2) { + BLI_endian_switch_uint16((uint16_t *)ptr); + } + else if (type_size == 4) { + BLI_endian_switch_uint32((uint32_t *)ptr); + } + else if (type_size == 8) { + BLI_endian_switch_uint64((uint64_t *)ptr); + } +} + +static void endian_switch_array(uint8_t *ptr, int type_size, int size) +{ + if (type_size == 2) { + BLI_endian_switch_uint16_array((uint16_t *)ptr, size); + } + else if (type_size == 4) { + BLI_endian_switch_uint32_array((uint32_t *)ptr, size); + } + else if (type_size == 8) { + BLI_endian_switch_uint64_array((uint64_t *)ptr, size); + } +} + +namespace blender::io::ply { + +static const int data_type_size[] = {0, 1, 1, 2, 2, 4, 4, 4, 8}; +static_assert(std::size(data_type_size) == PLY_TYPE_COUNT, "PLY data type size table mismatch"); + +static const float data_type_normalizer[] = { + 1.0f, 127.0f, 255.0f, 32767.0f, 65535.0f, float(INT_MAX), float(UINT_MAX), 1.0f, 1.0f}; +static_assert(std::size(data_type_normalizer) == PLY_TYPE_COUNT, + "PLY data type normalization factor table mismatch"); + +void PlyElement::calc_stride() +{ + stride = 0; + for (PlyProperty &p : properties) { + if (p.count_type != PlyDataTypes::NONE) { + stride = 0; + return; + } + stride += data_type_size[p.type]; + } +} + +static int get_index(const PlyElement &element, StringRef property) +{ + for (int i = 0, n = int(element.properties.size()); i != n; i++) { + const PlyProperty &prop = element.properties[i]; + if (prop.name == property) { + return i; + } + } + return -1; +} + +static const char *parse_row_ascii(PlyReadBuffer &file, Vector &r_values) +{ + Span line = file.read_line(); + + /* Parse whole line as floats. */ + const char *p = line.data(); + const char *end = p + line.size(); + int value_idx = 0; + while (p < end && value_idx < r_values.size()) { + float val; + p = parse_float(p, end, 0.0f, val); + r_values[value_idx++] = val; + } + return nullptr; +} + +template static T get_binary_value(PlyDataTypes type, const uint8_t *&r_ptr) +{ + T val = 0; + switch (type) { + case NONE: + break; + case CHAR: + val = *(int8_t *)r_ptr; + r_ptr += 1; + break; + case UCHAR: + val = *(uint8_t *)r_ptr; + r_ptr += 1; + break; + case SHORT: + val = *(int16_t *)r_ptr; + r_ptr += 2; + break; + case USHORT: + val = *(uint16_t *)r_ptr; + r_ptr += 2; + break; + case INT: + val = *(int32_t *)r_ptr; + r_ptr += 4; + break; + case UINT: + val = *(int32_t *)r_ptr; + r_ptr += 4; + break; + case FLOAT: + val = *(float *)r_ptr; + r_ptr += 4; + break; + case DOUBLE: + val = *(double *)r_ptr; + r_ptr += 8; + break; + default: + BLI_assert_msg(false, "Unknown property type"); + } + return val; +} + +static const char *parse_row_binary(PlyReadBuffer &file, + const PlyHeader &header, + const PlyElement &element, + Vector &r_scratch, + Vector &r_values) +{ + if (element.stride == 0) { + return "Vertex/Edge element contains list properties, this is not supported"; + } + BLI_assert(r_scratch.size() == element.stride); + BLI_assert(r_values.size() == element.properties.size()); + if (!file.read_bytes(r_scratch.data(), r_scratch.size())) { + return "Could not read row of binary property"; + } + + const uint8_t *ptr = r_scratch.data(); + if (header.type == PlyFormatType::BINARY_LE) { + /* Little endian: just read/convert the values. */ + for (int i = 0, n = int(element.properties.size()); i != n; i++) { + const PlyProperty &prop = element.properties[i]; + float val = get_binary_value(prop.type, ptr); + r_values[i] = val; + } + } + else if (header.type == PlyFormatType::BINARY_BE) { + /* Big endian: read, switch endian, convert the values. */ + for (int i = 0, n = int(element.properties.size()); i != n; i++) { + const PlyProperty &prop = element.properties[i]; + endian_switch((uint8_t *)ptr, data_type_size[prop.type]); + float val = get_binary_value(prop.type, ptr); + r_values[i] = val; + } + } + else { + return "Unknown binary ply format for vertex element"; + } + return nullptr; +} + +static const char *load_vertex_element(PlyReadBuffer &file, + const PlyHeader &header, + const PlyElement &element, + PlyData *data) +{ + /* Figure out vertex component indices. */ + int3 vertex_index = {get_index(element, "x"), get_index(element, "y"), get_index(element, "z")}; + int3 color_index = { + get_index(element, "red"), get_index(element, "green"), get_index(element, "blue")}; + int3 normal_index = { + get_index(element, "nx"), get_index(element, "ny"), get_index(element, "nz")}; + int2 uv_index = {get_index(element, "s"), get_index(element, "t")}; + int alpha_index = get_index(element, "alpha"); + + bool has_vertex = vertex_index.x >= 0 && vertex_index.y >= 0 && vertex_index.z >= 0; + bool has_color = color_index.x >= 0 && color_index.y >= 0 && color_index.z >= 0; + bool has_normal = normal_index.x >= 0 && normal_index.y >= 0 && normal_index.z >= 0; + bool has_uv = uv_index.x >= 0 && uv_index.y >= 0; + bool has_alpha = alpha_index >= 0; + + if (!has_vertex) { + return "Vertex positions are not present in the file"; + } + + data->vertices.reserve(element.count); + if (has_color) { + data->vertex_colors.reserve(element.count); + } + if (has_normal) { + data->vertex_normals.reserve(element.count); + } + if (has_uv) { + data->uv_coordinates.reserve(element.count); + } + + float4 color_norm = {1, 1, 1, 1}; + if (has_color) { + color_norm.x = data_type_normalizer[element.properties[color_index.x].type]; + color_norm.y = data_type_normalizer[element.properties[color_index.y].type]; + color_norm.z = data_type_normalizer[element.properties[color_index.z].type]; + } + if (has_alpha) { + color_norm.w = data_type_normalizer[element.properties[alpha_index].type]; + } + + Vector value_vec(element.properties.size()); + Vector scratch; + if (header.type != PlyFormatType::ASCII) { + scratch.resize(element.stride); + } + + for (int i = 0; i < element.count; i++) { + + const char *error = nullptr; + if (header.type == PlyFormatType::ASCII) { + error = parse_row_ascii(file, value_vec); + } + else { + error = parse_row_binary(file, header, element, scratch, value_vec); + } + if (error != nullptr) { + return error; + } + + /* Vertex coord */ + float3 vertex3; + vertex3.x = value_vec[vertex_index.x]; + vertex3.y = value_vec[vertex_index.y]; + vertex3.z = value_vec[vertex_index.z]; + data->vertices.append(vertex3); + + /* Vertex color */ + if (has_color) { + float4 colors4; + colors4.x = value_vec[color_index.x] / color_norm.x; + colors4.y = value_vec[color_index.y] / color_norm.y; + colors4.z = value_vec[color_index.z] / color_norm.z; + if (has_alpha) { + colors4.w = value_vec[alpha_index] / color_norm.w; + } + else { + colors4.w = 1.0f; + } + data->vertex_colors.append(colors4); + } + + /* If normals */ + if (has_normal) { + float3 normals3; + normals3.x = value_vec[normal_index.x]; + normals3.y = value_vec[normal_index.y]; + normals3.z = value_vec[normal_index.z]; + data->vertex_normals.append(normals3); + } + + /* If uv */ + if (has_uv) { + float2 uvmap; + uvmap.x = value_vec[uv_index.x]; + uvmap.y = value_vec[uv_index.y]; + data->uv_coordinates.append(uvmap); + } + } + return nullptr; +} + +static uint32_t read_list_count(PlyReadBuffer &file, + const PlyProperty &prop, + Vector &scratch, + bool big_endian) +{ + scratch.resize(8); + file.read_bytes(scratch.data(), data_type_size[prop.count_type]); + const uint8_t *ptr = scratch.data(); + if (big_endian) + endian_switch((uint8_t *)ptr, data_type_size[prop.count_type]); + uint32_t count = get_binary_value(prop.count_type, ptr); + return count; +} + +static void skip_property(PlyReadBuffer &file, + const PlyProperty &prop, + Vector &scratch, + bool big_endian) +{ + if (prop.count_type == PlyDataTypes::NONE) { + scratch.resize(8); + file.read_bytes(scratch.data(), data_type_size[prop.type]); + } + else { + uint32_t count = read_list_count(file, prop, scratch, big_endian); + scratch.resize(count * data_type_size[prop.type]); + file.read_bytes(scratch.data(), scratch.size()); + } +} + +static const char *load_face_element(PlyReadBuffer &file, + const PlyHeader &header, + const PlyElement &element, + PlyData *data) +{ + int prop_index = get_index(element, "vertex_indices"); + if (prop_index < 0) { + prop_index = get_index(element, "vertex_index"); + } + if (prop_index < 0 && element.properties.size() == 1) { + prop_index = 0; + } + if (prop_index < 0) { + return "Face element does not contain vertex indices property"; + } + const PlyProperty &prop = element.properties[prop_index]; + if (prop.count_type == PlyDataTypes::NONE) { + return "Face element vertex indices property must be a list"; + } + + data->face_vertices.reserve(element.count * 3); + data->face_sizes.reserve(element.count); + + if (header.type == PlyFormatType::ASCII) { + for (int i = 0; i < element.count; i++) { + /* Read line */ + Span line = file.read_line(); + + const char *p = line.data(); + const char *end = p + line.size(); + int count = 0; + + /* Skip any properties before vertex indices. */ + for (int j = 0; j < prop_index; j++) { + p = drop_whitespace(p, end); + if (element.properties[j].count_type == PlyDataTypes::NONE) { + p = drop_non_whitespace(p, end); + } + else { + p = parse_int(p, end, 0, count); + for (int k = 0; k < count; ++k) { + p = drop_whitespace(p, end); + p = drop_non_whitespace(p, end); + } + } + } + + /* Parse vertex indices list. */ + p = parse_int(p, end, 0, count); + if (count < 1 || count > 255) { + return "Invalid face size, must be between 1 and 255"; + } + + for (int j = 0; j < count; j++) { + int index; + p = parse_int(p, end, 0, index); + data->face_vertices.append(index); + } + data->face_sizes.append(count); + } + } + else { + Vector scratch(64); + + for (int i = 0; i < element.count; i++) { + const uint8_t *ptr; + + /* Skip any properties before vertex indices. */ + for (int j = 0; j < prop_index; j++) { + skip_property( + file, element.properties[j], scratch, header.type == PlyFormatType::BINARY_BE); + } + + /* Read vertex indices list. */ + uint32_t count = read_list_count( + file, prop, scratch, header.type == PlyFormatType::BINARY_BE); + if (count < 1 || count > 255) { + return "Invalid face size, must be between 1 and 255"; + } + + scratch.resize(count * data_type_size[prop.type]); + file.read_bytes(scratch.data(), scratch.size()); + ptr = scratch.data(); + if (header.type == PlyFormatType::BINARY_BE) + endian_switch_array((uint8_t *)ptr, data_type_size[prop.type], count); + for (int j = 0; j < count; ++j) { + uint32_t index = get_binary_value(prop.type, ptr); + data->face_vertices.append(index); + } + data->face_sizes.append(count); + + /* Skip any properties after vertex indices. */ + for (int j = prop_index + 1; j < element.properties.size(); j++) { + skip_property( + file, element.properties[j], scratch, header.type == PlyFormatType::BINARY_BE); + } + } + } + return nullptr; +} + +static const char *load_tristrips_element(PlyReadBuffer &file, + const PlyHeader &header, + const PlyElement &element, + PlyData *data) +{ + if (element.count != 1) { + return "Tristrips element should contain one row"; + } + if (element.properties.size() != 1) { + return "Tristrips element should contain one property"; + } + const PlyProperty &prop = element.properties[0]; + if (prop.count_type == PlyDataTypes::NONE) { + return "Tristrips element property must be a list"; + } + + Vector strip; + + if (header.type == PlyFormatType::ASCII) { + Span line = file.read_line(); + + const char *p = line.data(); + const char *end = p + line.size(); + int count = 0; + p = parse_int(p, end, 0, count); + + strip.resize(count); + for (int j = 0; j < count; j++) { + int index; + p = parse_int(p, end, 0, index); + strip[j] = index; + } + } + else { + Vector scratch(64); + + const uint8_t *ptr; + + uint32_t count = read_list_count(file, prop, scratch, header.type == PlyFormatType::BINARY_BE); + + strip.resize(count); + scratch.resize(count * data_type_size[prop.type]); + file.read_bytes(scratch.data(), scratch.size()); + ptr = scratch.data(); + if (header.type == PlyFormatType::BINARY_BE) + endian_switch_array((uint8_t *)ptr, data_type_size[prop.type], count); + for (int j = 0; j < count; ++j) { + int index = get_binary_value(prop.type, ptr); + strip[j] = index; + } + } + + /* Decode triangle strip (with possible -1 restart indices) into faces. */ + size_t start = 0; + + for (size_t i = 0; i < strip.size(); i++) { + if (strip[i] == -1) { + /* Restart strip. */ + start = i + 1; + } + else if (i - start >= 2) { + int a = strip[i - 2], b = strip[i - 1], c = strip[i]; + /* Flip odd triangles. */ + if ((i - start) & 1) { + SWAP(int, a, b); + } + /* Add triangle if it's not degenerate. */ + if (a != b && a != c && b != c) { + data->face_vertices.append(a); + data->face_vertices.append(b); + data->face_vertices.append(c); + data->face_sizes.append(3); + } + } + } + return nullptr; +} + +static const char *load_edge_element(PlyReadBuffer &file, + const PlyHeader &header, + const PlyElement &element, + PlyData *data) +{ + int prop_vertex1 = get_index(element, "vertex1"); + int prop_vertex2 = get_index(element, "vertex2"); + if (prop_vertex1 < 0 || prop_vertex2 < 0) { + return "Edge element does not contain vertex1 and vertex2 properties"; + } + + data->edges.reserve(element.count); + + Vector value_vec(element.properties.size()); + Vector scratch; + if (header.type != PlyFormatType::ASCII) { + scratch.resize(element.stride); + } + + for (int i = 0; i < element.count; i++) { + const char *error = nullptr; + if (header.type == PlyFormatType::ASCII) { + error = parse_row_ascii(file, value_vec); + } + else { + error = parse_row_binary(file, header, element, scratch, value_vec); + } + if (error != nullptr) { + return error; + } + int index1 = value_vec[prop_vertex1]; + int index2 = value_vec[prop_vertex2]; + data->edges.append(std::make_pair(index1, index2)); + } + return nullptr; +} + +std::unique_ptr import_ply_data(PlyReadBuffer &file, PlyHeader &header) +{ + std::unique_ptr data = std::make_unique(); + + for (const PlyElement &element : header.elements) { + const char *error = nullptr; + if (element.name == "vertex") { + error = load_vertex_element(file, header, element, data.get()); + } + else if (element.name == "face") { + error = load_face_element(file, header, element, data.get()); + } + else if (element.name == "tristrips") { + error = load_tristrips_element(file, header, element, data.get()); + } + else if (element.name == "edge") { + error = load_edge_element(file, header, element, data.get()); + } + if (error != nullptr) { + data->error = error; + return data; + } + } + + return data; +} + +} // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import_data.hh b/source/blender/io/ply/importer/ply_import_data.hh new file mode 100644 index 00000000000..7531d648941 --- /dev/null +++ b/source/blender/io/ply/importer/ply_import_data.hh @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup ply + */ + +#pragma once + +#include "ply_data.hh" + +namespace blender::io::ply { + +class PlyReadBuffer; + +/** + * Loads the information from a PLY file to a #PlyData data-structure. + * \param file: The PLY file that was opened. + * \param header: The information in the PLY header. + * \return The #PlyData data-structure that can be used for conversion to a Mesh. + */ +std::unique_ptr import_ply_data(PlyReadBuffer &file, PlyHeader &header); + +} // namespace blender::io::ply diff --git a/source/blender/io/ply/importer/ply_import_mesh.cc b/source/blender/io/ply/importer/ply_import_mesh.cc index 44c2ceb24ba..541796ed83b 100644 --- a/source/blender/io/ply/importer/ply_import_mesh.cc +++ b/source/blender/io/ply/importer/ply_import_mesh.cc @@ -33,36 +33,45 @@ Mesh *convert_ply_to_mesh(PlyData &data, Mesh *mesh, const PLYImportParams ¶ CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, mesh->totedge); MutableSpan edges = mesh->edges_for_write(); for (int i = 0; i < mesh->totedge; i++) { - edges[i].v1 = data.edges[i].first; - edges[i].v2 = data.edges[i].second; + uint32_t v1 = data.edges[i].first; + uint32_t v2 = data.edges[i].second; + if (v1 >= mesh->totvert) { + fprintf(stderr, "Invalid PLY vertex index in edge %i/1: %u\n", i, v1); + v1 = 0; + } + if (v2 >= mesh->totvert) { + fprintf(stderr, "Invalid PLY vertex index in edge %i/2: %u\n", i, v2); + v2 = 0; + } + edges[i].v1 = v1; + edges[i].v2 = v2; } } /* Add faces to the mesh. */ - if (!data.faces.is_empty()) { - /* Specify amount of total faces. */ - mesh->totpoly = int(data.faces.size()); - mesh->totloop = 0; - for (int i = 0; i < data.faces.size(); i++) { - /* Add number of loops from the vertex indices in the face. */ - mesh->totloop += data.faces[i].size(); - } + if (!data.face_sizes.is_empty()) { + /* Create poly and loop layers. */ + mesh->totpoly = int(data.face_sizes.size()); + mesh->totloop = int(data.face_vertices.size()); CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly); - CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, mesh->totloop); + CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totloop, ".corner_vert"); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); - int offset = 0; - /* Iterate over amount of faces. */ + /* Fill in face data. */ + uint32_t offset = 0; for (int i = 0; i < mesh->totpoly; i++) { - int size = int(data.faces[i].size()); - /* Set the index from where this face starts and specify the amount of edges it has. */ + uint32_t size = data.face_sizes[i]; polys[i].loopstart = offset; polys[i].totloop = size; - for (int j = 0; j < size; j++) { - /* Set the vertex index of the loop to the one in PlyData. */ - loops[offset + j].v = data.faces[i][j]; + uint32_t v = data.face_vertices[offset + j]; + if (v >= mesh->totvert) { + fprintf(stderr, "Invalid PLY vertex index in face %i loop %i: %u\n", i, j, v); + v = 0; + } + corner_verts[offset + j] = data.face_vertices[offset + j]; } offset += size; } @@ -93,12 +102,8 @@ Mesh *convert_ply_to_mesh(PlyData &data, Mesh *mesh, const PLYImportParams ¶ if (!data.uv_coordinates.is_empty()) { bke::SpanAttributeWriter uv_map = attributes.lookup_or_add_for_write_only_span( "UVMap", ATTR_DOMAIN_CORNER); - int counter = 0; - for (int i = 0; i < data.faces.size(); i++) { - for (int j = 0; j < data.faces[i].size(); j++) { - uv_map.span[counter] = data.uv_coordinates[data.faces[i][j]]; - counter++; - } + for (size_t i = 0; i < data.face_vertices.size(); i++) { + uv_map.span[i] = data.uv_coordinates[data.face_vertices[i]]; } uv_map.finish(); } diff --git a/source/blender/io/ply/intern/ply_data.hh b/source/blender/io/ply/intern/ply_data.hh index 087d6e61269..db14fdeefc0 100644 --- a/source/blender/io/ply/intern/ply_data.hh +++ b/source/blender/io/ply/intern/ply_data.hh @@ -12,30 +12,38 @@ namespace blender::io::ply { -enum PlyDataTypes { CHAR, UCHAR, SHORT, USHORT, INT, UINT, FLOAT, DOUBLE }; +enum PlyDataTypes { NONE, CHAR, UCHAR, SHORT, USHORT, INT, UINT, FLOAT, DOUBLE, PLY_TYPE_COUNT }; struct PlyData { Vector vertices; Vector vertex_normals; - /* Value between 0 and 1. */ - Vector vertex_colors; + Vector vertex_colors; /* Linear space, 0..1 range colors. */ Vector> edges; - Vector edge_colors; - Vector> faces; + Vector face_vertices; + Vector face_sizes; Vector uv_coordinates; + std::string error; }; enum PlyFormatType { ASCII, BINARY_LE, BINARY_BE }; +struct PlyProperty { + std::string name; + PlyDataTypes type = PlyDataTypes::NONE; + PlyDataTypes count_type = PlyDataTypes::NONE; /* NONE means it's not a list property */ +}; + +struct PlyElement { + std::string name; + int count = 0; + Vector properties; + int stride = 0; + + void calc_stride(); +}; + struct PlyHeader { - int vertex_count = 0; - int edge_count = 0; - int face_count = 0; - int header_size = 0; - /* List of elements in ply file with their count. */ - Vector> elements; - /* List of properties (Name, type) per element. */ - Vector>> properties; + Vector elements; PlyFormatType type; }; diff --git a/source/blender/io/ply/intern/ply_functions.cc b/source/blender/io/ply/intern/ply_functions.cc deleted file mode 100644 index 5cc61547dbe..00000000000 --- a/source/blender/io/ply/intern/ply_functions.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup ply - */ - -#include "ply_functions.hh" - -namespace blender::io::ply { - -line_ending safe_getline(fstream &file, std::string &line) -{ - line.clear(); - std::streambuf *sb = file.rdbuf(); - std::istream::sentry se(file, true); - - line_ending possible = UNSET; - char c; - while (sb->sgetc() != std::streambuf::traits_type::eof()) { - c = char(sb->sgetc()); - switch (c) { - case '\n': - if (possible == UNSET) { - possible = LF; - } - else if (possible == CR) { - possible = CR_LF; - } - break; - case '\r': - if (possible == UNSET) { - possible = CR; - } - else if (possible == LF) { - possible = LF_CR; - } - break; - default: - /* If a different character is encountered after the line ending is set, we know to return. - */ - if (possible != UNSET) { - return possible; - } - line += c; - break; - } - sb->sbumpc(); - } - return possible; -} -} // namespace blender::io::ply diff --git a/source/blender/io/ply/intern/ply_functions.hh b/source/blender/io/ply/intern/ply_functions.hh deleted file mode 100644 index e454167be87..00000000000 --- a/source/blender/io/ply/intern/ply_functions.hh +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup ply - */ - -#pragma once - -#include "BLI_fileops.hh" -#include - -namespace blender::io::ply { - -enum line_ending { CR_LF, LF, CR, LF_CR, UNSET }; - -/** - * Reads a line in the ply file in a line-ending safe manner. All different line endings are - * supported. This also supports a mix of different line endings in the same file. CR (\\r), LF - * (\\n), CR/LF (\\r\\n), LF/CR (\\n\\r). - * \param file: The file stream. - * \param line: The string you want to read to. - * \return The line ending enum if you're interested. - */ -line_ending safe_getline(fstream &file, std::string &line); - -} // namespace blender::io::ply diff --git a/source/blender/io/ply/tests/io_ply_exporter_test.cc b/source/blender/io/ply/tests/io_ply_exporter_test.cc index be25ec1b566..5a021aaf813 100644 --- a/source/blender/io/ply/tests/io_ply_exporter_test.cc +++ b/source/blender/io/ply/tests/io_ply_exporter_test.cc @@ -21,7 +21,7 @@ namespace blender::io::ply { -class PlyExportTest : public BlendfileLoadingBaseTest { +class ply_export_test : public BlendfileLoadingBaseTest { public: bool load_file_and_depsgraph(const std::string &filepath, const eEvaluationMode eval_mode = DAG_EVAL_VIEWPORT) @@ -57,27 +57,32 @@ class PlyExportTest : public BlendfileLoadingBaseTest { static std::unique_ptr load_cube(PLYExportParams ¶ms) { std::unique_ptr plyData = std::make_unique(); - plyData->vertices = {{1.122082, 1.122082, 1.122082}, - {1.122082, 1.122082, -1.122082}, - {1.122082, -1.122082, 1.122082}, - {1.122082, -1.122082, -1.122082}, - {-1.122082, 1.122082, 1.122082}, - {-1.122082, 1.122082, -1.122082}, - {-1.122082, -1.122082, 1.122082}, - {-1.122082, -1.122082, -1.122082}}; + plyData->vertices = { + {1.122082, 1.122082, 1.122082}, + {1.122082, 1.122082, -1.122082}, + {1.122082, -1.122082, 1.122082}, + {1.122082, -1.122082, -1.122082}, + {-1.122082, 1.122082, 1.122082}, + {-1.122082, 1.122082, -1.122082}, + {-1.122082, -1.122082, 1.122082}, + {-1.122082, -1.122082, -1.122082}, + }; - plyData->faces = { - {0, 2, 6, 4}, {3, 7, 6, 2}, {7, 5, 4, 6}, {5, 7, 3, 1}, {1, 3, 2, 0}, {5, 1, 0, 4}}; + plyData->face_sizes = {4, 4, 4, 4, 4, 4}; + plyData->face_vertices = {0, 2, 6, 4, 3, 7, 6, 2, 7, 5, 4, 6, + 5, 7, 3, 1, 1, 3, 2, 0, 5, 1, 0, 4}; if (params.export_normals) - plyData->vertex_normals = {{-0.5773503, -0.5773503, -0.5773503}, - {-0.5773503, -0.5773503, 0.5773503}, - {-0.5773503, 0.5773503, -0.5773503}, - {-0.5773503, 0.5773503, 0.5773503}, - {0.5773503, -0.5773503, -0.5773503}, - {0.5773503, -0.5773503, 0.5773503}, - {0.5773503, 0.5773503, -0.5773503}, - {0.5773503, 0.5773503, 0.5773503}}; + plyData->vertex_normals = { + {-0.5773503, -0.5773503, -0.5773503}, + {-0.5773503, -0.5773503, 0.5773503}, + {-0.5773503, 0.5773503, -0.5773503}, + {-0.5773503, 0.5773503, 0.5773503}, + {0.5773503, -0.5773503, -0.5773503}, + {0.5773503, -0.5773503, 0.5773503}, + {0.5773503, 0.5773503, -0.5773503}, + {0.5773503, 0.5773503, 0.5773503}, + }; return plyData; } @@ -122,7 +127,7 @@ static std::vector read_temp_file_in_vectorchar(const std::string &file_pa return res; } -TEST_F(PlyExportTest, WriteHeaderAscii) +TEST_F(ply_export_test, WriteHeaderAscii) { std::string filePath = get_temp_ply_filename(temp_file_path); PLYExportParams _params = {}; @@ -160,7 +165,7 @@ TEST_F(PlyExportTest, WriteHeaderAscii) ASSERT_STREQ(result.c_str(), expected.c_str()); } -TEST_F(PlyExportTest, WriteHeaderBinary) +TEST_F(ply_export_test, WriteHeaderBinary) { std::string filePath = get_temp_ply_filename(temp_file_path); PLYExportParams _params = {}; @@ -198,7 +203,7 @@ TEST_F(PlyExportTest, WriteHeaderBinary) ASSERT_STREQ(result.c_str(), expected.c_str()); } -TEST_F(PlyExportTest, WriteVerticesAscii) +TEST_F(ply_export_test, WriteVerticesAscii) { std::string filePath = get_temp_ply_filename(temp_file_path); PLYExportParams _params = {}; @@ -230,7 +235,7 @@ TEST_F(PlyExportTest, WriteVerticesAscii) ASSERT_STREQ(result.c_str(), expected.c_str()); } -TEST_F(PlyExportTest, WriteVerticesBinary) +TEST_F(ply_export_test, WriteVerticesBinary) { std::string filePath = get_temp_ply_filename(temp_file_path); PLYExportParams _params = {}; @@ -249,21 +254,15 @@ TEST_F(PlyExportTest, WriteVerticesBinary) std::vector result = read_temp_file_in_vectorchar(filePath); - std::vector expected( - {(char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, - (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, - (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, - (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, - (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, - (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, - (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, - (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, - (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, - (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, - (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, - (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, - (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, - (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF}); + std::vector expected({ + 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, + 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, + 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, + 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, + 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, + 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, + 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, + }); ASSERT_EQ(result.size(), expected.size()); @@ -272,7 +271,7 @@ TEST_F(PlyExportTest, WriteVerticesBinary) } } -TEST_F(PlyExportTest, WriteFacesAscii) +TEST_F(ply_export_test, WriteFacesAscii) { std::string filePath = get_temp_ply_filename(temp_file_path); PLYExportParams _params = {}; @@ -302,7 +301,7 @@ TEST_F(PlyExportTest, WriteFacesAscii) ASSERT_STREQ(result.c_str(), expected.c_str()); } -TEST_F(PlyExportTest, WriteFacesBinary) +TEST_F(ply_export_test, WriteFacesBinary) { std::string filePath = get_temp_ply_filename(temp_file_path); PLYExportParams _params = {}; @@ -321,22 +320,15 @@ TEST_F(PlyExportTest, WriteFacesBinary) std::vector result = read_temp_file_in_vectorchar(filePath); - std::vector expected( - {(char)0x04, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x02, (char)0x00, - (char)0x00, (char)0x00, (char)0x06, (char)0x00, (char)0x00, (char)0x00, (char)0x04, - (char)0x00, (char)0x00, (char)0x00, (char)0x04, (char)0x03, (char)0x00, (char)0x00, - (char)0x00, (char)0x07, (char)0x00, (char)0x00, (char)0x00, (char)0x06, (char)0x00, - (char)0x00, (char)0x00, (char)0x02, (char)0x00, (char)0x00, (char)0x00, (char)0x04, - (char)0x07, (char)0x00, (char)0x00, (char)0x00, (char)0x05, (char)0x00, (char)0x00, - (char)0x00, (char)0x04, (char)0x00, (char)0x00, (char)0x00, (char)0x06, (char)0x00, - (char)0x00, (char)0x00, (char)0x04, (char)0x05, (char)0x00, (char)0x00, (char)0x00, - (char)0x07, (char)0x00, (char)0x00, (char)0x00, (char)0x03, (char)0x00, (char)0x00, - (char)0x00, (char)0x01, (char)0x00, (char)0x00, (char)0x00, (char)0x04, (char)0x01, - (char)0x00, (char)0x00, (char)0x00, (char)0x03, (char)0x00, (char)0x00, (char)0x00, - (char)0x02, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, - (char)0x00, (char)0x04, (char)0x05, (char)0x00, (char)0x00, (char)0x00, (char)0x01, - (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, - (char)0x04, (char)0x00, (char)0x00, (char)0x00}); + std::vector expected({ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + }); ASSERT_EQ(result.size(), expected.size()); @@ -345,7 +337,7 @@ TEST_F(PlyExportTest, WriteFacesBinary) } } -TEST_F(PlyExportTest, WriteVertexNormalsAscii) +TEST_F(ply_export_test, WriteVertexNormalsAscii) { std::string filePath = get_temp_ply_filename(temp_file_path); PLYExportParams _params = {}; @@ -377,7 +369,7 @@ TEST_F(PlyExportTest, WriteVertexNormalsAscii) ASSERT_STREQ(result.c_str(), expected.c_str()); } -TEST_F(PlyExportTest, WriteVertexNormalsBinary) +TEST_F(ply_export_test, WriteVertexNormalsBinary) { std::string filePath = get_temp_ply_filename(temp_file_path); PLYExportParams _params = {}; @@ -396,35 +388,21 @@ TEST_F(PlyExportTest, WriteVertexNormalsBinary) std::vector result = read_temp_file_in_vectorchar(filePath); - std::vector expected( - {(char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, - (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x3B, (char)0xCD, - (char)0x13, (char)0xBF, (char)0x3B, (char)0xCD, (char)0x13, (char)0xBF, (char)0x3B, - (char)0xCD, (char)0x13, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, - (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, - (char)0xBF, (char)0x3B, (char)0xCD, (char)0x13, (char)0xBF, (char)0x3B, (char)0xCD, - (char)0x13, (char)0xBF, (char)0x3B, (char)0xCD, (char)0x13, (char)0x3F, (char)0x62, - (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, - (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x3B, (char)0xCD, (char)0x13, - (char)0xBF, (char)0x3B, (char)0xCD, (char)0x13, (char)0x3F, (char)0x3B, (char)0xCD, - (char)0x13, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, - (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, - (char)0x3B, (char)0xCD, (char)0x13, (char)0xBF, (char)0x3B, (char)0xCD, (char)0x13, - (char)0x3F, (char)0x3B, (char)0xCD, (char)0x13, (char)0x3F, (char)0x62, (char)0xA0, - (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0x3F, (char)0x62, - (char)0xA0, (char)0x8F, (char)0x3F, (char)0x3B, (char)0xCD, (char)0x13, (char)0x3F, - (char)0x3B, (char)0xCD, (char)0x13, (char)0xBF, (char)0x3B, (char)0xCD, (char)0x13, - (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, - (char)0x8F, (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, (char)0x3B, - (char)0xCD, (char)0x13, (char)0x3F, (char)0x3B, (char)0xCD, (char)0x13, (char)0xBF, - (char)0x3B, (char)0xCD, (char)0x13, (char)0x3F, (char)0x62, (char)0xA0, (char)0x8F, - (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, - (char)0x8F, (char)0x3F, (char)0x3B, (char)0xCD, (char)0x13, (char)0x3F, (char)0x3B, - (char)0xCD, (char)0x13, (char)0x3F, (char)0x3B, (char)0xCD, (char)0x13, (char)0xBF, - (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, - (char)0xBF, (char)0x62, (char)0xA0, (char)0x8F, (char)0xBF, (char)0x3B, (char)0xCD, - (char)0x13, (char)0x3F, (char)0x3B, (char)0xCD, (char)0x13, (char)0x3F, (char)0x3B, - (char)0xCD, (char)0x13, (char)0x3F}); + std::vector expected({ + 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0x3F, 0x3B, 0xCD, 0x13, + 0xBF, 0x3B, 0xCD, 0x13, 0xBF, 0x3B, 0xCD, 0x13, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, + 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0xBF, 0x3B, 0xCD, 0x13, 0xBF, 0x3B, 0xCD, 0x13, 0xBF, 0x3B, + 0xCD, 0x13, 0x3F, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, + 0x3B, 0xCD, 0x13, 0xBF, 0x3B, 0xCD, 0x13, 0x3F, 0x3B, 0xCD, 0x13, 0xBF, 0x62, 0xA0, 0x8F, + 0x3F, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, 0x3B, 0xCD, 0x13, 0xBF, 0x3B, 0xCD, + 0x13, 0x3F, 0x3B, 0xCD, 0x13, 0x3F, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, 0x62, + 0xA0, 0x8F, 0x3F, 0x3B, 0xCD, 0x13, 0x3F, 0x3B, 0xCD, 0x13, 0xBF, 0x3B, 0xCD, 0x13, 0xBF, + 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, 0x62, 0xA0, 0x8F, 0xBF, 0x3B, 0xCD, 0x13, + 0x3F, 0x3B, 0xCD, 0x13, 0xBF, 0x3B, 0xCD, 0x13, 0x3F, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, + 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0x3F, 0x3B, 0xCD, 0x13, 0x3F, 0x3B, 0xCD, 0x13, 0x3F, 0x3B, + 0xCD, 0x13, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, 0x62, 0xA0, 0x8F, 0xBF, + 0x3B, 0xCD, 0x13, 0x3F, 0x3B, 0xCD, 0x13, 0x3F, 0x3B, 0xCD, 0x13, 0x3F, + }); ASSERT_EQ(result.size(), expected.size()); @@ -433,7 +411,7 @@ TEST_F(PlyExportTest, WriteVertexNormalsBinary) } } -class ply_exporter_ply_data_test : public PlyExportTest { +class ply_exporter_ply_data_test : public ply_export_test { public: PlyData load_ply_data_from_blendfile(const std::string &blendfile, PLYExportParams ¶ms) { @@ -448,37 +426,107 @@ class ply_exporter_ply_data_test : public PlyExportTest { } }; -TEST_F(ply_exporter_ply_data_test, CubeLoadPLYDataVertices) +TEST_F(ply_exporter_ply_data_test, CubeLoadPLYData) { PLYExportParams params = {}; - PlyData plyData = load_ply_data_from_blendfile( - "io_tests" SEP_STR "blend_geometry" SEP_STR "cube_all_data.blend", params); + PlyData plyData = load_ply_data_from_blendfile("io_tests/blend_geometry/cube_all_data.blend", + params); EXPECT_EQ(plyData.vertices.size(), 8); + EXPECT_EQ(plyData.uv_coordinates.size(), 0); } TEST_F(ply_exporter_ply_data_test, CubeLoadPLYDataUV) { PLYExportParams params = {}; params.export_uv = true; - PlyData plyData = load_ply_data_from_blendfile( - "io_tests" SEP_STR "blend_geometry" SEP_STR "cube_all_data.blend", params); + PlyData plyData = load_ply_data_from_blendfile("io_tests/blend_geometry/cube_all_data.blend", + params); + EXPECT_EQ(plyData.vertices.size(), 8); EXPECT_EQ(plyData.uv_coordinates.size(), 8); } +TEST_F(ply_exporter_ply_data_test, CubeLooseEdgesLoadPLYData) +{ + PLYExportParams params = {}; + params.forward_axis = IO_AXIS_Y; + params.up_axis = IO_AXIS_Z; + params.global_scale = 1.0f; + PlyData plyData = load_ply_data_from_blendfile( + "io_tests/blend_geometry/cube_loose_edges_verts.blend", params); + float3 exp_vertices[] = { + {1, 1, 1}, + {1, 1, -1}, + {1, -1, 1}, + {1, -1, -1}, + {-1, 1, 1}, + {-1, 1, -1}, + {-1, -1, 1}, + {-1, -1, -1}, + }; + std::pair exp_edges[] = {{7, 6}, {6, 4}}; + uint32_t exp_face_sizes[] = {4, 4}; + uint32_t exp_faces[] = {5, 1, 3, 7, 5, 4, 0, 1}; + EXPECT_EQ(plyData.vertices.size(), ARRAY_SIZE(exp_vertices)); + EXPECT_EQ(plyData.uv_coordinates.size(), 0); + EXPECT_EQ(plyData.edges.size(), ARRAY_SIZE(exp_edges)); + EXPECT_EQ(plyData.face_sizes.size(), ARRAY_SIZE(exp_face_sizes)); + EXPECT_EQ(plyData.face_vertices.size(), ARRAY_SIZE(exp_faces)); + EXPECT_EQ_ARRAY(exp_vertices, plyData.vertices.data(), ARRAY_SIZE(exp_vertices)); + EXPECT_EQ_ARRAY(exp_edges, plyData.edges.data(), ARRAY_SIZE(exp_edges)); + EXPECT_EQ_ARRAY(exp_face_sizes, plyData.face_sizes.data(), ARRAY_SIZE(exp_face_sizes)); + EXPECT_EQ_ARRAY(exp_faces, plyData.face_vertices.data(), ARRAY_SIZE(exp_faces)); +} +TEST_F(ply_exporter_ply_data_test, CubeLooseEdgesLoadPLYDataUV) +{ + PLYExportParams params = {}; + params.forward_axis = IO_AXIS_Y; + params.up_axis = IO_AXIS_Z; + params.global_scale = 1.0f; + params.export_uv = true; + PlyData plyData = load_ply_data_from_blendfile( + "io_tests/blend_geometry/cube_loose_edges_verts.blend", params); + float3 exp_vertices[] = { + {1, 1, 1}, + {1, 1, -1}, + {1, -1, 1}, + {1, -1, -1}, + {-1, 1, 1}, + {-1, 1, -1}, + {-1, 1, -1}, + {-1, -1, 1}, + {-1, -1, -1}, + }; + float2 exp_uv[] = { + {0.625f, 0.5f}, + {0.375f, 0.5f}, + {0, 0}, + {0.375f, 0.75f}, + {0.625f, 0.25f}, + {0.125f, 0.5f}, + {0.375f, 0.25f}, + {0, 0}, + {0.125f, 0.75f}, + }; + std::pair exp_edges[] = {{8, 7}, {7, 4}}; + uint32_t exp_face_sizes[] = {4, 4}; + uint32_t exp_faces[] = {5, 1, 3, 8, 6, 4, 0, 1}; + EXPECT_EQ(plyData.vertices.size(), 9); + EXPECT_EQ(plyData.uv_coordinates.size(), 9); + EXPECT_EQ(plyData.edges.size(), ARRAY_SIZE(exp_edges)); + EXPECT_EQ(plyData.face_sizes.size(), ARRAY_SIZE(exp_face_sizes)); + EXPECT_EQ(plyData.face_vertices.size(), ARRAY_SIZE(exp_faces)); + EXPECT_EQ_ARRAY(exp_vertices, plyData.vertices.data(), ARRAY_SIZE(exp_vertices)); + EXPECT_EQ_ARRAY(exp_uv, plyData.uv_coordinates.data(), ARRAY_SIZE(exp_uv)); + EXPECT_EQ_ARRAY(exp_edges, plyData.edges.data(), ARRAY_SIZE(exp_edges)); + EXPECT_EQ_ARRAY(exp_face_sizes, plyData.face_sizes.data(), ARRAY_SIZE(exp_face_sizes)); + EXPECT_EQ_ARRAY(exp_faces, plyData.face_vertices.data(), ARRAY_SIZE(exp_faces)); +} + TEST_F(ply_exporter_ply_data_test, SuzanneLoadPLYDataUV) { PLYExportParams params = {}; params.export_uv = true; - PlyData plyData = load_ply_data_from_blendfile( - "io_tests" SEP_STR "blend_geometry" SEP_STR "suzanne_all_data.blend", params); + PlyData plyData = load_ply_data_from_blendfile("io_tests/blend_geometry/suzanne_all_data.blend", + params); EXPECT_EQ(plyData.uv_coordinates.size(), 542); } -TEST_F(ply_exporter_ply_data_test, CubeLoadPLYDataUVDisabled) -{ - PLYExportParams params = {}; - params.export_uv = false; - PlyData plyData = load_ply_data_from_blendfile( - "io_tests" SEP_STR "blend_geometry" SEP_STR "cube_all_data.blend", params); - EXPECT_EQ(plyData.uv_coordinates.size(), 0); -} - } // namespace blender::io::ply diff --git a/source/blender/io/ply/tests/io_ply_importer_test.cc b/source/blender/io/ply/tests/io_ply_importer_test.cc index c3e01727fae..73c9580e419 100644 --- a/source/blender/io/ply/tests/io_ply_importer_test.cc +++ b/source/blender/io/ply/tests/io_ply_importer_test.cc @@ -1,249 +1,278 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include "tests/blendfile_loading_base_test.h" +#include "testing/testing.h" -#include "BKE_attribute.hh" -#include "BKE_mesh.hh" -#include "BKE_object.h" +#include "BLI_fileops.hh" +#include "BLI_hash_mm2a.h" -#include "BLO_readfile.h" - -#include "DEG_depsgraph_query.h" - -#include "IO_ply.h" -#include "ply_data.hh" #include "ply_import.hh" -#include "ply_import_binary.hh" +#include "ply_import_buffer.hh" +#include "ply_import_data.hh" namespace blender::io::ply { struct Expectation { - std::string name; - PlyFormatType type; - int totvert, totpoly, totedge; + int totvert, totpoly, totindex, totedge; + uint16_t polyhash = 0, edgehash = 0; float3 vert_first, vert_last; float3 normal_first = {0, 0, 0}; - float2 uv_first; + float2 uv_first = {0, 0}; float4 color_first = {-1, -1, -1, -1}; }; -class PlyImportTest : public BlendfileLoadingBaseTest { +class ply_import_test : public testing::Test { public: - void import_and_check(const char *path, const Expectation *expect, size_t expect_count) + void import_and_check(const char *path, const Expectation &exp) { - if (!blendfile_load("io_tests/blend_geometry/all_quads.blend")) { + std::string ply_path = blender::tests::flags_test_asset_dir() + "/io_tests/ply/" + path; + + /* Use a small read buffer size for better coverage of buffer refilling behavior. */ + PlyReadBuffer infile(ply_path.c_str(), 128); + PlyHeader header; + const char *header_err = read_header(infile, header); + if (header_err != nullptr) { ADD_FAILURE(); return; } - - PLYImportParams params; - params.global_scale = 1.0f; - params.forward_axis = IO_AXIS_NEGATIVE_Z; - params.up_axis = IO_AXIS_Y; - params.merge_verts = false; - params.vertex_colors = PLY_VERTEX_COLOR_NONE; - - /* Import the test file. */ - std::string ply_path = blender::tests::flags_test_asset_dir() + "/io_tests/ply/" + path; - strncpy(params.filepath, ply_path.c_str(), FILE_MAX - 1); - importer_main(bfile->main, bfile->curscene, bfile->cur_view_layer, params, nullptr); - - depsgraph_create(DAG_EVAL_VIEWPORT); - - DEGObjectIterSettings deg_iter_settings{}; - deg_iter_settings.depsgraph = depsgraph; - deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI; - size_t object_index = 0; - - /* Iterate over the objects in the viewport */ - DEG_OBJECT_ITER_BEGIN (°_iter_settings, object) { - if (object_index >= expect_count) { - ADD_FAILURE(); - break; - } - - const Expectation &exp = expect[object_index]; - - ASSERT_STREQ(object->id.name, exp.name.c_str()); - EXPECT_V3_NEAR(object->loc, float3(0, 0, 0), 0.0001f); - - EXPECT_V3_NEAR(object->scale, float3(1, 1, 1), 0.0001f); - if (object->type == OB_MESH) { - Mesh *mesh = BKE_object_get_evaluated_mesh(object); - - /* Test if mesh has expected amount of vertices, edges, and faces. */ - ASSERT_EQ(mesh->totvert, exp.totvert); - ASSERT_EQ(mesh->totedge, exp.totedge); - ASSERT_EQ(mesh->totpoly, exp.totpoly); - - /* Test if first and last vertices match. */ - const Span verts = mesh->vert_positions(); - EXPECT_V3_NEAR(verts.first(), exp.vert_first, 0.0001f); - EXPECT_V3_NEAR(verts.last(), exp.vert_last, 0.0001f); - - /* Fetch normal data from mesh and test if it matches expectation. */ - if (BKE_mesh_has_custom_loop_normals(mesh)) { - const Span vertex_normals = mesh->vert_normals(); - ASSERT_FALSE(vertex_normals.is_empty()); - EXPECT_V3_NEAR(vertex_normals[0], exp.normal_first, 0.0001f); - } - - /* Fetch UV data from mesh and test if it matches expectation. */ - blender::bke::AttributeAccessor attributes = mesh->attributes(); - VArray uvs = attributes.lookup("UVMap"); - float2 uv_first = !uvs.is_empty() ? uvs[0] : float2(0, 0); - EXPECT_V2_NEAR(uv_first, exp.uv_first, 0.0001f); - - /* Check if expected mesh has vertex colors, and tests if it matches. */ - if (CustomData_has_layer(&mesh->vdata, CD_PROP_COLOR)) { - const float4 *colors = (const float4 *)CustomData_get_layer(&mesh->vdata, CD_PROP_COLOR); - ASSERT_TRUE(colors != nullptr); - EXPECT_V4_NEAR(colors[0], exp.color_first, 0.0001f); - } - } - ++object_index; + std::unique_ptr data = import_ply_data(infile, header); + if (!data->error.empty()) { + fprintf(stderr, "%s\n", data->error.c_str()); + ASSERT_EQ(0, exp.totvert); + ASSERT_EQ(0, exp.totpoly); + return; } - DEG_OBJECT_ITER_END; - EXPECT_EQ(object_index, expect_count); + /* Test expected amount of vertices, edges, and faces. */ + ASSERT_EQ(data->vertices.size(), exp.totvert); + ASSERT_EQ(data->edges.size(), exp.totedge); + ASSERT_EQ(data->face_sizes.size(), exp.totpoly); + ASSERT_EQ(data->face_vertices.size(), exp.totindex); + + /* Test hash of face and edge index data. */ + BLI_HashMurmur2A hash; + BLI_hash_mm2a_init(&hash, 0); + uint32_t offset = 0; + for (uint32_t face_size : data->face_sizes) { + BLI_hash_mm2a_add(&hash, (const unsigned char *)&data->face_vertices[offset], face_size * 4); + offset += face_size; + } + uint16_t face_hash = BLI_hash_mm2a_end(&hash); + if (!data->face_vertices.is_empty()) { + ASSERT_EQ(face_hash, exp.polyhash); + } + + if (!data->edges.is_empty()) { + uint16_t edge_hash = BLI_hash_mm2((const unsigned char *)data->edges.data(), + data->edges.size() * sizeof(data->edges[0]), + 0); + ASSERT_EQ(edge_hash, exp.edgehash); + } + + /* Test if first and last vertices match. */ + EXPECT_V3_NEAR(data->vertices.first(), exp.vert_first, 0.0001f); + EXPECT_V3_NEAR(data->vertices.last(), exp.vert_last, 0.0001f); + + /* Check if first normal matches. */ + float3 got_normal = data->vertex_normals.is_empty() ? float3(0, 0, 0) : + data->vertex_normals.first(); + EXPECT_V3_NEAR(got_normal, exp.normal_first, 0.0001f); + + /* Check if first UV matches. */ + float2 got_uv = data->uv_coordinates.is_empty() ? float2(0, 0) : data->uv_coordinates.first(); + EXPECT_V2_NEAR(got_uv, exp.uv_first, 0.0001f); + + /* Check if first color matches. */ + float4 got_color = data->vertex_colors.is_empty() ? float4(-1, -1, -1, -1) : + data->vertex_colors.first(); + EXPECT_V4_NEAR(got_color, exp.color_first, 0.0001f); } }; -TEST_F(PlyImportTest, PLYImportCube) +TEST_F(ply_import_test, PLYImportCube) { - Expectation expect[] = {{"OBCube", - ASCII, - 8, - 6, - 12, - float3(1, 1, -1), - float3(-1, 1, 1), - float3(0.5773, 0.5773, -0.5773), - float2(0, 0)}, - {"OBcube_ascii", - ASCII, - 24, - 6, - 24, - float3(1, 1, -1), - float3(-1, 1, 1), - float3(0, 0, -1), - float2(0.979336, 0.844958), - float4(1, 0.8470, 0, 1)}}; - import_and_check("cube_ascii.ply", expect, 2); + Expectation expect = {24, + 6, + 24, + 0, + 26429, + 0, + float3(1, 1, -1), + float3(-1, 1, 1), + float3(0, 0, -1), + float2(0.979336, 0.844958), + float4(1, 0.8470, 0, 1)}; + import_and_check("cube_ascii.ply", expect); } -TEST_F(PlyImportTest, PLYImportASCIIEdgeTest) +TEST_F(ply_import_test, PLYImportWireframeCube) { - Expectation expect[] = {{"OBCube", - ASCII, - 8, - 6, - 12, - float3(1, 1, -1), - float3(-1, 1, 1), - float3(0.5773, 0.5773, -0.5773)}, - {"OBASCII_wireframe_cube", - ASCII, - 8, - 0, - 12, - float3(-1, -1, -1), - float3(1, 1, 1), - float3(-2, 0, -1)}}; - - import_and_check("ASCII_wireframe_cube.ply", expect, 2); + Expectation expect = {8, 0, 0, 12, 0, 31435, float3(-1, -1, -1), float3(1, 1, 1)}; + import_and_check("ASCII_wireframe_cube.ply", expect); + import_and_check("wireframe_cube.ply", expect); } -TEST_F(PlyImportTest, PLYImportBunny) +TEST_F(ply_import_test, PLYImportBunny) { - Expectation expect[] = {{"OBCube", - ASCII, - 8, - 6, - 12, - float3(1, 1, -1), - float3(-1, 1, 1), - float3(0.5773, 0.5773, -0.5773)}, - {"OBbunny2", - BINARY_LE, - 1623, - 1000, - 1513, - float3(0.0380425, 0.109755, 0.0161689), - float3(-0.0722821, 0.143895, -0.0129091), - float3(-2, -2, -2)}}; - import_and_check("bunny2.ply", expect, 2); + Expectation expect = {1623, + 1000, + 3000, + 0, + 62556, + 0, + float3(0.0380425, 0.109755, 0.0161689), + float3(-0.0722821, 0.143895, -0.0129091)}; + import_and_check("bunny2.ply", expect); } -TEST_F(PlyImportTest, PlyImportManySmallHoles) +TEST_F(ply_import_test, PlyImportManySmallHoles) { - Expectation expect[] = {{"OBCube", - ASCII, - 8, - 6, - 12, - float3(1, 1, -1), - float3(-1, 1, 1), - float3(0.5773, 0.5773, -0.5773)}, - {"OBmany_small_holes", - BINARY_LE, - 2004, - 3524, - 5564, - float3(-0.0131592, -0.0598382, 1.58958), - float3(-0.0177622, 0.0105153, 1.61977), - float3(-2, -2, -2), - float2(0, 0), - float4(0.7215, 0.6784, 0.6627, 1)}}; - import_and_check("many_small_holes.ply", expect, 2); + Expectation expect = {2004, + 3524, + 10572, + 0, + 15143, + 0, + float3(-0.0131592, -0.0598382, 1.58958), + float3(-0.0177622, 0.0105153, 1.61977), + float3(0, 0, 0), + float2(0, 0), + float4(0.7215, 0.6784, 0.6627, 1)}; + import_and_check("many_small_holes.ply", expect); } -TEST_F(PlyImportTest, PlyImportWireframeCube) +TEST_F(ply_import_test, PlyImportColorNotFull) { - Expectation expect[] = {{"OBCube", - ASCII, - 8, - 6, - 12, - float3(1, 1, -1), - float3(-1, 1, 1), - float3(0.5773, 0.5773, -0.5773)}, - {"OBwireframe_cube", - BINARY_LE, - 8, - 0, - 12, - float3(-1, -1, -1), - float3(1, 1, 1), - float3(-2, -2, -2)}}; - import_and_check("wireframe_cube.ply", expect, 2); + Expectation expect = {4, 1, 4, 0, 37235, 0, float3(1, 0, 1), float3(-1, 0, 1)}; + import_and_check("color_not_full_a.ply", expect); + import_and_check("color_not_full_b.ply", expect); } -TEST(PlyImportFunctionsTest, PlySwapBytes) +TEST_F(ply_import_test, PlyImportDoubleXYZ) { - /* Individual bits shouldn't swap with each other. */ - uint8_t val8 = 0xA8; - uint8_t exp8 = 0xA8; - uint8_t actual8 = swap_bytes(val8); - ASSERT_EQ(exp8, actual8); - - uint16_t val16 = 0xFEB0; - uint16_t exp16 = 0xB0FE; - uint16_t actual16 = swap_bytes(val16); - ASSERT_EQ(exp16, actual16); - - uint32_t val32 = 0x80A37B0A; - uint32_t exp32 = 0x0A7BA380; - uint32_t actual32 = swap_bytes(val32); - ASSERT_EQ(exp32, actual32); - - uint64_t val64 = 0x0102030405060708; - uint64_t exp64 = 0x0807060504030201; - uint64_t actual64 = swap_bytes(val64); - ASSERT_EQ(exp64, actual64); + Expectation expect = {4, + 1, + 4, + 0, + 37235, + 0, + float3(1, 0, 1), + float3(-1, 0, 1), + float3(0, 0, 0), + float2(0, 0), + float4(1, 0, 0, 1)}; + import_and_check("double_xyz_a.ply", expect); + import_and_check("double_xyz_b.ply", expect); } +TEST_F(ply_import_test, PlyImportFaceIndicesNotFirstProp) +{ + Expectation expect = {4, 2, 6, 0, 4136, 0, float3(1, 0, 1), float3(-1, 0, 1)}; + import_and_check("face_indices_not_first_prop_a.ply", expect); + import_and_check("face_indices_not_first_prop_b.ply", expect); +} + +TEST_F(ply_import_test, PlyImportFaceIndicesPrecededByList) +{ + Expectation expect = {4, 2, 6, 0, 4136, 0, float3(1, 0, 1), float3(-1, 0, 1)}; + import_and_check("face_indices_preceded_by_list_a.ply", expect); + import_and_check("face_indices_preceded_by_list_b.ply", expect); +} + +TEST_F(ply_import_test, PlyImportFaceUVsColors) +{ + Expectation expect = {4, 1, 4, 0, 37235, 0, float3(1, 0, 1), float3(-1, 0, 1)}; + import_and_check("face_uvs_colors_a.ply", expect); + import_and_check("face_uvs_colors_b.ply", expect); +} + +TEST_F(ply_import_test, PlyImportFacesFirst) +{ + Expectation expect = {4, + 1, + 4, + 0, + 37235, + 0, + float3(1, 0, 1), + float3(-1, 0, 1), + float3(0, 0, 0), + float2(0, 0), + float4(1, 0, 0, 1)}; + import_and_check("faces_first_a.ply", expect); + import_and_check("faces_first_b.ply", expect); +} + +TEST_F(ply_import_test, PlyImportFloatFormats) +{ + Expectation expect = {4, + 1, + 4, + 0, + 37235, + 0, + float3(1, 0, 1), + float3(-1, 0, 1), + float3(0, 0, 0), + float2(0, 0), + float4(0.5f, 0, 0.25f, 1)}; + import_and_check("float_formats_a.ply", expect); + import_and_check("float_formats_b.ply", expect); +} + +TEST_F(ply_import_test, PlyImportPositionNotFull) +{ + Expectation expect = {0, 0, 0, 0}; + import_and_check("position_not_full_a.ply", expect); + import_and_check("position_not_full_b.ply", expect); +} + +TEST_F(ply_import_test, PlyImportTristrips) +{ + Expectation expect = {6, 4, 12, 0, 3404, 0, float3(1, 0, 1), float3(-3, 0, 1)}; + import_and_check("tristrips_a.ply", expect); + import_and_check("tristrips_b.ply", expect); +} + +TEST_F(ply_import_test, PlyImportTypeAliases) +{ + Expectation expect = {4, + 1, + 4, + 0, + 37235, + 0, + float3(1, 0, 1), + float3(-1, 0, 1), + float3(0, 0, 0), + float2(0, 0), + float4(220 / 255.0f, 20 / 255.0f, 20 / 255.0f, 1)}; + import_and_check("type_aliases_a.ply", expect); + import_and_check("type_aliases_b.ply", expect); + import_and_check("type_aliases_be_b.ply", expect); +} + +TEST_F(ply_import_test, PlyImportVertexCompOrder) +{ + Expectation expect = {4, + 1, + 4, + 0, + 37235, + 0, + float3(1, 0, 1), + float3(-1, 0, 1), + float3(0, 0, 0), + float2(0, 0), + float4(0.8f, 0.2f, 0, 1)}; + import_and_check("vertex_comp_order_a.ply", expect); + import_and_check("vertex_comp_order_b.ply", expect); +} + +//@TODO: test with vertex element having list properties +//@TODO: test with edges starting with non-vertex index properties +//@TODO: test various malformed headers +//@TODO: UVs with: s,t; u,v; texture_u,texture_v; texture_s,texture_t (from miniply) +//@TODO: colors with: r,g,b in addition to red,green,blue (from miniply) +//@TODO: importing bunny2 with old importer results in smooth shading; flat shading with new one + } // namespace blender::io::ply diff --git a/source/blender/io/stl/importer/stl_import_mesh.cc b/source/blender/io/stl/importer/stl_import_mesh.cc index 2a7b074b094..39a24c2c13a 100644 --- a/source/blender/io/stl/importer/stl_import_mesh.cc +++ b/source/blender/io/stl/importer/stl_import_mesh.cc @@ -83,17 +83,18 @@ Mesh *STLMeshHelper::to_mesh(Main *bmain, char *mesh_name) mesh->totpoly = tris_.size(); mesh->totloop = tris_.size() * 3; CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly); - CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, mesh->totloop); + CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_vert"); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); threading::parallel_for(tris_.index_range(), 2048, [&](IndexRange tris_range) { for (const int i : tris_range) { polys[i].loopstart = 3 * i; polys[i].totloop = 3; - loops[3 * i].v = tris_[i].v1; - loops[3 * i + 1].v = tris_[i].v2; - loops[3 * i + 2].v = tris_[i].v3; + corner_verts[3 * i] = tris_[i].v1; + corner_verts[3 * i + 1] = tris_[i].v2; + corner_verts[3 * i + 2] = tris_[i].v3; } }); diff --git a/source/blender/io/usd/intern/usd_reader_material.cc b/source/blender/io/usd/intern/usd_reader_material.cc index 2c50f852a48..5de28d0f197 100644 --- a/source/blender/io/usd/intern/usd_reader_material.cc +++ b/source/blender/io/usd/intern/usd_reader_material.cc @@ -786,10 +786,27 @@ void USDMaterialReader::convert_usd_primvar_reader_float2( /* Set the texmap name. */ pxr::UsdShadeInput varname_input = usd_shader.GetInput(usdtokens::varname); + + /* First check if the shader's "varname" input is connected to another source, + * and use that instead if so. */ + if (varname_input) { + for (const pxr::UsdShadeConnectionSourceInfo &source_info : + varname_input.GetConnectedSources()) { + pxr::UsdShadeShader shader = pxr::UsdShadeShader(source_info.source.GetPrim()); + pxr::UsdShadeInput secondary_varname_input = shader.GetInput(source_info.sourceName); + if (secondary_varname_input) { + varname_input = secondary_varname_input; + break; + } + } + } + if (varname_input) { pxr::VtValue varname_val; - if (varname_input.Get(&varname_val) && varname_val.IsHolding()) { - std::string varname = varname_val.Get().GetString(); + /* The varname input may be a string or TfToken, so just cast it to a string. + * The Cast function is defined to provide an empty result if it fails. */ + if (varname_input.Get(&varname_val) && varname_val.CanCastToTypeid(typeid(std::string))) { + std::string varname = varname_val.Cast().Get(); if (!varname.empty()) { NodeShaderUVMap *storage = (NodeShaderUVMap *)uv_map->storage; BLI_strncpy(storage->uv_map, varname.c_str(), sizeof(storage->uv_map)); diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 79446728acb..4716597dcb9 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -263,7 +263,7 @@ bool USDMeshReader::topology_changed(const Mesh *existing_mesh, const double mot void USDMeshReader::read_mpolys(Mesh *mesh) { MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); int loop_index = 0; @@ -280,12 +280,12 @@ void USDMeshReader::read_mpolys(Mesh *mesh) if (is_left_handed_) { int loop_end_index = loop_index + (face_size - 1); for (int f = 0; f < face_size; ++f, ++loop_index) { - loops[loop_index].v = face_indices_[loop_end_index - f]; + corner_verts[loop_index] = face_indices_[loop_end_index - f]; } } else { for (int f = 0; f < face_size; ++f, ++loop_index) { - loops[loop_index].v = face_indices_[loop_index]; + corner_verts[loop_index] = face_indices_[loop_index]; } } } @@ -351,7 +351,7 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo } } - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); for (int i = 0; i < face_counts_.size(); i++) { const int face_size = face_counts_[i]; @@ -387,7 +387,7 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo /* For Vertex interpolation, use the vertex index. */ int usd_uv_index = sample.interpolation == pxr::UsdGeomTokens->vertex ? - loops[loop_index].v : + corner_verts[loop_index] : loop_index; if (usd_uv_index >= sample.uvs.size()) { @@ -468,7 +468,7 @@ void USDMeshReader::read_colors(Mesh *mesh, const double motionSampleTime) MLoopCol *colors = static_cast(cd_ptr); const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; for (int j = 0; j < poly.totloop; ++j) { @@ -478,7 +478,7 @@ void USDMeshReader::read_colors(Mesh *mesh, const double motionSampleTime) int usd_index = 0; if (interp == pxr::UsdGeomTokens->vertex) { - usd_index = loops[loop_index].v; + usd_index = corner_verts[loop_index]; } else if (interp == pxr::UsdGeomTokens->faceVarying) { usd_index = poly.loopstart; diff --git a/source/blender/io/usd/intern/usd_reader_shape.cc b/source/blender/io/usd/intern/usd_reader_shape.cc index 58ef6d5cd36..fe661b5acab 100644 --- a/source/blender/io/usd/intern/usd_reader_shape.cc +++ b/source/blender/io/usd/intern/usd_reader_shape.cc @@ -143,7 +143,7 @@ Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh, } MutableSpan polys = active_mesh->polys_for_write(); - MutableSpan loops = active_mesh->loops_for_write(); + MutableSpan corner_verts = active_mesh->corner_verts_for_write(); /* Don't smooth-shade cubes; we're not worrying about sharpness for Gprims. */ BKE_mesh_smooth_flag_set(active_mesh, !prim_.IsA()); @@ -157,7 +157,7 @@ Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh, poly.totloop = face_size; for (int f = 0; f < face_size; ++f, ++loop_index) { - loops[loop_index].v = face_indices[loop_index]; + corner_verts[loop_index] = face_indices[loop_index]; } } diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index b71997df8ef..6a0d41238f3 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -288,13 +288,13 @@ static void get_loops_polys(const Mesh *mesh, USDMeshData &usd_mesh_data) usd_mesh_data.face_indices.reserve(mesh->totloop); const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; usd_mesh_data.face_vertex_counts.push_back(poly.totloop); - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - usd_mesh_data.face_indices.push_back(loop.v); + for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + usd_mesh_data.face_indices.push_back(vert); } } } @@ -427,7 +427,7 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ const float(*lnors)[3] = static_cast( CustomData_get_layer(&mesh->ldata, CD_NORMAL)); const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); pxr::VtVec3fArray loop_normals; loop_normals.reserve(mesh->totloop); @@ -457,8 +457,8 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ } else { /* Smooth shaded, use individual vert normals. */ - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - loop_normals.push_back(pxr::GfVec3f(&vert_normals[loop.v].x)); + for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + loop_normals.push_back(pxr::GfVec3f(&vert_normals[vert].x)); } } } diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc index 8ae878f2222..23737a5c068 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc @@ -348,7 +348,7 @@ void OBJWriter::write_poly_elements(FormatHandler &fh, int prev_i = obj_mesh_data.remap_poly_index(idx - 1); int i = obj_mesh_data.remap_poly_index(idx); - Vector poly_vertex_indices = obj_mesh_data.calc_poly_vertex_indices(i); + Span poly_vertex_indices = obj_mesh_data.calc_poly_vertex_indices(i); Span poly_uv_indices = obj_mesh_data.calc_poly_uv_indices(i); Vector poly_normal_indices = obj_mesh_data.calc_poly_normal_indices(i); diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh index 59ee7bd32c0..8aa08987943 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh @@ -7,14 +7,13 @@ #pragma once #include -#include #include -#include #include "BLI_compiler_attrs.h" #include "BLI_fileops.h" #include "BLI_string_ref.hh" #include "BLI_utility_mixins.hh" +#include "BLI_vector.hh" /* SEP macro from BLI path utils clashes with SEP symbol in fmt headers. */ #undef SEP @@ -32,8 +31,8 @@ namespace blender::io::obj { */ class FormatHandler : NonCopyable, NonMovable { private: - typedef std::vector VectorChar; - std::vector blocks_; + using VectorChar = Vector; + Vector blocks_; size_t buffer_chunk_size_; public: @@ -202,9 +201,9 @@ class FormatHandler : NonCopyable, NonMovable { * If not, add a new block with max of block size & the amount of space needed. */ void ensure_space(size_t at_least) { - if (blocks_.empty() || (blocks_.back().capacity() - blocks_.back().size() < at_least)) { - VectorChar &b = blocks_.emplace_back(VectorChar()); - b.reserve(std::max(at_least, buffer_chunk_size_)); + if (blocks_.is_empty() || (blocks_.last().capacity() - blocks_.last().size() < at_least)) { + blocks_.append(VectorChar()); + blocks_.last().reserve(std::max(at_least, buffer_chunk_size_)); } } @@ -215,7 +214,7 @@ class FormatHandler : NonCopyable, NonMovable { fmt::format_to(fmt::appender(buf), fmt, std::forward(args)...); size_t len = buf.size(); ensure_space(len); - VectorChar &bb = blocks_.back(); + VectorChar &bb = blocks_.last(); bb.insert(bb.end(), buf.begin(), buf.end()); } }; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 53c82330f74..b9de9e2f1f8 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -43,7 +43,7 @@ OBJMesh::OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Obj mesh_positions_ = export_mesh_->vert_positions(); mesh_edges_ = export_mesh_->edges(); mesh_polys_ = export_mesh_->polys(); - mesh_loops_ = export_mesh_->loops(); + mesh_corner_verts_ = export_mesh_->corner_verts(); sharp_faces_ = export_mesh_->attributes().lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); } @@ -77,7 +77,7 @@ void OBJMesh::set_mesh(Mesh *mesh) mesh_positions_ = mesh->vert_positions(); mesh_edges_ = mesh->edges(); mesh_polys_ = mesh->polys(); - mesh_loops_ = mesh->loops(); + mesh_corner_verts_ = mesh->corner_verts(); sharp_faces_ = export_mesh_->attributes().lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); } @@ -203,8 +203,8 @@ void OBJMesh::calc_smooth_groups(const bool use_bitflags) poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(mesh_edges_.size(), mesh_polys_.data(), mesh_polys_.size(), - mesh_loops_.data(), - mesh_loops_.size(), + export_mesh_->corner_edges().data(), + export_mesh_->totloop, sharp_edges, sharp_faces, &tot_smooth_groups_, @@ -282,16 +282,10 @@ float3 OBJMesh::calc_vertex_coords(const int vert_index, const float global_scal return r_coords; } -Vector OBJMesh::calc_poly_vertex_indices(const int poly_index) const +Span OBJMesh::calc_poly_vertex_indices(const int poly_index) const { const MPoly &poly = mesh_polys_[poly_index]; - const MLoop *mloop = &mesh_loops_[poly.loopstart]; - const int totloop = poly.totloop; - Vector r_poly_vertex_indices(totloop); - for (int loop_index = 0; loop_index < totloop; loop_index++) { - r_poly_vertex_indices[loop_index] = mloop[loop_index].v; - } - return r_poly_vertex_indices; + return mesh_corner_verts_.slice(poly.loopstart, poly.totloop); } void OBJMesh::store_uv_coords_and_indices() @@ -312,7 +306,7 @@ void OBJMesh::store_uv_coords_and_indices() mesh_polys_.data(), nullptr, nullptr, - mesh_loops_.data(), + mesh_corner_verts_.data(), reinterpret_cast(uv_map.data()), mesh_polys_.size(), totvert, @@ -363,7 +357,7 @@ float3 OBJMesh::calc_poly_normal(const int poly_index) const { const MPoly &poly = mesh_polys_[poly_index]; float3 r_poly_normal = bke::mesh::poly_normal_calc( - mesh_positions_, mesh_loops_.slice(poly.loopstart, poly.totloop)); + mesh_positions_, mesh_corner_verts_.slice(poly.loopstart, poly.totloop)); mul_m3_v3(world_and_axes_normal_transform_, r_poly_normal); normalize_v3(r_poly_normal); return r_poly_normal; @@ -477,9 +471,8 @@ int16_t OBJMesh::get_poly_deform_group_index(const int poly_index, group_weights.fill(0); bool found_any_group = false; const MPoly &poly = mesh_polys_[poly_index]; - const MLoop *mloop = &mesh_loops_[poly.loopstart]; - for (int loop_i = 0; loop_i < poly.totloop; ++loop_i, ++mloop) { - const MDeformVert &dv = dverts[mloop->v]; + for (const int vert : mesh_corner_verts_.slice(poly.loopstart, poly.totloop)) { + const MDeformVert &dv = dverts[vert]; for (int weight_i = 0; weight_i < dv.totweight; ++weight_i) { const auto group = dv.dw[weight_i].def_nr; if (group < group_weights.size()) { diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh index 21d212f5575..a90f6e3c3fd 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh @@ -40,7 +40,7 @@ class OBJMesh : NonCopyable { Span mesh_positions_; Span mesh_edges_; Span mesh_polys_; - Span mesh_loops_; + Span mesh_corner_verts_; VArray sharp_faces_; /** @@ -153,7 +153,7 @@ class OBJMesh : NonCopyable { /** * Calculate vertex indices of all vertices of the polygon at the given index. */ - Vector calc_poly_vertex_indices(int poly_index) const; + Span calc_poly_vertex_indices(int poly_index) const; /** * Calculate UV vertex coordinates of an Object. * Stores the coordinates and UV vertex indices in the member variables. diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index 5a24020d0e4..ee53dc32bf6 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -184,7 +184,7 @@ void MeshFromGeometry::create_polys_loops(Mesh *mesh, bool use_vertex_groups) } MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); bke::SpanAttributeWriter material_indices = attributes.lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); @@ -215,9 +215,9 @@ void MeshFromGeometry::create_polys_loops(Mesh *mesh, bool use_vertex_groups) for (int idx = 0; idx < curr_face.corner_count_; ++idx) { const PolyCorner &curr_corner = mesh_geometry_.face_corners_[curr_face.start_index_ + idx]; - MLoop &mloop = loops[tot_loop_idx]; + corner_verts[tot_loop_idx] = mesh_geometry_.global_to_local_vertices_.lookup_default( + curr_corner.vert_index, 0); tot_loop_idx++; - mloop.v = mesh_geometry_.global_to_local_vertices_.lookup_default(curr_corner.vert_index, 0); /* Setup vertex group data, if needed. */ if (dverts.is_empty()) { @@ -226,7 +226,8 @@ void MeshFromGeometry::create_polys_loops(Mesh *mesh, bool use_vertex_groups) const int group_index = curr_face.vertex_group_index; /* Note: face might not belong to any group */ if (group_index >= 0 || 1) { - MDeformWeight *dw = BKE_defvert_ensure_index(&dverts[mloop.v], group_index); + MDeformWeight *dw = BKE_defvert_ensure_index(&dverts[corner_verts[tot_loop_idx]], + group_index); dw->weight = 1.0f; } } diff --git a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh index 60c9b7d7764..d8ac3191401 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh +++ b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh @@ -41,7 +41,7 @@ struct GlobalVertices { }; /** - * A face's corner in an OBJ file. In Blender, it translates to a mloop vertex. + * A face's corner in an OBJ file. In Blender, it translates to a corner vertex. */ struct PolyCorner { /* These indices range from zero to total vertices in the OBJ file. */ diff --git a/source/blender/makesdna/DNA_asset_types.h b/source/blender/makesdna/DNA_asset_types.h index 5ed625211e5..0857d92cff7 100644 --- a/source/blender/makesdna/DNA_asset_types.h +++ b/source/blender/makesdna/DNA_asset_types.h @@ -140,6 +140,10 @@ typedef struct AssetLibraryReference { * Not part of the core design, we should try to get rid of it. Only needed to wrap FileDirEntry * into a type with PropertyGroup as base, so we can have an RNA collection of #AssetHandle's to * pass to the UI. + * + * \warning Never store this! When using #ED_assetlist_iterate(), only access it within the + * iterator function. The contained file data can be freed since the file cache has a + * maximum number of items. */ # # diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 3d5cd273eda..93588519a06 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -191,7 +191,6 @@ typedef enum eCustomDataType { // #define CD_MASK_RECAST (1 << CD_RECAST) /* DEPRECATED */ #define CD_MASK_MPOLY (1 << CD_MPOLY) -#define CD_MASK_MLOOP (1 << CD_MLOOP) #define CD_MASK_SHAPE_KEYINDEX (1 << CD_SHAPE_KEYINDEX) #define CD_MASK_SHAPEKEY (1 << CD_SHAPEKEY) #define CD_MASK_BWEIGHT (1 << CD_BWEIGHT) diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h index 00543b9df9a..ce714dc9879 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h @@ -330,10 +330,10 @@ .edge_types = LRT_EDGE_FLAG_INIT_TYPE, \ .thickness = 25, \ .opacity = 1.0f, \ - .flags = LRT_GPENCIL_MATCH_OUTPUT_VGROUP, \ .crease_threshold = DEG2RAD(140.0f), \ .calculation_flags = LRT_ALLOW_DUPLI_OBJECTS | LRT_ALLOW_CLIPPING_BOUNDARIES | \ - LRT_USE_CREASE_ON_SHARP_EDGES | LRT_FILTER_FACE_MARK_KEEP_CONTOUR, \ + LRT_USE_CREASE_ON_SHARP_EDGES | LRT_FILTER_FACE_MARK_KEEP_CONTOUR | \ + LRT_GPENCIL_MATCH_OUTPUT_VGROUP, \ /* Do not split by default, this is for better chaining quality. */ \ .angle_splitting_threshold = 0.0f, \ .chaining_image_threshold = 0.001f, \ diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 87c21447fa4..67c1606be94 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -71,7 +71,7 @@ typedef struct Mesh { int totedge; /** The number of polygons/faces (#MPoly) in the mesh, and the size of #pdata. */ int totpoly; - /** The number of face corners (#MLoop) in the mesh, and the size of #ldata. */ + /** The number of face corners in the mesh, and the size of #ldata. */ int totloop; CustomData vdata, edata, pdata, ldata; @@ -226,8 +226,9 @@ typedef struct Mesh { blender::MutableSpan vert_positions_for_write(); /** * Array of edges, containing vertex indices. For simple triangle or quad meshes, edges could be - * calculated from the #MPoly and #MLoop arrays, however, edges need to be stored explicitly to - * edge domain attributes and to support loose edges that aren't connected to faces. + * calculated from the #MPoly and "corner edge" arrays, however, edges need to be stored + * explicitly to edge domain attributes and to support loose edges that aren't connected to + * faces. */ blender::Span edges() const; /** Write access to edge data. */ @@ -238,13 +239,28 @@ typedef struct Mesh { blender::Span polys() const; /** Write access to polygon data. */ blender::MutableSpan polys_for_write(); + /** - * Mesh face corners that "loop" around each face, storing the vertex index and the index of the - * subsequent edge. + * Array of vertices for every face corner, stored in the ".corner_vert" integer attribute. + * For example, the vertices in a face can be retrieved with the #slice method: + * \code{.cc} + * const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + * \endcode + * Such a span can often be passed as an argument in lieu of a polygon and the entire corner + * verts array. */ - blender::Span loops() const; - /** Write access to loop data. */ - blender::MutableSpan loops_for_write(); + blender::Span corner_verts() const; + /** Write access to the #corner_verts data. */ + blender::MutableSpan corner_verts_for_write(); + + /** + * Array of edges following every face corner traveling around each face, stored in the + * ".corner_edge" attribute. The array sliced the same way as the #corner_verts data. The edge + * previous to a corner must be accessed with the index of the previous face corner. + */ + blender::Span corner_edges() const; + /** Write access to the #corner_edges data. */ + blender::MutableSpan corner_edges_for_write(); blender::bke::AttributeAccessor attributes() const; blender::bke::MutableAttributeAccessor attributes_for_write(); diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index e2bfef9629d..4410e670b88 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -52,7 +52,8 @@ enum { /** * Mesh Faces. - * This only stores the polygon size & flags, the vertex & edge indices are stored in the #MLoop. + * This only stores the polygon size & flags, the vertex & edge indices are stored in the "corner + * edges" array. * * Typically accessed with #Mesh.polys(). */ @@ -78,19 +79,6 @@ enum { }; #endif -/** - * Mesh Face Corners. - * "Loop" is an internal name for the corner of a polygon (#MPoly). - * - * Typically accessed with #Mesh.loops(). - */ -typedef struct MLoop { - /** Vertex index. */ - unsigned int v; - /** Edge index into an #MEdge array. */ - unsigned int e; -} MLoop; - /** \} */ /* -------------------------------------------------------------------- */ @@ -126,7 +114,7 @@ enum { /** * #MLoopTri's are lightweight triangulation data, * for functionality that doesn't support ngons (#MPoly). - * This is cache data created from (#MPoly, #MLoop & position arrays). + * This is cache data created from (#MPoly, corner vert & position arrays). * There is no attempt to maintain this data's validity over time, * any changes to the underlying mesh invalidate the #MLoopTri array, * which will need to be re-calculated. @@ -153,9 +141,9 @@ enum { * * // access vertex locations. * float *vtri_co[3] = { - * positions[mloop[lt->tri[0]].v], - * positions[mloop[lt->tri[1]].v], - * positions[mloop[lt->tri[2]].v], + * positions[corner_verts[lt->tri[0]]], + * positions[corner_verts[lt->tri[1]]], + * positions[corner_verts[lt->tri[2]]], * }; * * // access UV coordinates (works for all loop data, vertex colors... etc). @@ -179,10 +167,10 @@ enum { * int j, lt_tot = ME_POLY_TRI_TOT(poly); * * for (j = 0; j < lt_tot; j++, lt++) { - * unsigned int vtri[3] = { - * mloop[lt->tri[0]].v, - * mloop[lt->tri[1]].v, - * mloop[lt->tri[2]].v, + * int vtri[3] = { + * corner_verts[lt->tri[0]], + * corner_verts[lt->tri[1]], + * corner_verts[lt->tri[2]], * }; * printf("tri %u %u %u\n", vtri[0], vtri[1], vtri[2]); * }; @@ -191,16 +179,16 @@ enum { * It may also be useful to check whether or not two vertices of a triangle * form an edge in the underlying mesh. * - * This can be done by checking the edge of the referenced loop (#MLoop.e), - * the winding of the #MLoopTri and the #MLoop's will always match, + * This can be done by checking the edge of the referenced corner, + * the winding of the #MLoopTri and the corners's will always match, * however the order of vertices in the edge is undefined. * * \code{.c} * // print real edges from an MLoopTri: lt * int j, j_next; * for (j = 2, j_next = 0; j_next < 3; j = j_next++) { - * MEdge *ed = &medge[mloop[lt->tri[j]].e]; - * unsigned int tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v}; + * MEdge *ed = &medge[corner_edges[lt->tri[j]]]; + * unsigned int tri_edge[2] = {corner_verts[lt->tri[j]], corner_verts[lt->tri[j_next]]}; * * if (((ed->v1 == tri_edge[0]) && (ed->v2 == tri_edge[1])) || * ((ed->v1 == tri_edge[1]) && (ed->v2 == tri_edge[0]))) @@ -410,10 +398,9 @@ enum { /** \name Utility Macros * \{ */ -#define ME_POLY_LOOP_PREV(mloop, poly, i) \ - (&(mloop)[(poly)->loopstart + (((i) + (poly)->totloop - 1) % (poly)->totloop)]) -#define ME_POLY_LOOP_NEXT(mloop, poly, i) \ - (&(mloop)[(poly)->loopstart + (((i) + 1) % (poly)->totloop)]) +#define ME_POLY_LOOP_PREV(poly, i) \ + ((poly)->loopstart + (((i) + (poly)->totloop - 1) % (poly)->totloop)) +#define ME_POLY_LOOP_NEXT(poly, i) ((poly)->loopstart + (((i) + 1) % (poly)->totloop)) /** Number of tri's that make up this polygon once tessellated. */ #define ME_POLY_TRI_TOT(poly) ((poly)->totloop - 2) @@ -452,12 +439,10 @@ enum { MLOOPUV_PINNED = (1 << 2), }; -#endif - /** * Deprecated mesh vertex data structure. Now stored with generic attributes. */ -#ifdef DNA_DEPRECATED_ALLOW + typedef struct MVert { float co_legacy[3]; /** @@ -479,11 +464,24 @@ enum { /** Deprecated hide status. Now stored in ".hide_vert" attribute. */ ME_HIDE = (1 << 4), }; + +/** + * Mesh Face Corners. + * Deprecated storage for the vertex of a face corner and the following edge. + * Replaced by the "corner_verts" and "corner_edges" arrays. + */ +typedef struct MLoop { + /** Vertex index. */ + unsigned int v; + /** Edge index into an #MEdge array. */ + unsigned int e; +} MLoop; + #endif /** - * Used in Blender pre 2.63, See #MLoop, #MPoly for face data stored in the blend file. - * Use for reading old files and in a handful of cases which should be removed eventually. + * Used in Blender pre 2.63, See #Mesh::corner_verts(), #MPoly for face data stored in the blend + * file. Use for reading old files and in a handful of cases which should be removed eventually. */ typedef struct MFace { unsigned int v1, v2, v3, v4; diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index fb2aef28551..cc7360ae6a4 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -470,7 +470,7 @@ typedef struct ARegion { short flag; /** Current split size in unscaled pixels (if zero it uses regiontype). - * To convert to pixels use: `UI_DPI_FAC * region->sizex + 0.5f`. + * To convert to pixels use: `UI_SCALE_FAC * region->sizex + 0.5f`. * However to get the current region size, you should usually use winx/winy from above, not this! */ short sizex, sizey; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 3a7802fb7c6..d916e323d23 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -15,6 +15,20 @@ extern "C" { #endif +/** + * Scaling factor for all UI elements, based on the "Resolution Scale" user preference and the + * DPI/OS Scale of each monitor. This is a read-only, run-time value calculated by + * `WM_window_set_dpi` at various times, including between the drawing of each window and so can + * vary between monitors. + */ +#define UI_SCALE_FAC ((void)0, U.scale_factor) + +/* Inverse of UI_SCALE_FAC ( 1 / UI_SCALE_FAC). */ +#define UI_INV_SCALE_FAC ((void)0, U.inv_scale_factor) + +/* 16 to copy ICON_DEFAULT_HEIGHT */ +#define UI_ICON_SIZE ((float)16 * U.scale_factor) + /* Themes; defines in `BIF_resource.h`. */ struct ColorBand; @@ -750,10 +764,10 @@ typedef struct UserDef { int ui_line_width; /** Runtime, full DPI divided by `pixelsize`. */ int dpi; - /** Runtime, multiplier to scale UI elements based on DPI (fractional). */ - float dpi_fac; - /** Runtime, `1.0 / dpi_fac` */ - float inv_dpi_fac; + /** Runtime multiplier to scale UI elements. Use macro UI_SCALE_FAC instead of this. */ + float scale_factor; + /** Runtime, `1.0 / scale_factor` */ + float inv_scale_factor; /** Runtime, calculated from line-width and point-size based on DPI (rounded to int). */ float pixelsize; /** Deprecated, for forward compatibility. */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 0854f89a410..50b3c6fc432 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -22,6 +22,7 @@ extern "C" { struct wmWindow; struct wmWindowManager; +struct wmEvent_ConsecutiveData; struct wmEvent; struct wmKeyConfig; struct wmKeyMap; @@ -280,6 +281,15 @@ typedef struct wmWindow { short grabcursor; /** Internal: tag this for extra mouse-move event, * makes cursors/buttons active on UI switching. */ + + /** Internal, lock pie creation from this event until released. */ + short pie_event_type_lock; + /** + * Exception to the above rule for nested pies, store last pie event for operators + * that spawn a new pie right after destruction of last pie. + */ + short pie_event_type_last; + char addmousemove; char tag_cursor_refresh; @@ -296,15 +306,12 @@ typedef struct wmWindow { */ char event_queue_check_drag_handled; - char _pad0[1]; - - /** Internal, lock pie creation from this event until released. */ - short pie_event_type_lock; - /** - * Exception to the above rule for nested pies, store last pie event for operators - * that spawn a new pie right after destruction of last pie. - */ - short pie_event_type_last; + /** The last event type (that passed #WM_event_consecutive_gesture_test check). */ + char event_queue_consecutive_gesture_type; + /** The cursor location when `event_queue_consecutive_gesture_type` was set. */ + int event_queue_consecutive_gesture_xy[2]; + /** See #WM_event_consecutive_data_get and related API. Freed when consecutive events end. */ + struct wmEvent_ConsecutiveData *event_queue_consecutive_gesture_data; /** * Storage for event system. diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c index 4a48562b03e..b88322e7c25 100644 --- a/source/blender/makesrna/intern/rna_asset.c +++ b/source/blender/makesrna/intern/rna_asset.c @@ -578,6 +578,17 @@ static void rna_def_asset_handle(BlenderRNA *brna) rna_def_asset_handle_api(srna); } +static void rna_def_asset_representation(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "AssetRepresentation", NULL); + RNA_def_struct_ui_text(srna, + "Asset Representation", + "Information about an entity that makes it possible for the asset system " + "to deal with the entity as asset"); +} + static void rna_def_asset_catalog_path(BlenderRNA *brna) { StructRNA *srna = RNA_def_struct(brna, "AssetCatalogPath", NULL); @@ -610,6 +621,7 @@ void RNA_def_asset(BlenderRNA *brna) rna_def_asset_data(brna); rna_def_asset_library_reference(brna); rna_def_asset_handle(brna); + rna_def_asset_representation(brna); rna_def_asset_catalog_path(brna); RNA_define_animate_sdna(true); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 37c02367f05..e41c3e7179d 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -395,8 +395,8 @@ static int rna_MeshPolygon_index_get(PointerRNA *ptr) static int rna_MeshLoop_index_get(PointerRNA *ptr) { const Mesh *mesh = rna_mesh(ptr); - const MLoop *mloop = (MLoop *)ptr->data; - const int index = (int)(mloop - BKE_mesh_loops(mesh)); + const int *corner_vert = (const int *)ptr->data; + const int index = (int)(corner_vert - BKE_mesh_corner_verts(mesh)); BLI_assert(index >= 0); BLI_assert(index < mesh->totloop); return index; @@ -560,6 +560,30 @@ static void rna_MEdge_crease_set(PointerRNA *ptr, float value) values[index] = clamp_f(value, 0.0f, 1.0f); } +static int rna_MeshLoop_vertex_index_get(PointerRNA *ptr) +{ + return *(int *)ptr->data; +} + +static void rna_MeshLoop_vertex_index_set(PointerRNA *ptr, int value) +{ + *(int *)ptr->data = value; +} + +static int rna_MeshLoop_edge_index_get(PointerRNA *ptr) +{ + const Mesh *me = rna_mesh(ptr); + const int index = rna_MeshLoop_index_get(ptr); + return BKE_mesh_corner_edges(me)[index]; +} + +static void rna_MeshLoop_edge_index_set(PointerRNA *ptr, int value) +{ + Mesh *me = rna_mesh(ptr); + const int index = rna_MeshLoop_index_get(ptr); + BKE_mesh_corner_edges_for_write(me)[index] = value; +} + static void rna_MeshLoop_normal_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); @@ -629,9 +653,9 @@ static void rna_MeshPolygon_normal_get(PointerRNA *ptr, float *values) Mesh *me = rna_mesh(ptr); MPoly *poly = (MPoly *)ptr->data; const float(*positions)[3] = BKE_mesh_vert_positions(me); - const MLoop *loops = BKE_mesh_loops(me); + const int *corner_verts = BKE_mesh_corner_verts(me); BKE_mesh_calc_poly_normal( - &loops[poly->loopstart], poly->totloop, positions, me->totvert, values); + &corner_verts[poly->loopstart], poly->totloop, positions, me->totvert, values); } static bool rna_MeshPolygon_hide_get(PointerRNA *ptr) @@ -725,7 +749,7 @@ static void rna_MeshPolygon_material_index_set(PointerRNA *ptr, int value) Mesh *mesh = rna_mesh(ptr); int *material_indices = BKE_mesh_material_indices_for_write(mesh); const int index = rna_MeshPolygon_index_get(ptr); - material_indices[index] = value; + material_indices[index] = max_ii(0, value); } static void rna_MeshPolygon_center_get(PointerRNA *ptr, float *values) @@ -733,9 +757,9 @@ static void rna_MeshPolygon_center_get(PointerRNA *ptr, float *values) Mesh *me = rna_mesh(ptr); MPoly *poly = (MPoly *)ptr->data; const float(*positions)[3] = BKE_mesh_vert_positions(me); - const MLoop *loops = BKE_mesh_loops(me); + const int *corner_verts = BKE_mesh_corner_verts(me); BKE_mesh_calc_poly_center( - &loops[poly->loopstart], poly->totloop, positions, me->totvert, values); + &corner_verts[poly->loopstart], poly->totloop, positions, me->totvert, values); } static float rna_MeshPolygon_area_get(PointerRNA *ptr) @@ -743,15 +767,17 @@ static float rna_MeshPolygon_area_get(PointerRNA *ptr) Mesh *me = (Mesh *)ptr->owner_id; MPoly *poly = (MPoly *)ptr->data; const float(*positions)[3] = BKE_mesh_vert_positions(me); - const MLoop *loops = BKE_mesh_loops(me); - return BKE_mesh_calc_poly_area(&loops[poly->loopstart], poly->totloop, positions, me->totvert); + const int *corner_verts = BKE_mesh_corner_verts(me); + return BKE_mesh_calc_poly_area( + &corner_verts[poly->loopstart], poly->totloop, positions, me->totvert); } static void rna_MeshPolygon_flip(ID *id, MPoly *poly) { Mesh *me = (Mesh *)id; - MLoop *loops = BKE_mesh_loops_for_write(me); - BKE_mesh_polygon_flip(poly, loops, &me->ldata, me->totloop); + int *corner_verts = BKE_mesh_corner_verts_for_write(me); + int *corner_edges = BKE_mesh_corner_edges_for_write(me); + BKE_mesh_polygon_flip(poly, corner_verts, corner_edges, &me->ldata, me->totloop); BKE_mesh_tessface_clear(me); BKE_mesh_runtime_clear_geometry(me); } @@ -759,11 +785,11 @@ static void rna_MeshPolygon_flip(ID *id, MPoly *poly) static void rna_MeshLoopTriangle_verts_get(PointerRNA *ptr, int *values) { Mesh *me = rna_mesh(ptr); - const MLoop *loops = BKE_mesh_loops(me); + const int *corner_verts = BKE_mesh_corner_verts(me); MLoopTri *lt = (MLoopTri *)ptr->data; - values[0] = loops[lt->tri[0]].v; - values[1] = loops[lt->tri[1]].v; - values[2] = loops[lt->tri[2]].v; + values[0] = corner_verts[lt->tri[0]]; + values[1] = corner_verts[lt->tri[1]]; + values[2] = corner_verts[lt->tri[2]]; } static void rna_MeshLoopTriangle_normal_get(PointerRNA *ptr, float *values) @@ -771,10 +797,10 @@ static void rna_MeshLoopTriangle_normal_get(PointerRNA *ptr, float *values) Mesh *me = rna_mesh(ptr); MLoopTri *lt = (MLoopTri *)ptr->data; const float(*positions)[3] = BKE_mesh_vert_positions(me); - const MLoop *loops = BKE_mesh_loops(me); - uint v1 = loops[lt->tri[0]].v; - uint v2 = loops[lt->tri[1]].v; - uint v3 = loops[lt->tri[2]].v; + const int *corner_verts = BKE_mesh_corner_verts(me); + const int v1 = corner_verts[lt->tri[0]]; + const int v2 = corner_verts[lt->tri[1]]; + const int v3 = corner_verts[lt->tri[2]]; normal_tri_v3(values, positions[v1], positions[v2], positions[v3]); } @@ -802,10 +828,10 @@ static float rna_MeshLoopTriangle_area_get(PointerRNA *ptr) Mesh *me = rna_mesh(ptr); MLoopTri *lt = (MLoopTri *)ptr->data; const float(*positions)[3] = BKE_mesh_vert_positions(me); - const MLoop *loops = BKE_mesh_loops(me); - uint v1 = loops[lt->tri[0]].v; - uint v2 = loops[lt->tri[1]].v; - uint v3 = loops[lt->tri[2]].v; + const int *corner_verts = BKE_mesh_corner_verts(me); + const int v1 = corner_verts[lt->tri[0]]; + const int v2 = corner_verts[lt->tri[1]]; + const int v3 = corner_verts[lt->tri[2]]; return area_tri_v3(positions[v1], positions[v2], positions[v3]); } @@ -1643,27 +1669,17 @@ static int rna_MeshPoly_vertices_get_length(const PointerRNA *ptr, static void rna_MeshPoly_vertices_get(PointerRNA *ptr, int *values) { - Mesh *me = rna_mesh(ptr); - MPoly *poly = (MPoly *)ptr->data; - const MLoop *loops = BKE_mesh_loops(me); - const MLoop *ml = &loops[poly->loopstart]; - uint i; - for (i = poly->totloop; i > 0; i--, values++, ml++) { - *values = ml->v; - } + const Mesh *me = rna_mesh(ptr); + const MPoly *poly = (const MPoly *)ptr->data; + memcpy(values, BKE_mesh_corner_verts(me) + poly->loopstart, sizeof(int) * poly->totloop); } static void rna_MeshPoly_vertices_set(PointerRNA *ptr, const int *values) { Mesh *me = rna_mesh(ptr); const MPoly *poly = (const MPoly *)ptr->data; - MLoop *loops = BKE_mesh_loops_for_write(me); - - MLoop *ml = &loops[poly->loopstart]; - uint i; - for (i = poly->totloop; i > 0; i--, values++, ml++) { - ml->v = *values; - } + memcpy( + BKE_mesh_corner_verts_for_write(me) + poly->loopstart, values, sizeof(int) * poly->totloop); } /* disabling, some importers don't know the total material count when assigning materials */ @@ -2009,7 +2025,7 @@ static void rna_Mesh_loops_begin(CollectionPropertyIterator *iter, PointerRNA *p { Mesh *mesh = rna_mesh(ptr); rna_iterator_array_begin( - iter, BKE_mesh_loops_for_write(mesh), sizeof(MLoop), mesh->totloop, false, NULL); + iter, BKE_mesh_corner_verts_for_write(mesh), sizeof(int), mesh->totloop, false, NULL); } static int rna_Mesh_loops_length(PointerRNA *ptr) { @@ -2024,7 +2040,7 @@ int rna_Mesh_loops_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) } r_ptr->owner_id = &mesh->id; r_ptr->type = &RNA_MeshLoop; - r_ptr->data = &BKE_mesh_loops_for_write(mesh)[index]; + r_ptr->data = &BKE_mesh_corner_verts_for_write(mesh)[index]; return true; } @@ -2856,17 +2872,18 @@ static void rna_def_mloop(BlenderRNA *brna) PropertyRNA *prop; srna = RNA_def_struct(brna, "MeshLoop", NULL); - RNA_def_struct_sdna(srna, "MLoop"); RNA_def_struct_ui_text(srna, "Mesh Loop", "Loop in a Mesh data-block"); RNA_def_struct_path_func(srna, "rna_MeshLoop_path"); RNA_def_struct_ui_icon(srna, ICON_EDGESEL); prop = RNA_def_property(srna, "vertex_index", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "v"); + RNA_def_property_int_funcs( + prop, "rna_MeshLoop_vertex_index_get", "rna_MeshLoop_vertex_index_set", false); RNA_def_property_ui_text(prop, "Vertex", "Vertex index"); prop = RNA_def_property(srna, "edge_index", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "e"); + RNA_def_property_int_funcs( + prop, "rna_MeshLoop_edge_index_get", "rna_MeshLoop_edge_index_set", false); RNA_def_property_ui_text(prop, "Edge", "Edge index"); prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 3699a2ed66d..c24cd7c6d3a 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -98,7 +98,7 @@ static void rna_Mesh_calc_smooth_groups( *r_poly_group = BKE_mesh_calc_smoothgroups(mesh->totedge, BKE_mesh_polys(mesh), mesh->totpoly, - BKE_mesh_loops(mesh), + BKE_mesh_corner_edges(mesh), mesh->totloop, sharp_edges, sharp_faces, @@ -171,8 +171,11 @@ static void rna_Mesh_transform(Mesh *mesh, float mat[16], bool shape_keys) static void rna_Mesh_flip_normals(Mesh *mesh) { - BKE_mesh_polys_flip( - BKE_mesh_polys(mesh), BKE_mesh_loops_for_write(mesh), &mesh->ldata, mesh->totpoly); + BKE_mesh_polys_flip(BKE_mesh_polys(mesh), + BKE_mesh_corner_verts_for_write(mesh), + BKE_mesh_corner_edges_for_write(mesh), + &mesh->ldata, + mesh->totpoly); BKE_mesh_tessface_clear(mesh); BKE_mesh_runtime_clear_geometry(mesh); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index cac380e92ee..eff44f016c9 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -10034,6 +10034,32 @@ static void def_geo_points_to_volume(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_points_to_sdf_volume(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem resolution_mode_items[] = { + {GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT, + "VOXEL_AMOUNT", + 0, + "Amount", + "Specify the approximate number of voxels along the diagonal"}, + {GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE, + "VOXEL_SIZE", + 0, + "Size", + "Specify the voxel side length"}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_struct_sdna_from(srna, "NodeGeometryPointsToVolume", "storage"); + + prop = RNA_def_property(srna, "resolution_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, resolution_mode_items); + RNA_def_property_ui_text(prop, "Resolution Mode", "How the voxel size is specified"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + static void def_geo_uv_unwrap(StructRNA *srna) { PropertyRNA *prop; @@ -10181,6 +10207,32 @@ static void def_geo_mesh_to_volume(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_mesh_to_sdf_volume(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem resolution_mode_items[] = { + {MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT, + "VOXEL_AMOUNT", + 0, + "Amount", + "Desired number of voxels along one axis"}, + {MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE, + "VOXEL_SIZE", + 0, + "Size", + "Desired voxel side length"}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_struct_sdna_from(srna, "NodeGeometryMeshToVolume", "storage"); + + prop = RNA_def_property(srna, "resolution_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, resolution_mode_items); + RNA_def_property_ui_text(prop, "Resolution Mode", "How the voxel size is specified"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + static void def_geo_mesh_circle(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 3beaf9c9a45..5fd5d2c09b1 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -3328,6 +3328,7 @@ static void rna_def_text(StructRNA *srna) prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Text", "Text that will be displayed"); + RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "use_shadow", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 3077463e5cc..5fb55eb6f20 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2624,8 +2624,8 @@ static void rna_SpaceNodeEditor_cursor_location_from_region(SpaceNode *snode, float cursor_location[2]; UI_view2d_region_to_view(®ion->v2d, x, y, &cursor_location[0], &cursor_location[1]); - cursor_location[0] /= UI_DPI_FAC; - cursor_location[1] /= UI_DPI_FAC; + cursor_location[0] /= UI_SCALE_FAC; + cursor_location[1] /= UI_SCALE_FAC; ED_node_cursor_location_set(snode, cursor_location); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 449bf86e810..e6e0a3526e0 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -5503,7 +5503,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) prop = RNA_def_property(srna, "ui_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_float_sdna(prop, NULL, "dpi_fac"); + RNA_def_property_float_sdna(prop, NULL, "scale_factor"); RNA_def_property_ui_text( prop, "UI Scale", diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 6140c9ed43a..ace7ca9c136 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -664,6 +664,12 @@ static bool rna_Event_is_repeat_get(PointerRNA *ptr) return (event->flag & WM_EVENT_IS_REPEAT) != 0; } +static bool rna_Event_is_consecutive_get(PointerRNA *ptr) +{ + const wmEvent *event = ptr->data; + return (event->flag & WM_EVENT_IS_CONSECUTIVE) != 0; +} + static float rna_Event_pressure_get(PointerRNA *ptr) { const wmEvent *event = ptr->data; @@ -2154,6 +2160,15 @@ static void rna_def_event(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_Event_is_repeat_get", NULL); RNA_def_property_ui_text(prop, "Is Repeat", "The event is generated by holding a key down"); + /* Track-pad & NDOF. */ + prop = RNA_def_property(srna, "is_consecutive", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_boolean_funcs(prop, "rna_Event_is_consecutive_get", NULL); + RNA_def_property_ui_text(prop, + "Is Consecutive", + "Part of a track-pad or NDOF motion, " + "interrupted by cursor motion, button or key press events"); + /* mouse */ prop = RNA_def_property(srna, "mouse_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "xy[0]"); diff --git a/source/blender/modifiers/intern/MOD_array.cc b/source/blender/modifiers/intern/MOD_array.cc index 458983c0ca5..4c76976a792 100644 --- a/source/blender/modifiers/intern/MOD_array.cc +++ b/source/blender/modifiers/intern/MOD_array.cc @@ -284,11 +284,11 @@ static void mesh_merge_transform(Mesh *result, int *index_orig; int i; MEdge *edge; - MLoop *ml; float(*result_positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan result_edges = result->edges_for_write(); blender::MutableSpan result_polys = result->polys_for_write(); - blender::MutableSpan result_loops = result->loops_for_write(); + blender::MutableSpan result_corner_verts = result->corner_verts_for_write(); + blender::MutableSpan result_corner_edges = result->corner_edges_for_write(); CustomData_copy_data(&cap_mesh->vdata, &result->vdata, 0, cap_verts_index, cap_nverts); CustomData_copy_data(&cap_mesh->edata, &result->edata, 0, cap_edges_index, cap_nedges); @@ -327,10 +327,9 @@ static void mesh_merge_transform(Mesh *result, } /* adjust cap loop vertex and edge indices */ - ml = &result_loops[cap_loops_index]; - for (i = 0; i < cap_nloops; i++, ml++) { - ml->v += cap_verts_index; - ml->e += cap_edges_index; + for (i = 0; i < cap_nloops; i++) { + result_corner_verts[cap_loops_index + i] += cap_verts_index; + result_corner_edges[cap_loops_index + i] += cap_edges_index; } const bke::AttributeAccessor cap_attributes = cap_mesh->attributes(); @@ -379,7 +378,6 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } MEdge *edge; - MLoop *ml; int i, j, c, count; float length = amd->length; /* offset matrix */ @@ -557,7 +555,8 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, float(*result_positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan result_edges = result->edges_for_write(); blender::MutableSpan result_polys = result->polys_for_write(); - blender::MutableSpan result_loops = result->loops_for_write(); + blender::MutableSpan result_corner_verts = result->corner_verts_for_write(); + blender::MutableSpan result_corner_edges = result->corner_edges_for_write(); if (use_merge) { /* Will need full_doubles_map for handling merge */ @@ -621,10 +620,10 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } /* adjust loop vertex and edge indices */ - ml = &result_loops[c * chunk_nloops]; - for (i = 0; i < chunk_nloops; i++, ml++) { - ml->v += c * chunk_nverts; - ml->e += c * chunk_nedges; + const int chunk_corner_start = c * chunk_nloops; + for (i = 0; i < chunk_nloops; i++) { + result_corner_verts[chunk_corner_start + i] += c * chunk_nverts; + result_corner_edges[chunk_corner_start + i] += c * chunk_nedges; } /* Handle merge between chunk n and n-1 */ diff --git a/source/blender/modifiers/intern/MOD_build.cc b/source/blender/modifiers/intern/MOD_build.cc index e4c28530bc1..e0df87ef849 100644 --- a/source/blender/modifiers/intern/MOD_build.cc +++ b/source/blender/modifiers/intern/MOD_build.cc @@ -61,8 +61,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * int faces_dst_num, edges_dst_num, loops_dst_num = 0; float frac; MPoly *mpoly_dst; - MLoop *ml_dst; - const MLoop *ml_src; GHashIterator gh_iter; /* maps vert indices in old mesh to indices in new mesh */ GHash *vertHash = BLI_ghash_int_new("build ve apply gh"); @@ -74,7 +72,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * const int vert_src_num = mesh->totvert; const blender::Span edges_src = mesh->edges(); const blender::Span polys_src = mesh->polys(); - const blender::Span loops_src = mesh->loops(); + const blender::Span corner_verts_src = mesh->corner_verts(); + const blender::Span corner_edges_src = mesh->corner_edges(); int *vertMap = static_cast(MEM_malloc_arrayN(vert_src_num, sizeof(int), __func__)); int *edgeMap = static_cast(MEM_malloc_arrayN(edges_src.size(), sizeof(int), __func__)); @@ -97,7 +96,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* if there's at least one face, build based on faces */ if (faces_dst_num) { const MPoly *polys, *poly; - const MLoop *ml, *mloop; uintptr_t hash_num, hash_num_alt; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { @@ -108,15 +106,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * * mapped to the new indices */ polys = polys_src.data(); - mloop = loops_src.data(); hash_num = 0; for (i = 0; i < faces_dst_num; i++) { poly = polys + faceMap[i]; - ml = mloop + poly->loopstart; - - for (j = 0; j < poly->totloop; j++, ml++) { + for (j = 0; j < poly->totloop; j++) { + const int vert_i = corner_verts_src[poly->loopstart + j]; void **val_p; - if (!BLI_ghash_ensure_p(vertHash, POINTER_FROM_INT(ml->v), &val_p)) { + if (!BLI_ghash_ensure_p(vertHash, POINTER_FROM_INT(vert_i), &val_p)) { *val_p = (void *)hash_num; hash_num++; } @@ -200,7 +196,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * mesh, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), loops_dst_num, faces_dst_num); blender::MutableSpan result_edges = result->edges_for_write(); blender::MutableSpan result_polys = result->polys_for_write(); - blender::MutableSpan result_loops = result->loops_for_write(); + blender::MutableSpan result_corner_verts = result->corner_verts_for_write(); + blender::MutableSpan result_corner_edges = result->corner_edges_for_write(); /* copy the vertices across */ GHASH_ITER (gh_iter, vertHash) { @@ -226,7 +223,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } mpoly_dst = result_polys.data(); - ml_dst = result_loops.data(); /* copy the faces across, remapping indices */ k = 0; @@ -243,10 +239,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * CustomData_copy_data( &mesh->ldata, &result->ldata, source->loopstart, dest->loopstart, dest->totloop); - ml_src = &loops_src[source->loopstart]; - for (j = 0; j < source->totloop; j++, k++, ml_src++, ml_dst++) { - ml_dst->v = POINTER_AS_INT(BLI_ghash_lookup(vertHash, POINTER_FROM_INT(ml_src->v))); - ml_dst->e = POINTER_AS_INT(BLI_ghash_lookup(edgeHash2, POINTER_FROM_INT(ml_src->e))); + for (j = 0; j < source->totloop; j++, k++) { + const int vert_src = corner_verts_src[source->loopstart + j]; + const int edge_src = corner_edges_src[source->loopstart + j]; + result_corner_verts[dest->loopstart + j] = POINTER_AS_INT( + BLI_ghash_lookup(vertHash, POINTER_FROM_INT(vert_src))); + result_corner_edges[dest->loopstart + j] = POINTER_AS_INT( + BLI_ghash_lookup(edgeHash2, POINTER_FROM_INT(edge_src))); } } diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 5f5cbfc342d..788adb5f62f 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -159,11 +159,11 @@ static void deformVerts(ModifierData *md, collmd->mvert_num = mvert_num; { - const MLoop *mloop = BKE_mesh_loops(mesh_src); const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh_src); collmd->tri_num = BKE_mesh_runtime_looptri_len(mesh_src); MVertTri *tri = MEM_mallocN(sizeof(*tri) * collmd->tri_num, __func__); - BKE_mesh_runtime_verttri_from_looptri(tri, mloop, looptri, collmd->tri_num); + BKE_mesh_runtime_verttri_from_looptri( + tri, BKE_mesh_corner_verts(mesh_src), looptri, collmd->tri_num); collmd->tri = tri; } diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.cc b/source/blender/modifiers/intern/MOD_correctivesmooth.cc index 7dfbe03ca84..eecaad2e1aa 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.cc +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.cc @@ -129,7 +129,7 @@ static void mesh_get_boundaries(Mesh *mesh, float *smooth_weights) { const blender::Span edges = mesh->edges(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_edges = mesh->corner_edges(); /* Flag boundary edges so only boundaries are set to 1. */ uint8_t *boundaries = static_cast( @@ -139,7 +139,7 @@ static void mesh_get_boundaries(Mesh *mesh, float *smooth_weights) const int totloop = polys[i].totloop; int j; for (j = 0; j < totloop; j++) { - uint8_t *e_value = &boundaries[loops[polys[i].loopstart + j].e]; + uint8_t *e_value = &boundaries[corner_edges[polys[i].loopstart + j]]; *e_value |= uint8_t((*e_value) + 1); } } @@ -435,7 +435,7 @@ static void calc_tangent_spaces(const Mesh *mesh, { const uint mvert_num = uint(mesh->totvert); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + blender::Span corner_verts = mesh->corner_verts(); if (r_tangent_weights_per_vertex != nullptr) { copy_vn_fl(r_tangent_weights_per_vertex, int(mvert_num), 0.0f); @@ -443,40 +443,42 @@ static void calc_tangent_spaces(const Mesh *mesh, for (const int64_t i : polys.index_range()) { const MPoly &poly = polys[i]; - const MLoop *l_next = &loops[poly.loopstart]; - const MLoop *l_term = l_next + poly.totloop; - const MLoop *l_prev = l_term - 2; - const MLoop *l_curr = l_term - 1; + int next_corner = poly.loopstart; + int term_corner = next_corner + poly.totloop; + int prev_corner = term_corner - 2; + int curr_corner = term_corner - 1; /* loop directions */ float v_dir_prev[3], v_dir_next[3]; /* needed entering the loop */ - sub_v3_v3v3(v_dir_prev, vertexCos[l_prev->v], vertexCos[l_curr->v]); + sub_v3_v3v3( + v_dir_prev, vertexCos[corner_verts[prev_corner]], vertexCos[corner_verts[curr_corner]]); normalize_v3(v_dir_prev); - for (; l_next != l_term; l_prev = l_curr, l_curr = l_next, l_next++) { - uint l_index = uint(l_curr - loops.data()); - float(*ts)[3] = r_tangent_spaces[l_index]; + for (; next_corner != term_corner; + prev_corner = curr_corner, curr_corner = next_corner, next_corner++) { + float(*ts)[3] = r_tangent_spaces[curr_corner]; /* re-use the previous value */ #if 0 - sub_v3_v3v3(v_dir_prev, vertexCos[l_prev->v], vertexCos[l_curr->v]); + sub_v3_v3v3(v_dir_prev, vertexCos[corner_verts[prev_corner]], vertexCos[corner_verts[curr_corner]]); normalize_v3(v_dir_prev); #endif - sub_v3_v3v3(v_dir_next, vertexCos[l_curr->v], vertexCos[l_next->v]); + sub_v3_v3v3( + v_dir_next, vertexCos[corner_verts[curr_corner]], vertexCos[corner_verts[next_corner]]); normalize_v3(v_dir_next); if (calc_tangent_loop(v_dir_prev, v_dir_next, ts)) { if (r_tangent_weights != nullptr) { const float weight = fabsf(acosf(dot_v3v3(v_dir_next, v_dir_prev))); - r_tangent_weights[l_index] = weight; - r_tangent_weights_per_vertex[l_curr->v] += weight; + r_tangent_weights[curr_corner] = weight; + r_tangent_weights_per_vertex[corner_verts[curr_corner]] += weight; } } else { if (r_tangent_weights != nullptr) { - r_tangent_weights[l_index] = 0; + r_tangent_weights[curr_corner] = 0; } } @@ -513,34 +515,34 @@ static void calc_deltas(CorrectiveSmoothModifierData *csmd, const float (*rest_coords)[3], uint verts_num) { - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); float(*smooth_vertex_coords)[3] = static_cast(MEM_dupallocN(rest_coords)); uint l_index; float(*tangent_spaces)[3][3] = static_cast( - MEM_malloc_arrayN(size_t(loops.size()), sizeof(float[3][3]), __func__)); + MEM_malloc_arrayN(size_t(corner_verts.size()), sizeof(float[3][3]), __func__)); - if (csmd->delta_cache.deltas_num != uint(loops.size())) { + if (csmd->delta_cache.deltas_num != uint(corner_verts.size())) { MEM_SAFE_FREE(csmd->delta_cache.deltas); } /* allocate deltas if they have not yet been allocated, otherwise we will just write over them */ if (!csmd->delta_cache.deltas) { - csmd->delta_cache.deltas_num = uint(loops.size()); + csmd->delta_cache.deltas_num = uint(corner_verts.size()); csmd->delta_cache.deltas = static_cast( - MEM_malloc_arrayN(size_t(loops.size()), sizeof(float[3]), __func__)); + MEM_malloc_arrayN(size_t(corner_verts.size()), sizeof(float[3]), __func__)); } smooth_verts(csmd, mesh, dvert, defgrp_index, smooth_vertex_coords, verts_num); calc_tangent_spaces(mesh, smooth_vertex_coords, tangent_spaces, nullptr, nullptr); - copy_vn_fl(&csmd->delta_cache.deltas[0][0], int(loops.size()) * 3, 0.0f); + copy_vn_fl(&csmd->delta_cache.deltas[0][0], int(corner_verts.size()) * 3, 0.0f); - for (l_index = 0; l_index < loops.size(); l_index++) { - const int v_index = int(loops[l_index].v); + for (l_index = 0; l_index < corner_verts.size(); l_index++) { + const int v_index = corner_verts[l_index]; float delta[3]; sub_v3_v3v3(delta, rest_coords[v_index], smooth_vertex_coords[v_index]); @@ -571,7 +573,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO) && (((ID *)ob->data)->recalc & ID_RECALC_ALL)); - const blender::Span loops = mesh->loops(); + blender::Span corner_verts = mesh->corner_verts(); bool use_only_smooth = (csmd->flag & MOD_CORRECTIVESMOOTH_ONLY_SMOOTH) != 0; const MDeformVert *dvert = nullptr; @@ -636,7 +638,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, } /* check to see if our deltas are still valid */ - if (!csmd->delta_cache.deltas || (csmd->delta_cache.deltas_num != loops.size()) || + if (!csmd->delta_cache.deltas || (csmd->delta_cache.deltas_num != corner_verts.size()) || force_delta_cache_update) { const float(*rest_coords)[3]; bool is_rest_coords_alloc = false; @@ -689,17 +691,17 @@ static void correctivesmooth_modifier_do(ModifierData *md, const float scale = csmd->scale; float(*tangent_spaces)[3][3] = static_cast( - MEM_malloc_arrayN(size_t(loops.size()), sizeof(float[3][3]), __func__)); + MEM_malloc_arrayN(size_t(corner_verts.size()), sizeof(float[3][3]), __func__)); float *tangent_weights = static_cast( - MEM_malloc_arrayN(size_t(loops.size()), sizeof(float), __func__)); + MEM_malloc_arrayN(size_t(corner_verts.size()), sizeof(float), __func__)); float *tangent_weights_per_vertex = static_cast( MEM_malloc_arrayN(verts_num, sizeof(float), __func__)); calc_tangent_spaces( mesh, vertexCos, tangent_spaces, tangent_weights, tangent_weights_per_vertex); - for (const int64_t l_index : loops.index_range()) { - const uint v_index = loops[l_index].v; + for (const int64_t l_index : corner_verts.index_range()) { + const int v_index = corner_verts[l_index]; const float weight = tangent_weights[l_index] / tangent_weights_per_vertex[v_index]; if (UNLIKELY(!(weight > 0.0f))) { /* Catches zero & divide by zero. */ diff --git a/source/blender/modifiers/intern/MOD_displace.cc b/source/blender/modifiers/intern/MOD_displace.cc index 1d6db98d8fd..52fe7db92d6 100644 --- a/source/blender/modifiers/intern/MOD_displace.cc +++ b/source/blender/modifiers/intern/MOD_displace.cc @@ -311,8 +311,11 @@ static void displaceModifier_do(DisplaceModifierData *dmd, CustomData_get_layer_for_write(ldata, CD_NORMAL, mesh->totloop)); vert_clnors = static_cast( MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__)); - BKE_mesh_normals_loop_to_vertex( - verts_num, mesh->loops().data(), mesh->totloop, (const float(*)[3])clnors, vert_clnors); + BKE_mesh_normals_loop_to_vertex(verts_num, + mesh->corner_verts().data(), + mesh->totloop, + (const float(*)[3])clnors, + vert_clnors); } else { direction = MOD_DISP_DIR_NOR; diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.cc b/source/blender/modifiers/intern/MOD_laplaciandeform.cc index bc329d3e5bc..7b5391b8bf9 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.cc +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.cc @@ -140,7 +140,7 @@ static void deleteLaplacianSystem(LaplacianSystem *sys) static void createFaceRingMap(const int mvert_tot, blender::Span looptris, - blender::Span loops, + blender::Span corner_verts, MeshElemMap **r_map, int **r_indices) { @@ -151,7 +151,7 @@ static void createFaceRingMap(const int mvert_tot, for (const int i : looptris.index_range()) { const MLoopTri &mlt = looptris[i]; for (int j = 0; j < 3; j++) { - const uint v_index = loops[mlt.tri[j]].v; + const int v_index = corner_verts[mlt.tri[j]]; map[v_index].count++; indices_num++; } @@ -166,7 +166,7 @@ static void createFaceRingMap(const int mvert_tot, for (const int i : looptris.index_range()) { const MLoopTri &mlt = looptris[i]; for (int j = 0; j < 3; j++) { - const uint v_index = loops[mlt.tri[j]].v; + const int v_index = corner_verts[mlt.tri[j]]; map[v_index].indices[map[v_index].count] = i; map[v_index].count++; } @@ -548,7 +548,7 @@ static void initSystem( } const blender::Span edges = mesh->edges(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); const blender::Span looptris = mesh->looptris(); anchors_num = STACK_SIZE(index_anchors); @@ -562,13 +562,13 @@ static void initSystem( memcpy(lmd->vertexco, vertexCos, sizeof(float[3]) * verts_num); lmd->verts_num = verts_num; - createFaceRingMap(mesh->totvert, looptris, loops, &sys->ringf_map, &sys->ringf_indices); + createFaceRingMap(mesh->totvert, looptris, corner_verts, &sys->ringf_map, &sys->ringf_indices); createVertRingMap(mesh->totvert, edges, &sys->ringv_map, &sys->ringv_indices); for (i = 0; i < sys->tris_num; i++) { - sys->tris[i][0] = loops[looptris[i].tri[0]].v; - sys->tris[i][1] = loops[looptris[i].tri[1]].v; - sys->tris[i][2] = loops[looptris[i].tri[2]].v; + sys->tris[i][0] = corner_verts[looptris[i].tri[0]]; + sys->tris[i][1] = corner_verts[looptris[i].tri[1]]; + sys->tris[i][2] = corner_verts[looptris[i].tri[2]]; } } } diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.cc b/source/blender/modifiers/intern/MOD_laplaciansmooth.cc index 7422f8d09bd..5673cfce1f3 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.cc +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.cc @@ -52,9 +52,9 @@ struct LaplacianSystem { /* Pointers to data. */ float (*vertexCos)[3]; - blender::Span polys; - blender::Span loops; blender::Span edges; + blender::Span polys; + blender::Span corner_verts; LinearSolver *context; /* Data. */ @@ -83,7 +83,7 @@ static void delete_laplacian_system(LaplacianSystem *sys) static void memset_laplacian_system(LaplacianSystem *sys, int val) { memset(sys->eweights, val, sizeof(float) * sys->edges.size()); - memset(sys->fweights, val, sizeof(float[3]) * sys->loops.size()); + memset(sys->fweights, val, sizeof(float[3]) * sys->corner_verts.size()); memset(sys->ne_ed_num, val, sizeof(short) * sys->verts_num); memset(sys->ne_fa_num, val, sizeof(short) * sys->verts_num); memset(sys->ring_areas, val, sizeof(float) * sys->verts_num); @@ -113,20 +113,22 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numLoops, in static float compute_volume(const float center[3], float (*vertexCos)[3], const blender::Span polys, - const blender::Span loops) + const blender::Span corner_verts) { float vol = 0.0f; for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; - const MLoop *l_first = &loops[poly.loopstart]; - const MLoop *l_prev = l_first + 1; - const MLoop *l_curr = l_first + 2; - const MLoop *l_term = l_first + poly.totloop; + int corner_first = poly.loopstart; + int corner_prev = corner_first + 1; + int corner_curr = corner_first + 2; + int corner_term = corner_first + poly.totloop; - for (; l_curr != l_term; l_prev = l_curr, l_curr++) { - vol += volume_tetrahedron_signed_v3( - center, vertexCos[l_first->v], vertexCos[l_prev->v], vertexCos[l_curr->v]); + for (; corner_curr != corner_term; corner_prev = corner_curr, corner_curr++) { + vol += volume_tetrahedron_signed_v3(center, + vertexCos[corner_verts[corner_first]], + vertexCos[corner_verts[corner_prev]], + vertexCos[corner_verts[corner_curr]]); } } @@ -186,42 +188,44 @@ static void init_laplacian_matrix(LaplacianSystem *sys) sys->eweights[i] = w1; } + const blender::Span corner_verts = sys->corner_verts; + for (const int i : sys->polys.index_range()) { const MPoly &poly = sys->polys[i]; - const MLoop *l_next = &sys->loops[poly.loopstart]; - const MLoop *l_term = l_next + poly.totloop; - const MLoop *l_prev = l_term - 2; - const MLoop *l_curr = l_term - 1; + int corner_next = poly.loopstart; + int corner_term = corner_next + poly.totloop; + int corner_prev = corner_term - 2; + int corner_curr = corner_term - 1; - for (; l_next != l_term; l_prev = l_curr, l_curr = l_next, l_next++) { - const float *v_prev = sys->vertexCos[l_prev->v]; - const float *v_curr = sys->vertexCos[l_curr->v]; - const float *v_next = sys->vertexCos[l_next->v]; - const uint l_curr_index = l_curr - sys->loops.data(); + for (; corner_next != corner_term; + corner_prev = corner_curr, corner_curr = corner_next, corner_next++) { + const float *v_prev = sys->vertexCos[corner_verts[corner_prev]]; + const float *v_curr = sys->vertexCos[corner_verts[corner_curr]]; + const float *v_next = sys->vertexCos[corner_verts[corner_next]]; - sys->ne_fa_num[l_curr->v] += 1; + sys->ne_fa_num[corner_verts[corner_curr]] += 1; areaf = area_tri_v3(v_prev, v_curr, v_next); if (areaf < sys->min_area) { - sys->zerola[l_curr->v] = true; + sys->zerola[corner_verts[corner_curr]] = true; } - sys->ring_areas[l_prev->v] += areaf; - sys->ring_areas[l_curr->v] += areaf; - sys->ring_areas[l_next->v] += areaf; + sys->ring_areas[corner_verts[corner_prev]] += areaf; + sys->ring_areas[corner_verts[corner_curr]] += areaf; + sys->ring_areas[corner_verts[corner_next]] += areaf; w1 = cotangent_tri_weight_v3(v_curr, v_next, v_prev) / 2.0f; w2 = cotangent_tri_weight_v3(v_next, v_prev, v_curr) / 2.0f; w3 = cotangent_tri_weight_v3(v_prev, v_curr, v_next) / 2.0f; - sys->fweights[l_curr_index][0] += w1; - sys->fweights[l_curr_index][1] += w2; - sys->fweights[l_curr_index][2] += w3; + sys->fweights[corner_curr][0] += w1; + sys->fweights[corner_curr][1] += w2; + sys->fweights[corner_curr][2] += w3; - sys->vweights[l_curr->v] += w2 + w3; - sys->vweights[l_next->v] += w1 + w3; - sys->vweights[l_prev->v] += w1 + w2; + sys->vweights[corner_verts[corner_curr]] += w2 + w3; + sys->vweights[corner_verts[corner_next]] += w1 + w3; + sys->vweights[corner_verts[corner_prev]] += w1 + w2; } } for (i = 0; i < sys->edges.size(); i++) { @@ -241,49 +245,57 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) int i; uint idv1, idv2; + const blender::Span corner_verts = sys->corner_verts; + for (const int i : sys->polys.index_range()) { const MPoly &poly = sys->polys[i]; - const MLoop *l_next = &sys->loops[poly.loopstart]; - const MLoop *l_term = l_next + poly.totloop; - const MLoop *l_prev = l_term - 2; - const MLoop *l_curr = l_term - 1; + int corner_next = poly.loopstart; + int corner_term = corner_next + poly.totloop; + int corner_prev = corner_term - 2; + int corner_curr = corner_term - 1; - for (; l_next != l_term; l_prev = l_curr, l_curr = l_next, l_next++) { - const uint l_curr_index = l_curr - sys->loops.data(); + for (; corner_next != corner_term; + corner_prev = corner_curr, corner_curr = corner_next, corner_next++) { /* Is ring if number of faces == number of edges around vertex. */ - if (sys->ne_ed_num[l_curr->v] == sys->ne_fa_num[l_curr->v] && - sys->zerola[l_curr->v] == false) { + if (sys->ne_ed_num[corner_verts[corner_curr]] == sys->ne_fa_num[corner_verts[corner_curr]] && + sys->zerola[corner_verts[corner_curr]] == false) { EIG_linear_solver_matrix_add(sys->context, - l_curr->v, - l_next->v, - sys->fweights[l_curr_index][2] * sys->vweights[l_curr->v]); + corner_verts[corner_curr], + corner_verts[corner_next], + sys->fweights[corner_curr][2] * + sys->vweights[corner_verts[corner_curr]]); EIG_linear_solver_matrix_add(sys->context, - l_curr->v, - l_prev->v, - sys->fweights[l_curr_index][1] * sys->vweights[l_curr->v]); + corner_verts[corner_curr], + corner_verts[corner_prev], + sys->fweights[corner_curr][1] * + sys->vweights[corner_verts[corner_curr]]); } - if (sys->ne_ed_num[l_next->v] == sys->ne_fa_num[l_next->v] && - sys->zerola[l_next->v] == false) { + if (sys->ne_ed_num[corner_verts[corner_next]] == sys->ne_fa_num[corner_verts[corner_next]] && + sys->zerola[corner_verts[corner_next]] == false) { EIG_linear_solver_matrix_add(sys->context, - l_next->v, - l_curr->v, - sys->fweights[l_curr_index][2] * sys->vweights[l_next->v]); + corner_verts[corner_next], + corner_verts[corner_curr], + sys->fweights[corner_curr][2] * + sys->vweights[corner_verts[corner_next]]); EIG_linear_solver_matrix_add(sys->context, - l_next->v, - l_prev->v, - sys->fweights[l_curr_index][0] * sys->vweights[l_next->v]); + corner_verts[corner_next], + corner_verts[corner_prev], + sys->fweights[corner_curr][0] * + sys->vweights[corner_verts[corner_next]]); } - if (sys->ne_ed_num[l_prev->v] == sys->ne_fa_num[l_prev->v] && - sys->zerola[l_prev->v] == false) { + if (sys->ne_ed_num[corner_verts[corner_prev]] == sys->ne_fa_num[corner_verts[corner_prev]] && + sys->zerola[corner_verts[corner_prev]] == false) { EIG_linear_solver_matrix_add(sys->context, - l_prev->v, - l_curr->v, - sys->fweights[l_curr_index][1] * sys->vweights[l_prev->v]); + corner_verts[corner_prev], + corner_verts[corner_curr], + sys->fweights[corner_curr][1] * + sys->vweights[corner_verts[corner_prev]]); EIG_linear_solver_matrix_add(sys->context, - l_prev->v, - l_next->v, - sys->fweights[l_curr_index][0] * sys->vweights[l_prev->v]); + corner_verts[corner_prev], + corner_verts[corner_next], + sys->fweights[corner_curr][0] * + sys->vweights[corner_verts[corner_prev]]); } } } @@ -310,7 +322,7 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl float vini = 0.0f, vend = 0.0f; if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { - vini = compute_volume(sys->vert_centroid, sys->vertexCos, sys->polys, sys->loops); + vini = compute_volume(sys->vert_centroid, sys->vertexCos, sys->polys, sys->corner_verts); } for (i = 0; i < sys->verts_num; i++) { if (sys->zerola[i] == false) { @@ -331,7 +343,7 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl } } if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { - vend = compute_volume(sys->vert_centroid, sys->vertexCos, sys->polys, sys->loops); + vend = compute_volume(sys->vert_centroid, sys->vertexCos, sys->polys, sys->corner_verts); volume_preservation(sys, vini, vend, flag); } } @@ -352,9 +364,9 @@ static void laplaciansmoothModifier_do( return; } - sys->polys = mesh->polys(); - sys->loops = mesh->loops(); sys->edges = mesh->edges(); + sys->polys = mesh->polys(); + sys->corner_verts = mesh->corner_verts(); sys->vertexCos = vertexCos; sys->min_area = 0.00001f; MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index); diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index eddd3b09633..2a00e3bd147 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -225,7 +225,7 @@ static void computed_masked_polys(const Mesh *mesh, { BLI_assert(mesh->totvert == vertex_mask.size()); const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); r_masked_poly_indices.reserve(mesh->totpoly); r_loop_starts.reserve(mesh->totpoly); @@ -235,9 +235,8 @@ static void computed_masked_polys(const Mesh *mesh, const MPoly &poly_src = polys[i]; bool all_verts_in_mask = true; - Span loops_src = loops.slice(poly_src.loopstart, poly_src.totloop); - for (const MLoop &loop : loops_src) { - if (!vertex_mask[loop.v]) { + for (const int vert_i : corner_verts.slice(poly_src.loopstart, poly_src.totloop)) { + if (!vertex_mask[vert_i]) { all_verts_in_mask = false; break; } @@ -271,7 +270,7 @@ static void compute_interpolated_polys(const Mesh *mesh, r_masked_poly_indices.reserve(r_masked_poly_indices.size() + verts_add_num); r_loop_starts.reserve(r_loop_starts.size() + verts_add_num); const Span polys = mesh->polys(); - const Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); uint edges_add_num = 0; uint polys_add_num = 0; @@ -282,10 +281,10 @@ static void compute_interpolated_polys(const Mesh *mesh, int in_count = 0; int start = -1; int dst_totloop = -1; - const Span loops_src = loops.slice(poly_src.loopstart, poly_src.totloop); - for (const int j : loops_src.index_range()) { - const MLoop &loop = loops_src[j]; - if (vertex_mask[loop.v]) { + const Span poly_verts_src = corner_verts.slice(poly_src.loopstart, poly_src.totloop); + for (const int j : poly_verts_src.index_range()) { + const int vert_i = poly_verts_src[j]; + if (vertex_mask[vert_i]) { in_count++; } else if (start == -1) { @@ -294,11 +293,11 @@ static void compute_interpolated_polys(const Mesh *mesh, } if (0 < in_count && in_count < poly_src.totloop) { /* Ring search starting at a vertex which is not included in the mask. */ - const MLoop *last_loop = &loops_src[start]; - bool v_loop_in_mask_last = vertex_mask[last_loop->v]; - for (const int j : loops_src.index_range()) { - const MLoop &loop = loops_src[(start + 1 + j) % poly_src.totloop]; - const bool v_loop_in_mask = vertex_mask[loop.v]; + int last_corner_vert = corner_verts[start]; + bool v_loop_in_mask_last = vertex_mask[last_corner_vert]; + for (const int j : poly_verts_src.index_range()) { + const int corner_vert = corner_verts[(start + 1 + j) % poly_src.totloop]; + const bool v_loop_in_mask = vertex_mask[corner_vert]; if (v_loop_in_mask && !v_loop_in_mask_last) { dst_totloop = 3; } @@ -315,7 +314,7 @@ static void compute_interpolated_polys(const Mesh *mesh, BLI_assert(dst_totloop > 2); dst_totloop++; } - last_loop = &loop; + last_corner_vert = corner_vert; v_loop_in_mask_last = v_loop_in_mask; } } @@ -446,9 +445,11 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, int polys_masked_num) { const Span src_polys = src_mesh.polys(); - const Span src_loops = src_mesh.loops(); MutableSpan dst_polys = dst_mesh.polys_for_write(); - MutableSpan dst_loops = dst_mesh.loops_for_write(); + const Span src_corner_verts = src_mesh.corner_verts(); + const Span src_corner_edges = src_mesh.corner_edges(); + MutableSpan dst_corner_verts = dst_mesh.corner_verts_for_write(); + MutableSpan dst_corner_edges = dst_mesh.corner_edges_for_write(); for (const int i_dst : IndexRange(polys_masked_num)) { const int i_src = masked_poly_indices[i_dst]; @@ -461,14 +462,11 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, CustomData_copy_data(&src_mesh.pdata, &dst_mesh.pdata, i_src, i_dst, 1); CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src, i_ml_dst, mp_src.totloop); - const MLoop *ml_src = src_loops.data() + i_ml_src; - MLoop *ml_dst = dst_loops.data() + i_ml_dst; - mp_dst = mp_src; mp_dst.loopstart = i_ml_dst; for (int i : IndexRange(mp_src.totloop)) { - ml_dst[i].v = vertex_map[ml_src[i].v]; - ml_dst[i].e = edge_map[ml_src[i].e]; + dst_corner_verts[i_ml_dst + i] = vertex_map[src_corner_verts[i_ml_src + i]]; + dst_corner_edges[i_ml_dst + i] = edge_map[src_corner_edges[i_ml_src + i]]; } } } @@ -487,10 +485,12 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, int edges_add_num) { const Span src_polys = src_mesh.polys(); - const Span src_loops = src_mesh.loops(); - MutableSpan dst_edges = dst_mesh.edges_for_write(); MutableSpan dst_polys = dst_mesh.polys_for_write(); - MutableSpan dst_loops = dst_mesh.loops_for_write(); + MutableSpan dst_edges = dst_mesh.edges_for_write(); + const Span src_corner_verts = src_mesh.corner_verts(); + const Span src_corner_edges = src_mesh.corner_edges(); + MutableSpan dst_corner_verts = dst_mesh.corner_verts_for_write(); + MutableSpan dst_corner_edges = dst_mesh.corner_edges_for_write(); int edge_index = dst_mesh.totedge - edges_add_num; int sub_poly_index = 0; @@ -523,9 +523,9 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, /* Ring search starting at a vertex which is not included in the mask. */ int start = -sub_poly_index - 1; bool skip = false; - Span loops_src(&src_loops[i_ml_src], mp_src.totloop); - for (const int j : loops_src.index_range()) { - if (!vertex_mask[loops_src[j].v]) { + Span corner_verts_src(&src_corner_verts[i_ml_src], mp_src.totloop); + for (const int j : corner_verts_src.index_range()) { + if (!vertex_mask[corner_verts_src[j]]) { if (start == -1) { start = j; break; @@ -543,50 +543,52 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, BLI_assert(start >= 0); BLI_assert(edge_index < dst_mesh.totedge); - const MLoop *last_loop = &loops_src[start]; - bool v_loop_in_mask_last = vertex_mask[last_loop->v]; + int last_corner_i = start; + bool v_loop_in_mask_last = vertex_mask[src_corner_verts[last_corner_i]]; int last_index = start; - for (const int j : loops_src.index_range()) { + for (const int j : corner_verts_src.index_range()) { const int index = (start + 1 + j) % mp_src.totloop; - const MLoop &loop = loops_src[index]; - const bool v_loop_in_mask = vertex_mask[loop.v]; + const bool v_loop_in_mask = vertex_mask[src_corner_verts[index]]; if (v_loop_in_mask && !v_loop_in_mask_last) { /* Start new cut. */ - float fac = get_interp_factor_from_vgroup( - dvert, defgrp_index, threshold, last_loop->v, loop.v); + float fac = get_interp_factor_from_vgroup(dvert, + defgrp_index, + threshold, + src_corner_verts[last_corner_i], + src_corner_verts[index]); float weights[2] = {1.0f - fac, fac}; int indices[2] = {i_ml_src + last_index, i_ml_src + index}; CustomData_interp( &src_mesh.ldata, &dst_mesh.ldata, indices, weights, nullptr, 2, i_ml_dst); - MLoop &cut_dst_loop = dst_loops[i_ml_dst]; - cut_dst_loop.e = edge_map[last_loop->e]; - cut_dst_loop.v = dst_edges[cut_dst_loop.e].v1; + dst_corner_edges[i_ml_dst] = edge_map[src_corner_edges[last_corner_i]]; + dst_corner_verts[i_ml_dst] = dst_edges[dst_corner_edges[i_ml_dst]].v1; i_ml_dst++; CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src + index, i_ml_dst, 1); - MLoop &next_dst_loop = dst_loops[i_ml_dst]; - next_dst_loop.v = vertex_map[loop.v]; - next_dst_loop.e = edge_map[loop.e]; + dst_corner_verts[i_ml_dst] = vertex_map[src_corner_verts[index]]; + dst_corner_edges[i_ml_dst] = edge_map[src_corner_edges[index]]; i_ml_dst++; } else if (!v_loop_in_mask && v_loop_in_mask_last) { BLI_assert(i_ml_dst != mp_dst.loopstart); /* End active cut. */ - float fac = get_interp_factor_from_vgroup( - dvert, defgrp_index, threshold, last_loop->v, loop.v); + float fac = get_interp_factor_from_vgroup(dvert, + defgrp_index, + threshold, + src_corner_verts[last_corner_i], + src_corner_verts[index]); float weights[2] = {1.0f - fac, fac}; int indices[2] = {i_ml_src + last_index, i_ml_src + index}; CustomData_interp( &src_mesh.ldata, &dst_mesh.ldata, indices, weights, nullptr, 2, i_ml_dst); - MLoop &cut_dst_loop = dst_loops[i_ml_dst]; - cut_dst_loop.e = edge_index; - cut_dst_loop.v = dst_edges[edge_map[last_loop->e]].v1; + dst_corner_edges[i_ml_dst] = edge_index; + dst_corner_verts[i_ml_dst] = dst_edges[edge_map[src_corner_edges[last_corner_i]]].v1; i_ml_dst++; /* Create closing edge. */ MEdge &cut_edge = dst_edges[edge_index]; - cut_edge.v1 = dst_loops[mp_dst.loopstart].v; - cut_edge.v2 = cut_dst_loop.v; + cut_edge.v1 = dst_corner_verts[mp_dst.loopstart]; + cut_edge.v2 = dst_corner_verts[i_ml_dst]; BLI_assert(cut_edge.v1 != cut_edge.v2); edge_index++; @@ -597,12 +599,11 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, BLI_assert(i_ml_dst != mp_dst.loopstart); /* Extend active poly. */ CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src + index, i_ml_dst, 1); - MLoop &dst_loop = dst_loops[i_ml_dst]; - dst_loop.v = vertex_map[loop.v]; - dst_loop.e = edge_map[loop.e]; + dst_corner_verts[i_ml_dst] = vertex_map[src_corner_verts[index]]; + dst_corner_edges[i_ml_dst] = edge_map[src_corner_edges[index]]; i_ml_dst++; } - last_loop = &loop; + last_corner_i = index; last_index = index; v_loop_in_mask_last = v_loop_in_mask; } diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc index 10af7065b39..cb13f032969 100644 --- a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc +++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc @@ -173,15 +173,15 @@ static Volume *mesh_to_volume(ModifierData *md, } /* Convert mesh to grid and add to volume. */ - geometry::volume_grid_add_from_mesh(volume, - "density", - mesh, - mesh_to_own_object_space_transform, - voxel_size, - mvmd->fill_volume, - mvmd->exterior_band_width, - mvmd->interior_band_width, - mvmd->density); + geometry::fog_volume_grid_add_from_mesh(volume, + "density", + mesh, + mesh_to_own_object_space_transform, + voxel_size, + mvmd->fill_volume, + mvmd->exterior_band_width, + mvmd->interior_band_width, + mvmd->density); return volume; diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index da1e2c9e703..0fd1e7bebda 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -181,7 +181,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, BKE_mesh_calc_relative_deform( BKE_mesh_polys(me), me->totpoly, - BKE_mesh_loops(me), + BKE_mesh_corner_verts(me), me->totvert, BKE_mesh_vert_positions(me), /* From the original Mesh. */ (const float(*)[3])vertexCos_Real, /* the input we've been given (shape keys!) */ diff --git a/source/blender/modifiers/intern/MOD_multires.cc b/source/blender/modifiers/intern/MOD_multires.cc index 528c5aee889..d2d0e614562 100644 --- a/source/blender/modifiers/intern/MOD_multires.cc +++ b/source/blender/modifiers/intern/MOD_multires.cc @@ -246,7 +246,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * sculpt_session->totpoly = mesh->totpoly; sculpt_session->vert_positions = nullptr; sculpt_session->polys = nullptr; - sculpt_session->mloop = nullptr; + sculpt_session->corner_verts = nullptr; } // BKE_subdiv_stats_print(&subdiv->stats); } diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc index 9cf960af128..267ad8b0b2b 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.cc +++ b/source/blender/modifiers/intern/MOD_normal_edit.cc @@ -125,7 +125,7 @@ static void mix_normals(const float mix_factor, const float mix_limit, const short mix_mode, const int verts_num, - const blender::Span loops, + const blender::Span corner_verts, blender::float3 *nos_old, blender::float3 *nos_new) { @@ -135,12 +135,18 @@ static void mix_normals(const float mix_factor, int i; if (dvert) { - facs = static_cast(MEM_malloc_arrayN(size_t(loops.size()), sizeof(*facs), __func__)); - BKE_defvert_extract_vgroup_to_loopweights( - dvert, defgrp_index, verts_num, loops.data(), loops.size(), use_invert_vgroup, facs); + facs = static_cast( + MEM_malloc_arrayN(size_t(corner_verts.size()), sizeof(*facs), __func__)); + BKE_defvert_extract_vgroup_to_loopweights(dvert, + defgrp_index, + verts_num, + corner_verts.data(), + corner_verts.size(), + use_invert_vgroup, + facs); } - for (i = loops.size(), no_new = nos_new, no_old = nos_old, wfac = facs; i--; + for (i = corner_verts.size(), no_new = nos_new, no_old = nos_old, wfac = facs; i--; no_new++, no_old++, wfac++) { const float fac = facs ? *wfac * mix_factor : mix_factor; @@ -173,14 +179,15 @@ static void mix_normals(const float mix_factor, /* Check poly normals and new loop normals are compatible, otherwise flip polygons * (and invert matching poly normals). */ -static bool polygons_check_flip(blender::MutableSpan loops, +static bool polygons_check_flip(blender::MutableSpan corner_verts, + blender::MutableSpan corner_edges, blender::float3 *nos, CustomData *ldata, const blender::Span polys, float (*poly_normals)[3]) { MDisps *mdisp = static_cast( - CustomData_get_layer_for_write(ldata, CD_MDISPS, loops.size())); + CustomData_get_layer_for_write(ldata, CD_MDISPS, corner_verts.size())); bool flipped = false; for (const int i : polys.index_range()) { @@ -197,8 +204,13 @@ static bool polygons_check_flip(blender::MutableSpan loops, /* If average of new loop normals is opposed to polygon normal, flip polygon. */ if (dot_v3v3(poly_normals[i], norsum) < 0.0f) { - BKE_mesh_polygon_flip_ex( - &poly, loops.data(), ldata, reinterpret_cast(nos), mdisp, true); + BKE_mesh_polygon_flip_ex(&poly, + corner_verts.data(), + corner_edges.data(), + ldata, + reinterpret_cast(nos), + mdisp, + true); negate_v3(poly_normals[i]); flipped = true; } @@ -222,7 +234,8 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, blender::Span vert_positions, const blender::Span edges, blender::MutableSpan sharp_edges, - blender::MutableSpan loops, + blender::MutableSpan corner_verts, + blender::MutableSpan corner_edges, const blender::Span polys) { Object *ob_target = enmd->target; @@ -231,7 +244,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, float(*cos)[3] = static_cast( MEM_malloc_arrayN(size_t(vert_positions.size()), sizeof(*cos), __func__)); - blender::Array nos(loops.size()); + blender::Array nos(corner_verts.size()); float size[3]; BLI_bitmap *done_verts = BLI_BITMAP_NEW(size_t(vert_positions.size()), __func__); @@ -275,8 +288,8 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, const float n2 = (c * c) / (a * a); /* We reuse cos to now store the ellipsoid-normal of the verts! */ - for (const int64_t i : loops.index_range()) { - const int vidx = loops[i].v; + for (const int64_t i : corner_verts.index_range()) { + const int vidx = corner_verts[i]; float *co = cos[vidx]; if (!BLI_BITMAP_TEST(done_verts, vidx)) { @@ -306,14 +319,17 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, mix_limit, mix_mode, vert_positions.size(), - loops, + corner_verts, loop_normals.data(), nos.data()); } - if (do_polynors_fix && - polygons_check_flip( - loops, nos.data(), &mesh->ldata, polys, BKE_mesh_poly_normals_for_write(mesh))) { + if (do_polynors_fix && polygons_check_flip(corner_verts, + corner_edges, + nos.data(), + &mesh->ldata, + polys, + BKE_mesh_poly_normals_for_write(mesh))) { mesh->runtime->vert_normals_dirty = true; } const bool *sharp_faces = static_cast( @@ -321,7 +337,8 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, blender::bke::mesh::normals_loop_custom_set(vert_positions, edges, polys, - loops, + corner_verts, + corner_edges, mesh->vert_normals(), mesh->poly_normals(), sharp_faces, @@ -348,7 +365,8 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, const blender::Span positions, const blender::Span edges, blender::MutableSpan sharp_edges, - blender::MutableSpan loops, + blender::MutableSpan corner_verts, + blender::MutableSpan corner_edges, const blender::Span polys) { Object *ob_target = enmd->target; @@ -356,7 +374,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0; const bool use_parallel_normals = (enmd->flag & MOD_NORMALEDIT_USE_DIRECTION_PARALLEL) != 0; - blender::Array nos(loops.size()); + blender::Array nos(corner_verts.size()); float target_co[3]; int i; @@ -374,7 +392,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, sub_v3_v3v3(no, target_co, enmd->offset); normalize_v3(no); - for (i = loops.size(); i--;) { + for (i = corner_verts.size(); i--;) { copy_v3_v3(nos[i], no); } } @@ -386,8 +404,8 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, BLI_bitmap *done_verts = BLI_BITMAP_NEW(size_t(positions.size()), __func__); /* We reuse cos to now store the 'to target' normal of the verts! */ - for (const int64_t i : loops.index_range()) { - const int vidx = loops[i].v; + for (const int64_t i : corner_verts.index_range()) { + const int vidx = corner_verts[i]; float *co = cos[vidx]; if (!BLI_BITMAP_TEST(done_verts, vidx)) { @@ -411,14 +429,17 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, mix_limit, mix_mode, positions.size(), - loops, + corner_verts, loop_normals.data(), nos.data()); } - if (do_polynors_fix && - polygons_check_flip( - loops, nos.data(), &mesh->ldata, polys, BKE_mesh_poly_normals_for_write(mesh))) { + if (do_polynors_fix && polygons_check_flip(corner_verts, + corner_edges, + nos.data(), + &mesh->ldata, + polys, + BKE_mesh_poly_normals_for_write(mesh))) { mesh->runtime->vert_normals_dirty = true; } const bool *sharp_faces = static_cast( @@ -426,7 +447,8 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, blender::bke::mesh::normals_loop_custom_set(positions, edges, polys, - loops, + corner_verts, + corner_edges, mesh->vert_normals(), mesh->poly_normals(), sharp_faces, @@ -501,7 +523,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, const blender::Span positions = result->vert_positions(); const blender::Span edges = result->edges(); const blender::Span polys = result->polys(); - blender::MutableSpan loops = result->loops_for_write(); + blender::MutableSpan corner_verts = result->corner_verts_for_write(); + blender::MutableSpan corner_edges = result->corner_edges_for_write(); int defgrp_index; const MDeformVert *dvert; @@ -515,17 +538,18 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, "sharp_edge", ATTR_DOMAIN_EDGE); short(*clnors)[2] = static_cast( - CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, loops.size())); + CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); if (use_current_clnors) { clnors = static_cast( - CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, loops.size())); - loop_normals.reinitialize(loops.size()); + CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); + loop_normals.reinitialize(corner_verts.size()); const bool *sharp_faces = static_cast( CustomData_get_layer_named(&result->pdata, CD_PROP_BOOL, "sharp_face")); blender::bke::mesh::normals_calc_loop(positions, edges, polys, - loops, + corner_verts, + corner_edges, {}, result->vert_normals(), result->poly_normals(), @@ -540,7 +564,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, if (clnors == nullptr) { clnors = static_cast( - CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, loops.size())); + CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, corner_verts.size())); } MOD_get_vgroup(ob, result, enmd->defgrp_name, &dvert, &defgrp_index); @@ -561,7 +585,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, positions, edges, sharp_edges.span, - loops, + corner_verts, + corner_edges, polys); } else if (enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) { @@ -580,7 +605,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, positions, edges, sharp_edges.span, - loops, + corner_verts, + corner_edges, polys); } diff --git a/source/blender/modifiers/intern/MOD_ocean.cc b/source/blender/modifiers/intern/MOD_ocean.cc index c9fe4aa4167..fc109f69acd 100644 --- a/source/blender/modifiers/intern/MOD_ocean.cc +++ b/source/blender/modifiers/intern/MOD_ocean.cc @@ -155,7 +155,7 @@ static bool dependsOnNormals(ModifierData *md) struct GenerateOceanGeometryData { float (*vert_positions)[3]; blender::MutableSpan polys; - blender::MutableSpan loops; + blender::MutableSpan corner_verts; float (*mloopuvs)[2]; int res_x, res_y; @@ -191,16 +191,11 @@ static void generate_ocean_geometry_polys(void *__restrict userdata, for (x = 0; x < gogd->res_x; x++) { const int fi = y * gogd->res_x + x; const int vi = y * (gogd->res_x + 1) + x; - MLoop *ml = &gogd->loops[fi * 4]; - ml->v = vi; - ml++; - ml->v = vi + 1; - ml++; - ml->v = vi + 1 + gogd->res_x + 1; - ml++; - ml->v = vi + gogd->res_x + 1; - ml++; + gogd->corner_verts[fi * 4 + 0] = vi; + gogd->corner_verts[fi * 4 + 1] = vi + 1; + gogd->corner_verts[fi * 4 + 2] = vi + 1 + gogd->res_x + 1; + gogd->corner_verts[fi * 4 + 3] = vi + gogd->res_x + 1; gogd->polys[fi].loopstart = fi * 4; gogd->polys[fi].totloop = 4; @@ -268,7 +263,7 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co gogd.vert_positions = BKE_mesh_vert_positions_for_write(result); gogd.polys = result->polys_for_write(); - gogd.loops = result->loops_for_write(); + gogd.corner_verts = result->corner_verts_for_write(); TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); @@ -365,20 +360,26 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes /* Add vertex-colors before displacement: allows lookup based on position. */ if (omd->flag & MOD_OCEAN_GENERATE_FOAM) { - const blender::Span loops = result->loops(); - MLoopCol *mloopcols = static_cast(CustomData_add_layer_named( - &result->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, loops.size(), omd->foamlayername)); + const blender::Span corner_verts = result->corner_verts(); + MLoopCol *mloopcols = static_cast(CustomData_add_layer_named(&result->ldata, + CD_PROP_BYTE_COLOR, + CD_SET_DEFAULT, + corner_verts.size(), + omd->foamlayername)); MLoopCol *mloopcols_spray = nullptr; if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) { - mloopcols_spray = static_cast(CustomData_add_layer_named( - &result->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, loops.size(), omd->spraylayername)); + mloopcols_spray = static_cast(CustomData_add_layer_named(&result->ldata, + CD_PROP_BYTE_COLOR, + CD_SET_DEFAULT, + corner_verts.size(), + omd->spraylayername)); } if (mloopcols) { /* unlikely to fail */ for (const int i : polys.index_range()) { - const MLoop *ml = &loops[polys[i].loopstart]; + const int *corner_vert = &corner_verts[polys[i].loopstart]; MLoopCol *mlcol = &mloopcols[polys[i].loopstart]; MLoopCol *mlcolspray = nullptr; @@ -386,8 +387,8 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes mlcolspray = &mloopcols_spray[polys[i].loopstart]; } - for (j = polys[i].totloop; j--; ml++, mlcol++) { - const float *vco = positions[ml->v]; + for (j = polys[i].totloop; j--; corner_vert++, mlcol++) { + const float *vco = positions[*corner_vert]; const float u = OCEAN_CO(size_co_inv, vco[0]); const float v = OCEAN_CO(size_co_inv, vco[1]); float foam; @@ -697,7 +698,7 @@ ModifierTypeInfo modifierType_Ocean = { /*icon*/ ICON_MOD_OCEAN, /*copyData*/ copyData, - /*deformMatrices_DM*/ nullptr, + /*deformMatrices*/ nullptr, /*deformMatrices*/ nullptr, /*deformVertsEM*/ nullptr, diff --git a/source/blender/modifiers/intern/MOD_particleinstance.cc b/source/blender/modifiers/intern/MOD_particleinstance.cc index c1e07497598..77e756c18cb 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.cc +++ b/source/blender/modifiers/intern/MOD_particleinstance.cc @@ -315,11 +315,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = BKE_mesh_new_nomain_from_template(mesh, maxvert, maxedge, maxloop, maxpoly); const blender::Span orig_polys = mesh->polys(); - const blender::Span orig_loops = mesh->loops(); + const blender::Span orig_corner_verts = mesh->corner_verts(); + const blender::Span orig_corner_edges = mesh->corner_edges(); float(*positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan edges = result->edges_for_write(); blender::MutableSpan polys = result->polys_for_write(); - blender::MutableSpan loops = result->loops_for_write(); + blender::MutableSpan corner_verts = result->corner_verts_for_write(); + blender::MutableSpan corner_edges = result->corner_edges_for_write(); MLoopCol *mloopcols_index = static_cast(CustomData_get_layer_named_for_write( &result->ldata, CD_PROP_BYTE_COLOR, pimd->index_layer_name, result->totloop)); @@ -485,23 +487,23 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * poly.loopstart += p_skip * totloop; { - const MLoop *inML = &orig_loops[in_poly.loopstart]; - MLoop *ml = &loops[poly.loopstart]; + int orig_corner_i = in_poly.loopstart; + int dst_corner_i = poly.loopstart; int j = poly.totloop; CustomData_copy_data(&mesh->ldata, &result->ldata, in_poly.loopstart, poly.loopstart, j); - for (; j; j--, ml++, inML++) { - ml->v = inML->v + (p_skip * totvert); - ml->e = inML->e + (p_skip * totedge); - const int ml_index = (ml - loops.data()); + for (; j; j--, orig_corner_i++, dst_corner_i++) { + corner_verts[dst_corner_i] = orig_corner_verts[orig_corner_i] + (p_skip * totvert); + corner_edges[dst_corner_i] = orig_corner_edges[orig_corner_i] + (p_skip * totedge); + const int vert = corner_verts[orig_corner_i]; if (mloopcols_index != nullptr) { - const int part_index = vert_part_index[ml->v]; - store_float_in_vcol(&mloopcols_index[ml_index], + const int part_index = vert_part_index[vert]; + store_float_in_vcol(&mloopcols_index[dst_corner_i], float(part_index) / float(psys->totpart - 1)); } if (mloopcols_value != nullptr) { - const float part_value = vert_part_value[ml->v]; - store_float_in_vcol(&mloopcols_value[ml_index], part_value); + const float part_value = vert_part_value[vert]; + store_float_in_vcol(&mloopcols_value[dst_corner_i], part_value); } } } diff --git a/source/blender/modifiers/intern/MOD_remesh.cc b/source/blender/modifiers/intern/MOD_remesh.cc index 9d6ca28759f..119c14d824a 100644 --- a/source/blender/modifiers/intern/MOD_remesh.cc +++ b/source/blender/modifiers/intern/MOD_remesh.cc @@ -63,8 +63,8 @@ static void init_dualcon_mesh(DualConInput *input, Mesh *mesh) input->co_stride = sizeof(float[3]); input->totco = mesh->totvert; - input->mloop = (DualConLoop)mesh->loops().data(); - input->loop_stride = sizeof(MLoop); + input->mloop = (DualConLoop)mesh->corner_verts().data(); + input->loop_stride = sizeof(int); input->looptri = (DualConTri)mesh->looptris().data(); input->tri_stride = sizeof(MLoopTri); @@ -80,7 +80,7 @@ typedef struct { Mesh *mesh; float (*vert_positions)[3]; MPoly *polys; - MLoop *loops; + int *corner_verts; int curvert, curface; } DualConOutput; @@ -96,7 +96,7 @@ static void *dualcon_alloc_output(int totvert, int totquad) output->mesh = BKE_mesh_new_nomain(totvert, 0, 4 * totquad, totquad); output->vert_positions = BKE_mesh_vert_positions_for_write(output->mesh); output->polys = output->mesh->polys_for_write().data(); - output->loops = output->mesh->loops_for_write().data(); + output->corner_verts = output->mesh->corner_verts_for_write().data(); return output; } @@ -123,9 +123,8 @@ static void dualcon_add_quad(void *output_v, const int vert_indices[4]) output->polys[output->curface].loopstart = output->curface * 4; output->polys[output->curface].totloop = 4; - MLoop *mloop = output->loops; for (i = 0; i < 4; i++) { - mloop[output->curface * 4 + i].v = vert_indices[i]; + output->corner_verts[output->curface * 4 + i] = vert_indices[i]; } output->curface++; diff --git a/source/blender/modifiers/intern/MOD_screw.cc b/source/blender/modifiers/intern/MOD_screw.cc index a3ba9056c55..f6cf87d1720 100644 --- a/source/blender/modifiers/intern/MOD_screw.cc +++ b/source/blender/modifiers/intern/MOD_screw.cc @@ -253,7 +253,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * uint edge_offset; MPoly *mp_new; - MLoop *ml_new; MEdge *edge_new, *med_new_firstloop; Object *ob_axis = ltmd->ob_axis; @@ -401,12 +400,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * const float(*vert_positions_orig)[3] = BKE_mesh_vert_positions(mesh); const blender::Span edges_orig = mesh->edges(); const blender::Span polys_orig = mesh->polys(); - const blender::Span loops_orig = mesh->loops(); + const blender::Span corner_verts_orig = mesh->corner_verts(); + const blender::Span corner_edges_orig = mesh->corner_edges(); float(*vert_positions_new)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan edges_new = result->edges_for_write(); blender::MutableSpan polys_new = result->polys_for_write(); - blender::MutableSpan loops_new = result->loops_for_write(); + blender::MutableSpan corner_verts_new = result->corner_verts_for_write(); + blender::MutableSpan corner_edges_new = result->corner_edges_for_write(); bke::MutableAttributeAccessor attributes = result->attributes_for_write(); bke::SpanAttributeWriter sharp_faces = attributes.lookup_or_add_for_write_span( "sharp_face", ATTR_DOMAIN_FACE); @@ -471,15 +472,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * uint loopstart = uint(polys_orig[i].loopstart); uint loopend = loopstart + uint(polys_orig[i].totloop); - const MLoop *ml_orig = &loops_orig[loopstart]; - uint k; - for (k = loopstart; k < loopend; k++, ml_orig++) { - edge_poly_map[ml_orig->e] = uint(i); - vert_loop_map[ml_orig->v] = k; + for (uint k = loopstart; k < loopend; k++) { + const uint vert_i = uint(corner_verts_orig[k]); + const uint edge_i = uint(corner_edges_orig[k]); + edge_poly_map[edge_i] = uint(i); + vert_loop_map[vert_i] = k; /* also order edges based on faces */ - if (edges_new[ml_orig->e].v1 != ml_orig->v) { - std::swap(edges_new[ml_orig->e].v1, edges_new[ml_orig->e].v2); + if (edges_new[edge_i].v1 != vert_i) { + std::swap(edges_new[edge_i].v1, edges_new[edge_i].v2); } } } @@ -827,7 +828,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } mp_new = polys_new.data(); - ml_new = loops_new.data(); + int new_loop_index = 0; med_new_firstloop = edges_new.data(); /* more of an offset in this case */ @@ -889,23 +890,22 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Loop-Custom-Data */ if (has_mloop_orig) { - int l_index = int(ml_new - loops_new.data()); CustomData_copy_data( - &mesh->ldata, &result->ldata, int(mloop_index_orig[0]), l_index + 0, 1); + &mesh->ldata, &result->ldata, int(mloop_index_orig[0]), new_loop_index + 0, 1); CustomData_copy_data( - &mesh->ldata, &result->ldata, int(mloop_index_orig[1]), l_index + 1, 1); + &mesh->ldata, &result->ldata, int(mloop_index_orig[1]), new_loop_index + 1, 1); CustomData_copy_data( - &mesh->ldata, &result->ldata, int(mloop_index_orig[1]), l_index + 2, 1); + &mesh->ldata, &result->ldata, int(mloop_index_orig[1]), new_loop_index + 2, 1); CustomData_copy_data( - &mesh->ldata, &result->ldata, int(mloop_index_orig[0]), l_index + 3, 1); + &mesh->ldata, &result->ldata, int(mloop_index_orig[0]), new_loop_index + 3, 1); if (mloopuv_layers_tot) { uint uv_lay; const float uv_u_offset_a = float(step) * uv_u_scale; const float uv_u_offset_b = float(step + 1) * uv_u_scale; for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) { - blender::float2 *mluv = &mloopuv_layers[uv_lay][l_index]; + blender::float2 *mluv = &mloopuv_layers[uv_lay][new_loop_index]; mluv[quad_ord[0]][0] += uv_u_offset_a; mluv[quad_ord[1]][0] += uv_u_offset_a; @@ -916,13 +916,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } else { if (mloopuv_layers_tot) { - int l_index = int(ml_new - loops_new.data()); - uint uv_lay; const float uv_u_offset_a = float(step) * uv_u_scale; const float uv_u_offset_b = float(step + 1) * uv_u_scale; for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) { - blender::float2 *mluv = &mloopuv_layers[uv_lay][l_index]; + blender::float2 *mluv = &mloopuv_layers[uv_lay][new_loop_index]; copy_v2_fl2(mluv[quad_ord[0]], uv_u_offset_a, uv_v_offset_a); copy_v2_fl2(mluv[quad_ord[1]], uv_u_offset_a, uv_v_offset_b); @@ -935,16 +933,17 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Loop-Data */ if (!(close && step == step_last)) { /* regular segments */ - ml_new[quad_ord[0]].v = i1; - ml_new[quad_ord[1]].v = i2; - ml_new[quad_ord[2]].v = i2 + totvert; - ml_new[quad_ord[3]].v = i1 + totvert; + corner_verts_new[new_loop_index + quad_ord[0]] = int(i1); + corner_verts_new[new_loop_index + quad_ord[1]] = int(i2); + corner_verts_new[new_loop_index + quad_ord[2]] = int(i2 + totvert); + corner_verts_new[new_loop_index + quad_ord[3]] = int(i1 + totvert); - ml_new[quad_ord_ofs[0]].e = step == 0 ? i : - (edge_offset + step + (i * (step_tot - 1))) - 1; - ml_new[quad_ord_ofs[1]].e = totedge + i2; - ml_new[quad_ord_ofs[2]].e = edge_offset + step + (i * (step_tot - 1)); - ml_new[quad_ord_ofs[3]].e = totedge + i1; + corner_edges_new[new_loop_index + quad_ord_ofs[0]] = int( + step == 0 ? i : (edge_offset + step + (i * (step_tot - 1))) - 1); + corner_edges_new[new_loop_index + quad_ord_ofs[1]] = int(totedge + i2); + corner_edges_new[new_loop_index + quad_ord_ofs[2]] = int(edge_offset + step + + (i * (step_tot - 1))); + corner_edges_new[new_loop_index + quad_ord_ofs[3]] = int(totedge + i1); /* new vertical edge */ if (step) { /* The first set is already done */ @@ -957,19 +956,20 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } else { /* last segment */ - ml_new[quad_ord[0]].v = i1; - ml_new[quad_ord[1]].v = i2; - ml_new[quad_ord[2]].v = med_new_firstloop->v2; - ml_new[quad_ord[3]].v = med_new_firstloop->v1; + corner_verts_new[new_loop_index + quad_ord[0]] = int(i1); + corner_verts_new[new_loop_index + quad_ord[1]] = int(i2); + corner_verts_new[new_loop_index + quad_ord[2]] = int(med_new_firstloop->v2); + corner_verts_new[new_loop_index + quad_ord[3]] = int(med_new_firstloop->v1); - ml_new[quad_ord_ofs[0]].e = (edge_offset + step + (i * (step_tot - 1))) - 1; - ml_new[quad_ord_ofs[1]].e = totedge + i2; - ml_new[quad_ord_ofs[2]].e = i; - ml_new[quad_ord_ofs[3]].e = totedge + i1; + corner_edges_new[new_loop_index + quad_ord_ofs[0]] = int( + (edge_offset + step + (i * (step_tot - 1))) - 1); + corner_edges_new[new_loop_index + quad_ord_ofs[1]] = int(totedge + i2); + corner_edges_new[new_loop_index + quad_ord_ofs[2]] = int(i); + corner_edges_new[new_loop_index + quad_ord_ofs[3]] = int(totedge + i1); } mp_new++; - ml_new += 4; + new_loop_index += 4; mpoly_index++; } diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.cc b/source/blender/modifiers/intern/MOD_solidify_extrude.cc index 63b8cf1eeab..c12e25d0d98 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.cc +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.cc @@ -24,10 +24,6 @@ #include "MOD_solidify_util.hh" /* own include */ #include "MOD_util.h" -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -#endif - /* -------------------------------------------------------------------- */ /** \name High Quality Normal Calculation Function * \{ */ @@ -64,7 +60,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, const int verts_num = mesh->totvert; const blender::Span edges = mesh->edges(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_edges = mesh->corner_edges(); { EdgeFaceRef *edge_ref_array = MEM_cnew_array(size_t(edges.size()), __func__); @@ -75,11 +71,11 @@ static void mesh_calc_hq_normal(Mesh *mesh, for (const int i : polys.index_range()) { int j; - const MLoop *ml = &loops[polys[i].loopstart]; + for (j = 0; j < polys[i].totloop; j++) { + const int edge_i = corner_edges[polys[i].loopstart + j]; - for (j = 0; j < polys[i].totloop; j++, ml++) { /* --- add edge ref to face --- */ - edge_ref = &edge_ref_array[ml->e]; + edge_ref = &edge_ref_array[edge_i]; if (!edgeref_is_init(edge_ref)) { edge_ref->p1 = i; edge_ref->p2 = -1; @@ -91,7 +87,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, /* 3+ faces using an edge, we can't handle this usefully */ edge_ref->p1 = edge_ref->p2 = -1; #ifdef USE_NONMANIFOLD_WORKAROUND - BLI_BITMAP_ENABLE(edge_tmp_tag, ml->e); + BLI_BITMAP_ENABLE(edge_tmp_tag, edge_i); #endif } /* --- done --- */ @@ -212,7 +208,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex const float(*orig_vert_positions)[3] = BKE_mesh_vert_positions(mesh); const blender::Span orig_edges = mesh->edges(); const blender::Span orig_polys = mesh->polys(); - const blender::Span orig_loops = mesh->loops(); + const blender::Span orig_corner_verts = mesh->corner_verts(); + const blender::Span orig_corner_edges = mesh->corner_edges(); if (need_poly_normals) { /* calculate only face normals */ @@ -252,23 +249,26 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex const MPoly &poly = orig_polys[i]; int j; - const MLoop *ml = &orig_loops[poly.loopstart]; - const MLoop *ml_prev = ml + (poly.totloop - 1); + int corner_i_prev = poly.loopstart + (poly.totloop - 1); - for (j = 0; j < poly.totloop; j++, ml++) { + for (j = 0; j < poly.totloop; j++) { + const int corner_i = poly.loopstart + j; + const int vert_i = orig_corner_verts[corner_i]; + const int prev_vert_i = orig_corner_verts[corner_i_prev]; /* add edge user */ - eidx = ml_prev->e; + eidx = (int)(orig_corner_edges[corner_i_prev]); if (edge_users[eidx] == INVALID_UNUSED) { edge = &orig_edges[eidx]; - BLI_assert(ELEM(ml_prev->v, edge->v1, edge->v2) && ELEM(ml->v, edge->v1, edge->v2)); - edge_users[eidx] = (ml_prev->v > ml->v) == (edge->v1 < edge->v2) ? uint(i) : - (uint(i) + polys_num); + BLI_assert(ELEM(prev_vert_i, edge->v1, edge->v2) && ELEM(vert_i, edge->v1, edge->v2)); + edge_users[eidx] = (prev_vert_i > vert_i) == (edge->v1 < edge->v2) ? + uint(i) : + (uint(i) + polys_num); edge_order[eidx] = j; } else { edge_users[eidx] = INVALID_PAIR; } - ml_prev = ml; + corner_i_prev = corner_i; } } @@ -333,7 +333,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex float(*vert_positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan edges = result->edges_for_write(); blender::MutableSpan polys = result->polys_for_write(); - blender::MutableSpan loops = result->loops_for_write(); + blender::MutableSpan corner_verts = result->corner_verts_for_write(); + blender::MutableSpan corner_edges = result->corner_edges_for_write(); if (do_shell) { CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, int(verts_num)); @@ -417,13 +418,12 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex const int64_t poly_i = polys_num + i; MPoly &poly = polys[poly_i]; const int loop_end = poly.totloop - 1; - MLoop *ml2; - uint e; + int e; int j; - /* reverses the loop direction (MLoop.v as well as custom-data) - * MLoop.e also needs to be corrected too, done in a separate loop below. */ - ml2 = &loops[poly.loopstart + mesh->totloop]; + /* reverses the loop direction (corner verts as well as custom-data) + * Corner edges also need to be corrected too, done in a separate loop below. */ + const int corner_2 = poly.loopstart + mesh->totloop; #if 0 for (j = 0; j < poly.totloop; j++) { CustomData_copy_data(&mesh->ldata, @@ -450,17 +450,17 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex CLAMP(dst_material_index[poly_i], 0, mat_nr_max); } - e = ml2[0].e; + e = corner_edges[corner_2 + 0]; for (j = 0; j < loop_end; j++) { - ml2[j].e = ml2[j + 1].e; + corner_edges[corner_2 + j] = corner_edges[corner_2 + j + 1]; } - ml2[loop_end].e = e; + corner_edges[corner_2 + loop_end] = e; poly.loopstart += mesh->totloop; for (j = 0; j < poly.totloop; j++) { - ml2[j].e += edges_num; - ml2[j].v += verts_num; + corner_verts[corner_2 + j] += verts_num; + corner_edges[corner_2 + j] += edges_num; } } @@ -516,15 +516,16 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } for (const int64_t i : orig_polys.index_range()) { const MPoly &poly = orig_polys[i]; - const MLoop *ml = &orig_loops[poly.loopstart]; - const MLoop *ml_prev = ml + (poly.totloop - 1); - - for (uint j = 0; j < poly.totloop; j++, ml++) { + int prev_corner_i = poly.loopstart + poly.totloop - 1; + for (int j = 0; j < poly.totloop; j++) { + const int corner_i = poly.loopstart + j; + const int vert_i = orig_corner_verts[corner_i]; + const int prev_vert_i = orig_corner_verts[prev_corner_i]; /* add edge user */ - eidx = ml_prev->e; - const MEdge *edge = &orig_edges[eidx]; - BLI_assert(ELEM(ml_prev->v, edge->v1, edge->v2) && ELEM(ml->v, edge->v1, edge->v2)); - char flip = char((ml_prev->v > ml->v) == (edge->v1 < edge->v2)); + eidx = orig_corner_edges[prev_corner_i]; + const MEdge *ed = &orig_edges[eidx]; + BLI_assert(ELEM(prev_vert_i, ed->v1, ed->v2) && ELEM(vert_i, ed->v1, ed->v2)); + char flip = char((prev_vert_i > vert_i) == (ed->v1 < ed->v2)); if (edge_user_pairs[eidx][flip] == INVALID_UNUSED) { edge_user_pairs[eidx][flip] = uint(i); } @@ -532,7 +533,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex edge_user_pairs[eidx][0] = INVALID_PAIR; edge_user_pairs[eidx][1] = INVALID_PAIR; } - ml_prev = ml; + prev_corner_i = corner_i; } } const MEdge *edge = orig_edges.data(); @@ -722,14 +723,17 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex int i_curr = polys[i].totloop - 1; int i_next = 0; - const MLoop *ml = &loops[polys[i].loopstart]; + const int *poly_verts = &corner_verts[polys[i].loopstart]; + const int *poly_edges = &corner_edges[polys[i].loopstart]; - sub_v3_v3v3(nor_prev, vert_positions[ml[i_curr - 1].v], vert_positions[ml[i_curr].v]); + sub_v3_v3v3( + nor_prev, vert_positions[poly_verts[i_curr - 1]], vert_positions[poly_verts[i_curr]]); normalize_v3(nor_prev); while (i_next < polys[i].totloop) { float angle; - sub_v3_v3v3(nor_next, vert_positions[ml[i_curr].v], vert_positions[ml[i_next].v]); + sub_v3_v3v3( + nor_next, vert_positions[poly_verts[i_curr]], vert_positions[poly_verts[i_next]]); normalize_v3(nor_next); angle = angle_normalized_v3v3(nor_prev, nor_next); @@ -738,14 +742,14 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex angle = FLT_EPSILON; } - vidx = ml[i_curr].v; + vidx = poly_verts[i_curr]; vert_accum[vidx] += angle; #ifdef USE_NONMANIFOLD_WORKAROUND /* skip 3+ face user edges */ if ((check_non_manifold == false) || - LIKELY(!BLI_BITMAP_TEST(edge_tmp_tag, ml[i_curr].e) && - !BLI_BITMAP_TEST(edge_tmp_tag, ml[i_next].e))) { + LIKELY(!BLI_BITMAP_TEST(edge_tmp_tag, poly_edges[i_curr]) && + !BLI_BITMAP_TEST(edge_tmp_tag, poly_edges[i_next]))) { vert_angles[vidx] += shell_v3v3_normalized_to_dist(vert_nors[vidx], poly_normals[i]) * angle; } @@ -814,15 +818,17 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } for (const int i : orig_polys.index_range()) { const MPoly &poly = orig_polys[i]; - const MLoop *ml = &orig_loops[poly.loopstart]; - const MLoop *ml_prev = ml + (poly.totloop - 1); + int prev_corner_i = poly.loopstart + poly.totloop - 1; + for (int j = 0; j < poly.totloop; j++) { + const int corner_i = poly.loopstart + j; + const int vert_i = orig_corner_verts[corner_i]; + const int prev_vert_i = orig_corner_verts[prev_corner_i]; - for (int j = 0; j < poly.totloop; j++, ml++) { /* add edge user */ - eidx = ml_prev->e; + eidx = orig_corner_edges[prev_corner_i]; const MEdge *edge = &orig_edges[eidx]; - BLI_assert(ELEM(ml_prev->v, edge->v1, edge->v2) && ELEM(ml->v, edge->v1, edge->v2)); - char flip = char((ml_prev->v > ml->v) == (edge->v1 < edge->v2)); + BLI_assert(ELEM(prev_vert_i, edge->v1, edge->v2) && ELEM(vert_i, edge->v1, edge->v2)); + char flip = char((prev_vert_i > vert_i) == (edge->v1 < edge->v2)); if (edge_user_pairs[eidx][flip] == INVALID_UNUSED) { edge_user_pairs[eidx][flip] = uint(i); } @@ -830,7 +836,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex edge_user_pairs[eidx][0] = INVALID_PAIR; edge_user_pairs[eidx][1] = INVALID_PAIR; } - ml_prev = ml; + prev_corner_i = corner_i; } } const MEdge *edge = orig_edges.data(); @@ -971,6 +977,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* must recalculate normals with vgroups since they can displace unevenly #26888. */ if (BKE_mesh_vert_normals_are_dirty(mesh) || do_rim || dvert) { + /* Pass. */ } else if (do_shell) { uint i; @@ -1063,7 +1070,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* faces */ int new_poly_index = int(polys_num * stride); - blender::MutableSpan new_loops = loops.drop_front(loops_num * stride); + blender::MutableSpan new_corner_verts = corner_verts.drop_front(loops_num * stride); + blender::MutableSpan new_corner_edges = corner_edges.drop_front(loops_num * stride); j = 0; for (i = 0; i < newPolys; i++) { uint eidx = new_edge_arr[i]; @@ -1104,35 +1112,35 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex CustomData_copy_data(&mesh->ldata, &result->ldata, k2, int((loops_num * stride) + j + 3), 1); if (flip == false) { - new_loops[j].v = edge.v1; - new_loops[j++].e = eidx; + new_corner_verts[j] = edge.v1; + new_corner_edges[j++] = eidx; - new_loops[j].v = edge.v2; - new_loops[j++].e = (edges_num * stride) + old_vert_arr[edge.v2] + newEdges; + new_corner_verts[j] = edge.v2; + new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge.v2] + newEdges; - new_loops[j].v = (do_shell ? edge.v2 : old_vert_arr[edge.v2]) + verts_num; - new_loops[j++].e = (do_shell ? eidx : i) + edges_num; + new_corner_verts[j] = (do_shell ? edge.v2 : old_vert_arr[edge.v2]) + verts_num; + new_corner_edges[j++] = (do_shell ? eidx : i) + edges_num; - new_loops[j].v = (do_shell ? edge.v1 : old_vert_arr[edge.v1]) + verts_num; - new_loops[j++].e = (edges_num * stride) + old_vert_arr[edge.v1] + newEdges; + new_corner_verts[j] = (do_shell ? edge.v1 : old_vert_arr[edge.v1]) + verts_num; + new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge.v1] + newEdges; } else { - new_loops[j].v = edge.v2; - new_loops[j++].e = eidx; + new_corner_verts[j] = edge.v2; + new_corner_edges[j++] = eidx; - new_loops[j].v = edge.v1; - new_loops[j++].e = (edges_num * stride) + old_vert_arr[edge.v1] + newEdges; + new_corner_verts[j] = edge.v1; + new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge.v1] + newEdges; - new_loops[j].v = (do_shell ? edge.v1 : old_vert_arr[edge.v1]) + verts_num; - new_loops[j++].e = (do_shell ? eidx : i) + edges_num; + new_corner_verts[j] = (do_shell ? edge.v1 : old_vert_arr[edge.v1]) + verts_num; + new_corner_edges[j++] = (do_shell ? eidx : i) + edges_num; - new_loops[j].v = (do_shell ? edge.v2 : old_vert_arr[edge.v2]) + verts_num; - new_loops[j++].e = (edges_num * stride) + old_vert_arr[edge.v2] + newEdges; + new_corner_verts[j] = (do_shell ? edge.v2 : old_vert_arr[edge.v2]) + verts_num; + new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge.v2] + newEdges; } if (origindex_edge) { - origindex_edge[new_loops[j - 3].e] = ORIGINDEX_NONE; - origindex_edge[new_loops[j - 1].e] = ORIGINDEX_NONE; + origindex_edge[new_corner_edges[j - 3]] = ORIGINDEX_NONE; + origindex_edge[new_corner_edges[j - 1]] = ORIGINDEX_NONE; } /* use the next material index if option enabled */ @@ -1157,10 +1165,10 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex #ifdef SOLIDIFY_SIDE_NORMALS if (do_side_normals) { normal_quad_v3(nor, - vert_positions[new_loops[j - 4].v], - vert_positions[new_loops[j - 3].v], - vert_positions[new_loops[j - 2].v], - vert_positions[new_loops[j - 1].v]); + vert_positions[new_corner_verts[j - 4]], + vert_positions[new_corner_verts[j - 3]], + vert_positions[new_corner_verts[j - 2]], + vert_positions[new_corner_verts[j - 1]]); add_v3_v3(edge_vert_nos[edge.v1], nor); add_v3_v3(edge_vert_nos[edge.v2], nor); diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.cc b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.cc index 5dc456e0e3a..3af2a85ca8f 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.cc +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.cc @@ -22,10 +22,6 @@ #include "MOD_solidify_util.hh" /* Own include. */ #include "MOD_util.h" -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -#endif - /* -------------------------------------------------------------------- */ /** \name Local Utilities * \{ */ @@ -189,7 +185,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const float(*orig_vert_positions)[3] = BKE_mesh_vert_positions(mesh); const blender::Span orig_edges = mesh->edges(); const blender::Span orig_polys = mesh->polys(); - const blender::Span orig_loops = mesh->loops(); + const blender::Span orig_corner_verts = mesh->corner_verts(); + const blender::Span orig_corner_edges = mesh->corner_edges(); /* These might be null. */ const float *orig_vert_bweight = static_cast( @@ -222,7 +219,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const MPoly &poly = orig_polys[i]; /* Make normals for faces without area (should really be avoided though). */ if (len_squared_v3(poly_nors[i]) < 0.5f) { - const MEdge *edge = &orig_edges[orig_loops[poly.loopstart].e]; + const MEdge *edge = &orig_edges[orig_corner_edges[poly.loopstart]]; float edgedir[3]; sub_v3_v3v3(edgedir, orig_vert_positions[edge->v2], orig_vert_positions[edge->v1]); if (fabsf(edgedir[2]) < fabsf(edgedir[1])) { @@ -273,9 +270,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, { for (const int64_t i : orig_polys.index_range()) { const MPoly &poly = orig_polys[i]; - const MLoop *ml = &orig_loops[poly.loopstart]; - for (uint j = 0; j < poly.totloop; j++, ml++) { - edge_adj_faces_len[ml->e]++; + for (uint j = 0; j < poly.totloop; j++) { + edge_adj_faces_len[orig_corner_edges[poly.loopstart + j]]++; } } } @@ -323,10 +319,10 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, { for (const int64_t i : orig_polys.index_range()) { const MPoly &poly = orig_polys[i]; - const MLoop *ml = &orig_loops[poly.loopstart]; - for (uint j = 0; j < poly.totloop; j++, ml++) { - const uint edge = ml->e; - const bool reversed = orig_edges[edge].v2 != ml->v; + for (uint j = 0; j < poly.totloop; j++) { + const int vert = orig_corner_verts[poly.loopstart + j]; + const int edge = orig_corner_edges[poly.loopstart + j]; + const bool reversed = orig_edges[edge].v2 != vert; OldEdgeFaceRef *old_face_edge_ref = edge_adj_faces[edge]; if (old_face_edge_ref == nullptr) { const uint len = edge_adj_faces_len[edge]; @@ -399,8 +395,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint changes = 0; int cur = poly.totloop - 1; for (int next = 0; next < poly.totloop && changes <= 2; next++) { - uint cur_v = vm[orig_loops[poly.loopstart + cur].v]; - uint next_v = vm[orig_loops[poly.loopstart + next].v]; + uint cur_v = vm[orig_corner_verts[poly.loopstart + cur]]; + uint next_v = vm[orig_corner_verts[poly.loopstart + next]]; changes += (ELEM(cur_v, v1, v2) != ELEM(next_v, v1, v2)); cur = next; } @@ -458,7 +454,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (!face_singularity[face]) { bool is_singularity = true; for (uint k = 0; k < orig_polys[face].totloop; k++) { - if (vm[orig_loops[uint(orig_polys[face].loopstart) + k].v] != v1) { + if (vm[orig_corner_verts[uint(orig_polys[face].loopstart) + k]] != v1) { is_singularity = false; break; } @@ -626,7 +622,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const uint face = adj_faces->faces[j]; const int j_loopstart = orig_polys[face].loopstart; const int totloop = orig_polys[face].totloop; - const uint j_first_v = vm[orig_loops[j_loopstart].v]; + const uint j_first_v = vm[orig_corner_verts[j_loopstart]]; for (uint k = j + 1; k < adj_len; k++) { if (orig_polys[adj_faces->faces[k]].totloop != totloop) { continue; @@ -634,9 +630,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Find first face first loop vert in second face loops. */ const int k_loopstart = orig_polys[adj_faces->faces[k]].loopstart; int l; - const MLoop *ml = &orig_loops[k_loopstart]; - for (l = 0; l < totloop && vm[ml->v] != j_first_v; l++, ml++) { - /* Pass. */ + { + const int *corner_vert = &orig_corner_verts[k_loopstart]; + for (l = 0; l < totloop && vm[*corner_vert] != j_first_v; l++, corner_vert++) { + /* Pass. */ + } } if (l == totloop) { continue; @@ -645,17 +643,16 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const bool reversed = adj_faces->faces_reversed[j] != adj_faces->faces_reversed[k]; const int count_dir = reversed ? -1 : 1; bool has_diff = false; - ml = &orig_loops[j_loopstart]; - for (int m = 0, n = l + totloop; m < totloop && !has_diff; - m++, n += count_dir, ml++) { - has_diff = has_diff || vm[ml->v] != vm[orig_loops[k_loopstart + n % totloop].v]; + for (int m = 0, n = l + totloop; m < totloop && !has_diff; m++, n += count_dir) { + const int vert = orig_corner_verts[j_loopstart + m]; + has_diff = has_diff || + vm[vert] != vm[orig_corner_verts[k_loopstart + n % totloop]]; } /* If the faces are equal, discard one (j). */ if (!has_diff) { - ml = &orig_loops[j_loopstart]; uint del_loops = 0; - for (uint m = 0; m < totloop; m++, ml++) { - const uint e = ml->e; + for (uint m = 0; m < totloop; m++) { + const int e = orig_corner_edges[j_loopstart + m]; OldEdgeFaceRef *e_adj_faces = edge_adj_faces[e]; if (e_adj_faces) { uint face_index = j; @@ -874,11 +871,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, new_edges[j] = edge_data; for (uint k = 0; k < 2; k++) { if (faces[k] != nullptr) { - const MLoop *ml = &orig_loops[faces[k]->face->loopstart]; - for (int l = 0; l < faces[k]->face->totloop; l++, ml++) { - if (edge_adj_faces[ml->e] == edge_adj_faces[i]) { - if (ml->e != i && orig_edge_data_arr[ml->e] == nullptr) { - orig_edge_data_arr[ml->e] = new_edges; + for (int l = 0; l < faces[k]->face->totloop; l++) { + const int edge = orig_corner_edges[faces[k]->face->loopstart + l]; + if (edge_adj_faces[edge] == edge_adj_faces[i]) { + if (edge != i && orig_edge_data_arr[edge] == nullptr) { + orig_edge_data_arr[edge] = new_edges; } faces[k]->link_edges[l] = edge_data; break; @@ -1414,9 +1411,9 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const MPoly &poly = orig_polys[i]; float scalar_vgroup = 1.0f; int loopend = poly.loopstart + poly.totloop; - const MLoop *ml = &orig_loops[poly.loopstart]; - for (int j = poly.loopstart; j < loopend; j++, ml++) { - const MDeformVert *dv = &dvert[ml->v]; + for (int j = poly.loopstart; j < loopend; j++) { + const int vert = orig_corner_verts[poly.loopstart + j]; + const MDeformVert *dv = &dvert[vert]; if (defgrp_invert) { scalar_vgroup = min_ff(1.0f - BKE_defvert_find_weight(dv, defgrp_index), scalar_vgroup); @@ -1686,17 +1683,19 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN) { - const MLoop *ml_next = &orig_loops[face->face->loopstart]; - const MLoop *ml = ml_next + (face->face->totloop - 1); - const MLoop *ml_prev = ml - 1; - for (int m = 0; m < face->face->totloop && vm[ml->v] != i; - m++, ml_next++) { - ml_prev = ml; - ml = ml_next; + int corner_next = face->face->loopstart; + int corner = corner_next + (face->face->totloop - 1); + int corner_prev = corner - 1; + + for (int m = 0; + m < face->face->totloop && vm[orig_corner_verts[corner]] != i; + m++, corner_next++) { + corner_prev = corner; + corner = corner_next; } - angle = angle_v3v3v3(orig_mvert_co[vm[ml_prev->v]], + angle = angle_v3v3v3(orig_mvert_co[vm[orig_corner_verts[corner_prev]]], orig_mvert_co[i], - orig_mvert_co[vm[ml_next->v]]); + orig_mvert_co[vm[orig_corner_verts[corner_next]]]); if (face->reversed) { total_angle_back += angle * ofs * ofs; } @@ -1992,7 +1991,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, float(*vert_positions)[3] = BKE_mesh_vert_positions_for_write(result); blender::MutableSpan edges = result->edges_for_write(); blender::MutableSpan polys = result->polys_for_write(); - blender::MutableSpan loops = result->loops_for_write(); + blender::MutableSpan corner_verts = result->corner_verts_for_write(); + blender::MutableSpan corner_edges = result->corner_edges_for_write(); int *origindex_edge = static_cast( CustomData_get_layer_for_write(&result->edata, CD_ORIGINDEX, result->totedge)); @@ -2323,9 +2323,9 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, for (uint k = 0; g2->valid && k < j; g2++) { if ((do_rim && !g2->is_orig_closed) || (do_shell && g2->split)) { const MPoly *face = g2->edges[0]->faces[0]->face; - const MLoop *ml = &orig_loops[face->loopstart]; - for (int l = 0; l < face->totloop; l++, ml++) { - if (vm[ml->v] == i) { + for (int l = 0; l < face->totloop; l++) { + const int vert = orig_corner_verts[face->loopstart + l]; + if (vm[vert] == i) { loops_data[k] = face->loopstart + l; break; } @@ -2338,16 +2338,16 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, for (uint k = 0; k < j; k++) { CustomData_copy_data( &mesh->ldata, &result->ldata, loops_data[k], int(loop_index), 1); - loops[loop_index].v = edges[edge_index - j + k].v1; - loops[loop_index++].e = edge_index - j + k; + corner_verts[loop_index] = edges[edge_index - j + k].v1; + corner_edges[loop_index++] = edge_index - j + k; } } else { for (uint k = 1; k <= j; k++) { CustomData_copy_data( &mesh->ldata, &result->ldata, loops_data[j - k], int(loop_index), 1); - loops[loop_index].v = edges[edge_index - k].v2; - loops[loop_index++].e = edge_index - k; + corner_verts[loop_index] = edges[edge_index - k].v2; + corner_edges[loop_index++] = edge_index - k; } } MEM_freeN(loops_data); @@ -2396,14 +2396,14 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, int loop1 = -1; int loop2 = -1; - const MLoop *ml = &orig_loops[face->loopstart]; const uint old_v1 = vm[orig_edges[edge1->old_edge].v1]; const uint old_v2 = vm[orig_edges[edge1->old_edge].v2]; - for (uint j = 0; j < face->totloop; j++, ml++) { - if (vm[ml->v] == old_v1) { + for (uint j = 0; j < face->totloop; j++) { + const int vert = orig_corner_verts[face->loopstart + j]; + if (vm[vert] == old_v1) { loop1 = face->loopstart + int(j); } - else if (vm[ml->v] == old_v2) { + else if (vm[vert] == old_v2) { loop2 = face->loopstart + int(j); } } @@ -2416,8 +2416,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, int(loop_index), 1); - loops[loop_index].v = edges[edge1->new_edge].v1; - loops[loop_index++].e = edge1->new_edge; + corner_verts[loop_index] = edges[edge1->new_edge].v1; + corner_edges[loop_index++] = edge1->new_edge; if (!v2_singularity) { open_face_edge_index = edge1->link_edge_groups[1]->open_face_edge; @@ -2426,13 +2426,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, int(loop_index), 1); - loops[loop_index].v = edges[edge1->new_edge].v2; + corner_verts[loop_index] = edges[edge1->new_edge].v2; open_face_edge = &edges[open_face_edge_index]; if (ELEM(edges[edge2->new_edge].v2, open_face_edge->v1, open_face_edge->v2)) { - loops[loop_index++].e = open_face_edge_index; + corner_edges[loop_index++] = open_face_edge_index; } else { - loops[loop_index++].e = edge2->link_edge_groups[1]->open_face_edge; + corner_edges[loop_index++] = edge2->link_edge_groups[1]->open_face_edge; } } @@ -2441,8 +2441,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, int(loop_index), 1); - loops[loop_index].v = edges[edge2->new_edge].v2; - loops[loop_index++].e = edge2->new_edge; + corner_verts[loop_index] = edges[edge2->new_edge].v2; + corner_edges[loop_index++] = edge2->new_edge; if (!v1_singularity) { open_face_edge_index = edge2->link_edge_groups[0]->open_face_edge; @@ -2451,13 +2451,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, int(loop_index), 1); - loops[loop_index].v = edges[edge2->new_edge].v1; + corner_verts[loop_index] = edges[edge2->new_edge].v1; open_face_edge = &edges[open_face_edge_index]; if (ELEM(edges[edge1->new_edge].v1, open_face_edge->v1, open_face_edge->v2)) { - loops[loop_index++].e = open_face_edge_index; + corner_edges[loop_index++] = open_face_edge_index; } else { - loops[loop_index++].e = edge1->link_edge_groups[0]->open_face_edge; + corner_edges[loop_index++] = edge1->link_edge_groups[0]->open_face_edge; } } } @@ -2469,13 +2469,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, int(loop_index), 1); - loops[loop_index].v = edges[edge1->new_edge].v1; + corner_verts[loop_index] = edges[edge1->new_edge].v1; open_face_edge = &edges[open_face_edge_index]; if (ELEM(edges[edge2->new_edge].v1, open_face_edge->v1, open_face_edge->v2)) { - loops[loop_index++].e = open_face_edge_index; + corner_edges[loop_index++] = open_face_edge_index; } else { - loops[loop_index++].e = edge2->link_edge_groups[0]->open_face_edge; + corner_edges[loop_index++] = edge2->link_edge_groups[0]->open_face_edge; } } @@ -2484,8 +2484,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, int(loop_index), 1); - loops[loop_index].v = edges[edge2->new_edge].v1; - loops[loop_index++].e = edge2->new_edge; + corner_verts[loop_index] = edges[edge2->new_edge].v1; + corner_edges[loop_index++] = edge2->new_edge; if (!v2_singularity) { open_face_edge_index = edge2->link_edge_groups[1]->open_face_edge; @@ -2494,13 +2494,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, int(loop_index), 1); - loops[loop_index].v = edges[edge2->new_edge].v2; + corner_verts[loop_index] = edges[edge2->new_edge].v2; open_face_edge = &edges[open_face_edge_index]; if (ELEM(edges[edge1->new_edge].v2, open_face_edge->v1, open_face_edge->v2)) { - loops[loop_index++].e = open_face_edge_index; + corner_edges[loop_index++] = open_face_edge_index; } else { - loops[loop_index++].e = edge1->link_edge_groups[1]->open_face_edge; + corner_edges[loop_index++] = edge1->link_edge_groups[1]->open_face_edge; } } @@ -2509,8 +2509,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, int(loop_index), 1); - loops[loop_index].v = edges[edge1->new_edge].v2; - loops[loop_index++].e = edge1->new_edge; + corner_verts[loop_index] = edges[edge1->new_edge].v2; + corner_edges[loop_index++] = edge1->new_edge; } } } @@ -2537,15 +2537,15 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (totloop > 0) { NewEdgeRef *prior_edge = fr->link_edges[totloop - 1]; uint prior_flip = uint(vm[orig_edges[prior_edge->old_edge].v1] == - vm[orig_loops[loopstart + (totloop - 1)].v]); + vm[orig_corner_verts[loopstart + (totloop - 1)]]); for (uint j = 0; j < totloop; j++) { NewEdgeRef *new_edge = fr->link_edges[j]; if (new_edge && new_edge->new_edge != MOD_SOLIDIFY_EMPTY_TAG) { valid_edges++; const uint flip = uint(vm[orig_edges[new_edge->old_edge].v2] == - vm[orig_loops[loopstart + j].v]); - BLI_assert(flip || - vm[orig_edges[new_edge->old_edge].v1] == vm[orig_loops[loopstart + j].v]); + vm[orig_corner_verts[loopstart + j]]); + BLI_assert(flip || vm[orig_edges[new_edge->old_edge].v1] == + vm[orig_corner_verts[loopstart + j]]); /* The vert that's in the current loop. */ const uint new_v1 = new_edge->link_edge_groups[flip]->new_vert; /* The vert that's in the next loop. */ @@ -2592,8 +2592,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } CustomData_copy_data( &mesh->ldata, &result->ldata, int(face_loops[l]), int(loop_index), 1); - loops[loop_index].v = face_verts[l]; - loops[loop_index++].e = face_edges[l]; + corner_verts[loop_index] = face_verts[l]; + corner_edges[loop_index++] = face_edges[l]; } } else { @@ -2601,8 +2601,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, for (uint next_l = 0; next_l < k; next_l++) { CustomData_copy_data( &mesh->ldata, &result->ldata, int(face_loops[l]), int(loop_index), 1); - loops[loop_index].v = face_verts[l]; - loops[loop_index++].e = face_edges[next_l]; + corner_verts[loop_index] = face_verts[l]; + corner_edges[loop_index++] = face_edges[next_l]; l = next_l; } } diff --git a/source/blender/modifiers/intern/MOD_subsurf.cc b/source/blender/modifiers/intern/MOD_subsurf.cc index 88a456944bb..6619523bee6 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.cc +++ b/source/blender/modifiers/intern/MOD_subsurf.cc @@ -437,9 +437,6 @@ static void panel_draw(const bContext *C, Panel *panel) if (runtime_data->used_cpu) { uiItemL(layout, "Using both CPU and GPU subdivision", ICON_INFO); } - else { - uiItemL(layout, "Using GPU subdivision", ICON_INFO); - } } } } diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.cc b/source/blender/modifiers/intern/MOD_surfacedeform.cc index d13a15e724b..c1ce4e14242 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.cc +++ b/source/blender/modifiers/intern/MOD_surfacedeform.cc @@ -70,7 +70,8 @@ struct SDefBindCalcData { SDefVert *bind_verts; blender::Span edges; blender::Span polys; - blender::Span loops; + blender::Span corner_verts; + blender::Span corner_edges; blender::Span looptris; /** Coordinates to bind to, transformed into local space (compatible with `vertexCos`). */ @@ -290,27 +291,24 @@ static void freeAdjacencyMap(SDefAdjacencyArray *const vert_edges, static int buildAdjacencyMap(const blender::Span polys, const blender::Span edges, - const blender::Span loops, + const blender::Span corner_edges, SDefAdjacencyArray *const vert_edges, SDefAdjacency *adj, SDefEdgePolys *const edge_polys) { - const MLoop *loop; - /* Find polygons adjacent to edges. */ for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; - loop = &loops[poly.loopstart]; - - for (int j = 0; j < poly.totloop; j++, loop++) { - if (edge_polys[loop->e].num == 0) { - edge_polys[loop->e].polys[0] = i; - edge_polys[loop->e].polys[1] = -1; - edge_polys[loop->e].num++; + for (int j = 0; j < poly.totloop; j++) { + const int edge_i = corner_edges[poly.loopstart + j]; + if (edge_polys[edge_i].num == 0) { + edge_polys[edge_i].polys[0] = i; + edge_polys[edge_i].polys[1] = -1; + edge_polys[edge_i].num++; } - else if (edge_polys[loop->e].num == 1) { - edge_polys[loop->e].polys[1] = i; - edge_polys[loop->e].num++; + else if (edge_polys[edge_i].num == 1) { + edge_polys[edge_i].polys[1] = i; + edge_polys[edge_i].num++; } else { return MOD_SDEF_BIND_RESULT_NONMANY_ERR; @@ -338,41 +336,42 @@ static int buildAdjacencyMap(const blender::Span polys, } BLI_INLINE void sortPolyVertsEdge(uint *indices, - const MLoop *const loops, + const int *const corner_verts, + const int *const corner_edges, const uint edge, const uint num) { bool found = false; for (int i = 0; i < num; i++) { - if (loops[i].e == edge) { + if (corner_edges[i] == edge) { found = true; } if (found) { - *indices = loops[i].v; + *indices = corner_verts[i]; indices++; } } /* Fill in remaining vertex indices that occur before the edge */ - for (int i = 0; loops[i].e != edge; i++) { - *indices = loops[i].v; + for (int i = 0; corner_edges[i] != edge; i++) { + *indices = corner_verts[i]; indices++; } } BLI_INLINE void sortPolyVertsTri(uint *indices, - const MLoop *const loops, + const int *const corner_verts, const uint loopstart, const uint num) { for (int i = loopstart; i < num; i++) { - *indices = loops[i].v; + *indices = corner_verts[i]; indices++; } for (int i = 0; i < loopstart; i++) { - *indices = loops[i].v; + *indices = corner_verts[i]; indices++; } } @@ -384,7 +383,6 @@ BLI_INLINE uint nearestVert(SDefBindCalcData *const data, const float point_co[3 nearest.index = -1; const MEdge *edge; - const MLoop *loop; float t_point[3]; float max_dist = FLT_MAX; float dist; @@ -396,16 +394,16 @@ BLI_INLINE uint nearestVert(SDefBindCalcData *const data, const float point_co[3 data->treeData->tree, t_point, &nearest, data->treeData->nearest_callback, data->treeData); const MPoly &poly = data->polys[data->looptris[nearest.index].poly]; - loop = &data->loops[poly.loopstart]; - for (int i = 0; i < poly.totloop; i++, loop++) { - edge = &data->edges[loop->e]; + for (int i = 0; i < poly.totloop; i++) { + const int edge_i = data->corner_edges[poly.loopstart + i]; + edge = &data->edges[edge_i]; dist = dist_squared_to_line_segment_v3( point_co, data->targetCos[edge->v1], data->targetCos[edge->v2]); if (dist < max_dist) { max_dist = dist; - index = loop->e; + index = edge_i; } } @@ -488,7 +486,6 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, const SDefEdgePolys *const edge_polys = data->edge_polys; const SDefAdjacency *vedge; - const MLoop *loop; SDefBindWeightData *bwdata; SDefBindPoly *bpoly; @@ -546,7 +543,6 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, /* Copy poly data */ const MPoly &poly = data->polys[bpoly->index]; - loop = &data->loops[poly.loopstart]; bpoly->verts_num = poly.totloop; bpoly->loopstart = poly.loopstart; @@ -567,17 +563,19 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, return nullptr; } - for (int j = 0; j < poly.totloop; j++, loop++) { - copy_v3_v3(bpoly->coords[j], data->targetCos[loop->v]); + for (int j = 0; j < poly.totloop; j++) { + const int vert_i = data->corner_verts[poly.loopstart + j]; + const int edge_i = data->corner_edges[poly.loopstart + j]; + copy_v3_v3(bpoly->coords[j], data->targetCos[vert_i]); /* Find corner and edge indices within poly loop array */ - if (loop->v == nearest) { + if (vert_i == nearest) { bpoly->corner_ind = j; bpoly->edge_vert_inds[0] = (j == 0) ? (poly.totloop - 1) : (j - 1); bpoly->edge_vert_inds[1] = (j == poly.totloop - 1) ? (0) : (j + 1); - bpoly->edge_inds[0] = data->loops[poly.loopstart + bpoly->edge_vert_inds[0]].e; - bpoly->edge_inds[1] = loop->e; + bpoly->edge_inds[0] = data->corner_edges[poly.loopstart + bpoly->edge_vert_inds[0]]; + bpoly->edge_inds[1] = edge_i; } } @@ -1013,8 +1011,6 @@ static void bindVert(void *__restrict userdata, for (int i = 0; i < bwdata->binds_num; bpoly++) { if (bpoly->weight >= FLT_EPSILON) { if (bpoly->inside) { - const MLoop *loop = &data->loops[bpoly->loopstart]; - sdbind->influence = bpoly->weight; sdbind->verts_num = bpoly->verts_num; @@ -1039,9 +1035,10 @@ static void bindVert(void *__restrict userdata, /* Re-project vert based on weights and original poly verts, * to reintroduce poly non-planarity */ zero_v3(point_co_proj); - for (int j = 0; j < bpoly->verts_num; j++, loop++) { + for (int j = 0; j < bpoly->verts_num; j++) { + const int vert_i = data->corner_verts[bpoly->loopstart + j]; madd_v3_v3fl(point_co_proj, bpoly->coords[j], sdbind->vert_weights[j]); - sdbind->vert_inds[j] = loop->v; + sdbind->vert_inds[j] = vert_i; } sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal); @@ -1074,7 +1071,8 @@ static void bindVert(void *__restrict userdata, } sortPolyVertsEdge(sdbind->vert_inds, - &data->loops[bpoly->loopstart], + &data->corner_verts[bpoly->loopstart], + &data->corner_edges[bpoly->loopstart], bpoly->edge_inds[bpoly->dominant_edge], bpoly->verts_num); @@ -1121,7 +1119,7 @@ static void bindVert(void *__restrict userdata, } sortPolyVertsTri(sdbind->vert_inds, - &data->loops[bpoly->loopstart], + &data->corner_verts[bpoly->loopstart], bpoly->edge_vert_inds[0], bpoly->verts_num); @@ -1183,7 +1181,8 @@ static bool surfacedeformBind(Object *ob, const float(*positions)[3] = BKE_mesh_vert_positions(target); const blender::Span edges = target->edges(); const blender::Span polys = target->polys(); - const blender::Span loops = target->loops(); + const blender::Span corner_verts = target->corner_verts(); + const blender::Span corner_edges = target->corner_edges(); uint tedges_num = target->totedge; int adj_result; @@ -1228,7 +1227,7 @@ static bool surfacedeformBind(Object *ob, return false; } - adj_result = buildAdjacencyMap(polys, edges, loops, vert_edges, adj_array, edge_polys); + adj_result = buildAdjacencyMap(polys, edges, corner_edges, vert_edges, adj_array, edge_polys); if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { BKE_modifier_set_error( @@ -1256,7 +1255,8 @@ static bool surfacedeformBind(Object *ob, data.edge_polys = edge_polys; data.polys = polys; data.edges = edges; - data.loops = loops; + data.corner_verts = corner_verts; + data.corner_edges = corner_edges; data.looptris = target->looptris(); data.targetCos = static_cast( MEM_malloc_arrayN(target_verts_num, sizeof(float[3]), "SDefTargetBindVertArray")); diff --git a/source/blender/modifiers/intern/MOD_util.cc b/source/blender/modifiers/intern/MOD_util.cc index a5c15420f28..19f57a6fee1 100644 --- a/source/blender/modifiers/intern/MOD_util.cc +++ b/source/blender/modifiers/intern/MOD_util.cc @@ -61,6 +61,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, float (*cos)[3], float (*r_texco)[3]) { + using namespace blender; const int verts_num = mesh->totvert; int i; int texmapping = dmd->texmapping; @@ -93,7 +94,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, if (texmapping == MOD_DISP_MAP_UV) { if (CustomData_has_layer(&mesh->ldata, CD_PROP_FLOAT2)) { const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); BLI_bitmap *done = BLI_BITMAP_NEW(verts_num, __func__); char uvname[MAX_CUSTOMDATA_LAYER_NAME]; CustomData_validate_layer_name(&mesh->ldata, CD_PROP_FLOAT2, dmd->uvlayer_name, uvname); @@ -107,7 +108,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, do { uint lidx = poly.loopstart + fidx; - uint vidx = loops[lidx].v; + const int vidx = corner_verts[lidx]; if (!BLI_BITMAP_TEST(done, vidx)) { /* remap UVs from [0, 1] to [-1, 1] */ diff --git a/source/blender/modifiers/intern/MOD_uvproject.cc b/source/blender/modifiers/intern/MOD_uvproject.cc index ffaace78131..413774fd208 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.cc +++ b/source/blender/modifiers/intern/MOD_uvproject.cc @@ -94,6 +94,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, Object *ob, Mesh *mesh) { + using namespace blender; float(*coords)[3], (*co)[3]; int i, verts_num; Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; @@ -182,10 +183,10 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, const blender::Span positions = mesh->vert_positions(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const Span corner_verts = mesh->corner_verts(); - float(*mloop_uv)[2] = static_cast( - CustomData_get_layer_named_for_write(&mesh->ldata, CD_PROP_FLOAT2, uvname, loops.size())); + float(*mloop_uv)[2] = static_cast(CustomData_get_layer_named_for_write( + &mesh->ldata, CD_PROP_FLOAT2, uvname, corner_verts.size())); coords = BKE_mesh_vert_coords_alloc(mesh, &verts_num); @@ -209,7 +210,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, uint fidx = poly.totloop - 1; do { uint lidx = poly.loopstart + fidx; - uint vidx = loops[lidx].v; + const int vidx = corner_verts[lidx]; BLI_uvproject_from_camera( mloop_uv[lidx], coords[vidx], static_cast(projectors[0].uci)); } while (fidx--); @@ -219,7 +220,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, uint fidx = poly.totloop - 1; do { uint lidx = poly.loopstart + fidx; - uint vidx = loops[lidx].v; + const int vidx = corner_verts[lidx]; copy_v2_v2(mloop_uv[lidx], coords[vidx]); } while (fidx--); } @@ -232,7 +233,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, /* get the untransformed face normal */ const blender::float3 face_no = blender::bke::mesh::poly_normal_calc( - positions, loops.slice(poly.loopstart, poly.totloop)); + positions, corner_verts.slice(poly.loopstart, poly.totloop)); /* find the projector which the face points at most directly * (projector normal with largest dot product is best) @@ -252,7 +253,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, uint fidx = poly.totloop - 1; do { uint lidx = poly.loopstart + fidx; - uint vidx = loops[lidx].v; + const int vidx = corner_verts[lidx]; BLI_uvproject_from_camera( mloop_uv[lidx], coords[vidx], static_cast(best_projector->uci)); } while (fidx--); @@ -261,7 +262,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, uint fidx = poly.totloop - 1; do { uint lidx = poly.loopstart + fidx; - uint vidx = loops[lidx].v; + const int vidx = corner_verts[lidx]; mul_v2_project_m4_v3(mloop_uv[lidx], best_projector->projmat, coords[vidx]); } while (fidx--); } diff --git a/source/blender/modifiers/intern/MOD_uvwarp.cc b/source/blender/modifiers/intern/MOD_uvwarp.cc index 0c4c559c69b..562ff538654 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.cc +++ b/source/blender/modifiers/intern/MOD_uvwarp.cc @@ -81,7 +81,7 @@ static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonen struct UVWarpData { blender::Span polys; - blender::Span loops; + blender::Span corner_verts; float (*mloopuv)[2]; const MDeformVert *dvert; @@ -98,7 +98,7 @@ static void uv_warp_compute(void *__restrict userdata, const UVWarpData *data = static_cast(userdata); const MPoly &poly = data->polys[i]; - const MLoop *ml = &data->loops[poly.loopstart]; + const int *poly_verts = &data->corner_verts[poly.loopstart]; float(*mluv)[2] = &data->mloopuv[poly.loopstart]; const MDeformVert *dvert = data->dvert; @@ -109,11 +109,12 @@ static void uv_warp_compute(void *__restrict userdata, int l; if (dvert) { - for (l = 0; l < poly.totloop; l++, ml++, mluv++) { + for (l = 0; l < poly.totloop; l++, mluv++) { + const int vert_i = poly_verts[l]; float uv[2]; const float weight = data->invert_vgroup ? - 1.0f - BKE_defvert_find_weight(&dvert[ml->v], defgrp_index) : - BKE_defvert_find_weight(&dvert[ml->v], defgrp_index); + 1.0f - BKE_defvert_find_weight(&dvert[vert_i], defgrp_index) : + BKE_defvert_find_weight(&dvert[vert_i], defgrp_index); uv_warp_from_mat4_pair(uv, (*mluv), warp_mat); interp_v2_v2v2((*mluv), (*mluv), uv, weight); @@ -192,15 +193,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * CustomData_validate_layer_name(&mesh->ldata, CD_PROP_FLOAT2, umd->uvlayer_name, uvname); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); - float(*mloopuv)[2] = static_cast( - CustomData_get_layer_named_for_write(&mesh->ldata, CD_PROP_FLOAT2, uvname, loops.size())); + float(*mloopuv)[2] = static_cast(CustomData_get_layer_named_for_write( + &mesh->ldata, CD_PROP_FLOAT2, uvname, corner_verts.size())); MOD_get_vgroup(ctx->object, mesh, umd->vgroup_name, &dvert, &defgrp_index); UVWarpData data{}; data.polys = polys; - data.loops = loops; + data.corner_verts = corner_verts; data.mloopuv = mloopuv; data.dvert = dvert; data.defgrp_index = defgrp_index; diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.cc b/source/blender/modifiers/intern/MOD_weighted_normal.cc index 7dbf6ba13e8..fa2147f6615 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.cc +++ b/source/blender/modifiers/intern/MOD_weighted_normal.cc @@ -75,7 +75,8 @@ struct WeightedNormalData { blender::Span edges; blender::MutableSpan sharp_edges; - blender::Span loops; + blender::Span corner_verts; + blender::Span corner_edges; blender::Span loop_to_poly; short (*clnors)[2]; bool has_clnors; /* True if clnors already existed, false if we had to create them. */ @@ -187,10 +188,11 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, const blender::Span positions = wn_data->vert_positions; const blender::Span edges = wn_data->edges; const blender::Span polys = wn_data->polys; - const blender::Span loops = wn_data->loops; + const blender::Span corner_verts = wn_data->corner_verts; + const blender::Span corner_edges = wn_data->corner_edges; short(*clnors)[2] = wn_data->clnors; - const Span loop_to_poly = wn_data->loop_to_poly; + const blender::Span loop_to_poly = wn_data->loop_to_poly; const blender::Span poly_normals = wn_data->poly_normals; const int *poly_strength = wn_data->poly_strength; @@ -214,15 +216,16 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, WeightedNormalDataAggregateItem *items_data = nullptr; int items_num = 0; if (keep_sharp) { - BLI_bitmap *done_loops = BLI_BITMAP_NEW(loops.size(), __func__); + BLI_bitmap *done_loops = BLI_BITMAP_NEW(corner_verts.size(), __func__); /* This will give us loop normal spaces, * we do not actually care about computed loop_normals for now... */ - loop_normals.reinitialize(loops.size()); + loop_normals.reinitialize(corner_verts.size()); bke::mesh::normals_calc_loop(positions, edges, polys, - loops, + corner_verts, + corner_edges, loop_to_poly, wn_data->vert_normals, wn_data->poly_normals, @@ -292,7 +295,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, int ml_index = polys[poly_index].loopstart; const int ml_index_end = ml_index + polys[poly_index].totloop; for (; ml_index < ml_index_end; ml_index++) { - const int mv_index = loops[ml_index].v; + const int mv_index = corner_verts[ml_index]; WeightedNormalDataAggregateItem *item_data = keep_sharp ? static_cast( lnors_spacearr.lspacearr[ml_index]->user_data) : @@ -305,12 +308,12 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, break; case MOD_WEIGHTEDNORMAL_MODE_ANGLE: case MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE: - for (const int i : loops.index_range()) { + for (int i = 0; i < corner_verts.size(); i++) { const int ml_index = mode_pair[i].index; const float ml_val = mode_pair[i].val; const int poly_index = loop_to_poly[ml_index]; - const int mv_index = loops[ml_index].v; + const int mv_index = corner_verts[ml_index]; WeightedNormalDataAggregateItem *item_data = keep_sharp ? static_cast( lnors_spacearr.lspacearr[ml_index]->user_data) : @@ -336,7 +339,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, * Note that loop_normals is already populated with clnors * (before this modifier is applied, at start of this function), * so no need to recompute them here. */ - for (int ml_index = 0; ml_index < loops.size(); ml_index++) { + for (int ml_index = 0; ml_index < corner_verts.size(); ml_index++) { WeightedNormalDataAggregateItem *item_data = static_cast( lnors_spacearr.lspacearr[ml_index]->user_data); if (!is_zero_v3(item_data->normal)) { @@ -347,7 +350,8 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, blender::bke::mesh::normals_loop_custom_set(positions, edges, polys, - loops, + corner_verts, + corner_edges, wn_data->vert_normals, poly_normals, wn_data->sharp_faces, @@ -367,15 +371,16 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, * and it makes code simpler & cleaner. */ blender::Array vert_normals(verts_num, float3(0)); - for (int ml_index = 0; ml_index < loops.size(); ml_index++) { - const int mv_index = loops[ml_index].v; + for (int ml_index = 0; ml_index < corner_verts.size(); ml_index++) { + const int mv_index = corner_verts[ml_index]; copy_v3_v3(vert_normals[mv_index], items_data[mv_index].normal); } blender::bke::mesh::normals_loop_custom_set_from_verts(positions, edges, polys, - loops, + corner_verts, + corner_edges, wn_data->vert_normals, poly_normals, wn_data->sharp_faces, @@ -384,11 +389,12 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, clnors); } else { - loop_normals.reinitialize(loops.size()); + loop_normals.reinitialize(corner_verts.size()); blender::bke::mesh::normals_calc_loop(positions, edges, polys, - loops, + corner_verts, + corner_edges, loop_to_poly, wn_data->vert_normals, poly_normals, @@ -400,8 +406,8 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, nullptr, loop_normals); - for (int ml_index = 0; ml_index < loops.size(); ml_index++) { - const int item_index = loops[ml_index].v; + for (int ml_index = 0; ml_index < corner_verts.size(); ml_index++) { + const int item_index = corner_verts[ml_index]; if (!is_zero_v3(items_data[item_index].normal)) { copy_v3_v3(loop_normals[ml_index], items_data[item_index].normal); } @@ -409,7 +415,8 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, blender::bke::mesh::normals_loop_custom_set(positions, edges, polys, - loops, + corner_verts, + corner_edges, wn_data->vert_normals, poly_normals, wn_data->sharp_faces, @@ -428,7 +435,7 @@ static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *w { const blender::Span positions = wn_data->vert_positions; const blender::Span polys = wn_data->polys; - const blender::Span loops = wn_data->loops; + const blender::Span corner_verts = wn_data->corner_verts; ModePair *face_area = static_cast( MEM_malloc_arrayN(size_t(polys.size()), sizeof(*face_area), __func__)); @@ -436,7 +443,7 @@ static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *w ModePair *f_area = face_area; for (const int i : polys.index_range()) { f_area[i].val = blender::bke::mesh::poly_area_calc( - positions, loops.slice(polys[i].loopstart, polys[i].totloop)); + positions, corner_verts.slice(polys[i].loopstart, polys[i].totloop)); f_area[i].index = i; } @@ -450,17 +457,17 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData { const blender::Span positions = wn_data->vert_positions; const blender::Span polys = wn_data->polys; - const blender::Span loops = wn_data->loops; + const blender::Span corner_verts = wn_data->corner_verts; ModePair *corner_angle = static_cast( - MEM_malloc_arrayN(loops.size(), sizeof(*corner_angle), __func__)); + MEM_malloc_arrayN(corner_verts.size(), sizeof(*corner_angle), __func__)); for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; float *index_angle = static_cast( MEM_malloc_arrayN(poly.totloop, sizeof(*index_angle), __func__)); blender::bke::mesh::poly_angles_calc( - positions, loops.slice(poly.loopstart, poly.totloop), {index_angle, poly.totloop}); + positions, corner_verts.slice(poly.loopstart, poly.totloop), {index_angle, poly.totloop}); ModePair *c_angl = &corner_angle[poly.loopstart]; float *angl = index_angle; @@ -472,7 +479,7 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData MEM_freeN(index_angle); } - qsort(corner_angle, loops.size(), sizeof(*corner_angle), modepair_cmp_by_val_inverse); + qsort(corner_angle, corner_verts.size(), sizeof(*corner_angle), modepair_cmp_by_val_inverse); wn_data->mode_pair = corner_angle; apply_weights_vertex_normal(wnmd, wn_data); @@ -482,18 +489,18 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD { const blender::Span positions = wn_data->vert_positions; const blender::Span polys = wn_data->polys; - const blender::Span loops = wn_data->loops; + const blender::Span corner_verts = wn_data->corner_verts; ModePair *combined = static_cast( - MEM_malloc_arrayN(loops.size(), sizeof(*combined), __func__)); + MEM_malloc_arrayN(corner_verts.size(), sizeof(*combined), __func__)); for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; - const blender::Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - const float face_area = blender::bke::mesh::poly_area_calc(positions, poly_loops); + const blender::Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + const float face_area = blender::bke::mesh::poly_area_calc(positions, poly_verts); float *index_angle = static_cast( MEM_malloc_arrayN(size_t(poly.totloop), sizeof(*index_angle), __func__)); - blender::bke::mesh::poly_angles_calc(positions, poly_loops, {index_angle, poly.totloop}); + blender::bke::mesh::poly_angles_calc(positions, poly_verts, {index_angle, poly.totloop}); ModePair *cmbnd = &combined[poly.loopstart]; float *angl = index_angle; @@ -506,7 +513,7 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD MEM_freeN(index_angle); } - qsort(combined, loops.size(), sizeof(*combined), modepair_cmp_by_val_inverse); + qsort(combined, corner_verts.size(), sizeof(*combined), modepair_cmp_by_val_inverse); wn_data->mode_pair = combined; apply_weights_vertex_normal(wnmd, wn_data); @@ -541,7 +548,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * const blender::Span positions = mesh->vert_positions(); const blender::Span edges = mesh->edges(); const blender::Span polys = mesh->polys(); - const blender::Span loops = mesh->loops(); + const blender::Span corner_verts = mesh->corner_verts(); + const blender::Span corner_edges = mesh->corner_edges(); /* Right now: * If weight = 50 then all faces are given equal weight. @@ -568,8 +576,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * * it helps when generating clnor spaces and default normals. */ const bool has_clnors = clnors != nullptr; if (!clnors) { - clnors = static_cast( - CustomData_add_layer(&result->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, loops.size())); + clnors = static_cast(CustomData_add_layer( + &result->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, corner_verts.size())); } const MDeformVert *dvert; @@ -591,7 +599,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * wn_data.edges = edges; wn_data.sharp_edges = sharp_edges.span; - wn_data.loops = loops; + wn_data.corner_verts = corner_verts; + wn_data.corner_edges = corner_edges; wn_data.loop_to_poly = loop_to_poly_map; wn_data.clnors = clnors; wn_data.has_clnors = has_clnors; diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.cc b/source/blender/modifiers/intern/MOD_weightvgproximity.cc index 270283b0f30..3ebdb24e853 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.cc +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.cc @@ -516,12 +516,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Get our vertex coordinates. */ if (index_num != verts_num) { - float(*tv_cos)[3] = BKE_mesh_vert_coords_alloc(mesh, nullptr); + const float(*tv_cos)[3] = BKE_mesh_vert_positions(mesh); v_cos = static_cast(MEM_malloc_arrayN(index_num, sizeof(float[3]), __func__)); for (i = 0; i < index_num; i++) { copy_v3_v3(v_cos[i], tv_cos[indices[i]]); } - MEM_freeN(tv_cos); } else { v_cos = BKE_mesh_vert_coords_alloc(mesh, nullptr); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index e00c613ca54..19f02abc226 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -357,6 +357,7 @@ DefNode(GeometryNode, GEO_NODE_INSTANCES_TO_POINTS, 0, "INSTANCES_TO_POINTS",Ins DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "Retrieve whether the nodes are being evaluated for the viewport rather than the final render") DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "Merge separately generated geometries into a single one") DefNode(GeometryNode, GEO_NODE_MATERIAL_SELECTION, 0, "MATERIAL_SELECTION", MaterialSelection, "Material Selection", "Provide a selection of faces that use the specified material") +DefNode(GeometryNode, GEO_NODE_MEAN_FILTER_SDF_VOLUME, 0, "MEAN_FILTER_SDF_VOLUME", MeanFilterSDFVolume, "Mean Filter SDF Volume", "Smooth the surface of an SDF volume by applying a mean filter") DefNode(GeometryNode, GEO_NODE_MERGE_BY_DISTANCE, def_geo_merge_by_distance,"MERGE_BY_DISTANCE", MergeByDistance, "Merge by Distance", "Merge vertices or points within a given distance") DefNode(GeometryNode, GEO_NODE_MESH_BOOLEAN, def_geo_boolean, "MESH_BOOLEAN", MeshBoolean, "Mesh Boolean", "Cut, subtract, or join multiple mesh inputs") DefNode(GeometryNode, GEO_NODE_MESH_FACE_GROUP_BOUNDARIES, 0, "MESH_FACE_SET_BOUNDARIES", MeshFaceSetBoundaries, "Face Group Boundaries", "Find edges on the boundaries between groups of faces with the same ID value") @@ -370,6 +371,7 @@ DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRI DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_UV_SPHERE, 0, "MESH_PRIMITIVE_UV_SPHERE", MeshUVSphere, "UV Sphere", "Generate a spherical mesh with quads, except for triangles at the top and bottom") DefNode(GeometryNode, GEO_NODE_MESH_TO_CURVE, 0, "MESH_TO_CURVE", MeshToCurve, "Mesh to Curve", "Generate a curve from a mesh") DefNode(GeometryNode, GEO_NODE_MESH_TO_POINTS, def_geo_mesh_to_points, "MESH_TO_POINTS", MeshToPoints, "Mesh to Points", "Generate a point cloud from a mesh's vertices") +DefNode(GeometryNode, GEO_NODE_MESH_TO_SDF_VOLUME, def_geo_mesh_to_sdf_volume, "MESH_TO_SDF_VOLUME", MeshToSDFVolume, "Mesh to SDF Volume", "Create an SDF volume with the shape of the input mesh's surface") DefNode(GeometryNode, GEO_NODE_MESH_TO_VOLUME, def_geo_mesh_to_volume, "MESH_TO_VOLUME", MeshToVolume, "Mesh to Volume", "Create a fog volume with the shape of the input mesh's surface") DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_FACE, 0, "CORNERS_OF_FACE", CornersOfFace, "Corners of Face", "Retrieve corners that make up a face") DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_VERTEX, 0, "CORNERS_OF_VERTEX", CornersOfVertex, "Corners of Vertex", "Retrieve face corners connected to vertices") @@ -380,6 +382,8 @@ DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_OFFSET_CORNER_IN_FACE, 0, "OFFSET_C DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_VERTEX_OF_CORNER, 0, "VERTEX_OF_CORNER", VertexOfCorner, "Vertex of Corner", "Retrieve the vertex each face corner is attached to") DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, def_geo_object_info, "OBJECT_INFO", ObjectInfo, "Object Info", "Retrieve information from an object") DefNode(GeometryNode, GEO_NODE_OFFSET_POINT_IN_CURVE, 0, "OFFSET_POINT_IN_CURVE", OffsetPointInCurve, "Offset Point in Curve", "Offset a control point index within its curve") +DefNode(GeometryNode, GEO_NODE_OFFSET_SDF_VOLUME, 0, "OFFSET_SDF_VOLUME", OffsetSDFVolume, "Offset SDF Volume", "Move the surface of an SDF volume inwards or outwards") +DefNode(GeometryNode, GEO_NODE_POINTS_TO_SDF_VOLUME, def_geo_points_to_sdf_volume, "POINTS_TO_SDF_VOLUME", PointsToSDFVolume, "Points to SDF Volume", "Generate an SDF volume sphere around every point") DefNode(GeometryNode, GEO_NODE_POINTS_TO_VERTICES, 0, "POINTS_TO_VERTICES", PointsToVertices, "Points to Vertices", "Generate a mesh vertex for each point cloud point") DefNode(GeometryNode, GEO_NODE_POINTS_TO_VOLUME, def_geo_points_to_volume, "POINTS_TO_VOLUME", PointsToVolume, "Points to Volume", "Generate a fog volume sphere around every point") DefNode(GeometryNode, GEO_NODE_POINTS, 0, "POINTS", Points, "Points", "Generate a point cloud with positions and radii defined by fields") @@ -398,6 +402,7 @@ DefNode(GeometryNode, GEO_NODE_SAMPLE_NEAREST, def_geo_sample_nearest, "SAMPLE_N DefNode(GeometryNode, GEO_NODE_SAMPLE_UV_SURFACE, def_geo_sample_uv_surface, "SAMPLE_UV_SURFACE", SampleUVSurface, "Sample UV Surface", "Calculate the interpolated values of a mesh attribute at a UV coordinate") DefNode(GeometryNode, GEO_NODE_SCALE_ELEMENTS, def_geo_scale_elements, "SCALE_ELEMENTS", ScaleElements, "Scale Elements", "Scale groups of connected edges and faces") DefNode(GeometryNode, GEO_NODE_SCALE_INSTANCES, 0, "SCALE_INSTANCES", ScaleInstances, "Scale Instances", "Scale geometry instances in local or global space") +DefNode(GeometryNode, GEO_NODE_SDF_VOLUME_SPHERE, 0, "SDF_VOLUME_SPHERE", SDFVolumeSphere, "SDF Volume Sphere", "Generate an SDF Volume Sphere") DefNode(GeometryNode, GEO_NODE_SELF_OBJECT, 0, "SELF_OBJECT", SelfObject, "Self Object", "Retrieve the object that contains the geometry nodes modifier currently being executed") DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS",SeparateComponents, "Separate Components","Split a geometry into a separate output for each type of data in the geometry") DefNode(GeometryNode, GEO_NODE_SEPARATE_GEOMETRY, def_geo_separate_geometry,"SEPARATE_GEOMETRY", SeparateGeometry, "Separate Geometry", "Split a geometry into two geometry outputs based on a selection") diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 08947f42fbc..7346ae72e07 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -112,6 +112,7 @@ set(SRC nodes/node_geo_join_geometry.cc nodes/node_geo_material_replace.cc nodes/node_geo_material_selection.cc + nodes/node_geo_mean_filter_sdf_volume.cc nodes/node_geo_merge_by_distance.cc nodes/node_geo_mesh_face_group_boundaries.cc nodes/node_geo_mesh_primitive_circle.cc @@ -124,6 +125,7 @@ set(SRC nodes/node_geo_mesh_primitive_uv_sphere.cc nodes/node_geo_mesh_subdivide.cc nodes/node_geo_mesh_to_curve.cc + nodes/node_geo_mesh_to_sdf_volume.cc nodes/node_geo_mesh_to_points.cc nodes/node_geo_mesh_to_volume.cc nodes/node_geo_mesh_topology_corners_of_face.cc @@ -135,8 +137,10 @@ set(SRC nodes/node_geo_mesh_topology_vertex_of_corner.cc nodes/node_geo_object_info.cc nodes/node_geo_offset_point_in_curve.cc + nodes/node_geo_offset_sdf_volume.cc nodes/node_geo_points.cc nodes/node_geo_points_to_vertices.cc + nodes/node_geo_points_to_sdf_volume.cc nodes/node_geo_points_to_volume.cc nodes/node_geo_proximity.cc nodes/node_geo_raycast.cc @@ -149,6 +153,7 @@ set(SRC nodes/node_geo_sample_uv_surface.cc nodes/node_geo_scale_elements.cc nodes/node_geo_scale_instances.cc + nodes/node_geo_sdf_volume_sphere.cc nodes/node_geo_self_object.cc nodes/node_geo_separate_components.cc nodes/node_geo_separate_geometry.cc diff --git a/source/blender/nodes/geometry/node_geometry_register.cc b/source/blender/nodes/geometry/node_geometry_register.cc index a6f209db17f..202d60b5a12 100644 --- a/source/blender/nodes/geometry/node_geometry_register.cc +++ b/source/blender/nodes/geometry/node_geometry_register.cc @@ -96,6 +96,7 @@ void register_geometry_nodes() register_node_type_geo_join_geometry(); register_node_type_geo_material_replace(); register_node_type_geo_material_selection(); + register_node_type_geo_mean_filter_sdf_volume(); register_node_type_geo_merge_by_distance(); register_node_type_geo_mesh_face_group_boundaries(); register_node_type_geo_mesh_primitive_circle(); @@ -109,6 +110,7 @@ void register_geometry_nodes() register_node_type_geo_mesh_subdivide(); register_node_type_geo_mesh_to_curve(); register_node_type_geo_mesh_to_points(); + register_node_type_geo_mesh_to_sdf_volume(); register_node_type_geo_mesh_to_volume(); register_node_type_geo_mesh_topology_corners_of_face(); register_node_type_geo_mesh_topology_corners_of_vertex(); @@ -119,7 +121,9 @@ void register_geometry_nodes() register_node_type_geo_mesh_topology_vertex_of_corner(); register_node_type_geo_object_info(); register_node_type_geo_offset_point_in_curve(); + register_node_type_geo_offset_sdf_volume(); register_node_type_geo_points_to_vertices(); + register_node_type_geo_points_to_sdf_volume(); register_node_type_geo_points_to_volume(); register_node_type_geo_points(); register_node_type_geo_proximity(); @@ -133,6 +137,7 @@ void register_geometry_nodes() register_node_type_geo_sample_uv_surface(); register_node_type_geo_scale_elements(); register_node_type_geo_scale_instances(); + register_node_type_geo_sdf_volume_sphere(); register_node_type_geo_self_object(); register_node_type_geo_separate_components(); register_node_type_geo_separate_geometry(); diff --git a/source/blender/nodes/geometry/node_geometry_register.hh b/source/blender/nodes/geometry/node_geometry_register.hh index d2f1d2716c1..196b3315b70 100644 --- a/source/blender/nodes/geometry/node_geometry_register.hh +++ b/source/blender/nodes/geometry/node_geometry_register.hh @@ -94,6 +94,7 @@ void register_node_type_geo_join_geometry(); void register_node_type_geo_material_replace(); void register_node_type_geo_material_selection(); void register_node_type_geo_merge_by_distance(); +void register_node_type_geo_mean_filter_sdf_volume(); void register_node_type_geo_mesh_face_group_boundaries(); void register_node_type_geo_mesh_primitive_circle(); void register_node_type_geo_mesh_primitive_cone(); @@ -106,6 +107,7 @@ void register_node_type_geo_mesh_primitive_uv_sphere(); void register_node_type_geo_mesh_subdivide(); void register_node_type_geo_mesh_to_curve(); void register_node_type_geo_mesh_to_points(); +void register_node_type_geo_mesh_to_sdf_volume(); void register_node_type_geo_mesh_to_volume(); void register_node_type_geo_mesh_topology_corners_of_face(); void register_node_type_geo_mesh_topology_corners_of_vertex(); @@ -116,7 +118,9 @@ void register_node_type_geo_mesh_topology_offset_corner_in_face(); void register_node_type_geo_mesh_topology_vertex_of_corner(); void register_node_type_geo_object_info(); void register_node_type_geo_offset_point_in_curve(); +void register_node_type_geo_offset_sdf_volume(); void register_node_type_geo_points_to_vertices(); +void register_node_type_geo_points_to_sdf_volume(); void register_node_type_geo_points_to_volume(); void register_node_type_geo_points(); void register_node_type_geo_proximity(); @@ -130,6 +134,7 @@ void register_node_type_geo_sample_nearest(); void register_node_type_geo_sample_uv_surface(); void register_node_type_geo_scale_elements(); void register_node_type_geo_scale_instances(); +void register_node_type_geo_sdf_volume_sphere(); void register_node_type_geo_select_by_handle_type(); void register_node_type_geo_self_object(); void register_node_type_geo_separate_components(); diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 985d1bcc254..cce144a80f2 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -26,6 +26,10 @@ #include "node_geometry_register.hh" #include "node_util.h" +#ifdef WITH_OPENVDB +# include +#endif + struct BVHTreeFromMesh; void geo_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass); @@ -90,6 +94,17 @@ int apply_offset_in_cyclic_range(IndexRange range, int start_index, int offset); std::optional node_data_type_to_custom_data_type(eNodeSocketDatatype type); std::optional node_socket_to_custom_data_type(const bNodeSocket &socket); +#ifdef WITH_OPENVDB +/** + * Initializes the VolumeComponent of a GeometrySet with a new Volume from points. + * The grid class should be either openvdb::GRID_FOG_VOLUME or openvdb::GRID_LEVEL_SET. + */ +void initialize_volume_component_from_points(GeoNodeExecParams ¶ms, + const NodeGeometryPointsToVolume &storage, + GeometrySet &r_geometry_set, + openvdb::GridClass gridClass); +#endif + class FieldAtIndexInput final : public bke::GeometryFieldInput { private: Field index_field_; diff --git a/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc index 4c2a1336e02..10cc6137926 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc @@ -179,34 +179,34 @@ static Array> build_edge_to_edge_by_vert_map(const Span edges } static Array> build_face_to_edge_by_loop_map(const Span polys, - const Span loops, + const Span corner_edges, const int edges_num) { Array> map(edges_num); for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - map[loop.e].append(i); + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + map[edge].append(i); } } return map; } static Array> build_face_to_face_by_edge_map(const Span polys, - const Span loops, + const Span corner_edges, const int edges_num, const IndexMask poly_mask) { Array> map(polys.size()); - Array> faces_by_edge = build_face_to_edge_by_loop_map(polys, loops, edges_num); + Array> faces_by_edge = build_face_to_edge_by_loop_map( + polys, corner_edges, edges_num); threading::parallel_for(poly_mask.index_range(), 1024, [&](IndexRange range) { for (const int poly_i : poly_mask.slice(range)) { const MPoly &poly = polys[poly_i]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - const int edge_i = loop.e; - if (faces_by_edge[edge_i].size() > 1) { - for (const int neighbor : faces_by_edge[edge_i]) { + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + if (faces_by_edge[edge].size() > 1) { + for (const int neighbor : faces_by_edge[edge]) { if (neighbor != poly_i) { map[poly_i].append(neighbor); } @@ -235,9 +235,8 @@ static Array> create_mesh_map(const Mesh &mesh, } case ATTR_DOMAIN_FACE: { const Span polys = mesh.polys(); - const Span loops = mesh.loops(); const int edges_num = mesh.totedge; - return build_face_to_face_by_edge_map(polys, loops, edges_num, mask); + return build_face_to_face_by_edge_map(polys, mesh.corner_edges(), edges_num, mask); } case ATTR_DOMAIN_CORNER: { return {}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc index 0866074ebab..89d19905e74 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc @@ -69,7 +69,8 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span coords) /* NOTE: ConvexHull from Bullet uses a half-edge data structure * for its mesh. To convert that, each half-edge needs to be converted * to a loop and edges need to be created from that. */ - Array mloop_src(loops_num); + Array corner_verts(loops_num); + Array corner_edges(loops_num); uint edge_index = 0; MutableSpan edges = result->edges_for_write(); @@ -78,7 +79,7 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span coords) int v_to; plConvexHullGetLoop(hull, i, &v_from, &v_to); - mloop_src[i].v = uint(v_from); + corner_verts[i] = v_from; /* Add edges for ascending order loops only. */ if (v_from < v_to) { MEdge &edge = edges[edge_index]; @@ -87,8 +88,8 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span coords) /* Write edge index into both loops that have it. */ int reverse_index = plConvexHullGetReversedLoopIndex(hull, i); - mloop_src[i].e = edge_index; - mloop_src[reverse_index].e = edge_index; + corner_edges[i] = edge_index; + corner_edges[reverse_index] = edge_index; edge_index++; } } @@ -105,8 +106,9 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span coords) Array loops; int j = 0; MutableSpan polys = result->polys_for_write(); - MutableSpan mesh_loops = result->loops_for_write(); - MLoop *loop = mesh_loops.data(); + MutableSpan mesh_corner_verts = result->corner_verts_for_write(); + MutableSpan mesh_corner_edges = result->corner_edges_for_write(); + int dst_corner = 0; for (const int i : IndexRange(faces_num)) { const int len = plConvexHullGetFaceSize(hull, i); @@ -121,10 +123,9 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span coords) face.loopstart = j; face.totloop = len; for (const int k : IndexRange(len)) { - MLoop &src_loop = mloop_src[loops[k]]; - loop->v = src_loop.v; - loop->e = src_loop.e; - loop++; + mesh_corner_verts[dst_corner] = corner_verts[loops[k]]; + mesh_corner_edges[dst_corner] = corner_edges[loops[k]]; + dst_corner++; } j += len; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc index c64259a8f00..f0e6eafd662 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc @@ -83,7 +83,7 @@ static Mesh *cdt_to_mesh(const meshintersect::CDT_result &result) MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); for (const int i : IndexRange(result.vert.size())) { positions[i] = float3(float(result.vert[i].x), float(result.vert[i].y), 0.0f); @@ -97,7 +97,7 @@ static Mesh *cdt_to_mesh(const meshintersect::CDT_result &result) polys[i].loopstart = i_loop; polys[i].totloop = result.face[i].size(); for (const int j : result.face[i].index_range()) { - loops[i_loop].v = result.face[i][j]; + corner_verts[i_loop] = result.face[i][j]; i_loop++; } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc index f7279cdfe7e..d487085e0f3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc @@ -67,11 +67,11 @@ static void deform_curves(const CurvesGeometry &curves, const float4x4 curves_to_surface = math::invert(surface_to_curves); const Span surface_positions_old = surface_mesh_old.vert_positions(); - const Span surface_loops_old = surface_mesh_old.loops(); + const Span surface_corner_verts_old = surface_mesh_old.corner_verts(); const Span surface_looptris_old = surface_mesh_old.looptris(); const Span surface_positions_new = surface_mesh_new.vert_positions(); - const Span surface_loops_new = surface_mesh_new.loops(); + const Span surface_corner_verts_new = surface_mesh_new.corner_verts(); const Span surface_looptris_new = surface_mesh_new.looptris(); const OffsetIndices points_by_curve = curves.points_by_curve(); @@ -102,13 +102,13 @@ static void deform_curves(const CurvesGeometry &curves, const int corner_1_new = looptri_new.tri[1]; const int corner_2_new = looptri_new.tri[2]; - const int vert_0_old = surface_loops_old[corner_0_old].v; - const int vert_1_old = surface_loops_old[corner_1_old].v; - const int vert_2_old = surface_loops_old[corner_2_old].v; + const int vert_0_old = surface_corner_verts_old[corner_0_old]; + const int vert_1_old = surface_corner_verts_old[corner_1_old]; + const int vert_2_old = surface_corner_verts_old[corner_2_old]; - const int vert_0_new = surface_loops_new[corner_0_new].v; - const int vert_1_new = surface_loops_new[corner_1_new].v; - const int vert_2_new = surface_loops_new[corner_2_new].v; + const int vert_0_new = surface_corner_verts_new[corner_0_new]; + const int vert_1_new = surface_corner_verts_new[corner_1_new]; + const int vert_2_new = surface_corner_verts_new[corner_2_new]; const float3 &normal_0_old = corner_normals_old[corner_0_old]; const float3 &normal_1_old = corner_normals_old[corner_1_old]; diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index f89945f89ee..a4db785c644 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -206,27 +206,30 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Span new_loop_starts) { const Span src_polys = src_mesh.polys(); - const Span src_loops = src_mesh.loops(); + const Span src_corner_verts = src_mesh.corner_verts(); + const Span src_corner_edges = src_mesh.corner_edges(); MutableSpan dst_polys = dst_mesh.polys_for_write(); - MutableSpan dst_loops = dst_mesh.loops_for_write(); + MutableSpan dst_corner_verts = dst_mesh.corner_verts_for_write(); + MutableSpan dst_corner_edges = dst_mesh.corner_edges_for_write(); threading::parallel_for(masked_poly_indices.index_range(), 512, [&](const IndexRange range) { for (const int i_dst : range) { const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_polys[i_src]; + const int size = mp_src.totloop; + const Span src_poly_verts = src_corner_verts.slice(mp_src.loopstart, size); + const Span src_poly_edges = src_corner_edges.slice(mp_src.loopstart, size); + MPoly &mp_dst = dst_polys[i_dst]; - const int i_ml_src = mp_src.loopstart; - const int i_ml_dst = new_loop_starts[i_dst]; - - const MLoop *ml_src = &src_loops[i_ml_src]; - MLoop *ml_dst = &dst_loops[i_ml_dst]; - mp_dst = mp_src; - mp_dst.loopstart = i_ml_dst; - for (int i : IndexRange(mp_src.totloop)) { - ml_dst[i].v = ml_src[i].v; - ml_dst[i].e = edge_map[ml_src[i].e]; + mp_dst.loopstart = new_loop_starts[i_dst]; + MutableSpan dst_poly_verts = dst_corner_verts.slice(mp_dst.loopstart, size); + MutableSpan dst_poly_edges = dst_corner_edges.slice(mp_dst.loopstart, size); + + dst_poly_verts.copy_from(src_poly_verts); + + for (const int i : IndexRange(size)) { + dst_poly_edges[i] = edge_map[src_poly_edges[i]]; } } }); @@ -239,28 +242,28 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Span new_loop_starts) { const Span src_polys = src_mesh.polys(); - const Span src_loops = src_mesh.loops(); + const Span src_corner_verts = src_mesh.corner_verts(); + const Span src_corner_edges = src_mesh.corner_edges(); MutableSpan dst_polys = dst_mesh.polys_for_write(); - MutableSpan dst_loops = dst_mesh.loops_for_write(); + MutableSpan dst_corner_verts = dst_mesh.corner_verts_for_write(); + MutableSpan dst_corner_edges = dst_mesh.corner_edges_for_write(); threading::parallel_for(masked_poly_indices.index_range(), 512, [&](const IndexRange range) { for (const int i_dst : range) { const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_polys[i_src]; + const int size = mp_src.totloop; + const Span src_poly_verts = src_corner_verts.slice(mp_src.loopstart, size); + const Span src_poly_edges = src_corner_edges.slice(mp_src.loopstart, size); + MPoly &mp_dst = dst_polys[i_dst]; - const int i_ml_src = mp_src.loopstart; - const int i_ml_dst = new_loop_starts[i_dst]; - - const MLoop *ml_src = &src_loops[i_ml_src]; - MLoop *ml_dst = &dst_loops[i_ml_dst]; - mp_dst = mp_src; - mp_dst.loopstart = i_ml_dst; - for (int i : IndexRange(mp_src.totloop)) { - ml_dst[i].v = ml_src[i].v; - ml_dst[i].e = ml_src[i].e; - } + mp_dst.loopstart = new_loop_starts[i_dst]; + MutableSpan dst_poly_verts = dst_corner_verts.slice(mp_dst.loopstart, size); + MutableSpan dst_poly_edges = dst_corner_edges.slice(mp_dst.loopstart, size); + + dst_poly_verts.copy_from(src_poly_verts); + dst_poly_edges.copy_from(src_poly_edges); } }); } @@ -273,27 +276,31 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Span new_loop_starts) { const Span src_polys = src_mesh.polys(); - const Span src_loops = src_mesh.loops(); + const Span src_corner_verts = src_mesh.corner_verts(); + const Span src_corner_edges = src_mesh.corner_edges(); MutableSpan dst_polys = dst_mesh.polys_for_write(); - MutableSpan dst_loops = dst_mesh.loops_for_write(); + MutableSpan dst_corner_verts = dst_mesh.corner_verts_for_write(); + MutableSpan dst_corner_edges = dst_mesh.corner_edges_for_write(); threading::parallel_for(masked_poly_indices.index_range(), 512, [&](const IndexRange range) { for (const int i_dst : range) { const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_polys[i_src]; + const int size = mp_src.totloop; + const Span src_poly_verts = src_corner_verts.slice(mp_src.loopstart, size); + const Span src_poly_edges = src_corner_edges.slice(mp_src.loopstart, size); + MPoly &mp_dst = dst_polys[i_dst]; - const int i_ml_src = mp_src.loopstart; - const int i_ml_dst = new_loop_starts[i_dst]; - - const MLoop *ml_src = &src_loops[i_ml_src]; - MLoop *ml_dst = &dst_loops[i_ml_dst]; - mp_dst = mp_src; - mp_dst.loopstart = i_ml_dst; - for (int i : IndexRange(mp_src.totloop)) { - ml_dst[i].v = vertex_map[ml_src[i].v]; - ml_dst[i].e = edge_map[ml_src[i].e]; + mp_dst.loopstart = new_loop_starts[i_dst]; + MutableSpan dst_poly_verts = dst_corner_verts.slice(mp_dst.loopstart, size); + MutableSpan dst_poly_edges = dst_corner_edges.slice(mp_dst.loopstart, size); + + for (const int i : IndexRange(size)) { + dst_poly_verts[i] = vertex_map[src_poly_verts[i]]; + } + for (const int i : IndexRange(size)) { + dst_poly_edges[i] = edge_map[src_poly_edges[i]]; } } }); @@ -440,7 +447,7 @@ static void compute_selected_polys_from_vertex_selection(const Mesh &mesh, { BLI_assert(mesh.totvert == vertex_selection.size()); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); r_selected_poly_indices.reserve(mesh.totpoly); r_loop_starts.reserve(mesh.totloop); @@ -450,9 +457,8 @@ static void compute_selected_polys_from_vertex_selection(const Mesh &mesh, const MPoly &poly_src = polys[i]; bool all_verts_in_selection = true; - const Span poly_loops = loops.slice(poly_src.loopstart, poly_src.totloop); - for (const MLoop &loop : poly_loops) { - if (!vertex_selection[loop.v]) { + for (const int vert : corner_verts.slice(poly_src.loopstart, poly_src.totloop)) { + if (!vertex_selection[vert]) { all_verts_in_selection = false; break; } @@ -544,7 +550,7 @@ static void compute_selected_polys_from_edge_selection(const Mesh &mesh, int *r_selected_loops_num) { const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); r_selected_poly_indices.reserve(mesh.totpoly); r_loop_starts.reserve(mesh.totloop); @@ -554,9 +560,8 @@ static void compute_selected_polys_from_edge_selection(const Mesh &mesh, const MPoly &poly_src = polys[i]; bool all_edges_in_selection = true; - const Span poly_loops = loops.slice(poly_src.loopstart, poly_src.totloop); - for (const MLoop &loop : poly_loops) { - if (!edge_selection[loop.e]) { + for (const int edge : corner_edges.slice(poly_src.loopstart, poly_src.totloop)) { + if (!edge_selection[edge]) { all_edges_in_selection = false; break; } @@ -749,7 +754,7 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face( BLI_assert(mesh.totpoly == poly_selection.size()); BLI_assert(mesh.totedge == r_edge_map.size()); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); r_edge_map.fill(-1); @@ -767,11 +772,10 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face( selected_loops_num += poly_src.totloop; /* Add the vertices and the edges. */ - const Span poly_loops = loops.slice(poly_src.loopstart, poly_src.totloop); - for (const MLoop &loop : poly_loops) { + for (const int edge : corner_edges.slice(poly_src.loopstart, poly_src.totloop)) { /* Check first if it has not yet been added. */ - if (r_edge_map[loop.e] == -1) { - r_edge_map[loop.e] = selected_edges_num; + if (r_edge_map[edge] == -1) { + r_edge_map[edge] = selected_edges_num; selected_edges_num++; } } @@ -800,7 +804,8 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, BLI_assert(mesh.totpoly == poly_selection.size()); BLI_assert(mesh.totedge == r_edge_map.size()); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); + const Span corner_edges = mesh.corner_edges(); r_vertex_map.fill(-1); r_edge_map.fill(-1); @@ -820,15 +825,16 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, selected_loops_num += poly_src.totloop; /* Add the vertices and the edges. */ - const Span poly_loops = loops.slice(poly_src.loopstart, poly_src.totloop); - for (const MLoop &loop : poly_loops) { + for (const int corner : IndexRange(poly_src.loopstart, poly_src.totloop)) { + const int vert = corner_verts[corner]; + const int edge = corner_edges[corner]; /* Check first if it has not yet been added. */ - if (r_vertex_map[loop.v] == -1) { - r_vertex_map[loop.v] = selected_verts_num; + if (r_vertex_map[vert] == -1) { + r_vertex_map[vert] = selected_verts_num; selected_verts_num++; } - if (r_edge_map[loop.e] == -1) { - r_edge_map[loop.e] = selected_edges_num; + if (r_edge_map[edge] == -1) { + r_edge_map[edge] = selected_edges_num; selected_edges_num++; } } @@ -861,6 +867,8 @@ static void do_mesh_separation(GeometrySet &geometry_set, Map attributes; geometry_set.gather_attributes_for_propagation( {GEO_COMPONENT_TYPE_MESH}, GEO_COMPONENT_TYPE_MESH, false, propagation_info, attributes); + attributes.remove(".corner_vert"); + attributes.remove(".corner_edge"); switch (mode) { case GEO_NODE_DELETE_GEOMETRY_MODE_ALL: { diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 3ba718f211a..7344c6d29ce 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -111,7 +111,7 @@ static void sample_mesh_surface(const Mesh &mesh, Vector &r_looptri_indices) { const Span positions = mesh.vert_positions(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); const Span looptris = mesh.looptris(); for (const int looptri_index : looptris.index_range()) { @@ -119,12 +119,9 @@ static void sample_mesh_surface(const Mesh &mesh, const int v0_loop = looptri.tri[0]; const int v1_loop = looptri.tri[1]; const int v2_loop = looptri.tri[2]; - const int v0_index = loops[v0_loop].v; - const int v1_index = loops[v1_loop].v; - const int v2_index = loops[v2_loop].v; - const float3 v0_pos = positions[v0_index]; - const float3 v1_pos = positions[v1_index]; - const float3 v2_pos = positions[v2_index]; + const float3 &v0_pos = positions[corner_verts[v0_loop]]; + const float3 &v1_pos = positions[corner_verts[v1_loop]]; + const float3 &v2_pos = positions[corner_verts[v2_loop]]; float looptri_density_factor = 1.0f; if (!density_factors.is_empty()) { @@ -362,16 +359,16 @@ static void compute_legacy_normal_outputs(const Mesh &mesh, MutableSpan r_normals) { const Span positions = mesh.vert_positions(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); const Span looptris = mesh.looptris(); for (const int i : bary_coords.index_range()) { const int looptri_index = looptri_indices[i]; const MLoopTri &looptri = looptris[looptri_index]; - const int v0_index = loops[looptri.tri[0]].v; - const int v1_index = loops[looptri.tri[1]].v; - const int v2_index = loops[looptri.tri[2]].v; + const int v0_index = corner_verts[looptri.tri[0]]; + const int v1_index = corner_verts[looptri.tri[1]]; + const int v2_index = corner_verts[looptri.tri[2]]; const float3 v0_pos = positions[v0_index]; const float3 v1_pos = positions[v1_index]; const float3 v2_pos = positions[v2_index]; diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index 207e30992ef..44f20cbe2be 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -140,6 +140,8 @@ static void transfer_attributes( * Remove anonymous attributes that don't need to be propagated. */ Set attribute_ids = src_attributes.all_ids(); attribute_ids.remove("position"); + attribute_ids.remove(".corner_vert"); + attribute_ids.remove(".corner_edge"); attribute_ids.remove("sharp_face"); attribute_ids.remove_if([&](const AttributeIDRef &id) { return id.is_anonymous() && !propagation_info.propagate(id.anonymous_id()); @@ -209,7 +211,7 @@ static void calc_boundaries(const Mesh &mesh, BLI_assert(r_edge_types.size() == mesh.totedge); const Span edges = mesh.edges(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); r_vertex_types.fill(VertexType::Loose); r_edge_types.fill(EdgeType::Loose); @@ -217,9 +219,8 @@ static void calc_boundaries(const Mesh &mesh, /* Add up the number of polys connected to each edge. */ for (const int i : IndexRange(mesh.totpoly)) { const MPoly &poly = polys[i]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - for (const MLoop &loop : poly_loops) { - r_edge_types[loop.e] = get_edge_type_with_added_neighbor(r_edge_types[loop.e]); + for (const int edge_i : corner_edges.slice(poly.loopstart, poly.totloop)) { + r_edge_types[edge_i] = get_edge_type_with_added_neighbor(r_edge_types[edge_i]); } } @@ -312,7 +313,8 @@ static void calc_boundaries(const Mesh &mesh, */ static bool sort_vertex_polys(const Span edges, const Span polys, - const Span loops, + const Span corner_verts, + const Span corner_edges, const int vertex_index, const bool boundary_vertex, const Span edge_types, @@ -329,15 +331,15 @@ static bool sort_vertex_polys(const Span edges, for (const int i : connected_polys.index_range()) { const MPoly &poly = polys[connected_polys[i]]; bool first_edge_done = false; - for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = loops[loop_index]; - if (edges[loop.e].v1 == vertex_index || edges[loop.e].v2 == vertex_index) { + for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + const int edge = corner_edges[corner]; + if (edges[edge].v1 == vertex_index || edges[edge].v2 == vertex_index) { if (!first_edge_done) { - poly_vertex_corners[i].first = loop_index; + poly_vertex_corners[i].first = corner; first_edge_done = true; } else { - poly_vertex_corners[i].second = loop_index; + poly_vertex_corners[i].second = corner; break; } } @@ -351,17 +353,19 @@ static bool sort_vertex_polys(const Span edges, if (boundary_vertex) { /* Our first polygon needs to be one which has a boundary edge. */ for (const int i : connected_polys.index_range()) { - const MLoop &first_loop = loops[poly_vertex_corners[i].first]; - const MLoop &second_loop = loops[poly_vertex_corners[i].second]; - if (edge_types[first_loop.e] == EdgeType::Boundary && first_loop.v == vertex_index) { - shared_edge_i = second_loop.e; + const int corner_1 = poly_vertex_corners[i].first; + const int corner_2 = poly_vertex_corners[i].second; + if (edge_types[corner_edges[corner_1]] == EdgeType::Boundary && + corner_verts[corner_1] == vertex_index) { + shared_edge_i = corner_edges[corner_2]; r_sorted_corners[0] = poly_vertex_corners[i].first; std::swap(connected_polys[i], connected_polys[0]); std::swap(poly_vertex_corners[i], poly_vertex_corners[0]); break; } - if (edge_types[second_loop.e] == EdgeType::Boundary && second_loop.v == vertex_index) { - shared_edge_i = first_loop.e; + if (edge_types[corner_edges[corner_2]] == EdgeType::Boundary && + corner_verts[corner_2] == vertex_index) { + shared_edge_i = corner_edges[corner_1]; r_sorted_corners[0] = poly_vertex_corners[i].second; std::swap(connected_polys[i], connected_polys[0]); std::swap(poly_vertex_corners[i], poly_vertex_corners[0]); @@ -372,17 +376,17 @@ static bool sort_vertex_polys(const Span edges, /* The rotation is inconsistent between the two polygons on the boundary. Just choose one * of the polygon's orientation. */ for (const int i : connected_polys.index_range()) { - const MLoop &first_loop = loops[poly_vertex_corners[i].first]; - const MLoop &second_loop = loops[poly_vertex_corners[i].second]; - if (edge_types[first_loop.e] == EdgeType::Boundary) { - shared_edge_i = second_loop.e; + const int corner_1 = poly_vertex_corners[i].first; + const int corner_2 = poly_vertex_corners[i].second; + if (edge_types[corner_edges[corner_1]] == EdgeType::Boundary) { + shared_edge_i = corner_edges[corner_2]; r_sorted_corners[0] = poly_vertex_corners[i].first; std::swap(connected_polys[i], connected_polys[0]); std::swap(poly_vertex_corners[i], poly_vertex_corners[0]); break; } - if (edge_types[second_loop.e] == EdgeType::Boundary) { - shared_edge_i = first_loop.e; + if (edge_types[corner_edges[corner_2]] == EdgeType::Boundary) { + shared_edge_i = corner_edges[corner_1]; r_sorted_corners[0] = poly_vertex_corners[i].second; std::swap(connected_polys[i], connected_polys[0]); std::swap(poly_vertex_corners[i], poly_vertex_corners[0]); @@ -393,15 +397,15 @@ static bool sort_vertex_polys(const Span edges, } else { /* Any polygon can be the first. Just need to check the orientation. */ - const MLoop &first_loop = loops[poly_vertex_corners[0].first]; - const MLoop &second_loop = loops[poly_vertex_corners[0].second]; - if (first_loop.v == vertex_index) { - shared_edge_i = second_loop.e; + const int corner_1 = poly_vertex_corners.first().first; + const int corner_2 = poly_vertex_corners.first().second; + if (corner_verts[corner_1] == vertex_index) { + shared_edge_i = corner_edges[corner_2]; r_sorted_corners[0] = poly_vertex_corners[0].first; } else { r_sorted_corners[0] = poly_vertex_corners[0].second; - shared_edge_i = first_loop.e; + shared_edge_i = corner_edges[corner_1]; } } BLI_assert(shared_edge_i != -1); @@ -412,16 +416,17 @@ static bool sort_vertex_polys(const Span edges, /* Look at the other polys to see if it has this shared edge. */ int j = i + 1; for (; j < connected_polys.size(); ++j) { - const MLoop &first_loop = loops[poly_vertex_corners[j].first]; - const MLoop &second_loop = loops[poly_vertex_corners[j].second]; - if (first_loop.e == shared_edge_i) { + const int corner_1 = poly_vertex_corners[j].first; + const int corner_2 = poly_vertex_corners[j].second; + + if (corner_edges[corner_1] == shared_edge_i) { r_sorted_corners[i + 1] = poly_vertex_corners[j].first; - shared_edge_i = second_loop.e; + shared_edge_i = corner_edges[corner_2]; break; } - if (second_loop.e == shared_edge_i) { + if (corner_edges[corner_2] == shared_edge_i) { r_sorted_corners[i + 1] = poly_vertex_corners[j].second; - shared_edge_i = first_loop.e; + shared_edge_i = corner_edges[corner_1]; break; } } @@ -447,17 +452,16 @@ static bool sort_vertex_polys(const Span edges, */ static void boundary_edge_on_poly(const MPoly &poly, const Span edges, - const Span loops, + const Span corner_edges, const int vertex_index, const Span edge_types, int &r_edge) { - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - for (const MLoop &loop : poly_loops) { - if (edge_types[loop.e] == EdgeType::Boundary) { - const MEdge &edge = edges[loop.e]; + for (const int edge_i : corner_edges.slice(poly.loopstart, poly.totloop)) { + if (edge_types[edge_i] == EdgeType::Boundary) { + const MEdge &edge = edges[edge_i]; if (edge.v1 == vertex_index || edge.v2 == vertex_index) { - r_edge = loop.e; + r_edge = edge_i; return; } } @@ -470,7 +474,8 @@ static void boundary_edge_on_poly(const MPoly &poly, */ static void boundary_edges_on_poly(const MPoly &poly, const Span edges, - const Span loops, + const Span corner_verts, + const Span corner_edges, const int vertex_index, const Span edge_types, int &r_edge1, @@ -480,24 +485,24 @@ static void boundary_edges_on_poly(const MPoly &poly, /* This is set to true if the order in which we encounter the two edges is inconsistent with the * orientation of the polygon. */ bool needs_swap = false; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - for (const MLoop &loop : poly_loops) { - if (edge_types[loop.e] == EdgeType::Boundary) { - const MEdge &edge = edges[loop.e]; + for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + const int edge_i = corner_edges[corner]; + if (edge_types[edge_i] == EdgeType::Boundary) { + const MEdge &edge = edges[edge_i]; if (edge.v1 == vertex_index || edge.v2 == vertex_index) { if (edge1_done) { if (needs_swap) { r_edge2 = r_edge1; - r_edge1 = loop.e; + r_edge1 = edge_i; } else { - r_edge2 = loop.e; + r_edge2 = edge_i; } return; } - r_edge1 = loop.e; + r_edge1 = edge_i; edge1_done = true; - if (loop.v == vertex_index) { + if (corner_verts[corner] == vertex_index) { needs_swap = true; } } @@ -545,7 +550,7 @@ static bool vertex_needs_dissolving(const int vertex, */ static void dissolve_redundant_verts(const Span edges, const Span polys, - const Span loops, + const Span corner_edges, const Span> vert_to_poly_map, MutableSpan vertex_types, MutableSpan old_to_new_edges_map, @@ -562,9 +567,8 @@ static void dissolve_redundant_verts(const Span edges, const int new_edge_index = new_edges.size(); bool edge_created = false; const MPoly &poly = polys[first_poly_index]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - for (const MLoop &loop : poly_loops) { - const MEdge &edge = edges[loop.e]; + for (const int edge_i : corner_edges.slice(poly.loopstart, poly.totloop)) { + const MEdge &edge = edges[edge_i]; const int v1 = edge.v1; const int v2 = edge.v2; bool mark_edge = false; @@ -586,11 +590,11 @@ static void dissolve_redundant_verts(const Span edges, /* The vertex indices in the dual mesh are the polygon indices of the input mesh. */ new_edge.v1 = first_poly_index; new_edge.v2 = second_poly_index; - new_to_old_edges_map.append(loop.e); + new_to_old_edges_map.append(edge_i); new_edges.append(new_edge); edge_created = true; } - old_to_new_edges_map[loop.e] = new_edge_index; + old_to_new_edges_map[edge_i] = new_edge_index; } } } @@ -617,7 +621,8 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, const Span src_positions = src_mesh.vert_positions(); const Span src_edges = src_mesh.edges(); const Span src_polys = src_mesh.polys(); - const Span src_loops = src_mesh.loops(); + const Span src_corner_verts = src_mesh.corner_verts(); + const Span src_corner_edges = src_mesh.corner_edges(); Array vertex_types(src_mesh.totvert); Array edge_types(src_mesh.totedge); @@ -626,7 +631,7 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, * over in order of their indices, the polygon's indices will be sorted in ascending order. * (This can change once they are sorted using `sort_vertex_polys`). */ Array> vert_to_poly_map = bke::mesh_topology::build_vert_to_poly_map( - src_polys, src_loops, src_positions.size()); + src_polys, src_corner_verts, src_positions.size()); Array> vertex_shared_edges(src_mesh.totvert); Array> vertex_corners(src_mesh.totvert); threading::parallel_for(vert_to_poly_map.index_range(), 512, [&](IndexRange range) { @@ -643,7 +648,8 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, Array shared_edges(loop_indices.size()); vertex_ok = sort_vertex_polys(src_edges, src_polys, - src_loops, + src_corner_verts, + src_corner_edges, i, false, edge_types, @@ -656,7 +662,8 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, Array shared_edges(loop_indices.size() - 1); vertex_ok = sort_vertex_polys(src_edges, src_polys, - src_loops, + src_corner_verts, + src_corner_edges, i, true, edge_types, @@ -678,8 +685,8 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, Vector vert_positions(src_mesh.totpoly); for (const int i : src_polys.index_range()) { const MPoly &poly = src_polys[i]; - vert_positions[i] = bke::mesh::poly_center_calc(src_positions, - src_loops.slice(poly.loopstart, poly.totloop)); + vert_positions[i] = bke::mesh::poly_center_calc( + src_positions, src_corner_verts.slice(poly.loopstart, poly.totloop)); } Array boundary_edge_midpoint_index; @@ -718,7 +725,7 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, * anything for most meshes. */ dissolve_redundant_verts(src_edges, src_polys, - src_loops, + src_corner_edges, vert_to_poly_map, vertex_types, old_to_new_edges_map, @@ -808,14 +815,20 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, if (loop_indices.size() >= 2) { /* The first boundary edge is at the end of the chain of polygons. */ boundary_edge_on_poly( - src_polys[loop_indices.last()], src_edges, src_loops, i, edge_types, edge1); + src_polys[loop_indices.last()], src_edges, src_corner_edges, i, edge_types, edge1); boundary_edge_on_poly( - src_polys[loop_indices.first()], src_edges, src_loops, i, edge_types, edge2); + src_polys[loop_indices.first()], src_edges, src_corner_edges, i, edge_types, edge2); } else { /* If there is only one polygon both edges are in that polygon. */ - boundary_edges_on_poly( - src_polys[loop_indices[0]], src_edges, src_loops, i, edge_types, edge1, edge2); + boundary_edges_on_poly(src_polys[loop_indices[0]], + src_edges, + src_corner_verts, + src_corner_edges, + i, + edge_types, + edge1, + edge2); } const int last_face_center = loop_indices.last(); @@ -900,7 +913,6 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, mesh_out->vert_positions_for_write().copy_from(vert_positions); MutableSpan dst_edges = mesh_out->edges_for_write(); MutableSpan dst_polys = mesh_out->polys_for_write(); - MutableSpan dst_loops = mesh_out->loops_for_write(); int loop_start = 0; for (const int i : IndexRange(mesh_out->totpoly)) { @@ -908,10 +920,9 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, dst_polys[i].totloop = loop_lengths[i]; loop_start += loop_lengths[i]; } - for (const int i : IndexRange(mesh_out->totloop)) { - dst_loops[i].v = loops[i]; - dst_loops[i].e = loop_edges[i]; - } + mesh_out->corner_verts_for_write().copy_from(loops); + mesh_out->corner_edges_for_write().copy_from(loop_edges); + dst_edges.copy_from(new_edges); return mesh_out; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index d2efdbbddcc..caac413e797 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -389,8 +389,12 @@ static void copy_face_attributes_without_id( const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes) { - for (auto &attribute : bke::retrieve_attributes_for_transfer( - src_attributes, dst_attributes, ATTR_DOMAIN_MASK_ALL, propagation_info, {"id"})) { + for (auto &attribute : + bke::retrieve_attributes_for_transfer(src_attributes, + dst_attributes, + ATTR_DOMAIN_MASK_ALL, + propagation_info, + {"id", ".corner_vert", ".corner_edge"})) { attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); const Span src = attribute.src.typed(); @@ -484,7 +488,8 @@ static void duplicate_faces(GeometrySet &geometry_set, const Mesh &mesh = *geometry_set.get_mesh_for_read(); const Span edges = mesh.edges(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); + const Span corner_edges = mesh.corner_edges(); bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_FACE}; FieldEvaluator evaluator(field_context, polys.size()); @@ -510,11 +515,12 @@ static void duplicate_faces(GeometrySet &geometry_set, Mesh *new_mesh = BKE_mesh_new_nomain(total_loops, total_loops, total_loops, total_polys); MutableSpan new_edges = new_mesh->edges_for_write(); MutableSpan new_polys = new_mesh->polys_for_write(); - MutableSpan new_loops = new_mesh->loops_for_write(); + MutableSpan new_corner_verts = new_mesh->corner_verts_for_write(); + MutableSpan new_corner_edges = new_mesh->corner_edges_for_write(); Array vert_mapping(new_mesh->totvert); Array edge_mapping(new_edges.size()); - Array loop_mapping(new_loops.size()); + Array loop_mapping(total_loops); int poly_index = 0; int loop_index = 0; @@ -526,11 +532,11 @@ static void duplicate_faces(GeometrySet &geometry_set, new_polys[poly_index] = source; new_polys[poly_index].loopstart = loop_index; for (const int i_loops : IndexRange(source.totloop)) { - const MLoop ¤t_loop = loops[source.loopstart + i_loops]; - loop_mapping[loop_index] = source.loopstart + i_loops; - vert_mapping[loop_index] = current_loop.v; - new_edges[loop_index] = edges[current_loop.e]; - edge_mapping[loop_index] = current_loop.e; + const int src_corner = source.loopstart + i_loops; + loop_mapping[loop_index] = src_corner; + vert_mapping[loop_index] = corner_verts[src_corner]; + new_edges[loop_index] = edges[corner_edges[src_corner]]; + edge_mapping[loop_index] = corner_edges[src_corner]; new_edges[loop_index].v1 = loop_index; if (i_loops + 1 != source.totloop) { new_edges[loop_index].v2 = loop_index + 1; @@ -538,8 +544,8 @@ static void duplicate_faces(GeometrySet &geometry_set, else { new_edges[loop_index].v2 = new_polys[poly_index].loopstart; } - new_loops[loop_index].v = loop_index; - new_loops[loop_index].e = loop_index; + new_corner_verts[loop_index] = loop_index; + new_corner_edges[loop_index] = loop_index; loop_index++; } poly_index++; diff --git a/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc b/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc index cc27c4e9fe3..7d6b55a3085 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc @@ -53,10 +53,9 @@ class FaceSetFromBoundariesInput final : public bke::MeshFieldInput { const IndexMask non_boundary_edges = evaluator.get_evaluated_as_mask(0); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); const Array> edge_to_face_map = bke::mesh_topology::build_edge_to_poly_map( - polys, loops, mesh.totedge); + polys, mesh.corner_edges(), mesh.totedge); AtomicDisjointSet islands(polys.size()); for (const int edge : non_boundary_edges) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index c1afbf2a0fa..71c3ecbee37 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -230,6 +230,9 @@ static void extrude_mesh_vertices(Mesh &mesh, if (!ELEM(meta_data.domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE)) { return true; } + if (ELEM(id.name(), ".corner_vert", ".corner_edge")) { + return true; + } if (meta_data.data_type == CD_PROP_STRING) { return true; } @@ -287,8 +290,10 @@ static void extrude_mesh_vertices(Mesh &mesh, BKE_mesh_runtime_clear_cache(&mesh); } -static void fill_quad_consistent_direction(Span other_poly_loops, - MutableSpan new_loops, +static void fill_quad_consistent_direction(const Span other_poly_verts, + const Span other_poly_edges, + MutableSpan new_corner_verts, + MutableSpan new_corner_edges, const int vert_connected_to_poly_1, const int vert_connected_to_poly_2, const int vert_across_from_poly_1, @@ -300,31 +305,31 @@ static void fill_quad_consistent_direction(Span other_poly_loops, { /* Find the loop on the polygon connected to the new quad that uses the duplicate edge. */ bool start_with_connecting_edge = true; - for (const MLoop &loop : other_poly_loops) { - if (loop.e == edge_connected_to_poly) { - start_with_connecting_edge = loop.v == vert_connected_to_poly_1; + for (const int i : other_poly_edges.index_range()) { + if (other_poly_edges[i] == edge_connected_to_poly) { + start_with_connecting_edge = other_poly_verts[i] == vert_connected_to_poly_1; break; } } if (start_with_connecting_edge) { - new_loops[0].v = vert_connected_to_poly_1; - new_loops[0].e = connecting_edge_1; - new_loops[1].v = vert_across_from_poly_1; - new_loops[1].e = edge_across_from_poly; - new_loops[2].v = vert_across_from_poly_2; - new_loops[2].e = connecting_edge_2; - new_loops[3].v = vert_connected_to_poly_2; - new_loops[3].e = edge_connected_to_poly; + new_corner_verts[0] = vert_connected_to_poly_1; + new_corner_edges[0] = connecting_edge_1; + new_corner_verts[1] = vert_across_from_poly_1; + new_corner_edges[1] = edge_across_from_poly; + new_corner_verts[2] = vert_across_from_poly_2; + new_corner_edges[2] = connecting_edge_2; + new_corner_verts[3] = vert_connected_to_poly_2; + new_corner_edges[3] = edge_connected_to_poly; } else { - new_loops[0].v = vert_connected_to_poly_1; - new_loops[0].e = edge_connected_to_poly; - new_loops[1].v = vert_connected_to_poly_2; - new_loops[1].e = connecting_edge_2; - new_loops[2].v = vert_across_from_poly_2; - new_loops[2].e = edge_across_from_poly; - new_loops[3].v = vert_across_from_poly_1; - new_loops[3].e = connecting_edge_1; + new_corner_verts[0] = vert_connected_to_poly_1; + new_corner_edges[0] = edge_connected_to_poly; + new_corner_verts[1] = vert_connected_to_poly_2; + new_corner_edges[1] = connecting_edge_2; + new_corner_verts[2] = vert_across_from_poly_2; + new_corner_edges[2] = edge_across_from_poly; + new_corner_verts[3] = vert_across_from_poly_1; + new_corner_edges[3] = connecting_edge_1; } } @@ -366,7 +371,7 @@ static void extrude_mesh_edges(Mesh &mesh, } const Array> edge_to_poly_map = bke::mesh_topology::build_edge_to_poly_map( - orig_polys, mesh.loops(), mesh.totedge); + orig_polys, mesh.corner_edges(), mesh.totedge); /* Find the offsets on the vertex domain for translation. This must be done before the mesh's * custom data layers are reallocated, in case the virtual array references one of them. */ @@ -406,8 +411,10 @@ static void extrude_mesh_edges(Mesh &mesh, MutableSpan duplicate_edges = edges.slice(duplicate_edge_range); MutableSpan polys = mesh.polys_for_write(); MutableSpan new_polys = polys.slice(new_poly_range); - MutableSpan loops = mesh.loops_for_write(); - MutableSpan new_loops = loops.slice(new_loop_range); + MutableSpan corner_verts = mesh.corner_verts_for_write(); + MutableSpan new_corner_verts = corner_verts.slice(new_loop_range); + MutableSpan corner_edges = mesh.corner_edges_for_write(); + MutableSpan new_corner_edges = corner_edges.slice(new_loop_range); for (const int i : connect_edges.index_range()) { connect_edges[i] = new_edge(new_vert_indices[i], new_vert_range[i]); @@ -438,13 +445,17 @@ static void extrude_mesh_edges(Mesh &mesh, /* When there was a single polygon connected to the new polygon, we can use the old one to keep * the face direction consistent. When there is more than one connected edge, the new face * direction is totally arbitrary and the only goal for the behavior is to be deterministic. */ - Span connected_poly_loops = {}; + Span connected_poly_verts = {}; + Span connected_poly_edges = {}; if (connected_polys.size() == 1) { const MPoly &connected_poly = polys[connected_polys.first()]; - connected_poly_loops = loops.slice(connected_poly.loopstart, connected_poly.totloop); + connected_poly_verts = corner_verts.slice(connected_poly.loopstart, connected_poly.totloop); + connected_poly_edges = corner_edges.slice(connected_poly.loopstart, connected_poly.totloop); } - fill_quad_consistent_direction(connected_poly_loops, - new_loops.slice(4 * i, 4), + fill_quad_consistent_direction(connected_poly_verts, + connected_poly_edges, + new_corner_verts.slice(4 * i, 4), + new_corner_edges.slice(4 * i, 4), new_vert_indices[extrude_index_1], new_vert_indices[extrude_index_2], new_vert_1, @@ -467,6 +478,9 @@ static void extrude_mesh_edges(Mesh &mesh, if (meta_data.data_type == CD_PROP_STRING) { return true; } + if (ELEM(id.name(), ".corner_vert", ".corner_edge")) { + return true; + } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); @@ -534,11 +548,10 @@ static void extrude_mesh_edges(Mesh &mesh, const MPoly &connected_poly = polys[connected_polys[i_connected_poly]]; for (const int i_loop : IndexRange(connected_poly.loopstart, connected_poly.totloop)) { - const MLoop &loop = loops[i_loop]; - if (loop.v == orig_vert_1) { + if (corner_verts[i_loop] == orig_vert_1) { mixer.mix_in(0, data[i_loop]); } - if (loop.v == orig_vert_2) { + if (corner_verts[i_loop] == orig_vert_2) { mixer.mix_in(1, data[i_loop]); } } @@ -550,10 +563,10 @@ static void extrude_mesh_edges(Mesh &mesh, * simpler (though probably slower) to just match the corner data based on the vertex * indices. */ for (const int i : IndexRange(4 * i_edge_selection, 4)) { - if (ELEM(new_loops[i].v, new_vert_1, orig_vert_1)) { + if (ELEM(new_corner_verts[i], new_vert_1, orig_vert_1)) { new_data[i] = side_poly_corner_data.first(); } - else if (ELEM(new_loops[i].v, new_vert_2, orig_vert_2)) { + else if (ELEM(new_corner_verts[i], new_vert_2, orig_vert_2)) { new_data[i] = side_poly_corner_data.last(); } } @@ -629,7 +642,7 @@ static void extrude_mesh_face_regions(Mesh &mesh, const int orig_vert_size = mesh.totvert; const Span orig_edges = mesh.edges(); const Span orig_polys = mesh.polys(); - const Span orig_loops = mesh.loops(); + const Span orig_corner_verts = mesh.corner_verts(); const bke::MeshFieldContext poly_context{mesh, ATTR_DOMAIN_FACE}; FieldEvaluator poly_evaluator{poly_context, mesh.totpoly}; @@ -657,8 +670,8 @@ static void extrude_mesh_face_regions(Mesh &mesh, for (const int i_poly : poly_selection) { const MPoly &poly = orig_polys[i_poly]; const float3 offset = poly_offsets[i_poly]; - for (const MLoop &loop : orig_loops.slice(poly.loopstart, poly.totloop)) { - mixer.mix_in(loop.v, offset); + for (const int vert : orig_corner_verts.slice(poly.loopstart, poly.totloop)) { + mixer.mix_in(vert, offset); } } mixer.finalize(); @@ -666,7 +679,7 @@ static void extrude_mesh_face_regions(Mesh &mesh, /* All of the faces (selected and deselected) connected to each edge. */ const Array> edge_to_poly_map = bke::mesh_topology::build_edge_to_poly_map( - orig_polys, orig_loops, orig_edges.size()); + orig_polys, mesh.corner_edges(), orig_edges.size()); /* All vertices that are connected to the selected polygons. * Start the size at one vert per poly to reduce unnecessary reallocation. */ @@ -674,8 +687,8 @@ static void extrude_mesh_face_regions(Mesh &mesh, all_selected_verts.reserve(orig_polys.size()); for (const int i_poly : poly_selection) { const MPoly &poly = orig_polys[i_poly]; - for (const MLoop &loop : orig_loops.slice(poly.loopstart, poly.totloop)) { - all_selected_verts.add(loop.v); + for (const int vert : orig_corner_verts.slice(poly.loopstart, poly.totloop)) { + all_selected_verts.add(vert); } } @@ -749,7 +762,7 @@ static void extrude_mesh_face_regions(Mesh &mesh, /* Each edge selected for extrusion is extruded into a single face. */ const IndexRange side_poly_range{orig_polys.size(), boundary_edge_indices.size()}; /* The loops that form the new side faces. */ - const IndexRange side_loop_range{orig_loops.size(), side_poly_range.size() * 4}; + const IndexRange side_loop_range{orig_corner_verts.size(), side_poly_range.size() * 4}; expand_mesh(mesh, new_vert_range.size(), @@ -763,8 +776,10 @@ static void extrude_mesh_face_regions(Mesh &mesh, MutableSpan new_inner_edges = edges.slice(new_inner_edge_range); MutableSpan polys = mesh.polys_for_write(); MutableSpan new_polys = polys.slice(side_poly_range); - MutableSpan loops = mesh.loops_for_write(); - MutableSpan new_loops = loops.slice(side_loop_range); + MutableSpan corner_verts = mesh.corner_verts_for_write(); + MutableSpan new_corner_verts = corner_verts.slice(side_loop_range); + MutableSpan corner_edges = mesh.corner_edges_for_write(); + MutableSpan new_corner_edges = corner_edges.slice(side_loop_range); /* Initialize the edges that form the sides of the extrusion. */ for (const int i : connect_edges.index_range()) { @@ -808,20 +823,20 @@ static void extrude_mesh_face_regions(Mesh &mesh, /* Connect the selected faces to the extruded or duplicated edges and the new vertices. */ for (const int i_poly : poly_selection) { const MPoly &poly = polys[i_poly]; - for (MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - const int i_new_vert = new_vert_indices.index_of_try(loop.v); + for (const int corner : IndexRange(poly.loopstart, poly.totloop)) { + const int i_new_vert = new_vert_indices.index_of_try(corner_verts[corner]); if (i_new_vert != -1) { - loop.v = new_vert_range[i_new_vert]; + corner_verts[corner] = new_vert_range[i_new_vert]; } - const int i_boundary_edge = boundary_edge_indices.index_of_try(loop.e); + const int i_boundary_edge = boundary_edge_indices.index_of_try(corner_edges[corner]); if (i_boundary_edge != -1) { - loop.e = boundary_edge_range[i_boundary_edge]; + corner_edges[corner] = boundary_edge_range[i_boundary_edge]; /* Skip the next check, an edge cannot be both a boundary edge and an inner edge. */ continue; } - const int i_new_inner_edge = new_inner_edge_indices.index_of_try(loop.e); + const int i_new_inner_edge = new_inner_edge_indices.index_of_try(corner_edges[corner]); if (i_new_inner_edge != -1) { - loop.e = new_inner_edge_range[i_new_inner_edge]; + corner_edges[corner] = new_inner_edge_range[i_new_inner_edge]; } } } @@ -836,16 +851,19 @@ static void extrude_mesh_face_regions(Mesh &mesh, const MPoly &extrude_poly = polys[edge_extruded_face_indices[i]]; - fill_quad_consistent_direction(loops.slice(extrude_poly.loopstart, extrude_poly.totloop), - new_loops.slice(4 * i, 4), - new_vert_1, - new_vert_2, - new_vert_indices[extrude_index_1], - new_vert_indices[extrude_index_2], - boundary_edge_range[i], - connect_edge_range[extrude_index_1], - boundary_edge_indices[i], - connect_edge_range[extrude_index_2]); + fill_quad_consistent_direction( + corner_verts.slice(extrude_poly.loopstart, extrude_poly.totloop), + corner_edges.slice(extrude_poly.loopstart, extrude_poly.totloop), + new_corner_verts.slice(4 * i, 4), + new_corner_edges.slice(4 * i, 4), + new_vert_1, + new_vert_2, + new_vert_indices[extrude_index_1], + new_vert_indices[extrude_index_2], + boundary_edge_range[i], + connect_edge_range[extrude_index_1], + boundary_edge_indices[i], + connect_edge_range[extrude_index_2]); } /* Create a map of indices in the extruded vertices array to all of the indices of edges @@ -860,6 +878,9 @@ static void extrude_mesh_face_regions(Mesh &mesh, if (meta_data.data_type == CD_PROP_STRING) { return true; } + if (ELEM(id.name(), ".corner_vert", ".corner_edge")) { + return true; + } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); @@ -918,10 +939,10 @@ static void extrude_mesh_face_regions(Mesh &mesh, T data_1; T data_2; for (const int i_loop : IndexRange(poly.loopstart, poly.totloop)) { - if (loops[i_loop].v == new_vert_1) { + if (corner_verts[i_loop] == new_vert_1) { data_1 = data[i_loop]; } - if (loops[i_loop].v == new_vert_2) { + if (corner_verts[i_loop] == new_vert_2) { data_2 = data[i_loop]; } } @@ -930,10 +951,10 @@ static void extrude_mesh_face_regions(Mesh &mesh, * simpler (though probably slower) to just match the corner data based on the * vertex indices. */ for (const int i : IndexRange(4 * i_boundary_edge, 4)) { - if (ELEM(new_loops[i].v, new_vert_1, orig_vert_1)) { + if (ELEM(new_corner_verts[i], new_vert_1, orig_vert_1)) { new_data[i] = data_1; } - else if (ELEM(new_loops[i].v, new_vert_2, orig_vert_2)) { + else if (ELEM(new_corner_verts[i], new_vert_2, orig_vert_2)) { new_data[i] = data_2; } } @@ -1038,7 +1059,7 @@ static void extrude_individual_mesh_faces(Mesh &mesh, const int orig_vert_size = mesh.totvert; const int orig_edge_size = mesh.totedge; const Span orig_polys = mesh.polys(); - const Span orig_loops = mesh.loops(); + const Span orig_corner_verts = mesh.corner_verts(); /* Use a mesh for the result of the evaluation because the mesh is reallocated before * the vertices are moved, and the evaluated result might reference an attribute. */ @@ -1069,7 +1090,7 @@ static void extrude_individual_mesh_faces(Mesh &mesh, const IndexRange duplicate_edge_range = connect_edge_range.after(extrude_corner_size); /* Each edge selected for extrusion is extruded into a single face. */ const IndexRange side_poly_range{orig_polys.size(), duplicate_edge_range.size()}; - const IndexRange side_loop_range{orig_loops.size(), side_poly_range.size() * 4}; + const IndexRange side_loop_range{orig_corner_verts.size(), side_poly_range.size() * 4}; expand_mesh(mesh, new_vert_range.size(), @@ -1083,7 +1104,8 @@ static void extrude_individual_mesh_faces(Mesh &mesh, MutableSpan duplicate_edges = edges.slice(duplicate_edge_range); MutableSpan polys = mesh.polys_for_write(); MutableSpan new_polys = polys.slice(side_poly_range); - MutableSpan loops = mesh.loops_for_write(); + MutableSpan corner_verts = mesh.corner_verts_for_write(); + MutableSpan corner_edges = mesh.corner_edges_for_write(); /* For every selected polygon, change it to use the new extruded vertices and the duplicate * edges, and build the faces that form the sides of the extrusion. Build "original index" @@ -1098,15 +1120,16 @@ static void extrude_individual_mesh_faces(Mesh &mesh, const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection); const MPoly &poly = polys[poly_selection[i_selection]]; - MutableSpan poly_loops = loops.slice(poly.loopstart, poly.totloop); + MutableSpan poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + MutableSpan poly_edges = corner_edges.slice(poly.loopstart, poly.totloop); for (const int i : IndexRange(poly.totloop)) { const int i_extrude = extrude_range[i]; - new_vert_indices[i_extrude] = poly_loops[i].v; - duplicate_edge_indices[i_extrude] = poly_loops[i].e; + new_vert_indices[i_extrude] = poly_verts[i]; + duplicate_edge_indices[i_extrude] = poly_edges[i]; - poly_loops[i].v = new_vert_range[i_extrude]; - poly_loops[i].e = duplicate_edge_range[i_extrude]; + poly_verts[i] = new_vert_range[i_extrude]; + poly_edges[i] = duplicate_edge_range[i_extrude]; } for (const int i : IndexRange(poly.totloop)) { @@ -1127,15 +1150,16 @@ static void extrude_individual_mesh_faces(Mesh &mesh, new_polys[i_extrude] = new_poly(side_loop_range[i_extrude * 4], 4); - MutableSpan side_loops = loops.slice(side_loop_range[i_extrude * 4], 4); - side_loops[0].v = new_vert_next; - side_loops[0].e = i_duplicate_edge; - side_loops[1].v = new_vert; - side_loops[1].e = connect_edge_range[i_extrude]; - side_loops[2].v = orig_vert; - side_loops[2].e = orig_edge; - side_loops[3].v = orig_vert_next; - side_loops[3].e = connect_edge_range[i_extrude_next]; + MutableSpan side_poly_verts = corner_verts.slice(side_loop_range[i_extrude * 4], 4); + MutableSpan side_poly_edges = corner_edges.slice(side_loop_range[i_extrude * 4], 4); + side_poly_verts[0] = new_vert_next; + side_poly_edges[0] = i_duplicate_edge; + side_poly_verts[1] = new_vert; + side_poly_edges[1] = connect_edge_range[i_extrude]; + side_poly_verts[2] = orig_vert; + side_poly_edges[2] = orig_edge; + side_poly_verts[3] = orig_vert_next; + side_poly_edges[3] = connect_edge_range[i_extrude_next]; connect_edges[i_extrude] = new_edge(orig_vert, new_vert); } @@ -1148,6 +1172,9 @@ static void extrude_individual_mesh_faces(Mesh &mesh, if (meta_data.data_type == CD_PROP_STRING) { return true; } + if (ELEM(id.name(), ".corner_vert", ".corner_edge")) { + return true; + } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); @@ -1170,13 +1197,11 @@ static void extrude_individual_mesh_faces(Mesh &mesh, threading::parallel_for(poly_selection.index_range(), 512, [&](const IndexRange range) { for (const int i_selection : range) { const MPoly &poly = polys[poly_selection[i_selection]]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection); /* For the extruded edges, mix the data from the two neighboring original edges of * the extruded polygon. */ - for (const int i : poly_loops.index_range()) { + for (const int i : IndexRange(poly.totloop)) { const int i_prev = (i == 0) ? poly.totloop - 1 : i - 1; const int i_extrude = extrude_range[i]; const int i_extrude_prev = extrude_range[i_prev]; diff --git a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc index 14e2449d80d..0345868e963 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc @@ -30,7 +30,8 @@ static void mesh_flip_faces(Mesh &mesh, const Field &selection_field) const IndexMask selection = evaluator.get_evaluated_as_mask(0); const Span polys = mesh.polys(); - MutableSpan loops = mesh.loops_for_write(); + MutableSpan corner_verts = mesh.corner_verts_for_write(); + MutableSpan corner_edges = mesh.corner_edges_for_write(); threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) { for (const int i : selection.slice(range)) { @@ -38,8 +39,8 @@ static void mesh_flip_faces(Mesh &mesh, const Field &selection_field) for (const int j : IndexRange(poly.size() / 2)) { const int a = poly[j + 1]; const int b = poly.last(j); - std::swap(loops[a].v, loops[b].v); - std::swap(loops[a - 1].e, loops[b].e); + std::swap(corner_verts[a], corner_verts[b]); + std::swap(corner_edges[a - 1], corner_edges[b]); } } }); @@ -53,6 +54,9 @@ static void mesh_flip_faces(Mesh &mesh, const Field &selection_field) if (meta_data.domain != ATTR_DOMAIN_CORNER) { return true; } + if (ELEM(attribute_id.name(), ".corner_vert", ".corner_edge")) { + return true; + } GSpanAttributeWriter attribute = attributes.lookup_for_write_span(attribute_id); attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc index e2e20237470..850f9db2101 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc @@ -35,15 +35,15 @@ struct EdgeMapEntry { }; static Array create_edge_map(const Span polys, - const Span loops, + const Span corner_edges, const int total_edges) { Array edge_map(total_edges, {0, 0, 0}); for (const int i_poly : polys.index_range()) { const MPoly &poly = polys[i_poly]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - EdgeMapEntry &entry = edge_map[loop.e]; + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + EdgeMapEntry &entry = edge_map[edge]; if (entry.face_count == 0) { entry.face_index_1 = i_poly; } @@ -69,20 +69,21 @@ class AngleFieldInput final : public bke::MeshFieldInput { { const Span positions = mesh.vert_positions(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); - Array edge_map = create_edge_map(polys, loops, mesh.totedge); + const Span corner_verts = mesh.corner_verts(); + const Span corner_edges = mesh.corner_edges(); + Array edge_map = create_edge_map(polys, corner_edges, mesh.totedge); auto angle_fn = - [edge_map = std::move(edge_map), positions, polys, loops](const int i) -> float { + [edge_map = std::move(edge_map), positions, polys, corner_verts](const int i) -> float { if (edge_map[i].face_count != 2) { return 0.0f; } const MPoly &poly_1 = polys[edge_map[i].face_index_1]; const MPoly &poly_2 = polys[edge_map[i].face_index_2]; const float3 normal_1 = bke::mesh::poly_normal_calc( - positions, loops.slice(poly_1.loopstart, poly_1.totloop)); + positions, corner_verts.slice(poly_1.loopstart, poly_1.totloop)); const float3 normal_2 = bke::mesh::poly_normal_calc( - positions, loops.slice(poly_2.loopstart, poly_2.totloop)); + positions, corner_verts.slice(poly_2.loopstart, poly_2.totloop)); return angle_normalized_v3v3(normal_1, normal_2); }; @@ -121,11 +122,12 @@ class SignedAngleFieldInput final : public bke::MeshFieldInput { const Span positions = mesh.vert_positions(); const Span edges = mesh.edges(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); - Array edge_map = create_edge_map(polys, loops, mesh.totedge); + const Span corner_verts = mesh.corner_verts(); + const Span corner_edges = mesh.corner_edges(); + Array edge_map = create_edge_map(polys, corner_edges, mesh.totedge); - auto angle_fn = - [edge_map = std::move(edge_map), positions, edges, polys, loops](const int i) -> float { + auto angle_fn = [edge_map = std::move(edge_map), positions, edges, polys, corner_verts]( + const int i) -> float { if (edge_map[i].face_count != 2) { return 0.0f; } @@ -134,9 +136,9 @@ class SignedAngleFieldInput final : public bke::MeshFieldInput { /* Find the normals of the 2 polys. */ const float3 poly_1_normal = bke::mesh::poly_normal_calc( - positions, loops.slice(poly_1.loopstart, poly_1.totloop)); + positions, corner_verts.slice(poly_1.loopstart, poly_1.totloop)); const float3 poly_2_normal = bke::mesh::poly_normal_calc( - positions, loops.slice(poly_2.loopstart, poly_2.totloop)); + positions, corner_verts.slice(poly_2.loopstart, poly_2.totloop)); /* Find the centerpoint of the axis edge */ const float3 edge_centerpoint = (positions[edges[i].v1] + positions[edges[i].v2]) * 0.5f; @@ -144,7 +146,7 @@ class SignedAngleFieldInput final : public bke::MeshFieldInput { /* Get the centerpoint of poly 2 and subtract the edge centerpoint to get a tangent * normal for poly 2. */ const float3 poly_center_2 = bke::mesh::poly_center_calc( - positions, loops.slice(poly_2.loopstart, poly_2.totloop)); + positions, corner_verts.slice(poly_2.loopstart, poly_2.totloop)); const float3 poly_2_tangent = math::normalize(poly_center_2 - edge_centerpoint); const float concavity = math::dot(poly_1_normal, poly_2_tangent); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc index 9fc5b361b5a..03018baa81a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc @@ -28,10 +28,10 @@ class EdgeNeighborCountFieldInput final : public bke::MeshFieldInput { const eAttrDomain domain, const IndexMask /*mask*/) const final { - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); Array face_count(mesh.totedge, 0); - for (const MLoop &loop : loops) { - face_count[loop.e]++; + for (const int edge : corner_edges) { + face_count[edge]++; } return mesh.attributes().adapt_domain( diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc index d8aeac6df8f..4dcf63342e8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc @@ -20,11 +20,11 @@ static VArray construct_face_area_varray(const Mesh &mesh, const eAttrDom { const Span positions = mesh.vert_positions(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); - auto area_fn = [positions, polys, loops](const int i) -> float { + auto area_fn = [positions, polys, corner_verts](const int i) -> float { const MPoly &poly = polys[i]; - return bke::mesh::poly_area_calc(positions, loops.slice(poly.loopstart, poly.totloop)); + return bke::mesh::poly_area_calc(positions, corner_verts.slice(poly.loopstart, poly.totloop)); }; return mesh.attributes().adapt_domain( diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc index 71ab9ab3018..d70d0292ae1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc @@ -41,7 +41,7 @@ class PlanarFieldInput final : public bke::MeshFieldInput { { const Span positions = mesh.vert_positions(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); const Span poly_normals = mesh.poly_normals(); bke::MeshFieldContext context{mesh, ATTR_DOMAIN_FACE}; @@ -50,20 +50,19 @@ class PlanarFieldInput final : public bke::MeshFieldInput { evaluator.evaluate(); const VArray thresholds = evaluator.get_evaluated(0); - auto planar_fn = [positions, polys, loops, thresholds, poly_normals](const int i) -> bool { + auto planar_fn = + [positions, polys, corner_verts, thresholds, poly_normals](const int i) -> bool { const MPoly &poly = polys[i]; if (poly.totloop <= 3) { return true; } - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); const float3 &reference_normal = poly_normals[i]; float min = FLT_MAX; float max = -FLT_MAX; - for (const int i_loop : poly_loops.index_range()) { - const float3 &vert = positions[poly_loops[i_loop].v]; - float dot = math::dot(reference_normal, vert); + for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) { + float dot = math::dot(reference_normal, positions[vert]); if (dot > max) { max = dot; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc index a4b71941c23..e0fa844a2df 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc @@ -22,18 +22,18 @@ static void node_declare(NodeDeclarationBuilder &b) static VArray construct_neighbor_count_varray(const Mesh &mesh, const eAttrDomain domain) { const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); Array edge_count(mesh.totedge, 0); - for (const MLoop &loop : loops) { - edge_count[loop.e]++; + for (const int edge : corner_edges) { + edge_count[edge]++; } Array poly_count(polys.size(), 0); for (const int poly_index : polys.index_range()) { const MPoly &poly = polys[poly_index]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - poly_count[poly_index] += edge_count[loop.e] - 1; + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { + poly_count[poly_index] += edge_count[edge] - 1; } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc index 2fb8e4f54fa..dd233828d6f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc @@ -67,12 +67,11 @@ class VertexCountFieldInput final : public bke::MeshFieldInput { static VArray construct_face_count_gvarray(const Mesh &mesh, const eAttrDomain domain) { - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); if (domain == ATTR_DOMAIN_POINT) { Array vertices(mesh.totvert, 0); - for (const int i : loops.index_range()) { - int vertex = loops[i].v; - vertices[vertex]++; + for (const int vert : corner_verts) { + vertices[vert]++; } return VArray::ForContainer(std::move(vertices)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mean_filter_sdf_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_mean_filter_sdf_volume.cc new file mode 100644 index 00000000000..442db31cb0e --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_mean_filter_sdf_volume.cc @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "DEG_depsgraph_query.h" +#ifdef WITH_OPENVDB +# include +#endif + +#include "node_geometry_util.hh" + +#include "BKE_geometry_set.h" +#include "BKE_volume.h" + +#include "DNA_node_types.h" + +#include "NOD_add_node_search.hh" +#include "NOD_socket_search_link.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_geo_mean_filter_sdf_volume_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input(N_("Volume")).supported_type(GEO_COMPONENT_TYPE_VOLUME); + b.add_input(N_("Iterations")).min(1).max(256).default_value(1); + b.add_input(N_("Width")).min(0).default_value(1); + b.add_output(N_("Volume")); +} + +static void search_node_add_ops(GatherAddNodeSearchParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_node_add_ops_for_basic_node(params); + } +} + +static void search_link_ops(GatherLinkSearchOpParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_link_ops_for_basic_node(params); + } +} + +#ifdef WITH_OPENVDB +static void sdf_volume_mean_filter(Volume &volume, const GeoNodeExecParams ¶ms) +{ + VolumeGrid *volume_grid = BKE_volume_grid_find_for_write(&volume, "distance"); + if (volume_grid == nullptr) { + return; + } + openvdb::GridBase::Ptr base_grid = BKE_volume_grid_openvdb_for_write( + &volume, volume_grid, false); + + if (!base_grid->isType()) { + return; + } + openvdb::FloatGrid::Ptr levelset_grid = openvdb::gridPtrCast(base_grid); + openvdb::tools::LevelSetFilter filter(*levelset_grid); + + int iterations = params.get_input("Iterations"); + for (int i = 0; i < iterations; i++) { + filter.mean(params.get_input("Width")); + } +} +#endif + +static void node_geo_exec(GeoNodeExecParams params) +{ +#ifdef WITH_OPENVDB + GeometrySet geometry_set = params.extract_input("Volume"); + + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + if (!geometry_set.has_volume()) { + return; + } + VolumeComponent &component = geometry_set.get_component_for_write(); + Volume *volume = component.get_for_write(); + BKE_volume_load(volume, DEG_get_bmain(params.depsgraph())); + sdf_volume_mean_filter(*volume, params); + }); + params.set_output("Volume", std::move(geometry_set)); +#else + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, + TIP_("Disabled, Blender was compiled without OpenVDB")); +#endif +} + +} // namespace blender::nodes::node_geo_mean_filter_sdf_volume_cc + +void register_node_type_geo_mean_filter_sdf_volume() +{ + namespace file_ns = blender::nodes::node_geo_mean_filter_sdf_volume_cc; + + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_MEAN_FILTER_SDF_VOLUME, "Mean Filter SDF Volume", NODE_CLASS_GEOMETRY); + node_type_size(&ntype, 160, 120, 700); + ntype.declare = file_ns::node_declare; + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.gather_add_node_search_ops = file_ns::search_node_add_ops; + ntype.gather_link_search_ops = file_ns::search_link_ops; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_face_group_boundaries.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_face_group_boundaries.cc index 90f7677f456..daa7333910e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_face_group_boundaries.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_face_group_boundaries.cc @@ -47,11 +47,10 @@ class BoundaryFieldInput final : public bke::MeshFieldInput { Array edge_visited(mesh.totedge, false); Array edge_face_set(mesh.totedge, 0); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); for (const int i : polys.index_range()) { const MPoly &poly = polys[i]; - for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { - const int edge = loop.e; + for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) { if (edge_visited[edge]) { if (edge_face_set[edge] != face_set[i]) { /* This edge is connected to two faces on different face sets. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc index d85d153972e..328e83612f0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc @@ -111,7 +111,8 @@ static Mesh *create_circle_mesh(const float radius, MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); + MutableSpan corner_edges = mesh->corner_edges_for_write(); BKE_mesh_smooth_flag_set(mesh, false); /* Assign vertex coordinates. */ @@ -144,13 +145,10 @@ static Mesh *create_circle_mesh(const float radius, if (fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) { MPoly &poly = polys[0]; poly.loopstart = 0; - poly.totloop = loops.size(); + poly.totloop = corner_verts.size(); - for (const int i : IndexRange(verts_num)) { - MLoop &loop = loops[i]; - loop.e = i; - loop.v = i; - } + std::iota(corner_verts.begin(), corner_verts.end(), 0); + std::iota(corner_edges.begin(), corner_edges.end(), 0); } else if (fill_type == GEO_NODE_MESH_CIRCLE_FILL_TRIANGLE_FAN) { for (const int i : IndexRange(verts_num)) { @@ -158,15 +156,14 @@ static Mesh *create_circle_mesh(const float radius, poly.loopstart = 3 * i; poly.totloop = 3; - MLoop &loop_a = loops[3 * i]; - loop_a.e = i; - loop_a.v = i; - MLoop &loop_b = loops[3 * i + 1]; - loop_b.e = verts_num + ((i + 1) % verts_num); - loop_b.v = (i + 1) % verts_num; - MLoop &loop_c = loops[3 * i + 2]; - loop_c.e = verts_num + i; - loop_c.v = verts_num; + corner_verts[3 * i] = i; + corner_edges[3 * i] = i; + + corner_verts[3 * i + 1] = (i + 1) % verts_num; + corner_edges[3 * i + 1] = verts_num + ((i + 1) % verts_num); + + corner_verts[3 * i + 2] = verts_num; + corner_edges[3 * i + 2] = verts_num + i; } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc index 3145211d1d8..3639a1e069b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc @@ -365,7 +365,8 @@ static void calculate_cone_edges(const ConeConfig &config, MutableSpan ed } static void calculate_cone_faces(const ConeConfig &config, - MutableSpan loops, + MutableSpan corner_verts, + MutableSpan corner_edges, MutableSpan polys) { int rings_poly_start = 0; @@ -384,14 +385,15 @@ static void calculate_cone_faces(const ConeConfig &config, poly.loopstart = loop_start; poly.totloop = 3; - loops[loop_start + 0].v = config.first_ring_verts_start + i; - loops[loop_start + 0].e = config.first_ring_edges_start + i; + corner_verts[loop_start + 0] = config.first_ring_verts_start + i; + corner_edges[loop_start + 0] = config.first_ring_edges_start + i; - loops[loop_start + 1].v = config.first_ring_verts_start + ((i + 1) % config.circle_segments); - loops[loop_start + 1].e = top_fan_edges_start + ((i + 1) % config.circle_segments); + corner_verts[loop_start + 1] = config.first_ring_verts_start + + ((i + 1) % config.circle_segments); + corner_edges[loop_start + 1] = top_fan_edges_start + ((i + 1) % config.circle_segments); - loops[loop_start + 2].v = top_center_vert; - loops[loop_start + 2].e = top_fan_edges_start + i; + corner_verts[loop_start + 2] = top_center_vert; + corner_edges[loop_start + 2] = top_fan_edges_start + i; } } else if (config.fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) { @@ -403,8 +405,8 @@ static void calculate_cone_faces(const ConeConfig &config, poly.loopstart = 0; poly.totloop = config.circle_segments; for (const int i : IndexRange(config.circle_segments)) { - loops[i].v = i; - loops[i].e = i; + corner_verts[i] = i; + corner_edges[i] = i; } } @@ -426,17 +428,17 @@ static void calculate_cone_faces(const ConeConfig &config, poly.loopstart = loop_start; poly.totloop = 4; - loops[loop_start + 0].v = this_ring_vert_start + j; - loops[loop_start + 0].e = ring_connections_start + j; + corner_verts[loop_start + 0] = this_ring_vert_start + j; + corner_edges[loop_start + 0] = ring_connections_start + j; - loops[loop_start + 1].v = next_ring_vert_start + j; - loops[loop_start + 1].e = next_ring_edges_start + j; + corner_verts[loop_start + 1] = next_ring_vert_start + j; + corner_edges[loop_start + 1] = next_ring_edges_start + j; - loops[loop_start + 2].v = next_ring_vert_start + ((j + 1) % config.circle_segments); - loops[loop_start + 2].e = ring_connections_start + ((j + 1) % config.circle_segments); + corner_verts[loop_start + 2] = next_ring_vert_start + ((j + 1) % config.circle_segments); + corner_edges[loop_start + 2] = ring_connections_start + ((j + 1) % config.circle_segments); - loops[loop_start + 3].v = this_ring_vert_start + ((j + 1) % config.circle_segments); - loops[loop_start + 3].e = this_ring_edges_start + j; + corner_verts[loop_start + 3] = this_ring_vert_start + ((j + 1) % config.circle_segments); + corner_edges[loop_start + 3] = this_ring_edges_start + j; } } @@ -452,14 +454,16 @@ static void calculate_cone_faces(const ConeConfig &config, poly.loopstart = loop_start; poly.totloop = 3; - loops[loop_start + 0].v = config.last_ring_verts_start + i; - loops[loop_start + 0].e = config.last_fan_edges_start + i; + corner_verts[loop_start + 0] = config.last_ring_verts_start + i; + corner_edges[loop_start + 0] = config.last_fan_edges_start + i; - loops[loop_start + 1].v = config.last_vert; - loops[loop_start + 1].e = config.last_fan_edges_start + (i + 1) % config.circle_segments; + corner_verts[loop_start + 1] = config.last_vert; + corner_edges[loop_start + 1] = config.last_fan_edges_start + + (i + 1) % config.circle_segments; - loops[loop_start + 2].v = config.last_ring_verts_start + (i + 1) % config.circle_segments; - loops[loop_start + 2].e = config.last_ring_edges_start + i; + corner_verts[loop_start + 2] = config.last_ring_verts_start + + (i + 1) % config.circle_segments; + corner_edges[loop_start + 2] = config.last_ring_edges_start + i; } } else if (config.fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) { @@ -470,8 +474,8 @@ static void calculate_cone_faces(const ConeConfig &config, for (const int i : IndexRange(config.circle_segments)) { /* Go backwards to reverse surface normal. */ - loops[bottom_loop_start + i].v = config.last_vert - i; - loops[bottom_loop_start + i].e = config.last_edge - ((i + 1) % config.circle_segments); + corner_verts[bottom_loop_start + i] = config.last_vert - i; + corner_edges[bottom_loop_start + i] = config.last_edge - ((i + 1) % config.circle_segments); } } } @@ -691,12 +695,13 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top, MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); + MutableSpan corner_edges = mesh->corner_edges_for_write(); BKE_mesh_smooth_flag_set(mesh, false); calculate_cone_verts(config, positions); calculate_cone_edges(config, edges); - calculate_cone_faces(config, loops, polys); + calculate_cone_faces(config, corner_verts, corner_edges, polys); if (attribute_outputs.uv_map_id) { calculate_cone_uvs(config, mesh, attribute_outputs.uv_map_id.get()); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc index 2d366debda7..10acbb1e4af 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc @@ -16,8 +16,8 @@ namespace blender::nodes { static void calculate_uvs(Mesh *mesh, - Span positions, - Span loops, + const Span positions, + const Span corner_verts, const float size_x, const float size_y, const AttributeIDRef &uv_map_id) @@ -29,9 +29,9 @@ static void calculate_uvs(Mesh *mesh, const float dx = (size_x == 0.0f) ? 0.0f : 1.0f / size_x; const float dy = (size_y == 0.0f) ? 0.0f : 1.0f / size_y; - threading::parallel_for(loops.index_range(), 1024, [&](IndexRange range) { + threading::parallel_for(corner_verts.index_range(), 1024, [&](IndexRange range) { for (const int i : range) { - const float3 &co = positions[loops[i].v]; + const float3 &co = positions[corner_verts[i]]; uv_attribute.span[i].x = (co.x + size_x * 0.5f) * dx; uv_attribute.span[i].y = (co.y + size_y * 0.5f) * dy; } @@ -56,7 +56,8 @@ Mesh *create_grid_mesh(const int verts_x, MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); + MutableSpan corner_edges = mesh->corner_edges_for_write(); BKE_mesh_smooth_flag_set(mesh, false); { @@ -125,25 +126,24 @@ Mesh *create_grid_mesh(const int verts_x, poly.totloop = 4; const int vert_index = x * verts_y + y; - MLoop &loop_a = loops[loop_index]; - loop_a.v = vert_index; - loop_a.e = x_edges_start + edges_x * y + x; - MLoop &loop_b = loops[loop_index + 1]; - loop_b.v = vert_index + verts_y; - loop_b.e = y_edges_start + edges_y * (x + 1) + y; - MLoop &loop_c = loops[loop_index + 2]; - loop_c.v = vert_index + verts_y + 1; - loop_c.e = x_edges_start + edges_x * (y + 1) + x; - MLoop &loop_d = loops[loop_index + 3]; - loop_d.v = vert_index + 1; - loop_d.e = y_edges_start + edges_y * x + y; + corner_verts[loop_index] = vert_index; + corner_edges[loop_index] = x_edges_start + edges_x * y + x; + + corner_verts[loop_index + 1] = vert_index + verts_y; + corner_edges[loop_index + 1] = y_edges_start + edges_y * (x + 1) + y; + + corner_verts[loop_index + 2] = vert_index + verts_y + 1; + corner_edges[loop_index + 2] = x_edges_start + edges_x * (y + 1) + x; + + corner_verts[loop_index + 3] = vert_index + 1; + corner_edges[loop_index + 3] = y_edges_start + edges_y * x + y; } }); } }); if (uv_map_id && mesh->totpoly != 0) { - calculate_uvs(mesh, positions, loops, size_x, size_y, uv_map_id); + calculate_uvs(mesh, positions, corner_verts, size_x, size_y, uv_map_id); } mesh->loose_edges_tag_none(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index 41a48e7bc73..51c5bbce8d3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -177,7 +177,8 @@ BLI_NOINLINE static void calculate_sphere_faces(MutableSpan polys, const } } -BLI_NOINLINE static void calculate_sphere_corners(MutableSpan loops, +BLI_NOINLINE static void calculate_sphere_corners(MutableSpan corner_verts, + MutableSpan corner_edges, const int segments, const int rings) { @@ -191,14 +192,14 @@ BLI_NOINLINE static void calculate_sphere_corners(MutableSpan loops, const int loop_start = segment * 3; const int segment_next = segment_next_or_first(segment); - loops[loop_start + 0].v = 0; - loops[loop_start + 0].e = segment; + corner_verts[loop_start + 0] = 0; + corner_edges[loop_start + 0] = segment; - loops[loop_start + 1].v = first_vert_ring_start + segment; - loops[loop_start + 1].e = segments + segment; + corner_verts[loop_start + 1] = first_vert_ring_start + segment; + corner_edges[loop_start + 1] = segments + segment; - loops[loop_start + 2].v = first_vert_ring_start + segment_next; - loops[loop_start + 2].e = segment_next; + corner_verts[loop_start + 2] = first_vert_ring_start + segment_next; + corner_edges[loop_start + 2] = segment_next; } const int rings_vert_start = 1; @@ -217,17 +218,17 @@ BLI_NOINLINE static void calculate_sphere_corners(MutableSpan loops, const int loop_start = ring_loop_start + segment * 4; const int segment_next = segment_next_or_first(segment); - loops[loop_start + 0].v = ring_vert_start + segment; - loops[loop_start + 0].e = ring_vertical_edge_start + segment; + corner_verts[loop_start + 0] = ring_vert_start + segment; + corner_edges[loop_start + 0] = ring_vertical_edge_start + segment; - loops[loop_start + 1].v = next_ring_vert_start + segment; - loops[loop_start + 1].e = next_ring_edge_start + segment; + corner_verts[loop_start + 1] = next_ring_vert_start + segment; + corner_edges[loop_start + 1] = next_ring_edge_start + segment; - loops[loop_start + 2].v = next_ring_vert_start + segment_next; - loops[loop_start + 2].e = ring_vertical_edge_start + segment_next; + corner_verts[loop_start + 2] = next_ring_vert_start + segment_next; + corner_edges[loop_start + 2] = ring_vertical_edge_start + segment_next; - loops[loop_start + 3].v = ring_vert_start + segment_next; - loops[loop_start + 3].e = ring_edge_start + segment; + corner_verts[loop_start + 3] = ring_vert_start + segment_next; + corner_edges[loop_start + 3] = ring_edge_start + segment; } } @@ -241,14 +242,14 @@ BLI_NOINLINE static void calculate_sphere_corners(MutableSpan loops, const int loop_start = bottom_loop_start + segment * 3; const int segment_next = segment_next_or_first(segment); - loops[loop_start + 0].v = last_vert_index; - loops[loop_start + 0].e = bottom_edge_fan_start + segment_next; + corner_verts[loop_start + 0] = last_vert_index; + corner_edges[loop_start + 0] = bottom_edge_fan_start + segment_next; - loops[loop_start + 1].v = last_vert_ring_start + segment_next; - loops[loop_start + 1].e = last_edge_ring_start + segment; + corner_verts[loop_start + 1] = last_vert_ring_start + segment_next; + corner_edges[loop_start + 1] = last_edge_ring_start + segment; - loops[loop_start + 2].v = last_vert_ring_start + segment; - loops[loop_start + 2].e = bottom_edge_fan_start + segment; + corner_verts[loop_start + 2] = last_vert_ring_start + segment; + corner_edges[loop_start + 2] = bottom_edge_fan_start + segment; } } @@ -314,7 +315,8 @@ static Mesh *create_uv_sphere_mesh(const float radius, MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); + MutableSpan corner_edges = mesh->corner_edges_for_write(); BKE_mesh_smooth_flag_set(mesh, false); threading::parallel_invoke( @@ -327,7 +329,7 @@ static Mesh *create_uv_sphere_mesh(const float radius, }, [&]() { calculate_sphere_edge_indices(edges, segments, rings); }, [&]() { calculate_sphere_faces(polys, segments); }, - [&]() { calculate_sphere_corners(loops, segments, rings); }, + [&]() { calculate_sphere_corners(corner_verts, corner_edges, segments, rings); }, [&]() { if (uv_map_id) { calculate_sphere_uvs(mesh, segments, rings, uv_map_id); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_sdf_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_sdf_volume.cc new file mode 100644 index 00000000000..58fcfda2865 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_sdf_volume.cc @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "DEG_depsgraph_query.h" +#include "node_geometry_util.hh" + +#include "BKE_lib_id.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_mesh_wrapper.h" +#include "BKE_object.h" +#include "BKE_volume.h" + +#include "GEO_mesh_to_volume.hh" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "NOD_add_node_search.hh" +#include "NOD_socket_search_link.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_geo_mesh_to_sdf_volume_cc { + +NODE_STORAGE_FUNCS(NodeGeometryMeshToVolume) + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH); + b.add_input(N_("Voxel Size")) + .default_value(0.3f) + .min(0.01f) + .max(FLT_MAX) + .subtype(PROP_DISTANCE); + b.add_input(N_("Voxel Amount")).default_value(64.0f).min(0.0f).max(FLT_MAX); + b.add_input(N_("Half-Band Width")) + .description(N_("Half the width of the narrow band in voxel units")) + .default_value(3.0f) + .min(1.01f) + .max(10.0f); + b.add_output(N_("Volume")); +} + +static void search_node_add_ops(GatherAddNodeSearchParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_node_add_ops_for_basic_node(params); + } +} + +static void search_link_ops(GatherLinkSearchOpParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_link_ops_for_basic_node(params); + } +} + +static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) +{ + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + uiItemR(layout, ptr, "resolution_mode", 0, IFACE_("Resolution"), ICON_NONE); +} + +static void node_init(bNodeTree * /*tree*/, bNode *node) +{ + NodeGeometryMeshToVolume *data = MEM_cnew(__func__); + data->resolution_mode = MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT; + node->storage = data; +} + +static void node_update(bNodeTree *ntree, bNode *node) +{ + NodeGeometryMeshToVolume &data = node_storage(*node); + + bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size"); + bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount"); + nodeSetSocketAvailability(ntree, + voxel_amount_socket, + data.resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT); + nodeSetSocketAvailability( + ntree, voxel_size_socket, data.resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE); +} + +#ifdef WITH_OPENVDB + +static Volume *create_volume_from_mesh(const Mesh &mesh, GeoNodeExecParams ¶ms) +{ + const NodeGeometryMeshToVolume &storage = node_storage(params.node()); + + const float half_band_width = params.get_input("Half-Band Width"); + + geometry::MeshToVolumeResolution resolution; + resolution.mode = (MeshToVolumeModifierResolutionMode)storage.resolution_mode; + if (resolution.mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT) { + resolution.settings.voxel_amount = params.get_input("Voxel Amount"); + if (resolution.settings.voxel_amount <= 0.0f) { + return nullptr; + } + } + else if (resolution.mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE) { + resolution.settings.voxel_size = params.get_input("Voxel Size"); + if (resolution.settings.voxel_size <= 0.0f) { + return nullptr; + } + } + + if (mesh.totpoly == 0) { + return nullptr; + } + + const float4x4 mesh_to_volume_space_transform = float4x4::identity(); + + auto bounds_fn = [&](float3 &r_min, float3 &r_max) { + float3 min{std::numeric_limits::max()}; + float3 max{-std::numeric_limits::max()}; + BKE_mesh_wrapper_minmax(&mesh, min, max); + r_min = min; + r_max = max; + }; + + const float voxel_size = geometry::volume_compute_voxel_size( + params.depsgraph(), bounds_fn, resolution, half_band_width, mesh_to_volume_space_transform); + + if (voxel_size < 1e-5f) { + /* The voxel size is too small. */ + return nullptr; + } + + Volume *volume = reinterpret_cast(BKE_id_new_nomain(ID_VO, nullptr)); + + /* Convert mesh to grid and add to volume. */ + geometry::sdf_volume_grid_add_from_mesh(volume, "distance", mesh, voxel_size, half_band_width); + + return volume; +} + +#endif /* WITH_OPENVDB */ + +static void node_geo_exec(GeoNodeExecParams params) +{ +#ifdef WITH_OPENVDB + GeometrySet geometry_set(params.extract_input("Mesh")); + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + if (geometry_set.has_mesh()) { + Volume *volume = create_volume_from_mesh(*geometry_set.get_mesh_for_read(), params); + geometry_set.replace_volume(volume); + geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_VOLUME}); + } + }); + params.set_output("Volume", std::move(geometry_set)); +#else + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, + TIP_("Disabled, Blender was compiled without OpenVDB")); + return; +#endif +} + +} // namespace blender::nodes::node_geo_mesh_to_sdf_volume_cc + +void register_node_type_geo_mesh_to_sdf_volume() +{ + namespace file_ns = blender::nodes::node_geo_mesh_to_sdf_volume_cc; + + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_MESH_TO_SDF_VOLUME, "Mesh to SDF Volume", NODE_CLASS_GEOMETRY); + ntype.declare = file_ns::node_declare; + node_type_size(&ntype, 180, 120, 300); + ntype.initfunc = file_ns::node_init; + ntype.updatefunc = file_ns::node_update; + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.draw_buttons = file_ns::node_layout; + ntype.gather_add_node_search_ops = file_ns::search_node_add_ops; + ntype.gather_link_search_ops = file_ns::search_link_ops; + node_type_storage( + &ntype, "NodeGeometryMeshToVolume", node_free_standard_storage, node_copy_standard_storage); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc index 117971602a4..67e2b83e3c2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_volume.cc @@ -127,15 +127,15 @@ static Volume *create_volume_from_mesh(const Mesh &mesh, GeoNodeExecParams ¶ Volume *volume = reinterpret_cast(BKE_id_new_nomain(ID_VO, nullptr)); /* Convert mesh to grid and add to volume. */ - geometry::volume_grid_add_from_mesh(volume, - "density", - &mesh, - mesh_to_volume_space_transform, - voxel_size, - fill_volume, - exterior_band_width, - interior_band_width, - density); + geometry::fog_volume_grid_add_from_mesh(volume, + "density", + &mesh, + mesh_to_volume_space_transform, + voxel_size, + fill_volume, + exterior_band_width, + interior_band_width, + density); return volume; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc index 2a115560d7e..2e9bd6ec2d7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc @@ -60,8 +60,8 @@ class CornersOfVertInput final : public bke::MeshFieldInput { const IndexMask mask) const final { const IndexRange vert_range(mesh.totvert); - const Span loops = mesh.loops(); - Array> vert_to_loop_map = bke::mesh_topology::build_vert_to_loop_map(loops, + const Span corner_verts = mesh.corner_verts(); + Array> vert_to_loop_map = bke::mesh_topology::build_vert_to_loop_map(corner_verts, mesh.totvert); const bke::MeshFieldContext context{mesh, domain}; @@ -73,7 +73,7 @@ class CornersOfVertInput final : public bke::MeshFieldInput { const VArray indices_in_sort = evaluator.get_evaluated(1); const bke::MeshFieldContext corner_context{mesh, ATTR_DOMAIN_CORNER}; - fn::FieldEvaluator corner_evaluator{corner_context, loops.size()}; + fn::FieldEvaluator corner_evaluator{corner_context, corner_verts.size()}; corner_evaluator.add(sort_weight_); corner_evaluator.evaluate(); const VArray all_sort_weights = corner_evaluator.get_evaluated(0); @@ -172,10 +172,10 @@ class CornersOfVertCountInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_POINT) { return {}; } - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); Array counts(mesh.totvert, 0); - for (const int i : loops.index_range()) { - counts[loops[i].v]++; + for (const int i : corner_verts.index_range()) { + counts[corner_verts[i]]++; } return VArray::ForContainer(std::move(counts)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc index ecec64c0950..df0b924dfbd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc @@ -25,11 +25,6 @@ static void node_declare(NodeDeclarationBuilder &b) N_("The edge before the corner in the face, in the direction of decreasing indices")); } -static int get_loop_edge(const MLoop &loop) -{ - return loop.e; -} - class CornerNextEdgeFieldInput final : public bke::MeshFieldInput { public: CornerNextEdgeFieldInput() : bke::MeshFieldInput(CPPType::get(), "Corner Next Edge") @@ -44,7 +39,7 @@ class CornerNextEdgeFieldInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_CORNER) { return {}; } - return VArray::ForDerivedSpan(mesh.loops()); + return VArray::ForSpan(mesh.corner_edges()); } uint64_t hash() const final @@ -81,15 +76,13 @@ class CornerPreviousEdgeFieldInput final : public bke::MeshFieldInput { return {}; } const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_edges = mesh.corner_edges(); Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys, mesh.totloop); return VArray::ForFunc( mesh.totloop, - [polys, loops, loop_to_poly_map = std::move(loop_to_poly_map)](const int corner_i) { - const int poly_i = loop_to_poly_map[corner_i]; - const MPoly &poly = polys[poly_i]; - const int corner_i_prev = bke::mesh_topology::poly_loop_prev(poly, corner_i); - return loops[corner_i_prev].e; + [polys, corner_edges, loop_to_poly_map = std::move(loop_to_poly_map)](const int corner_i) { + const MPoly &poly = polys[loop_to_poly_map[corner_i]]; + return corner_edges[bke::mesh_topology::poly_loop_prev(poly, corner_i)]; }); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_vertex_of_corner.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_vertex_of_corner.cc index 59ce296b1e7..58f2403338d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_vertex_of_corner.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_vertex_of_corner.cc @@ -19,11 +19,6 @@ static void node_declare(NodeDeclarationBuilder &b) .description(N_("The vertex the corner is attached to")); } -static int get_loop_vert(const MLoop &loop) -{ - return loop.v; -} - class CornerVertFieldInput final : public bke::MeshFieldInput { public: CornerVertFieldInput() : bke::MeshFieldInput(CPPType::get(), "Corner Vertex") @@ -38,7 +33,7 @@ class CornerVertFieldInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_CORNER) { return {}; } - return VArray::ForDerivedSpan(mesh.loops()); + return VArray::ForSpan(mesh.corner_verts()); } uint64_t hash() const final diff --git a/source/blender/nodes/geometry/nodes/node_geo_offset_sdf_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_offset_sdf_volume.cc new file mode 100644 index 00000000000..093e1164357 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_offset_sdf_volume.cc @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "DEG_depsgraph_query.h" +#ifdef WITH_OPENVDB +# include +#endif + +#include "node_geometry_util.hh" + +#include "BKE_geometry_set.h" +#include "BKE_volume.h" + +#include "DNA_node_types.h" + +#include "NOD_add_node_search.hh" +#include "NOD_socket_search_link.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_geo_offset_sdf_volume_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input(N_("Volume")).supported_type(GEO_COMPONENT_TYPE_VOLUME); + b.add_input(N_("Distance")).default_value(0.1f).subtype(PROP_DISTANCE); + b.add_output(N_("Volume")); +} + +static void search_node_add_ops(GatherAddNodeSearchParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_node_add_ops_for_basic_node(params); + } +} + +static void search_link_ops(GatherLinkSearchOpParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_link_ops_for_basic_node(params); + } +} + +#ifdef WITH_OPENVDB +static void sdf_volume_offset(Volume &volume, const GeoNodeExecParams ¶ms) +{ + VolumeGrid *volume_grid = BKE_volume_grid_find_for_write(&volume, "distance"); + if (volume_grid == nullptr) { + return; + } + openvdb::GridBase::Ptr base_grid = BKE_volume_grid_openvdb_for_write( + &volume, volume_grid, false); + + if (!base_grid->isType()) { + return; + } + openvdb::FloatGrid::Ptr levelset_grid = openvdb::gridPtrCast(base_grid); + openvdb::tools::LevelSetFilter filter(*levelset_grid); + + filter.offset(-params.get_input("Distance")); +} +#endif + +static void node_geo_exec(GeoNodeExecParams params) +{ +#ifdef WITH_OPENVDB + GeometrySet geometry_set = params.extract_input("Volume"); + + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + if (!geometry_set.has_volume()) { + return; + } + VolumeComponent &component = geometry_set.get_component_for_write(); + Volume *volume = component.get_for_write(); + BKE_volume_load(volume, DEG_get_bmain(params.depsgraph())); + sdf_volume_offset(*volume, params); + }); + params.set_output("Volume", std::move(geometry_set)); +#else + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, + TIP_("Disabled, Blender was compiled without OpenVDB")); +#endif +} + +} // namespace blender::nodes::node_geo_offset_sdf_volume_cc + +void register_node_type_geo_offset_sdf_volume() +{ + namespace file_ns = blender::nodes::node_geo_offset_sdf_volume_cc; + + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_OFFSET_SDF_VOLUME, "Offset SDF Volume", NODE_CLASS_GEOMETRY); + ntype.declare = file_ns::node_declare; + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.gather_add_node_search_ops = file_ns::search_node_add_ops; + ntype.gather_link_search_ops = file_ns::search_link_ops; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_sdf_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_sdf_volume.cc new file mode 100644 index 00000000000..ea3e8a3b675 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_sdf_volume.cc @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifdef WITH_OPENVDB +# include +#endif + +#include "node_geometry_util.hh" + +#include "GEO_points_to_volume.hh" + +#include "NOD_add_node_search.hh" +#include "NOD_socket_search_link.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +namespace blender::nodes::node_geo_points_to_sdf_volume_cc { + +NODE_STORAGE_FUNCS(NodeGeometryPointsToVolume) + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input(N_("Points")); + b.add_input(N_("Voxel Size")) + .default_value(0.3f) + .min(0.01f) + .subtype(PROP_DISTANCE) + .make_available([](bNode &node) { + node_storage(node).resolution_mode = GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE; + }); + b.add_input(N_("Voxel Amount")) + .default_value(64.0f) + .min(0.0f) + .make_available([](bNode &node) { + node_storage(node).resolution_mode = GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT; + }); + b.add_input(N_("Radius")) + .default_value(0.5f) + .min(0.0f) + .subtype(PROP_DISTANCE) + .field_on_all(); + b.add_output(N_("Volume")); +} + +static void search_node_add_ops(GatherAddNodeSearchParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_node_add_ops_for_basic_node(params); + } +} + +static void search_link_ops(GatherLinkSearchOpParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_link_ops_for_basic_node(params); + } +} + +static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) +{ + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + uiItemR(layout, ptr, "resolution_mode", 0, IFACE_("Resolution"), ICON_NONE); +} + +static void node_init(bNodeTree * /*tree*/, bNode *node) +{ + NodeGeometryPointsToVolume *data = MEM_cnew(__func__); + data->resolution_mode = GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT; + node->storage = data; +} + +static void node_update(bNodeTree *ntree, bNode *node) +{ + const NodeGeometryPointsToVolume &storage = node_storage(*node); + bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size"); + bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount"); + nodeSetSocketAvailability(ntree, + voxel_amount_socket, + storage.resolution_mode == + GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT); + nodeSetSocketAvailability(ntree, + voxel_size_socket, + storage.resolution_mode == + GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE); +} + +static void node_geo_exec(GeoNodeExecParams params) +{ +#ifdef WITH_OPENVDB + GeometrySet geometry_set = params.extract_input("Points"); + const NodeGeometryPointsToVolume &storage = node_storage(params.node()); + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + initialize_volume_component_from_points( + params, storage, geometry_set, openvdb::GRID_LEVEL_SET); + }); + params.set_output("Volume", std::move(geometry_set)); +#else + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, + TIP_("Disabled, Blender was compiled without OpenVDB")); +#endif +} + +} // namespace blender::nodes::node_geo_points_to_sdf_volume_cc + +void register_node_type_geo_points_to_sdf_volume() +{ + namespace file_ns = blender::nodes::node_geo_points_to_sdf_volume_cc; + + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_POINTS_TO_SDF_VOLUME, "Points to SDF Volume", NODE_CLASS_GEOMETRY); + node_type_storage(&ntype, + "NodeGeometryPointsToVolume", + node_free_standard_storage, + node_copy_standard_storage); + node_type_size(&ntype, 170, 120, 700); + ntype.initfunc = file_ns::node_init; + ntype.updatefunc = file_ns::node_update; + ntype.declare = file_ns::node_declare; + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.draw_buttons = file_ns::node_layout; + ntype.gather_add_node_search_ops = file_ns::search_node_add_ops; + ntype.gather_link_search_ops = file_ns::search_link_ops; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc index 6fa4cff9e99..8f7a07b52ce 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc @@ -10,12 +10,128 @@ #include "node_geometry_util.hh" +#include "GEO_points_to_volume.hh" + #include "BKE_lib_id.h" #include "BKE_volume.h" #include "UI_interface.h" #include "UI_resources.h" +#ifdef WITH_OPENVDB +namespace blender::nodes { +static void gather_point_data_from_component(Field radius_field, + const GeometryComponent &component, + Vector &r_positions, + Vector &r_radii) +{ + if (component.is_empty()) { + return; + } + VArray positions = component.attributes()->lookup_or_default( + "position", ATTR_DOMAIN_POINT, {0, 0, 0}); + + bke::GeometryFieldContext field_context{component, ATTR_DOMAIN_POINT}; + const int domain_num = component.attribute_domain_size(ATTR_DOMAIN_POINT); + + r_positions.resize(r_positions.size() + domain_num); + positions.materialize(r_positions.as_mutable_span().take_back(domain_num)); + + r_radii.resize(r_radii.size() + domain_num); + fn::FieldEvaluator evaluator{field_context, domain_num}; + evaluator.add_with_destination(radius_field, r_radii.as_mutable_span().take_back(domain_num)); + evaluator.evaluate(); +} + +static float compute_voxel_size_from_amount(const float voxel_amount, + Span positions, + const float radius) +{ + if (positions.is_empty()) { + return 0.0f; + } + + if (voxel_amount <= 1) { + return 0.0f; + } + + const Bounds bounds = *bounds::min_max(positions); + + /* The voxel size adapts to the final size of the volume. */ + const float diagonal = math::distance(bounds.min, bounds.max); + const float extended_diagonal = diagonal + 2.0f * radius; + const float voxel_size = extended_diagonal / voxel_amount; + return voxel_size; +} + +static void convert_to_grid_index_space(const float voxel_size, + MutableSpan positions, + MutableSpan radii) +{ + const float voxel_size_inv = 1.0f / voxel_size; + for (const int i : positions.index_range()) { + positions[i] *= voxel_size_inv; + /* Better align generated grid with source points. */ + positions[i] -= float3(0.5f); + radii[i] *= voxel_size_inv; + } +} + +void initialize_volume_component_from_points(GeoNodeExecParams ¶ms, + const NodeGeometryPointsToVolume &storage, + GeometrySet &r_geometry_set, + openvdb::GridClass gridClass) +{ + Vector positions; + Vector radii; + Field radius_field = params.get_input>("Radius"); + + for (const GeometryComponentType type : + {GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE}) { + if (r_geometry_set.has(type)) { + gather_point_data_from_component( + radius_field, *r_geometry_set.get_component_for_read(type), positions, radii); + } + } + + if (positions.is_empty()) { + return; + } + + float voxel_size; + if (storage.resolution_mode == GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE) { + voxel_size = params.get_input("Voxel Size"); + } + else if (storage.resolution_mode == GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT) { + const float voxel_amount = params.get_input("Voxel Amount"); + const float max_radius = *std::max_element(radii.begin(), radii.end()); + voxel_size = compute_voxel_size_from_amount(voxel_amount, positions, max_radius); + } + + const double determinant = std::pow(double(voxel_size), 3.0); + if (!BKE_volume_grid_determinant_valid(determinant)) { + return; + } + + Volume *volume = reinterpret_cast(BKE_id_new_nomain(ID_VO, nullptr)); + + convert_to_grid_index_space(voxel_size, positions, radii); + + if (gridClass == openvdb::GRID_FOG_VOLUME) { + const float density = params.get_input("Density"); + blender::geometry::fog_volume_grid_add_from_points( + volume, "density", positions, radii, voxel_size, density); + } + else if (gridClass == openvdb::GRID_LEVEL_SET) { + blender::geometry::sdf_volume_grid_add_from_points( + volume, "distance", positions, radii, voxel_size); + } + r_geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_VOLUME}); + r_geometry_set.replace_volume(volume); +} +} // namespace blender::nodes +#endif + namespace blender::nodes::node_geo_points_to_volume_cc { NODE_STORAGE_FUNCS(NodeGeometryPointsToVolume) @@ -74,171 +190,14 @@ static void node_update(bNodeTree *ntree, bNode *node) GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE); } -#ifdef WITH_OPENVDB -namespace { -/* Implements the interface required by #openvdb::tools::ParticlesToLevelSet. */ -struct ParticleList { - using PosType = openvdb::Vec3R; - - Span positions; - Span radii; - - size_t size() const - { - return size_t(positions.size()); - } - - void getPos(size_t n, openvdb::Vec3R &xyz) const - { - xyz = &positions[n].x; - } - - void getPosRad(size_t n, openvdb::Vec3R &xyz, openvdb::Real &radius) const - { - xyz = &positions[n].x; - radius = radii[n]; - } -}; -} // namespace - -static openvdb::FloatGrid::Ptr generate_volume_from_points(const Span positions, - const Span radii, - const float density) -{ - /* Create a new grid that will be filled. #ParticlesToLevelSet requires the background value to - * be positive. It will be set to zero later on. */ - openvdb::FloatGrid::Ptr new_grid = openvdb::FloatGrid::create(1.0f); - - /* Create a narrow-band level set grid based on the positions and radii. */ - openvdb::tools::ParticlesToLevelSet op{*new_grid}; - /* Don't ignore particles based on their radius. */ - op.setRmin(0.0f); - op.setRmax(FLT_MAX); - ParticleList particles{positions, radii}; - op.rasterizeSpheres(particles); - op.finalize(); - - /* Convert the level set to a fog volume. This also sets the background value to zero. Inside the - * fog there will be a density of 1. */ - openvdb::tools::sdfToFogVolume(*new_grid); - - /* Take the desired density into account. */ - openvdb::tools::foreach (new_grid->beginValueOn(), - [&](const openvdb::FloatGrid::ValueOnIter &iter) { - iter.modifyValue([&](float &value) { value *= density; }); - }); - return new_grid; -} - -static float compute_voxel_size(const GeoNodeExecParams ¶ms, - Span positions, - const float radius) -{ - const NodeGeometryPointsToVolume &storage = node_storage(params.node()); - - if (storage.resolution_mode == GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE) { - return params.get_input("Voxel Size"); - } - - if (positions.is_empty()) { - return 0.0f; - } - - const Bounds bounds = *bounds::min_max(positions); - - const float voxel_amount = params.get_input("Voxel Amount"); - if (voxel_amount <= 1) { - return 0.0f; - } - - /* The voxel size adapts to the final size of the volume. */ - const float diagonal = math::distance(bounds.min, bounds.max); - const float extended_diagonal = diagonal + 2.0f * radius; - const float voxel_size = extended_diagonal / voxel_amount; - return voxel_size; -} - -static void gather_point_data_from_component(GeoNodeExecParams ¶ms, - const GeometryComponent &component, - Vector &r_positions, - Vector &r_radii) -{ - if (component.is_empty()) { - return; - } - VArray positions = component.attributes()->lookup_or_default( - "position", ATTR_DOMAIN_POINT, {0, 0, 0}); - - Field radius_field = params.get_input>("Radius"); - bke::GeometryFieldContext field_context{component, ATTR_DOMAIN_POINT}; - const int domain_num = component.attribute_domain_size(ATTR_DOMAIN_POINT); - - r_positions.resize(r_positions.size() + domain_num); - positions.materialize(r_positions.as_mutable_span().take_back(domain_num)); - - r_radii.resize(r_radii.size() + domain_num); - fn::FieldEvaluator evaluator{field_context, domain_num}; - evaluator.add_with_destination(radius_field, r_radii.as_mutable_span().take_back(domain_num)); - evaluator.evaluate(); -} - -static void convert_to_grid_index_space(const float voxel_size, - MutableSpan positions, - MutableSpan radii) -{ - const float voxel_size_inv = 1.0f / voxel_size; - for (const int i : positions.index_range()) { - positions[i] *= voxel_size_inv; - /* Better align generated grid with source points. */ - positions[i] -= float3(0.5f); - radii[i] *= voxel_size_inv; - } -} - -static void initialize_volume_component_from_points(GeoNodeExecParams ¶ms, - GeometrySet &r_geometry_set) -{ - Vector positions; - Vector radii; - - for (const GeometryComponentType type : - {GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE}) { - if (r_geometry_set.has(type)) { - gather_point_data_from_component( - params, *r_geometry_set.get_component_for_read(type), positions, radii); - } - } - - if (positions.is_empty()) { - return; - } - - const float max_radius = *std::max_element(radii.begin(), radii.end()); - const float voxel_size = compute_voxel_size(params, positions, max_radius); - const double determinant = std::pow(double(voxel_size), 3.0); - if (!BKE_volume_grid_determinant_valid(determinant)) { - return; - } - - Volume *volume = reinterpret_cast(BKE_id_new_nomain(ID_VO, nullptr)); - - const float density = params.get_input("Density"); - convert_to_grid_index_space(voxel_size, positions, radii); - openvdb::FloatGrid::Ptr new_grid = generate_volume_from_points(positions, radii, density); - new_grid->transform().postScale(voxel_size); - BKE_volume_grid_add_vdb(*volume, "density", std::move(new_grid)); - - r_geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_VOLUME}); - r_geometry_set.replace_volume(volume); -} -#endif - static void node_geo_exec(GeoNodeExecParams params) { #ifdef WITH_OPENVDB GeometrySet geometry_set = params.extract_input("Points"); + const NodeGeometryPointsToVolume &storage = node_storage(params.node()); geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { - initialize_volume_component_from_points(params, geometry_set); + initialize_volume_component_from_points( + params, storage, geometry_set, openvdb::GRID_FOG_VOLUME); }); params.set_output("Volume", std::move(geometry_set)); #else diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc index e8de583d6e6..60a12cdde40 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc @@ -165,7 +165,7 @@ static void get_closest_mesh_corners(const Mesh &mesh, { const Span vert_positions = mesh.vert_positions(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); BLI_assert(mesh.totloop > 0); Array poly_indices(positions.size()); @@ -181,8 +181,7 @@ static void get_closest_mesh_corners(const Mesh &mesh, int closest_vert_index = 0; int closest_loop_index = 0; for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) { - const MLoop &loop = loops[loop_index]; - const int vertex_index = loop.v; + const int vertex_index = corner_verts[loop_index]; const float distance_sq = math::distance_squared(position, vert_positions[vertex_index]); if (distance_sq < min_distance_sq) { min_distance_sq = distance_sq; diff --git a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc index 819084cb9fa..5d3992bcd76 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc @@ -149,7 +149,7 @@ static float4x4 create_single_axis_transform(const float3 ¢er, using GetVertexIndicesFn = FunctionRef edges, Span polys, - Span loops, + Span corner_verts, int element_index, VectorSet &r_vertex_indices)>; @@ -161,7 +161,7 @@ static void scale_vertex_islands_uniformly(Mesh &mesh, MutableSpan positions = mesh.vert_positions_for_write(); const Span edges = mesh.edges(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); threading::parallel_for(islands.index_range(), 256, [&](const IndexRange range) { for (const int island_index : range) { @@ -172,7 +172,7 @@ static void scale_vertex_islands_uniformly(Mesh &mesh, VectorSet vertex_indices; for (const int poly_index : island.element_indices) { - get_vertex_indices(edges, polys, loops, poly_index, vertex_indices); + get_vertex_indices(edges, polys, corner_verts, poly_index, vertex_indices); center += params.centers[poly_index]; scale += params.scales[poly_index]; } @@ -199,7 +199,7 @@ static void scale_vertex_islands_on_axis(Mesh &mesh, MutableSpan positions = mesh.vert_positions_for_write(); const Span edges = mesh.edges(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); threading::parallel_for(islands.index_range(), 256, [&](const IndexRange range) { for (const int island_index : range) { @@ -211,7 +211,7 @@ static void scale_vertex_islands_on_axis(Mesh &mesh, VectorSet vertex_indices; for (const int poly_index : island.element_indices) { - get_vertex_indices(edges, polys, loops, poly_index, vertex_indices); + get_vertex_indices(edges, polys, corner_verts, poly_index, vertex_indices); center += params.centers[poly_index]; scale += params.scales[poly_index]; axis += params.axis_vectors[poly_index]; @@ -240,19 +240,19 @@ static void scale_vertex_islands_on_axis(Mesh &mesh, static Vector prepare_face_islands(const Mesh &mesh, const IndexMask face_selection) { const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); /* Use the disjoint set data structure to determine which vertices have to be scaled together. */ DisjointSet disjoint_set(mesh.totvert); for (const int poly_index : face_selection) { const MPoly &poly = polys[poly_index]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); + const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); for (const int loop_index : IndexRange(poly.totloop - 1)) { - const int v1 = poly_loops[loop_index].v; - const int v2 = poly_loops[loop_index + 1].v; + const int v1 = poly_verts[loop_index]; + const int v2 = poly_verts[loop_index + 1]; disjoint_set.join(v1, v2); } - disjoint_set.join(poly_loops.first().v, poly_loops.last().v); + disjoint_set.join(poly_verts.first(), poly_verts.last()); } VectorSet island_ids; @@ -263,8 +263,8 @@ static Vector prepare_face_islands(const Mesh &mesh, const IndexM /* Gather all of the face indices in each island into separate vectors. */ for (const int poly_index : face_selection) { const MPoly &poly = polys[poly_index]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - const int island_id = disjoint_set.find_root(poly_loops[0].v); + const Span poly_verts = corner_verts.slice(poly.loopstart, poly.totloop); + const int island_id = disjoint_set.find_root(poly_verts[0]); const int island_index = island_ids.index_of_or_add(island_id); if (island_index == islands.size()) { islands.append_as(); @@ -278,15 +278,12 @@ static Vector prepare_face_islands(const Mesh &mesh, const IndexM static void get_face_verts(const Span /*edges*/, const Span polys, - const Span loops, + const Span corner_verts, int face_index, VectorSet &r_vertex_indices) { const MPoly &poly = polys[face_index]; - const Span poly_loops = loops.slice(poly.loopstart, poly.totloop); - for (const MLoop &loop : poly_loops) { - r_vertex_indices.add(loop.v); - } + r_vertex_indices.add_multiple(corner_verts.slice(poly.loopstart, poly.totloop)); } static AxisScaleParams evaluate_axis_scale_fields(FieldEvaluator &evaluator, @@ -367,7 +364,7 @@ static Vector prepare_edge_islands(const Mesh &mesh, const IndexM static void get_edge_verts(const Span edges, const Span /*polys*/, - const Span /*loops*/, + const Span /*corner_verts*/, int edge_index, VectorSet &r_vertex_indices) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_sdf_volume_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_sdf_volume_sphere.cc new file mode 100644 index 00000000000..4364dc8dda4 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_sdf_volume_sphere.cc @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifdef WITH_OPENVDB +# include +# include +#endif + +#include "node_geometry_util.hh" + +#include "BKE_geometry_set.hh" +#include "BKE_lib_id.h" +#include "BKE_volume.h" + +#include "NOD_add_node_search.hh" +#include "NOD_socket_search_link.hh" + +namespace blender::nodes::node_geo_sdf_volume_sphere_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input(N_("Radius")).default_value(1.0f).min(0.0f).subtype(PROP_DISTANCE); + b.add_input(N_("Voxel Size")).default_value(0.2f).min(0.01f).subtype(PROP_DISTANCE); + b.add_input(N_("Half-Band Width")) + .description(N_("Half the width of the narrow band in voxel units")) + .default_value(3.0f) + .min(1.01f) + .max(10.0f); + b.add_output(N_("Volume")); +} + +static void search_node_add_ops(GatherAddNodeSearchParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_node_add_ops_for_basic_node(params); + } +} + +static void search_link_ops(GatherLinkSearchOpParams ¶ms) +{ + if (U.experimental.use_new_volume_nodes) { + blender::nodes::search_link_ops_for_basic_node(params); + } +} + +static void node_geo_exec(GeoNodeExecParams params) +{ +#ifdef WITH_OPENVDB + float radius = params.extract_input("Radius"); + float voxel_size = params.extract_input("Voxel Size"); + float half_width = params.extract_input("Half-Band Width"); + + if (radius <= 0.0f) { + params.error_message_add(NodeWarningType::Error, TIP_("Radius must be greater than 0")); + params.set_default_remaining_outputs(); + return; + } + + if (half_width <= 1.0f) { + params.error_message_add(NodeWarningType::Error, + TIP_("Half-band width must be greater than 1")); + params.set_default_remaining_outputs(); + return; + } + + openvdb::FloatGrid::Ptr grid; + + try { + grid = openvdb::tools::createLevelSetSphere( + radius, openvdb::Vec3f(0, 0, 0), voxel_size, half_width); + } + catch (openvdb::ArithmeticError &) { + params.error_message_add(NodeWarningType::Error, TIP_("Voxel size is too small")); + params.set_default_remaining_outputs(); + return; + } + Volume *volume = reinterpret_cast(BKE_id_new_nomain(ID_VO, nullptr)); + BKE_volume_grid_add_vdb(*volume, "distance", std::move(grid)); + + GeometrySet r_geometry_set = GeometrySet::create_with_volume(volume); + params.set_output("Volume", r_geometry_set); +#else + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, + TIP_("Disabled, Blender was compiled without OpenVDB")); +#endif +} + +} // namespace blender::nodes::node_geo_sdf_volume_sphere_cc + +void register_node_type_geo_sdf_volume_sphere() +{ + namespace file_ns = blender::nodes::node_geo_sdf_volume_sphere_cc; + static bNodeType ntype; + geo_node_type_base(&ntype, GEO_NODE_SDF_VOLUME_SPHERE, "SDF Volume Sphere", NODE_CLASS_GEOMETRY); + ntype.declare = file_ns::node_declare; + node_type_size(&ntype, 180, 120, 300); + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.gather_add_node_search_ops = file_ns::search_node_add_ops; + ntype.gather_link_search_ops = file_ns::search_link_ops; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc b/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc index d6a31c9133e..7f1c7d36a8d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc @@ -39,7 +39,7 @@ static VArray construct_uv_gvarray(const Mesh &mesh, { const Span positions = mesh.vert_positions(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); bke::MeshFieldContext face_context{mesh, ATTR_DOMAIN_FACE}; FieldEvaluator face_evaluator{face_context, polys.size()}; @@ -65,10 +65,11 @@ static VArray construct_uv_gvarray(const Mesh &mesh, Array mp_co(poly.totloop); Array mp_uv(poly.totloop); for (const int i : IndexRange(poly.totloop)) { - const MLoop &ml = loops[poly.loopstart + i]; - mp_vkeys[i] = ml.v; - mp_co[i] = positions[ml.v]; - mp_uv[i] = uv[poly.loopstart + i]; + const int corner = poly.loopstart + i; + const int vert = corner_verts[corner]; + mp_vkeys[i] = vert; + mp_co[i] = positions[vert]; + mp_uv[i] = uv[corner]; mp_pin[i] = false; mp_select[i] = false; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc b/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc index 492decd8eb9..98729eb67b6 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc @@ -65,7 +65,7 @@ static VArray construct_uv_gvarray(const Mesh &mesh, const Span positions = mesh.vert_positions(); const Span edges = mesh.edges(); const Span polys = mesh.polys(); - const Span loops = mesh.loops(); + const Span corner_verts = mesh.corner_verts(); bke::MeshFieldContext face_context{mesh, ATTR_DOMAIN_FACE}; FieldEvaluator face_evaluator{face_context, polys.size()}; @@ -82,7 +82,7 @@ static VArray construct_uv_gvarray(const Mesh &mesh, edge_evaluator.evaluate(); const IndexMask seam = edge_evaluator.get_evaluated_as_mask(0); - Array uv(loops.size(), float3(0)); + Array uv(corner_verts.size(), float3(0)); geometry::ParamHandle *handle = geometry::uv_parametrizer_construct_begin(); for (const int poly_index : selection) { @@ -93,10 +93,11 @@ static VArray construct_uv_gvarray(const Mesh &mesh, Array mp_co(poly.totloop); Array mp_uv(poly.totloop); for (const int i : IndexRange(poly.totloop)) { - const MLoop &ml = loops[poly.loopstart + i]; - mp_vkeys[i] = ml.v; - mp_co[i] = positions[ml.v]; - mp_uv[i] = uv[poly.loopstart + i]; + const int corner = poly.loopstart + i; + const int vert = corner_verts[corner]; + mp_vkeys[i] = vert; + mp_co[i] = positions[vert]; + mp_uv[i] = uv[corner]; mp_pin[i] = false; mp_select[i] = false; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc index 77bf69d187c..99311bbd003 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc @@ -125,7 +125,7 @@ static Mesh *create_mesh_from_volume_grids(Span gri BKE_id_material_eval_ensure_default_slot(&mesh->id); MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan polys = mesh->polys_for_write(); - MutableSpan loops = mesh->loops_for_write(); + MutableSpan corner_verts = mesh->corner_verts_for_write(); for (const int i : grids.index_range()) { const bke::OpenVDBMeshData &data = mesh_data[i]; @@ -137,7 +137,7 @@ static Mesh *create_mesh_from_volume_grids(Span gri loop_offsets[i], positions, polys, - loops); + corner_verts); } BKE_mesh_calc_edges(mesh, false, false); diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 16ffa2f3238..c0ce4348821 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -3468,8 +3468,8 @@ static Py_hash_t bpy_bm_hash(PyObject *self) return _Py_HashPointer(((BPy_BMesh *)self)->bm); } -/* Type Docstrings - * =============== */ +/* Type Doc-strings + * ================ */ PyDoc_STRVAR(bpy_bmesh_doc, "The BMesh data structure\n"); PyDoc_STRVAR(bpy_bmvert_doc, "The BMesh vertex type\n"); @@ -3694,7 +3694,7 @@ void BPy_BM_init_types(void) BPy_BMFaceSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter; BPy_BMLoopSeq_Type.tp_iter = NULL; /* no mapping */ - /* only 1 iteratir so far */ + /* Only 1 iterator so far. */ BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bmiter_next; BPy_BMIter_Type.tp_iter = PyObject_SelfIter; diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index ed25caee74d..e3feb5196b4 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -380,7 +380,7 @@ void BPy_BM_init_types_select(void) BPy_BMEditSelSeq_Type.tp_iter = (getiterfunc)bpy_bmeditselseq_iter; - /* only 1 iteratir so far */ + /* Only 1 iterator so far. */ BPy_BMEditSelIter_Type.tp_iternext = (iternextfunc)bpy_bmeditseliter_next; BPy_BMEditSelSeq_Type.tp_dealloc = NULL; //(destructor)bpy_bmeditselseq_dealloc; diff --git a/source/blender/python/gpu/gpu_py_state.c b/source/blender/python/gpu/gpu_py_state.c index 870a83eb9a8..2db477bfa9b 100644 --- a/source/blender/python/gpu/gpu_py_state.c +++ b/source/blender/python/gpu/gpu_py_state.c @@ -470,7 +470,7 @@ static struct PyMethodDef pygpu_state__tp_methods[] = { pygpu_state_scissor_get_doc}, {"scissor_test_set", (PyCFunction)pygpu_state_scissor_test_set, - METH_VARARGS, + METH_O, pygpu_state_scissor_test_set_doc}, {"line_width_set", (PyCFunction)pygpu_state_line_width_set, diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index 3fa3c5d75b1..b9b1b629eca 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -829,7 +829,7 @@ PyObject *BPY_app_translations_struct(void) { PyObject *ret; - /* Let's finalize our contexts structseq definition! */ + /* Let's finalize our contexts `PyStructSequence` definition! */ { BLT_i18n_contexts_descriptor *ctxt; PyStructSequence_Field *desc; diff --git a/source/blender/python/mathutils/mathutils_bvhtree.cc b/source/blender/python/mathutils/mathutils_bvhtree.cc index bf86ca4f1fc..ecc41aef0dc 100644 --- a/source/blender/python/mathutils/mathutils_bvhtree.cc +++ b/source/blender/python/mathutils/mathutils_bvhtree.cc @@ -803,7 +803,7 @@ static PyObject *C_BVHTree_FromPolygons(PyObject * /*cls*/, PyObject *args, PyOb } *p_plink_prev = nullptr; - /* all ngon's are parsed, now tessellate */ + /* All NGON's are parsed, now tessellate. */ pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__); tris = static_cast(MEM_mallocN(sizeof(*tris) * size_t(tris_len), __func__)); @@ -1111,7 +1111,7 @@ static PyObject *C_BVHTree_FromObject(PyObject * /*cls*/, PyObject *args, PyObje bool free_mesh = false; const MLoopTri *lt; - const MLoop *mloop; + const int *corner_verts; float(*coords)[3] = nullptr; uint(*tris)[3] = nullptr; @@ -1153,7 +1153,7 @@ static PyObject *C_BVHTree_FromObject(PyObject * /*cls*/, PyObject *args, PyObje tris = static_cast(MEM_mallocN(sizeof(*tris) * size_t(tris_len), __func__)); memcpy(coords, BKE_mesh_vert_positions(mesh), sizeof(float[3]) * size_t(mesh->totvert)); - mloop = BKE_mesh_loops(mesh); + corner_verts = BKE_mesh_corner_verts(mesh); } { @@ -1177,9 +1177,9 @@ static PyObject *C_BVHTree_FromObject(PyObject * /*cls*/, PyObject *args, PyObje for (i = 0; i < tris_len; i++, lt++) { float co[3][3]; - tris[i][0] = mloop[lt->tri[0]].v; - tris[i][1] = mloop[lt->tri[1]].v; - tris[i][2] = mloop[lt->tri[2]].v; + tris[i][0] = (uint)corner_verts[lt->tri[0]]; + tris[i][1] = (uint)corner_verts[lt->tri[1]]; + tris[i][2] = (uint)corner_verts[lt->tri[2]]; copy_v3_v3(co[0], coords[tris[i][0]]); copy_v3_v3(co[1], coords[tris[i][1]]); diff --git a/source/blender/render/intern/bake.cc b/source/blender/render/intern/bake.cc index f114f5cd3b9..474ddf73038 100644 --- a/source/blender/render/intern/bake.cc +++ b/source/blender/render/intern/bake.cc @@ -464,7 +464,7 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval const blender::Span positions = me->vert_positions(); const blender::Span polys = me->polys(); - const blender::Span loops = me->loops(); + const blender::Span corner_verts = me->corner_verts(); const bke::AttributeAccessor attributes = me->attributes(); const VArray sharp_faces = attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); @@ -480,10 +480,10 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval if (!precomputed_normals.is_empty()) { blender::bke::mesh::looptris_calc_with_normals( - positions, polys, loops, precomputed_normals, {looptri, tottri}); + positions, polys, corner_verts, precomputed_normals, {looptri, tottri}); } else { - blender::bke::mesh::looptris_calc(positions, polys, loops, {looptri, tottri}); + blender::bke::mesh::looptris_calc(positions, polys, corner_verts, {looptri, tottri}); } const TSpace *tspace = nullptr; @@ -505,12 +505,12 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval const MLoopTri *lt = &looptri[i]; const MPoly &poly = polys[lt->poly]; - triangles[i].positions[0] = positions[loops[lt->tri[0]].v]; - triangles[i].positions[1] = positions[loops[lt->tri[1]].v]; - triangles[i].positions[2] = positions[loops[lt->tri[2]].v]; - triangles[i].vert_normals[0] = vert_normals[loops[lt->tri[0]].v]; - triangles[i].vert_normals[1] = vert_normals[loops[lt->tri[1]].v]; - triangles[i].vert_normals[2] = vert_normals[loops[lt->tri[2]].v]; + triangles[i].positions[0] = positions[corner_verts[lt->tri[0]]]; + triangles[i].positions[1] = positions[corner_verts[lt->tri[1]]]; + triangles[i].positions[2] = positions[corner_verts[lt->tri[2]]]; + triangles[i].vert_normals[0] = vert_normals[corner_verts[lt->tri[0]]]; + triangles[i].vert_normals[1] = vert_normals[corner_verts[lt->tri[1]]]; + triangles[i].vert_normals[2] = vert_normals[corner_verts[lt->tri[2]]]; triangles[i].is_smooth = !sharp_faces[lt->poly]; if (tangent) { @@ -527,8 +527,8 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval if (calculate_normal) { if (lt->poly != mpoly_prev) { - no = blender::bke::mesh::poly_normal_calc(positions, - loops.slice(poly.loopstart, poly.totloop)); + no = blender::bke::mesh::poly_normal_calc( + positions, corner_verts.slice(poly.loopstart, poly.totloop)); mpoly_prev = lt->poly; } copy_v3_v3(triangles[i].normal, no); @@ -752,7 +752,7 @@ void RE_bake_pixels_populate(Mesh *me, MLoopTri *looptri = static_cast(MEM_mallocN(sizeof(*looptri) * tottri, __func__)); blender::bke::mesh::looptris_calc( - me->vert_positions(), me->polys(), me->loops(), {looptri, tottri}); + me->vert_positions(), me->polys(), me->corner_verts(), {looptri, tottri}); const int *material_indices = BKE_mesh_material_indices(me); const int materials_num = targets->materials_num; diff --git a/source/blender/render/intern/multires_bake.cc b/source/blender/render/intern/multires_bake.cc index 71fdfd54742..7e4921d6a70 100644 --- a/source/blender/render/intern/multires_bake.cc +++ b/source/blender/render/intern/multires_bake.cc @@ -65,8 +65,8 @@ struct MResolvePixelData { int verts_num; const MPoly *polys; const int *material_indices; + const int *corner_verts; const bool *sharp_faces; - MLoop *mloop; float (*mloopuv)[2]; float uv_offset[2]; const MLoopTri *mlooptri; @@ -119,7 +119,7 @@ static void multiresbake_get_normal(const MResolvePixelData *data, const bool smoothnormal = !(data->sharp_faces && data->sharp_faces[poly_index]); if (smoothnormal) { - const int vi = data->mloop[data->mlooptri[tri_num].tri[vert_index]].v; + const int vi = data->corner_verts[data->mlooptri[tri_num].tri[vert_index]]; copy_v3_v3(r_normal, data->vert_normals[vi]); } else { @@ -131,7 +131,7 @@ static void multiresbake_get_normal(const MResolvePixelData *data, r_normal, blender::bke::mesh::poly_normal_calc( {reinterpret_cast(data->vert_positions), data->verts_num}, - {&data->mloop[poly.loopstart], poly.totloop})); + {&data->corner_verts[poly.loopstart], poly.totloop})); } } } @@ -480,9 +480,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, const float(*positions)[3] = (float(*)[3])dm->getVertArray(dm); const MPoly *polys = dm->getPolyArray(dm); - MLoop *mloop = dm->getLoopArray(dm); float(*mloopuv)[2] = static_cast(dm->getLoopDataArray(dm, CD_PROP_FLOAT2)); - float *pvtangent = nullptr; + float *pvtangent = NULL; ListBase threads; int i, tot_thread = bkr->threads > 0 ? bkr->threads : BLI_system_thread_count(); @@ -496,7 +495,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, temp_mesh->totvert * sizeof(float[3])); temp_mesh->edges_for_write().copy_from({dm->getEdgeArray(dm), temp_mesh->totedge}); temp_mesh->polys_for_write().copy_from({dm->getPolyArray(dm), temp_mesh->totpoly}); - temp_mesh->loops_for_write().copy_from({dm->getLoopArray(dm), temp_mesh->totloop}); + temp_mesh->corner_verts_for_write().copy_from({dm->getCornerVertArray(dm), temp_mesh->totloop}); + temp_mesh->corner_edges_for_write().copy_from({dm->getCornerEdgeArray(dm), temp_mesh->totloop}); const blender::Span vert_normals = temp_mesh->vert_normals(); const blender::Span poly_normals = temp_mesh->poly_normals(); @@ -506,7 +506,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, positions, dm->getPolyArray(dm), dm->getNumPolys(dm), - dm->getLoopArray(dm), + dm->getCornerVertArray(dm), dm->getLoopTriArray(dm), dm->getNumLoopTri(dm), static_cast( @@ -565,7 +565,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, handle->data.mloopuv = mloopuv; BKE_image_get_tile_uv(ima, tile->tile_number, handle->data.uv_offset); handle->data.mlooptri = mlooptri; - handle->data.mloop = mloop; + handle->data.corner_verts = dm->getCornerVertArray(dm); handle->data.pvtangent = pvtangent; handle->data.poly_normals = poly_normals.data(); /* don't strictly need this */ handle->data.w = ibuf->x; @@ -721,7 +721,7 @@ static void get_ccgdm_data(DerivedMesh *lodm, * mode = 1: interpolate coord */ static void interp_bilinear_mpoly(DerivedMesh *dm, - MLoop *mloop, + const int *corner_verts, const MPoly &poly, const float u, const float v, @@ -731,23 +731,23 @@ static void interp_bilinear_mpoly(DerivedMesh *dm, float data[4][3]; if (mode == 0) { - dm->getVertNo(dm, mloop[poly.loopstart].v, data[0]); - dm->getVertNo(dm, mloop[poly.loopstart + 1].v, data[1]); - dm->getVertNo(dm, mloop[poly.loopstart + 2].v, data[2]); - dm->getVertNo(dm, mloop[poly.loopstart + 3].v, data[3]); + dm->getVertNo(dm, corner_verts[poly.loopstart], data[0]); + dm->getVertNo(dm, corner_verts[poly.loopstart + 1], data[1]); + dm->getVertNo(dm, corner_verts[poly.loopstart + 2], data[2]); + dm->getVertNo(dm, corner_verts[poly.loopstart + 3], data[3]); } else { - dm->getVertCo(dm, mloop[poly.loopstart].v, data[0]); - dm->getVertCo(dm, mloop[poly.loopstart + 1].v, data[1]); - dm->getVertCo(dm, mloop[poly.loopstart + 2].v, data[2]); - dm->getVertCo(dm, mloop[poly.loopstart + 3].v, data[3]); + dm->getVertCo(dm, corner_verts[poly.loopstart], data[0]); + dm->getVertCo(dm, corner_verts[poly.loopstart + 1], data[1]); + dm->getVertCo(dm, corner_verts[poly.loopstart + 2], data[2]); + dm->getVertCo(dm, corner_verts[poly.loopstart + 3], data[3]); } interp_bilinear_quad_v3(data, u, v, res); } static void interp_barycentric_mlooptri(DerivedMesh *dm, - MLoop *mloop, + const int *corner_verts, const MLoopTri *lt, const float u, const float v, @@ -757,14 +757,14 @@ static void interp_barycentric_mlooptri(DerivedMesh *dm, float data[3][3]; if (mode == 0) { - dm->getVertNo(dm, mloop[lt->tri[0]].v, data[0]); - dm->getVertNo(dm, mloop[lt->tri[1]].v, data[1]); - dm->getVertNo(dm, mloop[lt->tri[2]].v, data[2]); + dm->getVertNo(dm, corner_verts[lt->tri[0]], data[0]); + dm->getVertNo(dm, corner_verts[lt->tri[1]], data[1]); + dm->getVertNo(dm, corner_verts[lt->tri[2]], data[2]); } else { - dm->getVertCo(dm, mloop[lt->tri[0]].v, data[0]); - dm->getVertCo(dm, mloop[lt->tri[1]].v, data[1]); - dm->getVertCo(dm, mloop[lt->tri[2]].v, data[2]); + dm->getVertCo(dm, corner_verts[lt->tri[0]], data[0]); + dm->getVertCo(dm, corner_verts[lt->tri[1]], data[1]); + dm->getVertCo(dm, corner_verts[lt->tri[2]], data[2]); } interp_barycentric_tri_v3(data, u, v, res); @@ -840,7 +840,7 @@ static void apply_heights_callback(DerivedMesh *lores_dm, const int y) { const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index; - MLoop *mloop = lores_dm->getLoopArray(lores_dm); + const int *corner_verts = lores_dm->getCornerVertArray(lores_dm); const MPoly &poly = lores_dm->getPolyArray(lores_dm)[lt->poly]; float(*mloopuv)[2] = static_cast( lores_dm->getLoopDataArray(lores_dm, CD_PROP_FLOAT2)); @@ -884,12 +884,12 @@ static void apply_heights_callback(DerivedMesh *lores_dm, } else { if (poly.totloop == 4) { - interp_bilinear_mpoly(lores_dm, mloop, poly, uv[0], uv[1], 1, p0); - interp_bilinear_mpoly(lores_dm, mloop, poly, uv[0], uv[1], 0, n); + interp_bilinear_mpoly(lores_dm, corner_verts, poly, uv[0], uv[1], 1, p0); + interp_bilinear_mpoly(lores_dm, corner_verts, poly, uv[0], uv[1], 0, n); } else { - interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 1, p0); - interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 0, n); + interp_barycentric_mlooptri(lores_dm, corner_verts, lt, uv[0], uv[1], 1, p0); + interp_barycentric_mlooptri(lores_dm, corner_verts, lt, uv[0], uv[1], 0, n); } } diff --git a/source/blender/render/intern/texture_margin.cc b/source/blender/render/intern/texture_margin.cc index f99e895d303..84b337282de 100644 --- a/source/blender/render/intern/texture_margin.cc +++ b/source/blender/render/intern/texture_margin.cc @@ -54,30 +54,24 @@ class TextureMarginMap { uint32_t value_to_store_; char *mask_; - MPoly const *polys_; - MLoop const *mloop_; - float2 const *mloopuv_; - int totpoly_; - int totloop_; + Span polys_; + Span corner_edges_; + Span mloopuv_; int totedge_; public: TextureMarginMap(size_t w, size_t h, const float uv_offset[2], - MPoly const *polys, - MLoop const *mloop, - float2 const *mloopuv, - int totpoly, - int totloop, - int totedge) + const int totedge, + const Span polys, + const Span corner_edges, + const Span mloopuv) : w_(w), h_(h), polys_(polys), - mloop_(mloop), + corner_edges_(corner_edges), mloopuv_(mloopuv), - totpoly_(totpoly), - totloop_(totloop), totedge_(totedge) { copy_v2_v2(uv_offset_, uv_offset); @@ -290,16 +284,16 @@ class TextureMarginMap { void build_tables() { - loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map({polys_, totpoly_}, - totloop_); + loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys_, + corner_edges_.size()); - loop_adjacency_map_.resize(totloop_, -1); + loop_adjacency_map_.resize(corner_edges_.size(), -1); Vector tmpmap; tmpmap.resize(totedge_, -1); - for (size_t i = 0; i < totloop_; i++) { - int edge = mloop_[i].e; + for (const int64_t i : corner_edges_.index_range()) { + int edge = corner_edges_[i]; if (tmpmap[edge] == -1) { loop_adjacency_map_[i] = -1; tmpmap[edge] = i; @@ -481,60 +475,17 @@ const int TextureMarginMap::distances[8] = {2, 3, 2, 3, 2, 3, 2, 3}; static void generate_margin(ImBuf *ibuf, char *mask, const int margin, - const Mesh *me, - DerivedMesh *dm, - char const *uv_layer, + const Span vert_positions, + const int edges_num, + const Span polys, + const Span corner_edges, + const Span mloopuv, const float uv_offset[2]) { + Array looptris(poly_to_tri_count(polys.size(), corner_edges.size())); + bke::mesh::looptris_calc(vert_positions, polys, corner_edges, looptris); - const MPoly *polys; - const MLoop *mloop; - const float2 *mloopuv; - int totpoly, totloop, totedge; - - int tottri; - const MLoopTri *looptri; - MLoopTri *looptri_mem = nullptr; - - if (me) { - BLI_assert(dm == nullptr); - totpoly = me->totpoly; - totloop = me->totloop; - totedge = me->totedge; - polys = me->polys().data(); - mloop = me->loops().data(); - - if ((uv_layer == nullptr) || (uv_layer[0] == '\0')) { - mloopuv = static_cast(CustomData_get_layer(&me->ldata, CD_PROP_FLOAT2)); - } - else { - int uv_id = CustomData_get_named_layer(&me->ldata, CD_PROP_FLOAT2, uv_layer); - mloopuv = static_cast( - CustomData_get_layer_n(&me->ldata, CD_PROP_FLOAT2, uv_id)); - } - - tottri = poly_to_tri_count(me->totpoly, me->totloop); - looptri_mem = static_cast(MEM_mallocN(sizeof(*looptri) * tottri, __func__)); - bke::mesh::looptris_calc( - me->vert_positions(), me->polys(), me->loops(), {looptri_mem, tottri}); - looptri = looptri_mem; - } - else { - BLI_assert(dm != nullptr); - BLI_assert(me == nullptr); - totpoly = dm->getNumPolys(dm); - totedge = dm->getNumEdges(dm); - totloop = dm->getNumLoops(dm); - polys = dm->getPolyArray(dm); - mloop = dm->getLoopArray(dm); - mloopuv = static_cast(dm->getLoopDataArray(dm, CD_PROP_FLOAT2)); - - looptri = dm->getLoopTriArray(dm); - tottri = dm->getNumLoopTri(dm); - } - - TextureMarginMap map( - ibuf->x, ibuf->y, uv_offset, polys, mloop, mloopuv, totpoly, totloop, totedge); + TextureMarginMap map(ibuf->x, ibuf->y, uv_offset, edges_num, polys, corner_edges, mloopuv); bool draw_new_mask = false; /* Now the map contains 3 sorts of values: 0xFFFFFFFF for empty pixels, `0x80000000 + polyindex` @@ -547,8 +498,8 @@ static void generate_margin(ImBuf *ibuf, draw_new_mask = true; } - for (int i = 0; i < tottri; i++) { - const MLoopTri *lt = &looptri[i]; + for (const int i : looptris.index_range()) { + const MLoopTri *lt = &looptris[i]; float vec[3][2]; for (int a = 0; a < 3; a++) { @@ -587,10 +538,6 @@ static void generate_margin(ImBuf *ibuf, IMB_filter_extend(ibuf, mask, margin); MEM_freeN(mask); - - if (looptri_mem) { - MEM_freeN(looptri_mem); - } } } // namespace blender::render::texturemargin @@ -598,17 +545,45 @@ static void generate_margin(ImBuf *ibuf, void RE_generate_texturemargin_adjacentfaces(ImBuf *ibuf, char *mask, const int margin, - const Mesh *me, + const Mesh *mesh, char const *uv_layer, const float uv_offset[2]) { - blender::render::texturemargin::generate_margin( - ibuf, mask, margin, me, nullptr, uv_layer, uv_offset); + const blender::float2 *mloopuv; + if ((uv_layer == nullptr) || (uv_layer[0] == '\0')) { + mloopuv = static_cast( + CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2)); + } + else { + mloopuv = static_cast( + CustomData_get_layer_named(&mesh->ldata, CD_PROP_FLOAT2, uv_layer)); + } + + blender::render::texturemargin::generate_margin(ibuf, + mask, + margin, + mesh->vert_positions(), + mesh->totedge, + mesh->polys(), + mesh->corner_edges(), + {mloopuv, mesh->totloop}, + uv_offset); } void RE_generate_texturemargin_adjacentfaces_dm( ImBuf *ibuf, char *mask, const int margin, DerivedMesh *dm, const float uv_offset[2]) { + const blender::float2 *mloopuv = static_cast( + dm->getLoopDataArray(dm, CD_PROP_FLOAT2)); + blender::render::texturemargin::generate_margin( - ibuf, mask, margin, nullptr, dm, nullptr, uv_offset); + ibuf, + mask, + margin, + {reinterpret_cast(dm->getVertArray(dm)), dm->getNumVerts(dm)}, + dm->getNumEdges(dm), + {dm->getPolyArray(dm), dm->getNumPolys(dm)}, + {dm->getCornerEdgeArray(dm), dm->getNumLoops(dm)}, + {mloopuv, dm->getNumLoops(dm)}, + uv_offset); } diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c index d8b9a1955f5..d342c7362bb 100644 --- a/source/blender/render/intern/texture_pointdensity.c +++ b/source/blender/render/intern/texture_pointdensity.c @@ -267,7 +267,7 @@ static void pointdensity_cache_vertex_color(PointDensity *pd, Mesh *mesh, float *data_color) { - const MLoop *mloop = BKE_mesh_loops(mesh); + const int *corner_verts = BKE_mesh_corner_verts(mesh); const int totloop = mesh->totloop; char layername[MAX_CUSTOMDATA_LAYER_NAME]; int i; @@ -288,7 +288,7 @@ static void pointdensity_cache_vertex_color(PointDensity *pd, int *mcorners = MEM_callocN(sizeof(int) * pd->totpoints, "point density corner count"); for (i = 0; i < totloop; i++) { - int v = mloop[i].v; + int v = corner_verts[i]; if (mcorners[v] == 0) { rgb_uchar_to_float(&data_color[v * 3], &mcol[i].r); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index c681049c4b7..712b16f4113 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -187,7 +187,7 @@ int WM_window_pixels_y(const struct wmWindow *win); void WM_window_rect_calc(const struct wmWindow *win, struct rcti *r_rect); /** * Get boundaries usable by screen-layouts, excluding global areas. - * \note Depends on #U.dpi_fac. Should that be outdated, call #WM_window_set_dpi first. + * \note Depends on #UI_SCALE_FAC. Should that be outdated, call #WM_window_set_dpi first. */ void WM_window_screen_rect_calc(const struct wmWindow *win, struct rcti *r_rect); bool WM_window_is_fullscreen(const struct wmWindow *win); @@ -1258,6 +1258,15 @@ bool WM_gesture_is_modal_first(const struct wmGesture *gesture); void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op); void WM_event_fileselect_event(struct wmWindowManager *wm, void *ophandle, int eventval); +/* Event consecutive data. */ + +/** Return a borrowed reference to the custom-data. */ +void *WM_event_consecutive_data_get(wmWindow *win, const char *id); +/** Set the custom-data (and own the pointer), free with #MEM_freeN. */ +void WM_event_consecutive_data_set(wmWindow *win, const char *id, void *custom_data); +/** Clear and free the consecutive custom-data. */ +void WM_event_consecutive_data_free(wmWindow *win); + /** * Sets the active region for this space from the context. * @@ -1650,6 +1659,9 @@ char WM_event_utf8_to_ascii(const struct wmEvent *event) ATTR_NONNULL(1) ATTR_WA */ bool WM_cursor_test_motion_and_update(const int mval[2]) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT; +bool WM_event_consecutive_gesture_test(const wmEvent *event); +bool WM_event_consecutive_gesture_test_break(const wmWindow *win, const wmEvent *event); + int WM_event_drag_threshold(const struct wmEvent *event); bool WM_event_drag_test(const struct wmEvent *event, const int prev_xy[2]); bool WM_event_drag_test_with_delta(const struct wmEvent *event, const int delta[2]); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 6cea9719d2d..3e97abca3be 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -614,11 +614,19 @@ typedef enum eWM_EventFlag { * See #KMI_REPEAT_IGNORE for details on how key-map handling uses this. */ WM_EVENT_IS_REPEAT = (1 << 1), + /** + * Generated for consecutive track-pad or NDOF-motion events, + * the repeat chain is broken by key/button events, + * or cursor motion exceeding #WM_EVENT_CURSOR_MOTION_THRESHOLD. + * + * Changing the type of track-pad or gesture event also breaks the chain. + */ + WM_EVENT_IS_CONSECUTIVE = (1 << 2), /** * Mouse-move events may have this flag set to force creating a click-drag event * even when the threshold has not been met. */ - WM_EVENT_FORCE_DRAG_THRESHOLD = (1 << 2), + WM_EVENT_FORCE_DRAG_THRESHOLD = (1 << 3), } eWM_EventFlag; ENUM_OPERATORS(eWM_EventFlag, WM_EVENT_FORCE_DRAG_THRESHOLD); @@ -767,7 +775,7 @@ typedef struct wmEvent { * * Always check for <= this value since it may be zero. */ -#define WM_EVENT_CURSOR_MOTION_THRESHOLD ((float)U.move_threshold * U.dpi_fac) +#define WM_EVENT_CURSOR_MOTION_THRESHOLD ((float)U.move_threshold * UI_SCALE_FAC) /** Motion progress, for modal handlers. */ typedef enum { diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c index 9d212798f39..f503a089b76 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c @@ -453,7 +453,7 @@ void WM_gizmo_modal_set_while_modal(struct wmGizmoMap *gzmap, void wm_gizmo_calculate_scale(wmGizmo *gz, const bContext *C) { const RegionView3D *rv3d = CTX_wm_region_view3d(C); - float scale = UI_DPI_FAC; + float scale = UI_SCALE_FAC; if ((gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_SCALE) == 0) { scale *= U.gizmo_size; diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 671a69003dd..16c36a270bf 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -179,6 +179,8 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id) win->event_queue_check_click = 0; win->event_queue_check_drag = 0; win->event_queue_check_drag_handled = 0; + win->event_queue_consecutive_gesture_type = 0; + win->event_queue_consecutive_gesture_data = NULL; BLO_read_data_address(reader, &win->stereo3d_format); /* Multi-view always fallback to anaglyph at file opening diff --git a/source/blender/windowmanager/intern/wm_dragdrop.cc b/source/blender/windowmanager/intern/wm_dragdrop.cc index aec761da5ff..e9ae895c4da 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.cc +++ b/source/blender/windowmanager/intern/wm_dragdrop.cc @@ -884,13 +884,13 @@ static void wm_drag_draw_icon(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag col); } else { - int padding = 4 * UI_DPI_FAC; + int padding = 4 * UI_SCALE_FAC; x = xy[0] - 2 * padding; - y = xy[1] - 2 * UI_DPI_FAC; + y = xy[1] - 2 * UI_SCALE_FAC; const uchar text_col[] = {255, 255, 255, 255}; UI_icon_draw_ex( - x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT); + x, y, drag->icon, UI_INV_SCALE_FAC, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT); } } @@ -903,8 +903,8 @@ static void wm_drag_draw_item_name(wmDrag *drag, const int x, const int y) void WM_drag_draw_item_name_fn(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag, const int xy[2]) { - int x = xy[0] + 10 * UI_DPI_FAC; - int y = xy[1] + 1 * UI_DPI_FAC; + int x = xy[0] + 10 * UI_SCALE_FAC; + int y = xy[1] + 1 * UI_SCALE_FAC; wm_drag_draw_item_name(drag, x, y); } @@ -915,8 +915,8 @@ static void wm_drag_draw_tooltip(bContext *C, wmWindow *win, wmDrag *drag, const /* Some callbacks require the region. */ return; } - int iconsize = UI_DPI_ICON_SIZE; - int padding = 4 * UI_DPI_FAC; + int iconsize = UI_ICON_SIZE; + int padding = 4 * UI_SCALE_FAC; char *tooltip = nullptr; if (drag->drop_state.active_dropbox) { @@ -973,13 +973,13 @@ static void wm_drag_draw_default(bContext *C, wmWindow *win, wmDrag *drag, const /* Item name. */ if (drag->imb) { - int iconsize = UI_DPI_ICON_SIZE; + int iconsize = UI_ICON_SIZE; xy_tmp[0] = xy[0] - (wm_drag_imbuf_icon_width_get(drag) / 2); xy_tmp[1] = xy[1] - (wm_drag_imbuf_icon_height_get(drag) / 2) - iconsize; } else { - xy_tmp[0] = xy[0] + 10 * UI_DPI_FAC; - xy_tmp[1] = xy[1] + 1 * UI_DPI_FAC; + xy_tmp[0] = xy[0] + 10 * UI_SCALE_FAC; + xy_tmp[1] = xy[1] + 1 * UI_SCALE_FAC; } wm_drag_draw_item_name(drag, UNPACK2(xy_tmp)); diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 15707553e9d..1e0002a4f11 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -291,7 +291,7 @@ static void wm_software_cursor_draw_crosshair(const int event_xy[2]) /* Draw a primitive cross-hair cursor. * NOTE: the `win->cursor` could be used for drawing although it's complicated as some cursors * are set by the operating-system, where the pixel information isn't easily available. */ - const float unit = max_ff(U.dpi_fac, 1.0f); + const float unit = max_ff(UI_SCALE_FAC, 1.0f); uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); diff --git a/source/blender/windowmanager/intern/wm_event_query.c b/source/blender/windowmanager/intern/wm_event_query.c index 2e1afe808ad..18864b35aac 100644 --- a/source/blender/windowmanager/intern/wm_event_query.c +++ b/source/blender/windowmanager/intern/wm_event_query.c @@ -103,6 +103,7 @@ void WM_event_print(const wmEvent *event) struct FlagIdentifierPair flag_data[] = { {"SCROLL_INVERT", WM_EVENT_SCROLL_INVERT}, {"IS_REPEAT", WM_EVENT_IS_REPEAT}, + {"IS_CONSECUTIVE", WM_EVENT_IS_CONSECUTIVE}, {"FORCE_DRAG_THRESHOLD", WM_EVENT_FORCE_DRAG_THRESHOLD}, }; event_ids_from_flag(flag_id, sizeof(flag_id), flag_data, ARRAY_SIZE(flag_data), event->flag); @@ -336,6 +337,51 @@ bool WM_cursor_test_motion_and_update(const int mval[2]) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Event Consecutive Checks + * \{ */ + +/** + * Return true if this event type is a candidate for being flagged as consecutive. + * + * See: #WM_EVENT_IS_CONSECUTIVE doc-string. + */ +bool WM_event_consecutive_gesture_test(const wmEvent *event) +{ + return ISMOUSE_GESTURE(event->type) || (event->type == NDOF_MOTION); +} + +/** + * Return true if this event should break the chain of consecutive gestures. + * Practically all intentional user input should, key presses or button clicks. + */ +bool WM_event_consecutive_gesture_test_break(const wmWindow *win, const wmEvent *event) +{ + /* Cursor motion breaks the chain. */ + if (ISMOUSE_MOTION(event->type)) { + /* Mouse motion is checked because the user may navigate to a new area + * and perform the same gesture - logically it's best to view this as two separate gestures. */ + if (len_manhattan_v2v2_int(event->xy, win->event_queue_consecutive_gesture_xy) > + WM_EVENT_CURSOR_MOTION_THRESHOLD) { + return true; + } + } + else if (ISKEYBOARD_OR_BUTTON(event->type)) { + /* Modifiers are excluded because from a user perspective, + * releasing a modifier (for e.g.) should not begin a new action. */ + if (!ISKEYMODIFIER(event->type)) { + return true; + } + } + else if (event->type == WINDEACTIVATE) { + return true; + } + + return false; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Event Click/Drag Checks * @@ -362,7 +408,7 @@ int WM_event_drag_threshold(const struct wmEvent *event) /* Typically keyboard, could be NDOF button or other less common types. */ drag_threshold = U.drag_threshold; } - return drag_threshold * U.dpi_fac; + return drag_threshold * UI_SCALE_FAC; } bool WM_event_drag_test_with_delta(const wmEvent *event, const int drag_delta[2]) diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index 5042ad1c1ee..dcf73332410 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -2643,8 +2643,8 @@ static eHandlerActionFlag wm_handler_fileselect_do(bContext *C, IFACE_("Blender File View"), WM_window_pixels_x(win) / 2, WM_window_pixels_y(win) / 2, - U.file_space_data.temp_win_sizex * UI_DPI_FAC, - U.file_space_data.temp_win_sizey * UI_DPI_FAC, + U.file_space_data.temp_win_sizex * UI_SCALE_FAC, + U.file_space_data.temp_win_sizey * UI_SCALE_FAC, SPACE_FILE, U.filebrowser_display_type, true))) { @@ -3966,6 +3966,27 @@ void wm_event_do_handlers(bContext *C) } const bool event_queue_check_drag_prev = win->event_queue_check_drag; + { + const bool is_consecutive = WM_event_consecutive_gesture_test(event); + if (win->event_queue_consecutive_gesture_type != 0) { + if (event->type == win->event_queue_consecutive_gesture_type) { + event->flag |= WM_EVENT_IS_CONSECUTIVE; + } + else if (is_consecutive || WM_event_consecutive_gesture_test_break(win, event)) { + CLOG_INFO(WM_LOG_HANDLERS, 1, "consecutive gesture break (%d)", event->type); + win->event_queue_consecutive_gesture_type = 0; + WM_event_consecutive_data_free(win); + } + } + else if (is_consecutive) { + CLOG_INFO(WM_LOG_HANDLERS, 1, "consecutive gesture begin (%d)", event->type); + win->event_queue_consecutive_gesture_type = event->type; + copy_v2_v2_int(win->event_queue_consecutive_gesture_xy, event->xy); + /* While this should not be set, it's harmless to free here. */ + WM_event_consecutive_data_free(win); + } + } + /* Active screen might change during handlers, update pointer. */ screen = WM_window_get_active_screen(win); @@ -4309,6 +4330,56 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Consecutive Event Access + * \{ */ + +using wmEvent_ConsecutiveData = struct wmEvent_ConsecutiveData { + /** Owned custom-data. */ + void *custom_data; + /** Unique identifier per struct type. */ + char id[0]; +}; + +void *WM_event_consecutive_data_get(wmWindow *win, const char *id) +{ + wmEvent_ConsecutiveData *cdata = win->event_queue_consecutive_gesture_data; + if (cdata && STREQ(cdata->id, id)) { + return cdata->custom_data; + } + return nullptr; +} + +void WM_event_consecutive_data_set(wmWindow *win, const char *id, void *custom_data) +{ + if (win->event_queue_consecutive_gesture_data) { + WM_event_consecutive_data_free(win); + } + + const size_t id_size = strlen(id) + 1; + wmEvent_ConsecutiveData *cdata = static_cast( + MEM_mallocN(sizeof(*cdata) + id_size, __func__)); + cdata->custom_data = custom_data; + memcpy((cdata + 1), id, id_size); + win->event_queue_consecutive_gesture_data = cdata; +} + +void WM_event_consecutive_data_free(wmWindow *win) +{ + wmEvent_ConsecutiveData *cdata = win->event_queue_consecutive_gesture_data; + if (cdata == nullptr) { + return; + } + + if (cdata->custom_data) { + MEM_freeN(cdata->custom_data); + } + MEM_freeN(cdata); + win->event_queue_consecutive_gesture_data = nullptr; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Modal Operator Handling * \{ */ diff --git a/source/blender/windowmanager/intern/wm_files.cc b/source/blender/windowmanager/intern/wm_files.cc index 78b2a0bf9a9..c873c511414 100644 --- a/source/blender/windowmanager/intern/wm_files.cc +++ b/source/blender/windowmanager/intern/wm_files.cc @@ -43,6 +43,7 @@ #include "PIL_time.h" +#include "BLO_readfile.h" #include "BLT_translation.h" #include "BLF_api.h" @@ -79,7 +80,6 @@ #include "BKE_undo_system.h" #include "BKE_workspace.h" -#include "BLO_readfile.h" #include "BLO_undofile.h" /* to save from an undo memfile */ #include "BLO_writefile.h" @@ -3261,7 +3261,7 @@ static bool wm_save_mainfile_check(bContext * /*C*/, wmOperator *op) { char filepath[FILE_MAX]; RNA_string_get(op->ptr, "filepath", filepath); - if (!BLO_has_bfile_extension(filepath)) { + if (!BKE_blendfile_extension_check(filepath)) { /* some users would prefer BLI_path_extension_replace(), * we keep getting nitpicking bug reports about this - campbell */ BLI_path_extension_ensure(filepath, FILE_MAX, ".blend"); @@ -3553,7 +3553,7 @@ static uiBlock *block_create_autorun_warning(struct bContext *C, UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT); - UI_block_bounds_set_centered(block, 14 * U.dpi_fac); + UI_block_bounds_set_centered(block, 14 * UI_SCALE_FAC); return block; } @@ -3892,7 +3892,7 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, wm_block_file_close_save_button(block, post_action); } - UI_block_bounds_set_centered(block, 14 * U.dpi_fac); + UI_block_bounds_set_centered(block, 14 * UI_SCALE_FAC); return block; } diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index 3af7d2f26f0..ee2b7455a0d 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -37,6 +37,7 @@ #include "BLO_readfile.h" #include "BKE_armature.h" +#include "BKE_blendfile.h" #include "BKE_blendfile_link_append.h" #include "BKE_context.h" #include "BKE_global.h" @@ -216,7 +217,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) BLI_path_join(path, sizeof(path), root, relname); /* test if we have a valid data */ - if (!BLO_library_path_explode(path, libname, &group, &name)) { + if (!BKE_blendfile_library_path_explode(path, libname, &group, &name)) { BKE_reportf(op->reports, RPT_ERROR, "'%s': not a library", path); return OPERATOR_CANCELLED; } @@ -289,7 +290,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) BLI_path_join(path, sizeof(path), root, relname); - if (BLO_library_path_explode(path, libname, &group, &name)) { + if (BKE_blendfile_library_path_explode(path, libname, &group, &name)) { if (!wm_link_append_item_poll(NULL, path, group, name, do_append)) { continue; } @@ -308,7 +309,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) BLI_path_join(path, sizeof(path), root, relname); - if (BLO_library_path_explode(path, libname, &group, &name)) { + if (BKE_blendfile_library_path_explode(path, libname, &group, &name)) { BlendfileLinkAppendContextItem *item; if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) { @@ -610,7 +611,7 @@ static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UN void WM_lib_reload(Library *lib, bContext *C, ReportList *reports) { - if (!BLO_has_bfile_extension(lib->filepath_abs)) { + if (!BKE_blendfile_extension_check(lib->filepath_abs)) { BKE_reportf(reports, RPT_ERROR, "'%s' is not a valid library filepath", lib->filepath_abs); return; } @@ -687,7 +688,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) RNA_string_get(op->ptr, "directory", root); RNA_string_get(op->ptr, "filename", libname); - if (!BLO_has_bfile_extension(libname)) { + if (!BKE_blendfile_extension_check(libname)) { BKE_report(op->reports, RPT_ERROR, "Not a library"); return OPERATOR_CANCELLED; } @@ -750,7 +751,8 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) BLI_path_join(path, sizeof(path), root, relname); - if (BLI_path_cmp(path, lib->filepath_abs) == 0 || !BLO_has_bfile_extension(relname)) { + if (BLI_path_cmp(path, lib->filepath_abs) == 0 || + !BKE_blendfile_extension_check(relname)) { continue; } diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 83ecad59012..c6918f302ab 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -580,7 +580,7 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* Make a simple distance check to get a smoother lasso * add only when at least 2 pixels between this and previous location. */ - else if ((x * x + y * y) > pow2f(2.0f * UI_DPI_FAC)) { + else if ((x * x + y * y) > pow2f(2.0f * UI_SCALE_FAC)) { lasso[gesture->points][0] = event->xy[0] - gesture->winrct.xmin; lasso[gesture->points][1] = event->xy[1] - gesture->winrct.ymin; gesture->points++; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index df1555dfdd7..39d0f0cf843 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1411,7 +1411,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op) uiTemplateOperatorPropertyButs( C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL); + UI_block_bounds_set_popup(block, 6 * UI_SCALE_FAC, NULL); return block; } @@ -1486,7 +1486,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *userD /* center around the mouse */ UI_block_bounds_set_popup( - block, 6 * U.dpi_fac, (const int[2]){data->width / -2, data->height / 2}); + block, 6 * UI_SCALE_FAC, (const int[2]){data->width / -2, data->height / 2}); return block; } @@ -1510,7 +1510,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *region, void *userDa UI_block_func_set(block, NULL, NULL, NULL); - UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL); + UI_block_bounds_set_popup(block, 6 * UI_SCALE_FAC, NULL); return block; } @@ -1549,7 +1549,7 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width) { wmOpPopUp *data = MEM_callocN(sizeof(wmOpPopUp), "WM_operator_ui_popup"); data->op = op; - data->width = width * U.dpi_fac; + data->width = width * UI_SCALE_FAC; /* Actual used height depends on the content. */ data->height = 0; data->free_op = true; /* if this runs and gets registered we may want not to free it */ @@ -1619,7 +1619,7 @@ int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width) wmOpPopUp *data = MEM_callocN(sizeof(wmOpPopUp), "WM_operator_props_dialog_popup"); data->op = op; - data->width = width * U.dpi_fac; + data->width = width * UI_SCALE_FAC; /* Actual height depends on the content. */ data->height = 0; data->free_op = true; /* if this runs and gets registered we may want not to free it */ @@ -2173,8 +2173,8 @@ void WM_paint_cursor_remove_by_type(wmWindowManager *wm, void *draw_fn, void (*f /** \name Radial Control Operator * \{ */ -#define WM_RADIAL_CONTROL_DISPLAY_SIZE (200 * UI_DPI_FAC) -#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE (35 * UI_DPI_FAC) +#define WM_RADIAL_CONTROL_DISPLAY_SIZE (200 * UI_SCALE_FAC) +#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE (35 * UI_SCALE_FAC) #define WM_RADIAL_CONTROL_DISPLAY_WIDTH \ (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE) #define WM_RADIAL_MAX_STR 10 @@ -2558,7 +2558,7 @@ static void radial_control_paint_cursor(bContext *UNUSED(C), int x, int y, void immUnbindProgram(); - BLF_size(fontid, 1.75f * fstyle_points * U.dpi_fac); + BLF_size(fontid, 1.75f * fstyle_points * UI_SCALE_FAC); UI_GetThemeColor4fv(TH_TEXT_HI, text_color); BLF_color4fv(fontid, text_color); diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index 1bcd51ed9c7..abe8161f798 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -83,7 +83,7 @@ static void wm_block_splash_image_roundcorners_add(ImBuf *ibuf) } bTheme *btheme = UI_GetTheme(); - const float roundness = btheme->tui.wcol_menu_back.roundness * U.dpi_fac; + const float roundness = btheme->tui.wcol_menu_back.roundness * UI_SCALE_FAC; const int size = roundness * 20; if (size < ibuf->x && size < ibuf->y) { @@ -184,7 +184,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void *UNUSE UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points); - int splash_width = text_points_max * 45 * U.dpi_fac; + int splash_width = text_points_max * 45 * UI_SCALE_FAC; CLAMP_MAX(splash_width, CTX_wm_window(C)->sizex * 0.7f); int splash_height; @@ -199,17 +199,17 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void *UNUSE wm_block_splash_add_label(block, BKE_blender_version_string(), - splash_width - 8.0 * U.dpi_fac, - splash_height - 13.0 * U.dpi_fac); + splash_width - 8.0 * UI_SCALE_FAC, + splash_height - 13.0 * UI_SCALE_FAC); - const int layout_margin_x = U.dpi_fac * 26; + const int layout_margin_x = UI_SCALE_FAC * 26; uiLayout *layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, layout_margin_x, 0, splash_width - (layout_margin_x * 2), - U.dpi_fac * 110, + UI_SCALE_FAC * 110, 0, style); @@ -263,7 +263,7 @@ static uiBlock *wm_block_create_about(bContext *C, ARegion *region, void *UNUSED { const uiStyle *style = UI_style_get_dpi(); const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points); - const int dialog_width = text_points_max * 42 * U.dpi_fac; + const int dialog_width = text_points_max * 42 * UI_SCALE_FAC; uiBlock *block = UI_block_begin(C, region, "about", UI_EMBOSS); @@ -317,7 +317,7 @@ static uiBlock *wm_block_create_about(bContext *C, ARegion *region, void *UNUSED UI_menutype_draw(C, mt, col); } - UI_block_bounds_set_centered(block, 22 * U.dpi_fac); + UI_block_bounds_set_centered(block, 22 * UI_SCALE_FAC); return block; } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index ad146c0e393..3fd7bc603fb 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -256,6 +256,9 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win) if (win->event_last_handled) { MEM_freeN(win->event_last_handled); } + if (win->event_queue_consecutive_gesture_data) { + WM_event_consecutive_data_free(win); + } if (win->cursor_keymap_status) { MEM_freeN(win->cursor_keymap_status); @@ -518,12 +521,12 @@ void WM_window_set_dpi(const wmWindow *win) /* Set user preferences globals for drawing, and for forward compatibility. */ U.pixelsize = pixelsize; U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE; - U.dpi_fac = U.dpi / 72.0f; - U.inv_dpi_fac = 1.0f / U.dpi_fac; + U.scale_factor = U.dpi / 72.0f; + U.inv_scale_factor = 1.0f / U.scale_factor; /* Widget unit is 20 pixels at 1X scale. This consists of 18 user-scaled units plus * left and right borders of line-width (pixel-size). */ - U.widget_unit = (int)roundf(18.0f * U.dpi_fac) + (2 * pixelsize); + U.widget_unit = (int)roundf(18.0f * U.scale_factor) + (2 * pixelsize); } /** @@ -1778,7 +1781,7 @@ static uiBlock *block_create_opengl_usage_warning(struct bContext *C, uiItemS(layout); - UI_block_bounds_set_centered(block, 14 * U.dpi_fac); + UI_block_bounds_set_centered(block, 14 * UI_SCALE_FAC); return block; } diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index c7678223ce4..e17e1ae512e 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -60,7 +60,7 @@ enum { /* More mouse buttons - can't use 9 and 10 here (wheel) */ BUTTON6MOUSE = 0x0012, BUTTON7MOUSE = 0x0013, - /* Extra track-pad gestures. */ + /* Extra track-pad gestures (check #WM_EVENT_IS_CONSECUTIVE to detect motion events). */ MOUSEPAN = 0x000e, MOUSEZOOM = 0x000f, MOUSEROTATE = 0x0010, @@ -247,6 +247,10 @@ enum { * These must be kept in sync with `GHOST_NDOFManager.h`. * Ordering matters, exact values do not. */ + /** + * Motion from 3D input (translation & rotation). + * Check #WM_EVENT_IS_CONSECUTIVE to detect motion events. + */ NDOF_MOTION = 0x0190, /* 400 */ #define _NDOF_MIN NDOF_MOTION diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 33dba24170a..9edd16c5cac 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -6,7 +6,6 @@ set(INC ../../intern/guardedalloc ../blender/blenkernel ../blender/blenlib - ../blender/blenloader ../blender/depsgraph ../blender/editors/include ../blender/gpu diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 41708cc81a8..8b11aa07b03 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -29,9 +29,8 @@ # include "BLI_threads.h" # include "BLI_utildefines.h" -# include "BLO_readfile.h" /* only for BLO_has_bfile_extension */ - # include "BKE_blender_version.h" +# include "BKE_blendfile.h" # include "BKE_context.h" # include "BKE_global.h" @@ -2071,7 +2070,7 @@ static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data) return -1; } - if (BLO_has_bfile_extension(filepath)) { + if (BKE_blendfile_extension_check(filepath)) { /* Just pretend a file was loaded, so the user can press Save and it'll * save at the filepath from the CLI. */ STRNCPY(G_MAIN->filepath, filepath); diff --git a/tests/python/bl_blendfile_io.py b/tests/python/bl_blendfile_io.py index 8495c8a7ad6..e635d9ea593 100644 --- a/tests/python/bl_blendfile_io.py +++ b/tests/python/bl_blendfile_io.py @@ -64,7 +64,7 @@ class TestIdRuntimeTag(TestHelper): bpy.ops.wm.read_homefile(use_empty=False, use_factory_startup=True) obj = bpy.data.objects['Cube'] - assert obj.is_runtime_data == False + assert obj.is_runtime_data is False assert bpy.context.view_layer.depsgraph.ids['Cube'].is_runtime_data output_work_path = os.path.join(output_dir, self.unique_blendfile_name("blendfile")) @@ -72,7 +72,7 @@ class TestIdRuntimeTag(TestHelper): bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False) obj = bpy.data.objects['Cube'] - assert obj.is_runtime_data == False + assert obj.is_runtime_data is False obj.is_runtime_data = True assert obj.is_runtime_data @@ -82,7 +82,7 @@ class TestIdRuntimeTag(TestHelper): assert 'Cube' not in bpy.data.objects mesh = bpy.data.meshes['Cube'] - assert mesh.is_runtime_data == False + assert mesh.is_runtime_data is False assert mesh.users == 0 def test_linking(self): @@ -91,7 +91,11 @@ class TestIdRuntimeTag(TestHelper): bpy.ops.wm.read_homefile(use_empty=False, use_factory_startup=True) material = bpy.data.materials.new("LibMaterial") - material.use_fake_user = True + # Use a dummy mesh as user of the material, such that the material is saved + # without having to use fake user on it. + mesh = bpy.data.meshes.new("LibMesh") + mesh.materials.append(material) + mesh.use_fake_user = True output_lib_path = os.path.join(output_dir, self.unique_blendfile_name("blendlib_runtimetag_basic")) bpy.ops.wm.save_as_mainfile(filepath=output_lib_path, check_existing=False, compress=False) @@ -99,15 +103,22 @@ class TestIdRuntimeTag(TestHelper): bpy.ops.wm.read_homefile(use_empty=False, use_factory_startup=True) obj = bpy.data.objects['Cube'] - assert obj.is_runtime_data == False + assert obj.is_runtime_data is False obj.is_runtime_data = True link_dir = os.path.join(output_lib_path, "Material") bpy.ops.wm.link(directory=link_dir, filename="LibMaterial") linked_material = bpy.data.materials['LibMaterial'] - assert linked_material.is_library_indirect == False + assert linked_material.is_library_indirect is False + link_dir = os.path.join(output_lib_path, "Mesh") + bpy.ops.wm.link(directory=link_dir, filename="LibMesh") + + linked_mesh = bpy.data.meshes['LibMesh'] + assert linked_mesh.is_library_indirect is False + + obj.data = linked_mesh obj.material_slots[0].link = 'OBJECT' obj.material_slots[0].material = linked_material @@ -118,13 +129,17 @@ class TestIdRuntimeTag(TestHelper): # so writing .blend file will have properly reset its tag to indirectly linked data. assert linked_material.is_library_indirect + # Only usage of this linked mesh is a runtime ID (object), but it is flagged as 'fake user' in its library, + # so writing .blend file will have kept its tag to directly linked data. + assert not linked_mesh.is_library_indirect + bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False) assert 'Cube' not in bpy.data.objects - assert 'LibMaterial' not in bpy.data.materials - mesh = bpy.data.meshes['Cube'] - assert mesh.is_runtime_data == False - assert mesh.users == 0 + assert 'LibMaterial' in bpy.data.materials # Pulled-in by the linked mesh. + linked_mesh = bpy.data.meshes['LibMesh'] + assert linked_mesh.use_fake_user is True + assert linked_mesh.is_library_indirect is False TESTS = ( diff --git a/tests/python/bl_blendfile_liblink.py b/tests/python/bl_blendfile_liblink.py index e090e738386..0199132b0b9 100644 --- a/tests/python/bl_blendfile_liblink.py +++ b/tests/python/bl_blendfile_liblink.py @@ -248,8 +248,8 @@ class TestBlendLibLinkIndirect(TestBlendLibLinkHelper): bpy.ops.wm.save_as_mainfile(filepath=output_work_path, check_existing=False, compress=False) assert material.users == 2 - # Currently linked data which has no more local user never gets reset to indirectly linked status. - assert material.is_library_indirect + # Currently linked data with 'fake user' set are considered as directly linked data. + assert not material.is_library_indirect bpy.ops.wm.open_mainfile(filepath=output_work_path, load_ui=False) @@ -264,9 +264,8 @@ class TestBlendLibLinkIndirect(TestBlendLibLinkHelper): assert material.library is not None assert material.use_fake_user is True assert material.users == 2 # Fake user is not cleared when linking. - # Currently even re-reading the .blend file will not properly reset tag for indirectly linked data, - # if their reference was written in the .blend file. - assert material.is_library_indirect + # Currently linked data with 'fake user' set are considered as directly linked data. + assert not material.is_library_indirect assert mesh.library is not None assert mesh.use_fake_user is False diff --git a/tests/python/bl_usd_import_test.py b/tests/python/bl_usd_import_test.py index e05b32cf0e8..3c7d4e58c1c 100644 --- a/tests/python/bl_usd_import_test.py +++ b/tests/python/bl_usd_import_test.py @@ -3,6 +3,11 @@ import pathlib import sys import unittest +import tempfile +from pxr import Usd +from pxr import UsdShade +from pxr import UsdGeom +from pxr import Sdf import bpy @@ -13,6 +18,8 @@ class AbstractUSDTest(unittest.TestCase): @classmethod def setUpClass(cls): cls.testdir = args.testdir + cls._tempdir = tempfile.TemporaryDirectory() + cls.tempdir = pathlib.Path(cls._tempdir.name) def setUp(self): self.assertTrue(self.testdir.exists(), @@ -21,6 +28,9 @@ class AbstractUSDTest(unittest.TestCase): # Make sure we always start with a known-empty file. bpy.ops.wm.open_mainfile(filepath=str(self.testdir / "empty.blend")) + def tearDown(self): + self._tempdir.cleanup() + class USDImportTest(AbstractUSDTest): @@ -189,6 +199,107 @@ class USDImportTest(AbstractUSDTest): self.assertAlmostEqual(1.234, test_cam.shift_x, 3) self.assertAlmostEqual(5.678, test_cam.shift_y, 3) + def test_import_shader_varname_with_connection(self): + """Test importing USD shader where uv primvar is a connection""" + + varname = "testmap" + texfile = str(self.testdir / "textures/test_grid_1001.png") + + # Create the test USD file. + temp_usd_file = str(self.tempdir / "usd_varname_test.usda") + stage = Usd.Stage.CreateNew(temp_usd_file) + mesh1 = stage.DefinePrim("/mesh1", "Mesh") + mesh2 = stage.DefinePrim("/mesh2", "Mesh") + + # Create two USD preview surface shaders in two materials. + m1 = UsdShade.Material.Define(stage, "/mat1") + s1 = UsdShade.Shader.Define(stage, "/mat1/previewshader") + s1.CreateIdAttr("UsdPreviewSurface") + m1.CreateSurfaceOutput().ConnectToSource(s1.ConnectableAPI(), "surface") + t1 = UsdShade.Shader.Define(stage, "/mat1/diffuseTexture") + t1.CreateIdAttr("UsdUVTexture") + t1.CreateInput('file', Sdf.ValueTypeNames.Asset).Set(texfile) + t1.CreateOutput("rgb", Sdf.ValueTypeNames.Float3) + s1.CreateInput("diffuseColor", Sdf.ValueTypeNames.Color3f).ConnectToSource(t1.ConnectableAPI(), "rgb") + t2 = UsdShade.Shader.Define(stage, "/mat1/roughnessTexture") + t2.CreateIdAttr("UsdUVTexture") + t2.CreateInput('file', Sdf.ValueTypeNames.Asset).Set(texfile) + t2.CreateOutput("rgb", Sdf.ValueTypeNames.Float3) + s1.CreateInput("roughness", Sdf.ValueTypeNames.Color3f).ConnectToSource(t2.ConnectableAPI(), "rgb") + + m2 = UsdShade.Material.Define(stage, "/mat2") + s2 = UsdShade.Shader.Define(stage, "/mat2/previewshader") + s2.CreateIdAttr("UsdPreviewSurface") + m2.CreateSurfaceOutput().ConnectToSource(s2.ConnectableAPI(), "surface") + t3 = UsdShade.Shader.Define(stage, "/mat2/diffuseTexture") + t3.CreateIdAttr("UsdUVTexture") + t3.CreateInput('file', Sdf.ValueTypeNames.Asset).Set(texfile) + t3.CreateOutput("rgb", Sdf.ValueTypeNames.Float3) + s2.CreateInput("diffuseColor", Sdf.ValueTypeNames.Color3f).ConnectToSource(t3.ConnectableAPI(), "rgb") + t4 = UsdShade.Shader.Define(stage, "/mat2/roughnessTexture") + t4.CreateIdAttr("UsdUVTexture") + t4.CreateInput('file', Sdf.ValueTypeNames.Asset).Set(texfile) + t4.CreateOutput("rgb", Sdf.ValueTypeNames.Float3) + s2.CreateInput("roughness", Sdf.ValueTypeNames.Color3f).ConnectToSource(t4.ConnectableAPI(), "rgb") + + # Bind mat1 to mesh1, mat2 to mesh2. + bindingAPI = UsdShade.MaterialBindingAPI.Apply(mesh1) + bindingAPI.Bind(m1) + bindingAPI = UsdShade.MaterialBindingAPI.Apply(mesh2) + bindingAPI.Bind(m2) + + # Create varname defined as a token. + s3 = UsdShade.Shader.Define(stage, "/mat1/primvar_reader1") + s3.CreateIdAttr('UsdPrimvarReader_float2') + s3input = s3.CreateInput("varname", Sdf.ValueTypeNames.Token) + s3input.Set(varname) + t1.CreateInput("st", Sdf.ValueTypeNames.TexCoord2f).ConnectToSource(s3.ConnectableAPI(), "result") + + # Create varname defined as a connection to a token. + varname1 = m1.CreateInput("varname", Sdf.ValueTypeNames.Token) + varname1.Set(varname) + s4 = UsdShade.Shader.Define(stage, "/mat1/primvar_reader2") + s4.CreateIdAttr('UsdPrimvarReader_float2') + s4input = s4.CreateInput("varname", Sdf.ValueTypeNames.Token) + UsdShade.ConnectableAPI.ConnectToSource(s4input, varname1) + t2.CreateInput("st", Sdf.ValueTypeNames.TexCoord2f).ConnectToSource(s4.ConnectableAPI(), "result") + + # Create varname defined as a string. + s5 = UsdShade.Shader.Define(stage, "/mat2/primvar_reader1") + s5.CreateIdAttr('UsdPrimvarReader_float2') + s5input = s5.CreateInput("varname", Sdf.ValueTypeNames.String) + s5input.Set(varname) + t3.CreateInput("st", Sdf.ValueTypeNames.TexCoord2f).ConnectToSource(s5.ConnectableAPI(), "result") + + # Create varname defined as a connection to a string. + varname2 = m2.CreateInput("varname", Sdf.ValueTypeNames.String) + varname2.Set(varname) + s6 = UsdShade.Shader.Define(stage, "/mat2/primvar_reader2") + s6.CreateIdAttr('UsdPrimvarReader_float2') + s6input = s6.CreateInput("varname", Sdf.ValueTypeNames.String) + UsdShade.ConnectableAPI.ConnectToSource(s6input, varname2) + t4.CreateInput("st", Sdf.ValueTypeNames.TexCoord2f).ConnectToSource(s6.ConnectableAPI(), "result") + + stage.Save() + + # Now import the USD file. + res = bpy.ops.wm.usd_import(filepath=temp_usd_file, import_all_materials=True) + self.assertEqual({'FINISHED'}, res) + + # Ensure that we find the correct varname for all four primvar readers. + num_uvmaps_found = 0 + mats_to_test = [] + mats_to_test.append(bpy.data.materials["mat1"]) + mats_to_test.append(bpy.data.materials["mat2"]) + for mat in mats_to_test: + self.assertIsNotNone(mat.node_tree, "Material node tree is empty") + for node in mat.node_tree.nodes: + if node.type == "UVMAP": + self.assertEqual(varname, node.uv_map, "Unexpected value for varname") + num_uvmaps_found += 1 + + self.assertEqual(4, num_uvmaps_found, "One or more test materials failed to import") + def main(): global args