UI: Clicking the camera icon while rendering should open render window #105765
|
@ -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
|
||||
|
||||
|
|
|
@ -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)))
|
||||
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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%
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -581,6 +581,11 @@ void MetalDevice::compile_and_load(int device_id, MetalPipelineType pso_type)
|
|||
thread_scoped_lock lock(existing_devices_mutex);
|
||||
if (MetalDevice *instance = get_device_by_ID(device_id, lock)) {
|
||||
if (mtlLibrary) {
|
||||
if (error && [error localizedDescription]) {
|
||||
VLOG_WARNING << "MSL compilation messages: "
|
||||
<< [[error localizedDescription] UTF8String];
|
||||
}
|
||||
|
||||
instance->mtlLibrary[pso_type] = mtlLibrary;
|
||||
|
||||
starttime = time_dt();
|
||||
|
|
|
@ -715,7 +715,7 @@ void MetalKernelPipeline::compile()
|
|||
}
|
||||
}
|
||||
};
|
||||
if (computePipelineStateDescriptor.linkedFunctions) {
|
||||
if (linked_functions) {
|
||||
addComputePipelineFunctionsWithDescriptor();
|
||||
}
|
||||
|
||||
|
@ -748,7 +748,7 @@ void MetalKernelPipeline::compile()
|
|||
}
|
||||
|
||||
/* Add pipeline into the new archive (unless we did it earlier). */
|
||||
if (pipeline && !computePipelineStateDescriptor.linkedFunctions) {
|
||||
if (pipeline && !linked_functions) {
|
||||
addComputePipelineFunctionsWithDescriptor();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 prefered 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_;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -15,12 +15,19 @@
|
|||
#include "kernel/bvh/util.h"
|
||||
#include "kernel/geom/object.h"
|
||||
#include "kernel/integrator/state.h"
|
||||
#include "kernel/integrator/state_util.h"
|
||||
#include "kernel/sample/lcg.h"
|
||||
|
||||
#include "util/vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#if INTEGRATOR_SHADOW_ISECT_SIZE < 256
|
||||
using numhit_t = uint8_t;
|
||||
#else
|
||||
using numhit_t = uint32_t;
|
||||
#endif
|
||||
|
||||
#define EMBREE_IS_HAIR(x) (x & 1)
|
||||
|
||||
/* Intersection context. */
|
||||
|
@ -41,12 +48,11 @@ struct CCLIntersectContext {
|
|||
const Ray *ray;
|
||||
|
||||
/* for shadow rays */
|
||||
Intersection *isect_s;
|
||||
uint max_hits;
|
||||
uint num_hits;
|
||||
uint num_recorded_hits;
|
||||
IntegratorShadowState isect_s;
|
||||
numhit_t max_hits;
|
||||
numhit_t num_hits;
|
||||
numhit_t num_recorded_hits;
|
||||
float throughput;
|
||||
float max_t;
|
||||
bool opaque_hit;
|
||||
|
||||
/* for SSS Rays: */
|
||||
|
@ -54,16 +60,18 @@ struct CCLIntersectContext {
|
|||
int local_object_id;
|
||||
uint *lcg_state;
|
||||
|
||||
/* for Volume */
|
||||
Intersection *vol_isect;
|
||||
|
||||
CCLIntersectContext(KernelGlobals kg_, RayType type_)
|
||||
{
|
||||
kg = kg_;
|
||||
type = type_;
|
||||
ray = NULL;
|
||||
max_hits = 1;
|
||||
num_hits = 0;
|
||||
num_recorded_hits = 0;
|
||||
max_hits = numhit_t(1);
|
||||
num_hits = numhit_t(0);
|
||||
num_recorded_hits = numhit_t(0);
|
||||
throughput = 1.0f;
|
||||
max_t = FLT_MAX;
|
||||
opaque_hit = false;
|
||||
isect_s = NULL;
|
||||
local_isect = NULL;
|
||||
|
@ -112,31 +120,17 @@ ccl_device_inline void kernel_embree_setup_rayhit(const Ray &ray,
|
|||
|
||||
ccl_device_inline bool kernel_embree_is_self_intersection(const KernelGlobals kg,
|
||||
const RTCHit *hit,
|
||||
const Ray *ray)
|
||||
const Ray *ray,
|
||||
const intptr_t prim_offset)
|
||||
{
|
||||
int object, prim;
|
||||
object = (hit->instID[0] != RTC_INVALID_GEOMETRY_ID ? hit->instID[0] : hit->geomID) / 2;
|
||||
|
||||
if (hit->instID[0] != RTC_INVALID_GEOMETRY_ID) {
|
||||
object = hit->instID[0] / 2;
|
||||
if ((ray->self.object == object) || (ray->self.light_object == object)) {
|
||||
RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData(
|
||||
rtcGetGeometry(kernel_data.device_bvh, hit->instID[0]));
|
||||
prim = hit->primID +
|
||||
(intptr_t)rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID));
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
if ((ray->self.object == object) || (ray->self.light_object == object)) {
|
||||
prim = hit->primID + prim_offset;
|
||||
}
|
||||
else {
|
||||
object = hit->geomID / 2;
|
||||
if ((ray->self.object == object) || (ray->self.light_object == object)) {
|
||||
prim = hit->primID +
|
||||
(intptr_t)rtcGetGeometryUserData(rtcGetGeometry(kernel_data.device_bvh, hit->geomID));
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_hair = hit->geomID & 1;
|
||||
|
@ -150,21 +144,12 @@ ccl_device_inline bool kernel_embree_is_self_intersection(const KernelGlobals kg
|
|||
ccl_device_inline void kernel_embree_convert_hit(KernelGlobals kg,
|
||||
const RTCRay *ray,
|
||||
const RTCHit *hit,
|
||||
Intersection *isect)
|
||||
Intersection *isect,
|
||||
const intptr_t prim_offset)
|
||||
{
|
||||
isect->t = ray->tfar;
|
||||
if (hit->instID[0] != RTC_INVALID_GEOMETRY_ID) {
|
||||
RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData(
|
||||
rtcGetGeometry(kernel_data.device_bvh, hit->instID[0]));
|
||||
isect->prim = hit->primID +
|
||||
(intptr_t)rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID));
|
||||
isect->object = hit->instID[0] / 2;
|
||||
}
|
||||
else {
|
||||
isect->prim = hit->primID + (intptr_t)rtcGetGeometryUserData(
|
||||
rtcGetGeometry(kernel_data.device_bvh, hit->geomID));
|
||||
isect->object = hit->geomID / 2;
|
||||
}
|
||||
isect->prim = hit->primID + prim_offset;
|
||||
isect->object = hit->instID[0] != RTC_INVALID_GEOMETRY_ID ? hit->instID[0] / 2 : hit->geomID / 2;
|
||||
|
||||
const bool is_hair = hit->geomID & 1;
|
||||
if (is_hair) {
|
||||
|
@ -181,16 +166,35 @@ ccl_device_inline void kernel_embree_convert_hit(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_embree_convert_sss_hit(
|
||||
KernelGlobals kg, const RTCRay *ray, const RTCHit *hit, Intersection *isect, int object)
|
||||
ccl_device_inline void kernel_embree_convert_hit(KernelGlobals kg,
|
||||
const RTCRay *ray,
|
||||
const RTCHit *hit,
|
||||
Intersection *isect)
|
||||
{
|
||||
intptr_t prim_offset;
|
||||
if (hit->instID[0] != RTC_INVALID_GEOMETRY_ID) {
|
||||
RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData(
|
||||
rtcGetGeometry(kernel_data.device_bvh, hit->instID[0]));
|
||||
prim_offset = intptr_t(rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID)));
|
||||
}
|
||||
else {
|
||||
prim_offset = intptr_t(
|
||||
rtcGetGeometryUserData(rtcGetGeometry(kernel_data.device_bvh, hit->geomID)));
|
||||
}
|
||||
kernel_embree_convert_hit(kg, ray, hit, isect, prim_offset);
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_embree_convert_sss_hit(KernelGlobals kg,
|
||||
const RTCRay *ray,
|
||||
const RTCHit *hit,
|
||||
Intersection *isect,
|
||||
int object,
|
||||
const intptr_t prim_offset)
|
||||
{
|
||||
isect->u = hit->u;
|
||||
isect->v = hit->v;
|
||||
isect->t = ray->tfar;
|
||||
RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData(
|
||||
rtcGetGeometry(kernel_data.device_bvh, object * 2));
|
||||
isect->prim = hit->primID +
|
||||
(intptr_t)rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID));
|
||||
isect->prim = hit->primID + prim_offset;
|
||||
isect->object = object;
|
||||
isect->type = kernel_data_fetch(objects, object).primitive_type;
|
||||
}
|
||||
|
@ -211,7 +215,8 @@ ccl_device void kernel_embree_filter_intersection_func(const RTCFilterFunctionNA
|
|||
const KernelGlobalsCPU *kg = ctx->kg;
|
||||
const Ray *cray = ctx->ray;
|
||||
|
||||
if (kernel_embree_is_self_intersection(kg, hit, cray)) {
|
||||
if (kernel_embree_is_self_intersection(
|
||||
kg, hit, cray, reinterpret_cast<intptr_t>(args->geometryUserPtr))) {
|
||||
*args->valid = 0;
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +231,7 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum
|
|||
/* Current implementation in Cycles assumes only single-ray intersection queries. */
|
||||
assert(args->N == 1);
|
||||
|
||||
const RTCRay *ray = (RTCRay *)args->ray;
|
||||
RTCRay *ray = (RTCRay *)args->ray;
|
||||
RTCHit *hit = (RTCHit *)args->hit;
|
||||
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
|
||||
const KernelGlobalsCPU *kg = ctx->kg;
|
||||
|
@ -235,7 +240,8 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum
|
|||
switch (ctx->type) {
|
||||
case CCLIntersectContext::RAY_SHADOW_ALL: {
|
||||
Intersection current_isect;
|
||||
kernel_embree_convert_hit(kg, ray, hit, ¤t_isect);
|
||||
kernel_embree_convert_hit(
|
||||
kg, ray, hit, ¤t_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
if (intersection_skip_self_shadow(cray->self, current_isect.object, current_isect.prim)) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
|
@ -265,20 +271,21 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum
|
|||
}
|
||||
|
||||
/* Test if we need to record this transparent intersection. */
|
||||
const uint max_record_hits = min(ctx->max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
|
||||
if (ctx->num_recorded_hits < max_record_hits || ray->tfar < ctx->max_t) {
|
||||
const numhit_t max_record_hits = min(ctx->max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
|
||||
if (ctx->num_recorded_hits < max_record_hits) {
|
||||
/* If maximum number of hits was reached, replace the intersection with the
|
||||
* highest distance. We want to find the N closest intersections. */
|
||||
const uint num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits);
|
||||
uint isect_index = num_recorded_hits;
|
||||
const numhit_t num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits);
|
||||
numhit_t isect_index = num_recorded_hits;
|
||||
if (num_recorded_hits + 1 >= max_record_hits) {
|
||||
float max_t = ctx->isect_s[0].t;
|
||||
uint max_recorded_hit = 0;
|
||||
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
|
||||
numhit_t max_recorded_hit = numhit_t(0);
|
||||
|
||||
for (uint i = 1; i < num_recorded_hits; ++i) {
|
||||
if (ctx->isect_s[i].t > max_t) {
|
||||
for (numhit_t i = numhit_t(1); i < num_recorded_hits; ++i) {
|
||||
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
|
||||
if (isect_t > max_t) {
|
||||
max_recorded_hit = i;
|
||||
max_t = ctx->isect_s[i].t;
|
||||
max_t = isect_t;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,14 +293,11 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum
|
|||
isect_index = max_recorded_hit;
|
||||
}
|
||||
|
||||
/* Limit the ray distance and stop counting hits beyond this.
|
||||
* TODO: is there some way we can tell Embree to stop intersecting beyond
|
||||
* this distance when max number of hits is reached?. Or maybe it will
|
||||
* become irrelevant if we make max_hits a very high number on the CPU. */
|
||||
ctx->max_t = max(current_isect.t, max_t);
|
||||
/* Limit the ray distance and stop counting hits beyond this. */
|
||||
ray->tfar = max(current_isect.t, max_t);
|
||||
}
|
||||
|
||||
ctx->isect_s[isect_index] = current_isect;
|
||||
integrator_state_write_shadow_isect(ctx->isect_s, ¤t_isect, isect_index);
|
||||
}
|
||||
|
||||
/* Always increase the number of recorded hits, even beyond the maximum,
|
||||
|
@ -309,10 +313,16 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum
|
|||
/* Check if it's hitting the correct object. */
|
||||
Intersection current_isect;
|
||||
if (ctx->type == CCLIntersectContext::RAY_SSS) {
|
||||
kernel_embree_convert_sss_hit(kg, ray, hit, ¤t_isect, ctx->local_object_id);
|
||||
kernel_embree_convert_sss_hit(kg,
|
||||
ray,
|
||||
hit,
|
||||
¤t_isect,
|
||||
ctx->local_object_id,
|
||||
reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
}
|
||||
else {
|
||||
kernel_embree_convert_hit(kg, ray, hit, ¤t_isect);
|
||||
kernel_embree_convert_hit(
|
||||
kg, ray, hit, ¤t_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
if (ctx->local_object_id != current_isect.object) {
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
|
@ -387,13 +397,14 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum
|
|||
/* Append the intersection to the end of the array. */
|
||||
if (ctx->num_hits < ctx->max_hits) {
|
||||
Intersection current_isect;
|
||||
kernel_embree_convert_hit(kg, ray, hit, ¤t_isect);
|
||||
kernel_embree_convert_hit(
|
||||
kg, ray, hit, ¤t_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
if (intersection_skip_self(cray->self, current_isect.object, current_isect.prim)) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Intersection *isect = &ctx->isect_s[ctx->num_hits];
|
||||
Intersection *isect = &ctx->vol_isect[ctx->num_hits];
|
||||
++ctx->num_hits;
|
||||
*isect = current_isect;
|
||||
/* Only primitives from volume object. */
|
||||
|
@ -409,7 +420,8 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum
|
|||
}
|
||||
case CCLIntersectContext::RAY_REGULAR:
|
||||
default:
|
||||
if (kernel_embree_is_self_intersection(kg, hit, cray)) {
|
||||
if (kernel_embree_is_self_intersection(
|
||||
kg, hit, cray, reinterpret_cast<intptr_t>(args->geometryUserPtr))) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -433,7 +445,8 @@ ccl_device void kernel_embree_filter_func_backface_cull(const RTCFilterFunctionN
|
|||
const KernelGlobalsCPU *kg = ctx->kg;
|
||||
const Ray *cray = ctx->ray;
|
||||
|
||||
if (kernel_embree_is_self_intersection(kg, hit, cray)) {
|
||||
if (kernel_embree_is_self_intersection(
|
||||
kg, hit, cray, reinterpret_cast<intptr_t>(args->geometryUserPtr))) {
|
||||
*args->valid = 0;
|
||||
}
|
||||
}
|
||||
|
@ -544,9 +557,8 @@ ccl_device_intersect bool kernel_embree_intersect_shadow_all(KernelGlobals kg,
|
|||
ccl_private float *throughput)
|
||||
{
|
||||
CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SHADOW_ALL);
|
||||
Intersection *isect_array = (Intersection *)state->shadow_isect;
|
||||
ctx.isect_s = isect_array;
|
||||
ctx.max_hits = max_hits;
|
||||
ctx.isect_s = state;
|
||||
ctx.max_hits = numhit_t(max_hits);
|
||||
ctx.ray = ray;
|
||||
IntersectContext rtc_ctx(&ctx);
|
||||
RTCRay rtc_ray;
|
||||
|
@ -567,9 +579,9 @@ ccl_device_intersect uint kernel_embree_intersect_volume(KernelGlobals kg,
|
|||
const uint visibility)
|
||||
{
|
||||
CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_VOLUME_ALL);
|
||||
ctx.isect_s = isect;
|
||||
ctx.max_hits = max_hits;
|
||||
ctx.num_hits = 0;
|
||||
ctx.vol_isect = isect;
|
||||
ctx.max_hits = numhit_t(max_hits);
|
||||
ctx.num_hits = numhit_t(0);
|
||||
ctx.ray = ray;
|
||||
IntersectContext rtc_ctx(&ctx);
|
||||
RTCRay rtc_ray;
|
||||
|
|
|
@ -38,7 +38,7 @@ ccl_device_inline void gpu_parallel_sort_bucket_pass(const uint num_states,
|
|||
ccl_gpu_shared int *buckets,
|
||||
const ushort local_id,
|
||||
const ushort local_size,
|
||||
const ushort grid_id)
|
||||
const uint grid_id)
|
||||
{
|
||||
/* Zero the bucket sizes. */
|
||||
if (local_id < max_shaders) {
|
||||
|
@ -89,7 +89,7 @@ ccl_device_inline void gpu_parallel_sort_write_pass(const uint num_states,
|
|||
ccl_gpu_shared int *local_offset,
|
||||
const ushort local_id,
|
||||
const ushort local_size,
|
||||
const ushort grid_id)
|
||||
const uint grid_id)
|
||||
{
|
||||
/* Calculate each partition's global offset from the prefix sum of the active state counts per
|
||||
* partition. */
|
||||
|
|
|
@ -109,7 +109,7 @@ struct kernel_gpu_##name \
|
|||
const uint metal_global_id, \
|
||||
const ushort metal_local_id, \
|
||||
const ushort metal_local_size, \
|
||||
const ushort metal_grid_id, \
|
||||
const uint metal_grid_id, \
|
||||
uint simdgroup_size, \
|
||||
uint simd_lane_index, \
|
||||
uint simd_group_index, \
|
||||
|
@ -122,7 +122,7 @@ kernel void cycles_metal_##name(device const kernel_gpu_##name *params_struct, \
|
|||
const uint metal_global_id [[thread_position_in_grid]], \
|
||||
const ushort metal_local_id [[thread_position_in_threadgroup]], \
|
||||
const ushort metal_local_size [[threads_per_threadgroup]], \
|
||||
const ushort metal_grid_id [[threadgroup_position_in_grid]], \
|
||||
const uint metal_grid_id [[threadgroup_position_in_grid]], \
|
||||
uint simdgroup_size [[threads_per_simdgroup]], \
|
||||
uint simd_lane_index [[thread_index_in_simdgroup]], \
|
||||
uint simd_group_index [[simdgroup_index_in_threadgroup]], \
|
||||
|
@ -135,7 +135,7 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \
|
|||
const uint metal_global_id, \
|
||||
const ushort metal_local_id, \
|
||||
const ushort metal_local_size, \
|
||||
const ushort metal_grid_id, \
|
||||
const uint metal_grid_id, \
|
||||
uint simdgroup_size, \
|
||||
uint simd_lane_index, \
|
||||
uint simd_group_index, \
|
||||
|
|
|
@ -149,7 +149,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
|
|||
((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT)) ||
|
||||
((ls.shader & SHADER_EXCLUDE_CAMERA) && (path_flag & PATH_RAY_CAMERA)) ||
|
||||
((ls.shader & SHADER_EXCLUDE_SCATTER) && (path_flag & PATH_RAY_VOLUME_SCATTER)))
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -159,7 +159,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
|
|||
* generate a firefly for small lights since it is improbable. */
|
||||
const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp);
|
||||
if (klight->use_caustics)
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
#endif /* __MNEE__ */
|
||||
|
||||
|
@ -169,7 +169,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
|
|||
ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
|
||||
Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time);
|
||||
if (is_zero(light_eval)) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* MIS weighting. */
|
||||
|
|
|
@ -205,8 +205,8 @@ LightTree::LightTree(vector<LightTreePrimitive> &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<LightTreeBucketInfo> buckets(LightTreeBucketInfo::num_buckets);
|
||||
std::array<LightTreeBucketInfo, LightTreeBucketInfo::num_buckets> 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<float> bucket_costs(LightTreeBucketInfo::num_buckets - 1);
|
||||
std::array<float, LightTreeBucketInfo::num_buckets - 1> 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) {
|
||||
|
|
|
@ -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<EmissionNode *>(node);
|
||||
if (emission_node->from_auto_conversion) {
|
||||
estimate *= 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
return estimate;
|
||||
}
|
||||
else if (node->type == LightFalloffNode::get_node_type() ||
|
||||
|
|
|
@ -260,6 +260,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
|
|||
|
||||
if (to->type() == SocketType::CLOSURE) {
|
||||
EmissionNode *emission = create_node<EmissionNode>();
|
||||
emission->from_auto_conversion = true;
|
||||
emission->set_color(one_float3());
|
||||
emission->set_strength(1.0f);
|
||||
convert = add(emission);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -126,8 +126,8 @@ class GHOST_ContextVK : public GHOST_Context {
|
|||
void *image, void *framebuffer, void *render_pass, void *extent, uint32_t *fb_id);
|
||||
|
||||
/**
|
||||
* Sets the swap interval for swapBuffers.
|
||||
* \param interval The swap interval to use.
|
||||
* Sets the swap interval for `swapBuffers`.
|
||||
* \param interval: The swap interval to use.
|
||||
* \return A boolean success indicator.
|
||||
*/
|
||||
GHOST_TSuccess setSwapInterval(int /* interval */)
|
||||
|
@ -137,7 +137,7 @@ class GHOST_ContextVK : public GHOST_Context {
|
|||
|
||||
/**
|
||||
* Gets the current swap interval for swapBuffers.
|
||||
* \param intervalOut Variable to store the swap interval if it can be read.
|
||||
* \param intervalOut: Variable to store the swap interval if it can be read.
|
||||
* \return Whether the swap interval can be read.
|
||||
*/
|
||||
GHOST_TSuccess getSwapInterval(int &)
|
||||
|
|
3
make.bat
3
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
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
@ -128,7 +128,7 @@ const UserDef U_default = {
|
|||
.pad_rot_angle = 15,
|
||||
.rvisize = 25,
|
||||
.rvibright = 8,
|
||||
.recent_files = 10,
|
||||
.recent_files = 20,
|
||||
.smooth_viewtx = 200,
|
||||
.glreslimit = 0,
|
||||
.color_picker_type = USER_CP_CIRCLE_HSV,
|
||||
|
|
|
@ -671,6 +671,7 @@ class ShaderImageTextureWrapper():
|
|||
tree.links.new(node_image.outputs["Alpha" if self.use_alpha else "Color"], self.socket_dst)
|
||||
if self.use_alpha:
|
||||
self.owner_shader.material.blend_method = 'BLEND'
|
||||
self.owner_shader.material.show_transparent_back = False
|
||||
|
||||
self._node_image = node_image
|
||||
return self._node_image
|
||||
|
|
|
@ -138,10 +138,10 @@ class QuickFur(ObjectModeOperator, Operator):
|
|||
generate_modifier.node_group = generate_group
|
||||
generate_modifier["Input_2"] = mesh_object
|
||||
generate_modifier["Input_18_attribute_name"] = curves.surface_uv_map
|
||||
generate_modifier["Input_12"] = True
|
||||
generate_modifier["Input_20"] = self.length
|
||||
generate_modifier["Input_22"] = material
|
||||
generate_modifier["Input_15"] = density * 0.01
|
||||
curves_object.modifiers.move(1, 0)
|
||||
|
||||
radius_modifier = curves_object.modifiers.new(name="Set Hair Curve Profile", type='NODES')
|
||||
radius_modifier.node_group = radius_group
|
||||
|
@ -151,6 +151,7 @@ class QuickFur(ObjectModeOperator, Operator):
|
|||
interpolate_modifier.node_group = interpolate_group
|
||||
interpolate_modifier["Input_2"] = mesh_object
|
||||
interpolate_modifier["Input_18_attribute_name"] = curves.surface_uv_map
|
||||
interpolate_modifier["Input_12"] = True
|
||||
interpolate_modifier["Input_15"] = density
|
||||
interpolate_modifier["Input_17"] = self.view_percentage
|
||||
interpolate_modifier["Input_24"] = True
|
||||
|
@ -167,6 +168,8 @@ class QuickFur(ObjectModeOperator, Operator):
|
|||
with context.temp_override(object=curves_object):
|
||||
bpy.ops.object.modifier_apply(modifier=generate_modifier.name)
|
||||
|
||||
curves_object.modifiers.move(0, len(curves_object.modifiers) - 1)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
|
|
@ -728,7 +728,7 @@ class USERPREF_PT_viewport_display(ViewportPanel, CenterAlignMixIn, Panel):
|
|||
|
||||
col.separator()
|
||||
|
||||
col.prop(view, "mini_axis_type", text="3D Viewport Axis")
|
||||
col.prop(view, "mini_axis_type", text="3D Viewport Axes")
|
||||
|
||||
if view.mini_axis_type == 'MINIMAL':
|
||||
col.prop(view, "mini_axis_size", text="Size")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<eAssetImportMethod> AS_asset_representation_import_method_get(
|
||||
const ::AssetRepresentation *asset_handle);
|
||||
bool AS_asset_representation_may_override_import_method(const ::AssetRepresentation *asset_handle);
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
* \ingroup asset_system
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "BKE_blendfile.h"
|
||||
|
||||
#include "BLI_path_util.h"
|
||||
#include <iostream>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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<const asset_system::AssetRepresentation *>(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<const asset_system::AssetRepresentation *>(asset_handle);
|
||||
return asset->get_identifier().full_library_path();
|
||||
}
|
||||
|
||||
std::optional<eAssetImportMethod> 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<const asset_system::AssetRepresentation *>(asset_handle);
|
||||
return asset->local_id();
|
||||
}
|
||||
|
||||
bool AS_asset_representation_is_local_id(const AssetRepresentation *asset_handle)
|
||||
{
|
||||
const asset_system::AssetRepresentation *asset =
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -106,28 +106,11 @@ int BKE_id_attribute_to_index(const struct ID *id,
|
|||
eAttrDomainMask domain_mask,
|
||||
eCustomDataMask layer_mask);
|
||||
|
||||
/**
|
||||
* Sets up a temporary ID with arbitrary CustomData domains. `r_id` will
|
||||
* be zero initialized with ID type id_type and any non-nullptr
|
||||
* CustomData parameter will be copied into the appropriate struct members.
|
||||
*
|
||||
* \param r_id: Pointer to storage sufficient for ID type-code id_type.
|
||||
*/
|
||||
void BKE_id_attribute_copy_domains_temp(short id_type,
|
||||
const struct CustomData *vdata,
|
||||
const struct CustomData *edata,
|
||||
const struct CustomData *ldata,
|
||||
const struct CustomData *pdata,
|
||||
const struct CustomData *cdata,
|
||||
struct ID *r_id);
|
||||
|
||||
const char *BKE_id_attributes_active_color_name(const struct ID *id);
|
||||
const char *BKE_id_attributes_default_color_name(const struct ID *id);
|
||||
|
||||
struct CustomDataLayer *BKE_id_attributes_active_color_get(const struct ID *id);
|
||||
void BKE_id_attributes_active_color_set(struct ID *id, const char *name);
|
||||
struct CustomDataLayer *BKE_id_attributes_default_color_get(const struct ID *id);
|
||||
void BKE_id_attributes_default_color_set(struct ID *id, const char *name);
|
||||
|
||||
struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const char *name);
|
||||
|
||||
bool BKE_id_attribute_calc_unique_name(struct ID *id, const char *name, char *outname);
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 3
|
||||
#define BLENDER_FILE_SUBVERSION 4
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -233,17 +233,28 @@ void CustomData_free_temporary(struct CustomData *data, int totelem);
|
|||
* backed by an external data array. the different allocation types are
|
||||
* defined above. returns the data of the layer.
|
||||
*/
|
||||
void *CustomData_add_layer(
|
||||
struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem);
|
||||
void *CustomData_add_layer(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
const void *CustomData_add_layer_with_data(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
void *layer_data,
|
||||
int totelem);
|
||||
|
||||
/**
|
||||
* Same as above but accepts a name.
|
||||
*/
|
||||
void *CustomData_add_layer_named(struct CustomData *data,
|
||||
int type,
|
||||
eCustomDataType type,
|
||||
eCDAllocType alloctype,
|
||||
void *layer,
|
||||
int totelem,
|
||||
const char *name);
|
||||
const void *CustomData_add_layer_named_with_data(struct CustomData *data,
|
||||
eCustomDataType type,
|
||||
void *layer_data,
|
||||
int totelem,
|
||||
const char *name);
|
||||
void *CustomData_add_layer_anonymous(struct CustomData *data,
|
||||
int type,
|
||||
eCDAllocType alloctype,
|
||||
|
@ -475,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,
|
||||
|
|
|
@ -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).
|
||||
*
|
||||
|
@ -376,7 +376,7 @@ bool BKE_fcurve_calc_range(const struct FCurve *fcu,
|
|||
|
||||
/**
|
||||
* Calculate the x and y extents of F-Curve's data.
|
||||
* \param frame_range Only calculate the bounds of the FCurve in the given range.
|
||||
* \param frame_range: Only calculate the bounds of the FCurve in the given range.
|
||||
* Does the full range if NULL.
|
||||
* \return true if the bounds have been found.
|
||||
*/
|
||||
|
|
|
@ -344,7 +344,7 @@ typedef enum eGP_GetFrame_Mode {
|
|||
|
||||
/**
|
||||
* Get the appropriate gp-frame from a given layer
|
||||
* - this sets the layer's actframe var (if allowed to)
|
||||
* - this sets the layer's `actframe` var (if allowed to)
|
||||
* - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
|
||||
*
|
||||
* \param gpl: Grease pencil layer
|
||||
|
@ -523,7 +523,7 @@ struct Material *BKE_gpencil_object_material_new(struct Main *bmain,
|
|||
int *r_index);
|
||||
|
||||
/**
|
||||
* Get material index (0-based like mat_nr not actcol).
|
||||
* Get material index (0-based like mat_nr not #Object::actcol).
|
||||
* \param ob: Grease pencil object
|
||||
* \param ma: Material
|
||||
* \return Index of the material
|
||||
|
|
|
@ -185,7 +185,7 @@ typedef struct Main {
|
|||
ListBase particles;
|
||||
ListBase palettes;
|
||||
ListBase paintcurves;
|
||||
ListBase wm; /* Singleton (exception). */
|
||||
ListBase wm; /* Singleton (exception). */
|
||||
ListBase gpencils; /* Legacy Grease Pencil. */
|
||||
ListBase movieclips;
|
||||
ListBase masks;
|
||||
|
|
|
@ -323,27 +323,17 @@ void BKE_mesh_recalc_looptri(const struct MLoop *mloop,
|
|||
/* *** mesh_normals.cc *** */
|
||||
|
||||
/**
|
||||
* Returns the normals for each vertex, which is defined as the weighted average of the normals
|
||||
* from a vertices surrounding faces, or the normalized position of vertices connected to no faces.
|
||||
* \warning May still return null if the mesh is empty.
|
||||
* See #Mesh::vert_normals().
|
||||
* \warning May return null if the mesh is empty.
|
||||
*/
|
||||
const float (*BKE_mesh_vert_normals_ensure(const struct Mesh *mesh))[3];
|
||||
|
||||
/**
|
||||
* Return the normal direction of every polygon, which is defined by the winding direction of its
|
||||
* corners.
|
||||
* \warning May still return null if the mesh is empty or has no polygons.
|
||||
* See #Mesh::poly_normals().
|
||||
* \warning May return null if the mesh is empty or has no polygons.
|
||||
*/
|
||||
const float (*BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3];
|
||||
|
||||
/**
|
||||
* Tag mesh vertex and face normals to be recalculated when/if they are needed later.
|
||||
*
|
||||
* \note Dirty tagged normals are the default state of a new mesh, so tagging them
|
||||
* dirty explicitly is not always necessary if the mesh is created locally.
|
||||
*/
|
||||
void BKE_mesh_normals_tag_dirty(struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Retrieve write access to the cached vertex normals, ensuring that they are allocated but *not*
|
||||
* that they are calculated. The provided vertex normals should be the same as if they were
|
||||
|
@ -798,7 +788,7 @@ BLI_INLINE int *BKE_mesh_material_indices_for_write(Mesh *mesh)
|
|||
return indices;
|
||||
}
|
||||
return (int *)CustomData_add_layer_named(
|
||||
&mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, NULL, mesh->totpoly, "material_index");
|
||||
&mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totpoly, "material_index");
|
||||
}
|
||||
|
||||
BLI_INLINE const float (*BKE_mesh_vert_positions(const Mesh *mesh))[3]
|
||||
|
@ -850,7 +840,7 @@ BLI_INLINE MDeformVert *BKE_mesh_deform_verts_for_write(Mesh *mesh)
|
|||
return dvert;
|
||||
}
|
||||
return (MDeformVert *)CustomData_add_layer(
|
||||
&mesh->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, NULL, mesh->totvert);
|
||||
&mesh->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, mesh->totvert);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -43,7 +43,7 @@ float3 poly_center_calc(Span<float3> vert_positions, Span<MLoop> poly_loops);
|
|||
/** Calculate the surface area of the polygon described by the indexed vertices. */
|
||||
float poly_area_calc(Span<float3> vert_positions, Span<MLoop> poly_loops);
|
||||
|
||||
/** Calculate the angles at each of the polygons's corners. */
|
||||
/** Calculate the angles at each of the polygons corners. */
|
||||
void poly_angles_calc(Span<float3> vert_positions,
|
||||
Span<MLoop> poly_loops,
|
||||
MutableSpan<float> angles);
|
||||
|
@ -196,16 +196,4 @@ inline blender::MutableSpan<MDeformVert> Mesh::deform_verts_for_write()
|
|||
return {BKE_mesh_deform_verts_for_write(this), this->totvert};
|
||||
}
|
||||
|
||||
inline blender::Span<blender::float3> Mesh::poly_normals() const
|
||||
{
|
||||
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_poly_normals_ensure(this)),
|
||||
this->totpoly};
|
||||
}
|
||||
|
||||
inline blender::Span<blender::float3> Mesh::vert_normals() const
|
||||
{
|
||||
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vert_normals_ensure(this)),
|
||||
this->totvert};
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -45,7 +45,7 @@ void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, int index);
|
|||
* https://blenderartists.org/t/619105
|
||||
*
|
||||
* We could also use similar topology mappings inside a same mesh
|
||||
* (cf. Campbell's 'select face islands from similar topology' wip work).
|
||||
* (cf. Campbell's 'select face islands from similar topology' WIP work).
|
||||
* Also, users will have to check, whether we can get rid of some modes here,
|
||||
* not sure all will be useful!
|
||||
*/
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
# include "BLI_math_vector_types.hh"
|
||||
# include "BLI_shared_cache.hh"
|
||||
# include "BLI_span.hh"
|
||||
# include "BLI_vector.hh"
|
||||
|
||||
# include "DNA_customdata_types.h"
|
||||
# include "DNA_meshdata_types.h"
|
||||
|
@ -158,8 +159,8 @@ struct MeshRuntime {
|
|||
*/
|
||||
bool vert_normals_dirty = true;
|
||||
bool poly_normals_dirty = true;
|
||||
float (*vert_normals)[3] = nullptr;
|
||||
float (*poly_normals)[3] = nullptr;
|
||||
mutable Vector<float3> vert_normals;
|
||||
mutable Vector<float3> poly_normals;
|
||||
|
||||
/**
|
||||
* A cache of data about the loose edges. Can be shared with other data-blocks with unchanged
|
||||
|
|
|
@ -345,11 +345,6 @@ typedef struct bNodeType {
|
|||
|
||||
/* Execute a geometry node. */
|
||||
NodeGeometryExecFunction geometry_node_execute;
|
||||
/**
|
||||
* If true, the geometry nodes evaluator can call the execute function multiple times to improve
|
||||
* performance by specifying required data in one call and using it for calculations in another.
|
||||
*/
|
||||
bool geometry_node_execute_supports_laziness;
|
||||
|
||||
/* Declares which sockets the node has. */
|
||||
NodeDeclareFunction declare;
|
||||
|
|
|
@ -783,10 +783,8 @@ bool BKE_pbvh_node_has_vert_with_normal_update_tag(PBVH *pbvh, PBVHNode *node);
|
|||
// void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
|
||||
|
||||
bool pbvh_has_mask(const PBVH *pbvh);
|
||||
void pbvh_show_mask_set(PBVH *pbvh, bool show_mask);
|
||||
|
||||
bool pbvh_has_face_sets(PBVH *pbvh);
|
||||
void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets);
|
||||
|
||||
/* Parallelization. */
|
||||
|
||||
|
|
|
@ -256,8 +256,8 @@ struct NodeData {
|
|||
MEM_delete(node_data);
|
||||
}
|
||||
};
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Fix non-manifold edge bleeding.
|
||||
* \{ */
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -496,6 +496,7 @@ set(SRC
|
|||
nla_private.h
|
||||
particle_private.h
|
||||
tracking_private.h
|
||||
|
||||
intern/CCGSubSurf.h
|
||||
intern/CCGSubSurf_inline.h
|
||||
intern/CCGSubSurf_intern.h
|
||||
|
@ -507,6 +508,7 @@ set(SRC
|
|||
intern/multires_unsubdivide.h
|
||||
intern/ocean_intern.h
|
||||
intern/pbvh_intern.hh
|
||||
intern/pbvh_pixels_copy.hh
|
||||
intern/pbvh_uv_islands.hh
|
||||
intern/subdiv_converter.h
|
||||
intern/subdiv_inline.h
|
||||
|
|
|
@ -99,7 +99,7 @@ static float *dm_getVertArray(DerivedMesh *dm)
|
|||
|
||||
if (!positions) {
|
||||
positions = (float(*)[3])CustomData_add_layer_named(
|
||||
&dm->vertData, CD_PROP_FLOAT3, CD_SET_DEFAULT, nullptr, dm->getNumVerts(dm), "position");
|
||||
&dm->vertData, CD_PROP_FLOAT3, CD_SET_DEFAULT, dm->getNumVerts(dm), "position");
|
||||
CustomData_set_layer_flag(&dm->vertData, CD_PROP_FLOAT3, CD_FLAG_TEMPORARY);
|
||||
dm->copyVertArray(dm, positions);
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ static MEdge *dm_getEdgeArray(DerivedMesh *dm)
|
|||
|
||||
if (!edge) {
|
||||
edge = (MEdge *)CustomData_add_layer(
|
||||
&dm->edgeData, CD_MEDGE, CD_SET_DEFAULT, nullptr, dm->getNumEdges(dm));
|
||||
&dm->edgeData, CD_MEDGE, CD_SET_DEFAULT, dm->getNumEdges(dm));
|
||||
CustomData_set_layer_flag(&dm->edgeData, CD_MEDGE, CD_FLAG_TEMPORARY);
|
||||
dm->copyEdgeArray(dm, edge);
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ static MLoop *dm_getLoopArray(DerivedMesh *dm)
|
|||
|
||||
if (!mloop) {
|
||||
mloop = (MLoop *)CustomData_add_layer(
|
||||
&dm->loopData, CD_MLOOP, CD_SET_DEFAULT, nullptr, dm->getNumLoops(dm));
|
||||
&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);
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ static MPoly *dm_getPolyArray(DerivedMesh *dm)
|
|||
|
||||
if (!mpoly) {
|
||||
mpoly = (MPoly *)CustomData_add_layer(
|
||||
&dm->polyData, CD_MPOLY, CD_SET_DEFAULT, nullptr, dm->getNumPolys(dm));
|
||||
&dm->polyData, CD_MPOLY, CD_SET_DEFAULT, dm->getNumPolys(dm));
|
||||
CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY);
|
||||
dm->copyPolyArray(dm, mpoly);
|
||||
}
|
||||
|
@ -505,7 +505,7 @@ static void add_orco_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orc
|
|||
layerorco = (float(*)[3])CustomData_get_layer_for_write(&mesh->vdata, layer, mesh->totvert);
|
||||
if (!layerorco) {
|
||||
layerorco = (float(*)[3])CustomData_add_layer(
|
||||
&mesh->vdata, layer, CD_SET_DEFAULT, nullptr, mesh->totvert);
|
||||
&mesh->vdata, eCustomDataType(layer), CD_SET_DEFAULT, mesh->totvert);
|
||||
}
|
||||
|
||||
memcpy(layerorco, orco, sizeof(float[3]) * totvert);
|
||||
|
@ -886,11 +886,11 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX)) {
|
||||
/* calc */
|
||||
CustomData_add_layer(
|
||||
&mesh_final->vdata, CD_ORIGINDEX, CD_CONSTRUCT, nullptr, mesh_final->totvert);
|
||||
&mesh_final->vdata, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->totvert);
|
||||
CustomData_add_layer(
|
||||
&mesh_final->edata, CD_ORIGINDEX, CD_CONSTRUCT, nullptr, mesh_final->totedge);
|
||||
&mesh_final->edata, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->totedge);
|
||||
CustomData_add_layer(
|
||||
&mesh_final->pdata, CD_ORIGINDEX, CD_CONSTRUCT, nullptr, mesh_final->totpoly);
|
||||
&mesh_final->pdata, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->totpoly);
|
||||
|
||||
/* Not worth parallelizing this,
|
||||
* gives less than 0.1% overall speedup in best of best cases... */
|
||||
|
@ -929,11 +929,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
/* add an origspace layer if needed */
|
||||
if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) {
|
||||
if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
|
||||
CustomData_add_layer(&mesh_final->ldata,
|
||||
CD_ORIGSPACE_MLOOP,
|
||||
CD_SET_DEFAULT,
|
||||
nullptr,
|
||||
mesh_final->totloop);
|
||||
CustomData_add_layer(
|
||||
&mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_SET_DEFAULT, mesh_final->totloop);
|
||||
mesh_init_origspace(mesh_final);
|
||||
}
|
||||
}
|
||||
|
@ -1380,11 +1377,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
|
||||
if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) {
|
||||
if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
|
||||
CustomData_add_layer(&mesh_final->ldata,
|
||||
CD_ORIGSPACE_MLOOP,
|
||||
CD_SET_DEFAULT,
|
||||
nullptr,
|
||||
mesh_final->totloop);
|
||||
CustomData_add_layer(
|
||||
&mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_SET_DEFAULT, mesh_final->totloop);
|
||||
mesh_init_origspace(mesh_final);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -778,11 +778,6 @@ const char *BKE_id_attributes_default_color_name(const ID *id)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CustomDataLayer *BKE_id_attributes_active_color_get(const ID *id)
|
||||
{
|
||||
return BKE_id_attributes_color_find(id, BKE_id_attributes_active_color_name(id));
|
||||
}
|
||||
|
||||
void BKE_id_attributes_active_color_set(ID *id, const char *name)
|
||||
{
|
||||
switch (GS(id->name)) {
|
||||
|
@ -799,11 +794,6 @@ void BKE_id_attributes_active_color_set(ID *id, const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
CustomDataLayer *BKE_id_attributes_default_color_get(const ID *id)
|
||||
{
|
||||
return BKE_id_attributes_color_find(id, BKE_id_attributes_default_color_name(id));
|
||||
}
|
||||
|
||||
void BKE_id_attributes_default_color_set(ID *id, const char *name)
|
||||
{
|
||||
switch (GS(id->name)) {
|
||||
|
@ -822,71 +812,22 @@ void BKE_id_attributes_default_color_set(ID *id, const char *name)
|
|||
|
||||
CustomDataLayer *BKE_id_attributes_color_find(const ID *id, const char *name)
|
||||
{
|
||||
if (!name) {
|
||||
return nullptr;
|
||||
if (CustomDataLayer *layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_POINT)) {
|
||||
return layer;
|
||||
}
|
||||
CustomDataLayer *layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_POINT);
|
||||
if (layer == nullptr) {
|
||||
layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_CORNER);
|
||||
if (CustomDataLayer *layer = BKE_id_attribute_find(
|
||||
id, name, CD_PROP_COLOR, ATTR_DOMAIN_CORNER)) {
|
||||
return layer;
|
||||
}
|
||||
if (layer == nullptr) {
|
||||
layer = BKE_id_attribute_find(id, name, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_POINT);
|
||||
if (CustomDataLayer *layer = BKE_id_attribute_find(
|
||||
id, name, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_POINT)) {
|
||||
return layer;
|
||||
}
|
||||
if (layer == nullptr) {
|
||||
layer = BKE_id_attribute_find(id, name, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_CORNER);
|
||||
if (CustomDataLayer *layer = BKE_id_attribute_find(
|
||||
id, name, CD_PROP_BYTE_COLOR, ATTR_DOMAIN_CORNER)) {
|
||||
return layer;
|
||||
}
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
void BKE_id_attribute_copy_domains_temp(short id_type,
|
||||
const CustomData *vdata,
|
||||
const CustomData *edata,
|
||||
const CustomData *ldata,
|
||||
const CustomData *pdata,
|
||||
const CustomData *cdata,
|
||||
ID *r_id)
|
||||
{
|
||||
CustomData reset;
|
||||
|
||||
CustomData_reset(&reset);
|
||||
|
||||
switch (id_type) {
|
||||
case ID_ME: {
|
||||
Mesh *me = (Mesh *)r_id;
|
||||
memset((void *)me, 0, sizeof(*me));
|
||||
|
||||
me->edit_mesh = nullptr;
|
||||
|
||||
me->vdata = vdata ? *vdata : reset;
|
||||
me->edata = edata ? *edata : reset;
|
||||
me->ldata = ldata ? *ldata : reset;
|
||||
me->pdata = pdata ? *pdata : reset;
|
||||
|
||||
break;
|
||||
}
|
||||
case ID_PT: {
|
||||
PointCloud *pointcloud = (PointCloud *)r_id;
|
||||
|
||||
memset((void *)pointcloud, 0, sizeof(*pointcloud));
|
||||
|
||||
pointcloud->pdata = vdata ? *vdata : reset;
|
||||
break;
|
||||
}
|
||||
case ID_CV: {
|
||||
Curves *curves = (Curves *)r_id;
|
||||
|
||||
memset((void *)curves, 0, sizeof(*curves));
|
||||
|
||||
curves->geometry.point_data = vdata ? *vdata : reset;
|
||||
curves->geometry.curve_data = cdata ? *cdata : reset;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*((short *)r_id->name) = id_type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer)
|
||||
|
|
|
@ -181,18 +181,15 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
|
|||
{
|
||||
switch (initializer.type) {
|
||||
case AttributeInit::Type::Construct: {
|
||||
void *data = CustomData_add_layer(
|
||||
&custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num);
|
||||
void *data = CustomData_add_layer(&custom_data, data_type, CD_CONSTRUCT, domain_num);
|
||||
return data != nullptr;
|
||||
}
|
||||
case AttributeInit::Type::DefaultValue: {
|
||||
void *data = CustomData_add_layer(
|
||||
&custom_data, data_type, CD_SET_DEFAULT, nullptr, domain_num);
|
||||
void *data = CustomData_add_layer(&custom_data, data_type, CD_SET_DEFAULT, domain_num);
|
||||
return data != nullptr;
|
||||
}
|
||||
case AttributeInit::Type::VArray: {
|
||||
void *data = CustomData_add_layer(
|
||||
&custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num);
|
||||
void *data = CustomData_add_layer(&custom_data, data_type, CD_CONSTRUCT, domain_num);
|
||||
if (data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
@ -202,8 +199,8 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
|
|||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
void *source_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
|
||||
void *data = CustomData_add_layer(
|
||||
&custom_data, data_type, CD_ASSIGN, source_data, domain_num);
|
||||
const void *data = CustomData_add_layer_with_data(
|
||||
&custom_data, data_type, source_data, domain_num);
|
||||
if (data == nullptr) {
|
||||
MEM_freeN(source_data);
|
||||
return false;
|
||||
|
@ -219,19 +216,36 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
|
|||
static void *add_generic_custom_data_layer(CustomData &custom_data,
|
||||
const eCustomDataType data_type,
|
||||
const eCDAllocType alloctype,
|
||||
void *layer_data,
|
||||
const int domain_num,
|
||||
const int domain_size,
|
||||
const AttributeIDRef &attribute_id)
|
||||
{
|
||||
if (!attribute_id.is_anonymous()) {
|
||||
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
attribute_id.name().copy(attribute_name_c);
|
||||
return CustomData_add_layer_named(
|
||||
&custom_data, data_type, alloctype, layer_data, domain_num, attribute_name_c);
|
||||
&custom_data, data_type, alloctype, domain_size, attribute_name_c);
|
||||
}
|
||||
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
|
||||
return CustomData_add_layer_anonymous(
|
||||
&custom_data, data_type, alloctype, layer_data, domain_num, &anonymous_id);
|
||||
&custom_data, data_type, alloctype, nullptr, domain_size, &anonymous_id);
|
||||
}
|
||||
|
||||
static const void *add_generic_custom_data_layer_with_existing_data(
|
||||
CustomData &custom_data,
|
||||
const eCustomDataType data_type,
|
||||
void *layer_data,
|
||||
const int domain_size,
|
||||
const AttributeIDRef &attribute_id)
|
||||
{
|
||||
if (!attribute_id.is_anonymous()) {
|
||||
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
attribute_id.name().copy(attribute_name_c);
|
||||
return CustomData_add_layer_named_with_data(
|
||||
&custom_data, data_type, layer_data, domain_size, attribute_name_c);
|
||||
}
|
||||
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
|
||||
return CustomData_add_layer_anonymous(
|
||||
&custom_data, data_type, CD_ASSIGN, layer_data, domain_size, &anonymous_id);
|
||||
}
|
||||
|
||||
static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attribute_id,
|
||||
|
@ -244,17 +258,17 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
|
|||
switch (initializer.type) {
|
||||
case AttributeInit::Type::Construct: {
|
||||
add_generic_custom_data_layer(
|
||||
custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num, attribute_id);
|
||||
custom_data, data_type, CD_CONSTRUCT, domain_num, attribute_id);
|
||||
break;
|
||||
}
|
||||
case AttributeInit::Type::DefaultValue: {
|
||||
add_generic_custom_data_layer(
|
||||
custom_data, data_type, CD_SET_DEFAULT, nullptr, domain_num, attribute_id);
|
||||
custom_data, data_type, CD_SET_DEFAULT, domain_num, attribute_id);
|
||||
break;
|
||||
}
|
||||
case AttributeInit::Type::VArray: {
|
||||
void *data = add_generic_custom_data_layer(
|
||||
custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num, attribute_id);
|
||||
custom_data, data_type, CD_CONSTRUCT, domain_num, attribute_id);
|
||||
if (data != nullptr) {
|
||||
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray.materialize_to_uninitialized(varray.index_range(), data);
|
||||
|
@ -263,8 +277,8 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
|
|||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
void *source_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
|
||||
add_generic_custom_data_layer(
|
||||
custom_data, data_type, CD_ASSIGN, source_data, domain_num, attribute_id);
|
||||
add_generic_custom_data_layer_with_existing_data(
|
||||
custom_data, data_type, source_data, domain_num, attribute_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -633,7 +647,7 @@ bool CustomDataAttributes::create(const AttributeIDRef &attribute_id,
|
|||
const eCustomDataType data_type)
|
||||
{
|
||||
void *result = add_generic_custom_data_layer(
|
||||
data, data_type, CD_SET_DEFAULT, nullptr, size_, attribute_id);
|
||||
data, data_type, CD_SET_DEFAULT, size_, attribute_id);
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
|
@ -641,8 +655,8 @@ bool CustomDataAttributes::create_by_move(const AttributeIDRef &attribute_id,
|
|||
const eCustomDataType data_type,
|
||||
void *buffer)
|
||||
{
|
||||
void *result = add_generic_custom_data_layer(
|
||||
data, data_type, CD_ASSIGN, buffer, size_, attribute_id);
|
||||
const void *result = add_generic_custom_data_layer_with_existing_data(
|
||||
data, data_type, buffer, size_, attribute_id);
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
* \{ */
|
||||
|
|
|
@ -39,7 +39,7 @@ struct CDDerivedMesh {
|
|||
/* these point to data in the DerivedMesh custom data layers,
|
||||
* they are only here for efficiency and convenience */
|
||||
float (*vert_positions)[3];
|
||||
const float (*vert_normals)[3];
|
||||
const blender::float3 *vert_normals;
|
||||
MEdge *medge;
|
||||
MFace *mface;
|
||||
MLoop *mloop;
|
||||
|
@ -221,7 +221,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
|
|||
&dm->vertData, CD_PROP_FLOAT3, "position", mesh->totvert));
|
||||
/* Though this may be an unnecessary calculation, simply retrieving the layer may return nothing
|
||||
* or dirty normals. */
|
||||
cddm->vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
cddm->vert_normals = mesh->vert_normals().data();
|
||||
cddm->medge = static_cast<MEdge *>(
|
||||
CustomData_get_layer_for_write(&dm->edgeData, CD_MEDGE, mesh->totedge));
|
||||
cddm->mloop = static_cast<MLoop *>(
|
||||
|
|
|
@ -1387,7 +1387,7 @@ BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop
|
|||
}
|
||||
|
||||
static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
|
||||
const float (*vert_normals)[3],
|
||||
const blender::Span<blender::float3> vert_normals,
|
||||
uint v_idx,
|
||||
RNG *rng,
|
||||
float max_length,
|
||||
|
@ -1530,7 +1530,8 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
|
|||
BKE_bvhtree_from_mesh_get(&treedata, tmp_mesh ? tmp_mesh : mesh, BVHTREE_FROM_LOOPTRI, 2);
|
||||
rng = BLI_rng_new_srandom(0);
|
||||
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(tmp_mesh ? tmp_mesh : mesh);
|
||||
const blender::Span<blender::float3> vert_normals = tmp_mesh ? tmp_mesh->vert_normals() :
|
||||
mesh->vert_normals();
|
||||
|
||||
for (int i = 0; i < mvert_num; i++) {
|
||||
if (find_internal_spring_target_vertex(
|
||||
|
|
|
@ -1141,11 +1141,12 @@ static void collection_gobject_hash_ensure_fix(Collection *collection)
|
|||
/**
|
||||
* Update the collections object hash, removing `ob_old`, inserting `cob->ob` as the new key.
|
||||
*
|
||||
* \note This function is called fron foreach_id callback, and a difference of Object pointers is
|
||||
* only expected in case ID remapping is happening. This code is the only are in Blender allowed to
|
||||
* (temporarily) leave the CollectionObject list in an inconsistent/invalid state (with NULL object
|
||||
* pointers, or duplicates of CollectionObjects). If such invalid cases are encountered, it will
|
||||
* tag the collection objects list as dirty.
|
||||
* \note This function is called from #IDTypeInfo::foreach_id callback,
|
||||
* and a difference of Object pointers is only expected in case ID remapping is happening.
|
||||
* This code is the only are in Blender allowed to (temporarily) leave the #CollectionObject list
|
||||
* in an inconsistent/invalid state (with NULL object pointers, or duplicates of
|
||||
* #CollectionObjects). If such invalid cases are encountered,
|
||||
* it will tag the collection objects list as dirty.
|
||||
*
|
||||
* \param ob_old: The existing key to `cob` in the hash, not removed when NULL.
|
||||
* \param cob: The `cob->ob` is to be used as the new key,
|
||||
|
@ -1162,7 +1163,7 @@ static void collection_gobject_hash_update_object(Collection *collection,
|
|||
if (ob_old) {
|
||||
CollectionObject *cob_old = BLI_ghash_popkey(collection->runtime.gobject_hash, ob_old, NULL);
|
||||
if (cob_old != cob) {
|
||||
/* Old object alredy removed from the ghash. */
|
||||
/* Old object already removed from the #GHash. */
|
||||
collection->runtime.tag |= COLLECTION_TAG_COLLECTION_OBJECT_DIRTY;
|
||||
}
|
||||
}
|
||||
|
@ -1173,28 +1174,28 @@ static void collection_gobject_hash_update_object(Collection *collection,
|
|||
*cob_p = cob;
|
||||
}
|
||||
else {
|
||||
/* Duplicate CollectionObject entries. */
|
||||
/* Duplicate #CollectionObject entries. */
|
||||
collection->runtime.tag |= COLLECTION_TAG_COLLECTION_OBJECT_DIRTY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* CollectionObject with NULL objetc pointer. */
|
||||
/* #CollectionObject with NULL object pointer. */
|
||||
collection->runtime.tag |= COLLECTION_TAG_COLLECTION_OBJECT_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the integrity of the collection's CollectionObject list, and of its mapping.
|
||||
* Validate the integrity of the collection's #CollectionObject list, and of its mapping.
|
||||
*
|
||||
* Simple test is very fast, as it only checks that the 'dirty' tag for collection's objects is not
|
||||
* set.
|
||||
*
|
||||
* The extensive check is expensive. This should not be done from within loops over collections
|
||||
* items, or from low-level operations that can be assumed safe (like adding or removing an object
|
||||
* from a colleciton). It ensures that:
|
||||
* - There is a `gobject_hash` mapping.
|
||||
* - There is no NULL-object CollectionObject items.
|
||||
* - there is no duplicate CollectionObject items (two or more referencing the same Object).
|
||||
* from a collection). It ensures that:
|
||||
* - There is a `gobject_hash` mapping.
|
||||
* - There is no NULL-object #CollectionObject items.
|
||||
* - there is no duplicate #CollectionObject items (two or more referencing the same Object).
|
||||
*/
|
||||
static void collection_gobject_assert_internal_consistency(Collection *collection,
|
||||
const bool do_extensive_check)
|
||||
|
@ -1205,16 +1206,16 @@ static void collection_gobject_assert_internal_consistency(Collection *collectio
|
|||
}
|
||||
|
||||
if (collection->runtime.gobject_hash == NULL) {
|
||||
/* NOTE: If the ghash does not exist yet, it's creation will assert on errors, so in theory the
|
||||
* second loop below could be skipped. */
|
||||
/* NOTE: If the `ghash` does not exist yet, it's creation will assert on errors,
|
||||
* so in theory the second loop below could be skipped. */
|
||||
collection_gobject_hash_create(collection);
|
||||
}
|
||||
GHash *gobject_hash = collection->runtime.gobject_hash;
|
||||
UNUSED_VARS_NDEBUG(gobject_hash);
|
||||
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
|
||||
BLI_assert(cob->ob != NULL);
|
||||
/* If there are more than one CollectionObject for the same object, at most one of them will
|
||||
* pass this test. */
|
||||
/* If there are more than one #CollectionObject for the same object,
|
||||
* at most one of them will pass this test. */
|
||||
BLI_assert(BLI_ghash_lookup(gobject_hash, cob->ob) == cob);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<AssetRepresentation *>(ctx_data_pointer_get(C, "asset"));
|
||||
}
|
||||
|
||||
Depsgraph *CTX_data_depsgraph_pointer(const bContext *C)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
|
|
@ -59,12 +59,8 @@ CurvesGeometry::CurvesGeometry(const int point_num, const int curve_num)
|
|||
CustomData_reset(&this->point_data);
|
||||
CustomData_reset(&this->curve_data);
|
||||
|
||||
CustomData_add_layer_named(&this->point_data,
|
||||
CD_PROP_FLOAT3,
|
||||
CD_CONSTRUCT,
|
||||
nullptr,
|
||||
this->point_num,
|
||||
ATTR_POSITION.c_str());
|
||||
CustomData_add_layer_named(
|
||||
&this->point_data, CD_PROP_FLOAT3, CD_CONSTRUCT, this->point_num, ATTR_POSITION.c_str());
|
||||
|
||||
this->curve_offsets = (int *)MEM_malloc_arrayN(this->curve_num + 1, sizeof(int), __func__);
|
||||
#ifdef DEBUG
|
||||
|
@ -230,8 +226,7 @@ static MutableSpan<T> get_mutable_attribute(CurvesGeometry &curves,
|
|||
if (data != nullptr) {
|
||||
return {data, num};
|
||||
}
|
||||
data = (T *)CustomData_add_layer_named(
|
||||
&custom_data, type, CD_SET_DEFAULT, nullptr, num, name.c_str());
|
||||
data = (T *)CustomData_add_layer_named(&custom_data, type, CD_SET_DEFAULT, num, name.c_str());
|
||||
MutableSpan<T> span = {data, num};
|
||||
if (num > 0 && span.first() != default_value) {
|
||||
span.fill(default_value);
|
||||
|
|
|
@ -2686,6 +2686,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<CustomDataLayer *>(
|
||||
|
@ -2835,7 +2844,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
|||
return &data->layers[index];
|
||||
}
|
||||
|
||||
void *CustomData_add_layer(
|
||||
static void *customdata_add_layer(
|
||||
CustomData *data, const int type, eCDAllocType alloctype, void *layerdata, const int totelem)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
|
||||
|
@ -2851,12 +2860,28 @@ void *CustomData_add_layer(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void *CustomData_add_layer_named(CustomData *data,
|
||||
const int type,
|
||||
const eCDAllocType alloctype,
|
||||
void *layerdata,
|
||||
const int totelem,
|
||||
const char *name)
|
||||
void *CustomData_add_layer(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const eCDAllocType alloctype,
|
||||
const int totelem)
|
||||
{
|
||||
return customdata_add_layer(data, type, alloctype, nullptr, totelem);
|
||||
}
|
||||
|
||||
const void *CustomData_add_layer_with_data(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
void *layer_data,
|
||||
const int totelem)
|
||||
{
|
||||
return customdata_add_layer(data, type, CD_ASSIGN, layer_data, totelem);
|
||||
}
|
||||
|
||||
static void *customdata_add_layer_named(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const eCDAllocType alloctype,
|
||||
void *layerdata,
|
||||
const int totelem,
|
||||
const char *name)
|
||||
{
|
||||
CustomDataLayer *layer = customData_add_layer__internal(
|
||||
data, type, alloctype, layerdata, totelem, name);
|
||||
|
@ -2869,6 +2894,21 @@ void *CustomData_add_layer_named(CustomData *data,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void *CustomData_add_layer_named(CustomData *data,
|
||||
const eCustomDataType type,
|
||||
const eCDAllocType alloctype,
|
||||
const int totelem,
|
||||
const char *name)
|
||||
{
|
||||
return customdata_add_layer_named(data, type, alloctype, nullptr, totelem, name);
|
||||
}
|
||||
|
||||
const void *CustomData_add_layer_named_with_data(
|
||||
CustomData *data, const eCustomDataType type, void *layer_data, int totelem, const char *name)
|
||||
{
|
||||
return customdata_add_layer_named(data, type, CD_ASSIGN, layer_data, totelem, name);
|
||||
}
|
||||
|
||||
void *CustomData_add_layer_anonymous(CustomData *data,
|
||||
const int type,
|
||||
const eCDAllocType alloctype,
|
||||
|
|
|
@ -369,7 +369,7 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
|
|||
const bool do_loop_nors_dst = (loop_nors_dst == nullptr);
|
||||
if (do_loop_nors_dst) {
|
||||
loop_nors_dst = static_cast<blender::float3 *>(
|
||||
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, nullptr, me_dst->totloop));
|
||||
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, me_dst->totloop));
|
||||
CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
if (dirty_nors_dst || do_loop_nors_dst) {
|
||||
|
@ -416,8 +416,8 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
|
|||
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop));
|
||||
|
||||
if (!custom_nors_dst) {
|
||||
custom_nors_dst = static_cast<short(*)[2]>(CustomData_add_layer(
|
||||
ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, me_dst->totloop));
|
||||
custom_nors_dst = static_cast<short(*)[2]>(
|
||||
CustomData_add_layer(ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, me_dst->totloop));
|
||||
}
|
||||
|
||||
bke::MutableAttributeAccessor attributes = me_dst->attributes_for_write();
|
||||
|
@ -623,7 +623,8 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map
|
|||
if (use_create) {
|
||||
/* Create as much data layers as necessary! */
|
||||
for (; idx_dst < idx_src; idx_dst++) {
|
||||
CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst);
|
||||
CustomData_add_layer(
|
||||
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -677,7 +678,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map
|
|||
if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) {
|
||||
if (use_create) {
|
||||
CustomData_add_layer_named(
|
||||
cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst, name);
|
||||
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst, name);
|
||||
idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
|
||||
}
|
||||
else {
|
||||
|
@ -756,7 +757,8 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
|
|||
if (!use_create) {
|
||||
return true;
|
||||
}
|
||||
data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst);
|
||||
data_dst = CustomData_add_layer(
|
||||
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
|
||||
}
|
||||
|
||||
if (r_map) {
|
||||
|
@ -797,7 +799,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
|
|||
return true;
|
||||
}
|
||||
data_dst = CustomData_add_layer(
|
||||
cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst);
|
||||
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
|
||||
}
|
||||
else {
|
||||
data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
|
||||
|
@ -812,7 +814,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
|
|||
}
|
||||
/* Create as much data layers as necessary! */
|
||||
for (; num <= idx_dst; num++) {
|
||||
CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst);
|
||||
CustomData_add_layer(cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
|
||||
}
|
||||
}
|
||||
data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
|
||||
|
@ -824,7 +826,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
|
|||
return true;
|
||||
}
|
||||
CustomData_add_layer_named(
|
||||
cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst, name);
|
||||
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst, name);
|
||||
idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
|
||||
}
|
||||
data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
|
||||
|
@ -989,7 +991,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
|
|||
if (r_map && cddata_type == CD_FAKE_SEAM) {
|
||||
if (!CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, ".uv_seam")) {
|
||||
CustomData_add_layer_named(
|
||||
&me_dst->edata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me_dst->totedge, ".uv_seam");
|
||||
&me_dst->edata, CD_PROP_BOOL, CD_SET_DEFAULT, me_dst->totedge, ".uv_seam");
|
||||
}
|
||||
data_transfer_layersmapping_add_item_cd(
|
||||
r_map,
|
||||
|
@ -1007,7 +1009,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
|
|||
if (r_map && cddata_type == CD_FAKE_SHARP) {
|
||||
if (!CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge")) {
|
||||
CustomData_add_layer_named(
|
||||
&me_dst->edata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me_dst->totedge, "sharp_edge");
|
||||
&me_dst->edata, CD_PROP_BOOL, CD_SET_DEFAULT, me_dst->totedge, "sharp_edge");
|
||||
}
|
||||
data_transfer_layersmapping_add_item_cd(
|
||||
r_map,
|
||||
|
@ -1093,7 +1095,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
|
|||
if (r_map && cddata_type == CD_FAKE_SHARP) {
|
||||
if (!CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face")) {
|
||||
CustomData_add_layer_named(
|
||||
&me_dst->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me_dst->totpoly, "sharp_face");
|
||||
&me_dst->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, me_dst->totpoly, "sharp_face");
|
||||
}
|
||||
data_transfer_layersmapping_add_item_cd(
|
||||
r_map,
|
||||
|
|
|
@ -1262,7 +1262,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
|
|||
* Again, use_create is not relevant in this case */
|
||||
if (!data_dst) {
|
||||
data_dst = static_cast<MDeformVert *>(
|
||||
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, num_elem_dst));
|
||||
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, num_elem_dst));
|
||||
}
|
||||
|
||||
while (idx_src--) {
|
||||
|
@ -1323,8 +1323,8 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
|
|||
/* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
|
||||
* use_create is not relevant in this case */
|
||||
if (!data_dst) {
|
||||
data_dst = static_cast<MDeformVert *>(CustomData_add_layer(
|
||||
cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, num_elem_dst));
|
||||
data_dst = static_cast<MDeformVert *>(
|
||||
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, num_elem_dst));
|
||||
}
|
||||
|
||||
data_transfer_layersmapping_add_item(r_map,
|
||||
|
@ -1467,7 +1467,7 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map,
|
|||
* use_create is not relevant in this case */
|
||||
if (!data_dst) {
|
||||
data_dst = static_cast<MDeformVert *>(
|
||||
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, num_elem_dst));
|
||||
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, num_elem_dst));
|
||||
}
|
||||
|
||||
data_transfer_layersmapping_add_item(r_map,
|
||||
|
|
|
@ -1789,7 +1789,7 @@ struct DynamicPaintModifierApplyData {
|
|||
Object *ob;
|
||||
|
||||
float (*vert_positions)[3];
|
||||
const float (*vert_normals)[3];
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
blender::Span<MPoly> polys;
|
||||
blender::Span<MLoop> loops;
|
||||
|
||||
|
@ -1827,7 +1827,7 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Mesh
|
|||
DynamicPaintModifierApplyData data{};
|
||||
data.surface = surface;
|
||||
data.vert_positions = BKE_mesh_vert_positions_for_write(result);
|
||||
data.vert_normals = BKE_mesh_vert_normals_ensure(result);
|
||||
data.vert_normals = result->vert_normals();
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
|
@ -1958,7 +1958,6 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
|
|||
mloopcol = static_cast<MLoopCol *>(CustomData_add_layer_named(&result->ldata,
|
||||
CD_PROP_BYTE_COLOR,
|
||||
CD_SET_DEFAULT,
|
||||
nullptr,
|
||||
loops.size(),
|
||||
surface->output_name));
|
||||
}
|
||||
|
@ -1972,7 +1971,6 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
|
|||
CustomData_add_layer_named(&result->ldata,
|
||||
CD_PROP_BYTE_COLOR,
|
||||
CD_SET_DEFAULT,
|
||||
nullptr,
|
||||
loops.size(),
|
||||
surface->output_name2));
|
||||
}
|
||||
|
@ -2003,7 +2001,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
|
|||
/* apply weights into a vertex group, if doesn't exists add a new layer */
|
||||
if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) {
|
||||
dvert = static_cast<MDeformVert *>(CustomData_add_layer(
|
||||
&result->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, sData->total_points));
|
||||
&result->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, sData->total_points));
|
||||
}
|
||||
if (defgrp_index != -1 && dvert) {
|
||||
for (int i = 0; i < sData->total_points; i++) {
|
||||
|
@ -2028,7 +2026,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
|
|||
DynamicPaintModifierApplyData data{};
|
||||
data.surface = surface;
|
||||
data.vert_positions = BKE_mesh_vert_positions_for_write(result);
|
||||
data.vert_normals = BKE_mesh_vert_normals_ensure(result);
|
||||
data.vert_normals = result->vert_normals();
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
|
@ -4288,7 +4286,7 @@ 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 float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
const blender::Span<blender::float3> vert_normals = mesh->vert_normals();
|
||||
const blender::Span<MLoopTri> looptris = mesh->looptris();
|
||||
const blender::Span<MLoop> loops = mesh->loops();
|
||||
numOfVerts = mesh->totvert;
|
||||
|
@ -5912,7 +5910,7 @@ struct DynamicPaintGenerateBakeData {
|
|||
Object *ob;
|
||||
|
||||
const float (*positions)[3];
|
||||
const float (*vert_normals)[3];
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
const Vec3f *canvas_verts;
|
||||
|
||||
bool do_velocity_data;
|
||||
|
@ -6149,7 +6147,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
|
|||
data.surface = surface;
|
||||
data.ob = ob;
|
||||
data.positions = positions;
|
||||
data.vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
data.vert_normals = mesh->vert_normals();
|
||||
data.canvas_verts = canvas_verts;
|
||||
data.do_velocity_data = do_velocity_data;
|
||||
data.new_bdata = new_bdata;
|
||||
|
|
|
@ -194,7 +194,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
|
|||
if ((tangent_mask & DM_TANGENT_MASK_ORCO) &&
|
||||
CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, "") == -1) {
|
||||
CustomData_add_layer_named(
|
||||
loopdata_out, CD_TANGENT, CD_SET_DEFAULT, nullptr, int(loopdata_out_len), "");
|
||||
loopdata_out, CD_TANGENT, CD_SET_DEFAULT, int(loopdata_out_len), "");
|
||||
}
|
||||
if (calc_act && act_uv_name[0]) {
|
||||
BKE_mesh_add_loop_tangent_named_layer_for_uv(
|
||||
|
|
|
@ -556,9 +556,12 @@ int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[],
|
|||
|
||||
/* ...................................... */
|
||||
|
||||
/* Get the first and last index to the bezt array that satisfies the given parameters.
|
||||
* \param selected_keys_only Only accept indices of bezt that are selected. Is a subset of
|
||||
* frame_range. \param frame_range Only consider keyframes in that frame interval. Can be NULL.
|
||||
/**
|
||||
* Get the first and last index to the bezt array that satisfies the given parameters.
|
||||
*
|
||||
* \param selected_keys_only: Only accept indices of bezt that are selected.
|
||||
* Is a subset of frame_range.
|
||||
* \param frame_range: Only consider keyframes in that frame interval. Can be NULL.
|
||||
*/
|
||||
static bool get_bounding_bezt_indices(const FCurve *fcu,
|
||||
const bool selected_keys_only,
|
||||
|
@ -760,7 +763,8 @@ bool BKE_fcurve_calc_range(const FCurve *fcu,
|
|||
float *r_end,
|
||||
const bool selected_keys_only)
|
||||
{
|
||||
float min, max = 0.0f;
|
||||
float min = 0.0f;
|
||||
float max = 0.0f;
|
||||
bool foundvert = false;
|
||||
|
||||
if (fcu->totvert == 0) {
|
||||
|
|
|
@ -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 /* sel 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 /* sel 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 /* sel 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 /* sel 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);
|
||||
|
@ -461,13 +473,13 @@ TEST(BKE_fcurve, BKE_fcurve_calc_bounds)
|
|||
range[0] = 25;
|
||||
range[1] = 30;
|
||||
success = BKE_fcurve_calc_bounds(
|
||||
fcu, false /* sel only */, false /* include handles */, range /* frame range */, &bounds);
|
||||
fcu, false /* select only */, false /* include handles */, range /* frame range */, &bounds);
|
||||
EXPECT_FALSE(success) << "A frame range outside the range of keyframes should not find bounds.";
|
||||
|
||||
range[0] = 0;
|
||||
range[1] = 18.2f;
|
||||
success = BKE_fcurve_calc_bounds(
|
||||
fcu, false /* sel only */, false /* include handles */, range /* frame range */, &bounds);
|
||||
fcu, false /* select only */, false /* include handles */, range /* frame range */, &bounds);
|
||||
EXPECT_TRUE(success) << "A frame range within the range of keyframes should find bounds.";
|
||||
EXPECT_FLOAT_EQ(fcu->bezt[0].vec[1][0], bounds.xmin);
|
||||
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[1][0], bounds.xmax);
|
||||
|
@ -476,7 +488,7 @@ TEST(BKE_fcurve, BKE_fcurve_calc_bounds)
|
|||
|
||||
/* Range and handles. */
|
||||
success = BKE_fcurve_calc_bounds(
|
||||
fcu, false /* sel only */, true /* include handles */, range /* frame range */, &bounds);
|
||||
fcu, false /* select only */, true /* include handles */, range /* frame range */, &bounds);
|
||||
EXPECT_TRUE(success)
|
||||
<< "A frame range within the range of keyframes should find bounds with handles.";
|
||||
EXPECT_FLOAT_EQ(fcu->bezt[0].vec[0][0], bounds.xmin);
|
||||
|
@ -488,7 +500,7 @@ TEST(BKE_fcurve, BKE_fcurve_calc_bounds)
|
|||
range[0] = 8.0f;
|
||||
range[1] = 18.2f;
|
||||
success = BKE_fcurve_calc_bounds(
|
||||
fcu, true /* sel only */, true /* include handles */, range /* frame range */, &bounds);
|
||||
fcu, true /* select only */, true /* include handles */, range /* frame range */, &bounds);
|
||||
EXPECT_TRUE(success)
|
||||
<< "A frame range within the range of keyframes should find bounds of selected keyframes.";
|
||||
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[0][0], bounds.xmin);
|
||||
|
@ -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 /* sel 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);
|
||||
|
@ -513,7 +528,7 @@ TEST(BKE_fcurve, BKE_fcurve_calc_bounds)
|
|||
range[0] = 8.0f;
|
||||
range[1] = 20.0f;
|
||||
success = BKE_fcurve_calc_bounds(
|
||||
fcu, false /* sel only */, false /* include handles */, range /* frame range */, &bounds);
|
||||
fcu, false /* select only */, false /* include handles */, range /* frame range */, &bounds);
|
||||
EXPECT_TRUE(success) << "FCurve samples should have a range.";
|
||||
|
||||
EXPECT_FLOAT_EQ(range[0], bounds.xmin);
|
||||
|
@ -524,7 +539,7 @@ TEST(BKE_fcurve, BKE_fcurve_calc_bounds)
|
|||
range[0] = 20.1f;
|
||||
range[1] = 30.0f;
|
||||
success = BKE_fcurve_calc_bounds(
|
||||
fcu, false /* sel only */, false /* include handles */, range /* frame range */, &bounds);
|
||||
fcu, false /* select only */, false /* include handles */, range /* frame range */, &bounds);
|
||||
EXPECT_FALSE(success)
|
||||
<< "A frame range outside the range of keyframe samples should not have bounds.";
|
||||
|
||||
|
|
|
@ -1785,7 +1785,7 @@ static void update_distances(int index,
|
|||
|
||||
static void sample_mesh(FluidFlowSettings *ffs,
|
||||
const float (*vert_positions)[3],
|
||||
const float (*vert_normals)[3],
|
||||
const blender::Span<blender::float3> vert_normals,
|
||||
const MLoop *mloop,
|
||||
const MLoopTri *mlooptri,
|
||||
const float (*mloopuv)[2],
|
||||
|
@ -1980,7 +1980,7 @@ struct EmitFromDMData {
|
|||
FluidFlowSettings *ffs;
|
||||
|
||||
const float (*vert_positions)[3];
|
||||
const float (*vert_normals)[3];
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
blender::Span<MLoop> loops;
|
||||
blender::Span<MLoopTri> looptris;
|
||||
const float (*mloopuv)[2];
|
||||
|
@ -2091,18 +2091,11 @@ static void emit_from_mesh(
|
|||
|
||||
/* Transform mesh vertices to domain grid space for fast lookups.
|
||||
* This is valid because the mesh is copied above. */
|
||||
BKE_mesh_vert_normals_ensure(me);
|
||||
float(*vert_normals)[3] = BKE_mesh_vert_normals_for_write(me);
|
||||
for (i = 0; i < numverts; i++) {
|
||||
/* Vertex position. */
|
||||
mul_m4_v3(flow_ob->object_to_world, positions[i]);
|
||||
manta_pos_to_cell(fds, positions[i]);
|
||||
|
||||
/* Vertex normal. */
|
||||
mul_mat3_m4_v3(flow_ob->object_to_world, vert_normals[i]);
|
||||
mul_mat3_m4_v3(fds->imat, vert_normals[i]);
|
||||
normalize_v3(vert_normals[i]);
|
||||
|
||||
/* Vertex velocity. */
|
||||
if (ffs->flags & FLUID_FLOW_INITVELOCITY) {
|
||||
float co[3];
|
||||
|
@ -2117,6 +2110,7 @@ static void emit_from_mesh(
|
|||
/* Calculate emission map bounds. */
|
||||
bb_boundInsert(bb, positions[i]);
|
||||
}
|
||||
BKE_mesh_tag_positions_changed(me);
|
||||
mul_m4_v3(flow_ob->object_to_world, flow_center);
|
||||
manta_pos_to_cell(fds, flow_center);
|
||||
|
||||
|
@ -2141,7 +2135,7 @@ static void emit_from_mesh(
|
|||
data.fds = fds;
|
||||
data.ffs = ffs;
|
||||
data.vert_positions = positions;
|
||||
data.vert_normals = vert_normals;
|
||||
data.vert_normals = me->vert_normals();
|
||||
data.loops = loops;
|
||||
data.looptris = looptris;
|
||||
data.mloopuv = mloopuv;
|
||||
|
|
|
@ -368,7 +368,7 @@ static void gpencil_convert_spline(Main *bmain,
|
|||
if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
|
||||
segments--;
|
||||
}
|
||||
/* Get all interpolated curve points of Beziert */
|
||||
/* Get all interpolated curve points of Bezier. */
|
||||
for (int s = 0; s < segments; s++) {
|
||||
int inext = (s + 1) % nu->pntsu;
|
||||
BezTriple *prevbezt = &nu->bezt[s];
|
||||
|
@ -915,7 +915,7 @@ static float *gpencil_stroke_points_from_editcurve_adaptive_resolu(
|
|||
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 cpt_last = curve_point_array_len - 1;
|
||||
const uint num_segments = (is_cyclic) ? curve_point_array_len : curve_point_array_len - 1;
|
||||
|
@ -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;
|
||||
|
|
|
@ -2504,7 +2504,7 @@ static void gpencil_generate_edgeloops(Object *ob,
|
|||
const Span<float3> vert_positions = me->vert_positions();
|
||||
const Span<MEdge> edges = me->edges();
|
||||
const Span<MDeformVert> dverts = me->deform_verts();
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me);
|
||||
const blender::Span<blender::float3> vert_normals = me->vert_normals();
|
||||
const bke::AttributeAccessor attributes = me->attributes();
|
||||
const VArray<bool> uv_seams = attributes.lookup_or_default<bool>(
|
||||
".uv_seam", ATTR_DOMAIN_EDGE, false);
|
||||
|
|
|
@ -191,7 +191,7 @@ void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd)
|
|||
BLO_read_data_address(reader, &gpd->adt);
|
||||
BKE_animdata_blend_read_data(reader, gpd->adt);
|
||||
|
||||
/* Ensure full objectmode for linked grease pencil. */
|
||||
/* Ensure full object-mode for linked grease pencil. */
|
||||
if (ID_IS_LINKED(gpd)) {
|
||||
gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
|
||||
gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
|
||||
|
@ -1364,9 +1364,9 @@ bGPDframe *BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_
|
|||
gpl->actframe = gpl->frames.first;
|
||||
}
|
||||
else {
|
||||
/* unresolved errogenous situation! */
|
||||
/* Unresolved erogenous situation! */
|
||||
CLOG_STR_ERROR(&LOG, "cannot find appropriate gp-frame");
|
||||
/* gpl->actframe should still be NULL */
|
||||
/* `gpl->actframe` should still be NULL. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2324,7 +2324,7 @@ bool BKE_gpencil_from_image(
|
|||
pt->strength = 1.0f - color[3];
|
||||
}
|
||||
|
||||
/* Selet Alpha points. */
|
||||
/* Select Alpha points. */
|
||||
if (pt->strength < 0.03f) {
|
||||
gps->flag |= GP_STROKE_SELECT;
|
||||
pt->flag |= GP_SPOINT_SELECT;
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
|
||||
#include "BLI_strict_flags.h"
|
||||
|
||||
/* experimental (faster) normal calculation */
|
||||
// #define USE_ACCUM_NORMAL
|
||||
/* experimental (faster) normal calculation (see #103021) */
|
||||
#define USE_ACCUM_NORMAL
|
||||
|
||||
#define MBALL_ARRAY_LEN_INIT 4096
|
||||
|
||||
|
@ -1463,15 +1463,15 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)ob->data)->name + 2);
|
||||
|
||||
mesh->totvert = int(process.curvertex);
|
||||
CustomData_add_layer_named(
|
||||
&mesh->vdata, CD_PROP_FLOAT3, CD_ASSIGN, process.co, mesh->totvert, "position");
|
||||
CustomData_add_layer_named_with_data(
|
||||
&mesh->vdata, CD_PROP_FLOAT3, process.co, mesh->totvert, "position");
|
||||
process.co = nullptr;
|
||||
|
||||
mesh->totpoly = int(process.curindex);
|
||||
MPoly *polys = static_cast<MPoly *>(
|
||||
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CONSTRUCT, nullptr, mesh->totpoly));
|
||||
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CONSTRUCT, mesh->totpoly));
|
||||
MLoop *mloop = static_cast<MLoop *>(
|
||||
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CONSTRUCT, nullptr, mesh->totpoly * 4));
|
||||
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CONSTRUCT, mesh->totpoly * 4));
|
||||
|
||||
int loop_offset = 0;
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
|
|
|
@ -838,7 +838,7 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
|
|||
else {
|
||||
if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) {
|
||||
vs = (MVertSkin *)CustomData_add_layer(
|
||||
&me->vdata, CD_MVERT_SKIN, CD_SET_DEFAULT, nullptr, me->totvert);
|
||||
&me->vdata, CD_MVERT_SKIN, CD_SET_DEFAULT, me->totvert);
|
||||
|
||||
/* Mark an arbitrary vertex as root */
|
||||
if (vs) {
|
||||
|
@ -860,7 +860,7 @@ bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me)
|
|||
}
|
||||
else {
|
||||
if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
|
||||
CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, nullptr, me->totpoly);
|
||||
CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, me->totpoly);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -965,16 +965,16 @@ static void mesh_ensure_cdlayers_primary(Mesh *mesh)
|
|||
{
|
||||
if (!CustomData_get_layer_named(&mesh->vdata, CD_PROP_FLOAT3, "position")) {
|
||||
CustomData_add_layer_named(
|
||||
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, mesh->totvert, "position");
|
||||
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, mesh->totvert, "position");
|
||||
}
|
||||
if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) {
|
||||
CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, mesh->totedge);
|
||||
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, nullptr, mesh->totloop);
|
||||
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, mesh->totloop);
|
||||
}
|
||||
if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) {
|
||||
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly);
|
||||
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1094,7 +1094,7 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
|||
* even in cases where the source mesh does not. */
|
||||
mesh_ensure_cdlayers_primary(me_dst);
|
||||
if (do_tessface && !CustomData_get_layer(&me_dst->fdata, CD_MFACE)) {
|
||||
CustomData_add_layer(&me_dst->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, me_dst->totface);
|
||||
CustomData_add_layer(&me_dst->fdata, CD_MFACE, CD_SET_DEFAULT, me_dst->totface);
|
||||
}
|
||||
|
||||
/* Expect that normals aren't copied at all, since the destination mesh is new. */
|
||||
|
@ -1183,7 +1183,7 @@ static void ensure_orig_index_layer(CustomData &data, const int size)
|
|||
if (CustomData_has_layer(&data, CD_ORIGINDEX)) {
|
||||
return;
|
||||
}
|
||||
int *indices = (int *)CustomData_add_layer(&data, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, size);
|
||||
int *indices = (int *)CustomData_add_layer(&data, CD_ORIGINDEX, CD_SET_DEFAULT, size);
|
||||
range_vn_i(indices, size, 0);
|
||||
}
|
||||
|
||||
|
@ -1360,7 +1360,7 @@ void BKE_mesh_orco_ensure(Object *ob, Mesh *mesh)
|
|||
/* Orcos are stored in normalized 0..1 range by convention. */
|
||||
float(*orcodata)[3] = BKE_mesh_orco_verts_get(ob);
|
||||
BKE_mesh_orco_verts_transform(mesh, orcodata, mesh->totvert, false);
|
||||
CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_ASSIGN, orcodata, mesh->totvert);
|
||||
CustomData_add_layer_with_data(&mesh->vdata, CD_ORCO, orcodata, mesh->totvert);
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_from_object(Object *ob)
|
||||
|
@ -1830,7 +1830,7 @@ static float (*ensure_corner_normal_layer(Mesh &mesh))[3]
|
|||
}
|
||||
else {
|
||||
r_loop_normals = (float(*)[3])CustomData_add_layer(
|
||||
&mesh.ldata, CD_NORMAL, CD_SET_DEFAULT, nullptr, mesh.totloop);
|
||||
&mesh.ldata, CD_NORMAL, CD_SET_DEFAULT, mesh.totloop);
|
||||
CustomData_set_layer_flag(&mesh.ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
return r_loop_normals;
|
||||
|
|
|
@ -240,7 +240,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select
|
|||
/* Free old CustomData and assign new one. */
|
||||
CustomData_free(&mesh->edata, mesh->totedge);
|
||||
CustomData_reset(&mesh->edata);
|
||||
CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_ASSIGN, new_edges.data(), new_totedge);
|
||||
CustomData_add_layer_with_data(&mesh->edata, CD_MEDGE, new_edges.data(), new_totedge);
|
||||
mesh->totedge = new_totedge;
|
||||
|
||||
if (select_new_edges) {
|
||||
|
|
|
@ -215,7 +215,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
|||
"sharp_face", ATTR_DOMAIN_FACE);
|
||||
|
||||
blender::float2 *mloopuv = static_cast<blender::float2 *>(CustomData_add_layer_named(
|
||||
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, mesh->totloop, DATA_("UVMap")));
|
||||
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, mesh->totloop, DATA_("UVMap")));
|
||||
|
||||
int dst_vert = 0;
|
||||
int dst_edge = 0;
|
||||
|
@ -472,8 +472,6 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed
|
|||
const Span<MPoly> polys = me->polys();
|
||||
const Span<MLoop> loops = me->loops();
|
||||
|
||||
int totedges = 0;
|
||||
|
||||
/* only to detect edge polylines */
|
||||
int *edge_users;
|
||||
|
||||
|
@ -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<Nurb>("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;
|
||||
|
|
|
@ -67,13 +67,14 @@ void BKE_mesh_foreach_mapped_vert(
|
|||
else {
|
||||
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
|
||||
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX));
|
||||
const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
|
||||
BKE_mesh_vert_normals_ensure(mesh) :
|
||||
nullptr;
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
vert_normals = mesh->vert_normals();
|
||||
}
|
||||
|
||||
if (index) {
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[i] : nullptr;
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[i].x : nullptr;
|
||||
const int orig = *index++;
|
||||
if (orig == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
|
@ -83,7 +84,7 @@ void BKE_mesh_foreach_mapped_vert(
|
|||
}
|
||||
else {
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[i] : nullptr;
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[i].x : nullptr;
|
||||
func(userData, i, positions[i], no);
|
||||
}
|
||||
}
|
||||
|
@ -315,9 +316,10 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
|||
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
|
||||
const blender::Span<MPoly> polys = mesh->polys();
|
||||
const blender::Span<MLoop> loops = mesh->loops();
|
||||
const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
|
||||
BKE_mesh_vert_normals_ensure(mesh) :
|
||||
nullptr;
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
vert_normals = mesh->vert_normals();
|
||||
}
|
||||
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX));
|
||||
const blender::BitSpan facedot_tags = mesh->runtime->subsurf_face_dot_tags;
|
||||
|
||||
|
@ -332,7 +334,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
|||
func(userData,
|
||||
orig,
|
||||
positions[loop.v],
|
||||
(flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[loop.v] : nullptr);
|
||||
(flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[loop.v].x : nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +346,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
|||
func(userData,
|
||||
i,
|
||||
positions[loop.v],
|
||||
(flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[loop.v] : nullptr);
|
||||
(flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[loop.v].x : nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -228,7 +228,7 @@ void BKE_mesh_calc_edges_legacy(Mesh *me)
|
|||
return;
|
||||
}
|
||||
|
||||
edges = (MEdge *)CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, edges, totedge);
|
||||
edges = (MEdge *)CustomData_add_layer_with_data(&me->edata, CD_MEDGE, edges, totedge);
|
||||
me->totedge = totedge;
|
||||
|
||||
BKE_mesh_tag_topology_changed(me);
|
||||
|
@ -394,19 +394,17 @@ static void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int to
|
|||
for (int i = 0; i < fdata->totlayer; i++) {
|
||||
if (fdata->layers[i].type == CD_MTFACE) {
|
||||
CustomData_add_layer_named(
|
||||
ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
|
||||
ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
|
||||
}
|
||||
else if (fdata->layers[i].type == CD_MCOL) {
|
||||
CustomData_add_layer_named(
|
||||
ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
|
||||
ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
|
||||
}
|
||||
else if (fdata->layers[i].type == CD_MDISPS) {
|
||||
CustomData_add_layer_named(
|
||||
ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
|
||||
CustomData_add_layer_named(ldata, CD_MDISPS, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
|
||||
}
|
||||
else if (fdata->layers[i].type == CD_TESSLOOPNORMAL) {
|
||||
CustomData_add_layer_named(
|
||||
ldata, CD_NORMAL, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
|
||||
CustomData_add_layer_named(ldata, CD_NORMAL, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -440,18 +438,18 @@ static void convert_mfaces_to_mpolys(ID *id,
|
|||
CustomData_free(pdata, totpoly_i);
|
||||
|
||||
totpoly = totface_i;
|
||||
mpoly = (MPoly *)CustomData_add_layer(pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, totpoly);
|
||||
mpoly = (MPoly *)CustomData_add_layer(pdata, CD_MPOLY, CD_SET_DEFAULT, totpoly);
|
||||
int *material_indices = static_cast<int *>(
|
||||
CustomData_get_layer_named_for_write(pdata, CD_PROP_INT32, "material_index", totpoly));
|
||||
if (material_indices == nullptr) {
|
||||
material_indices = static_cast<int *>(CustomData_add_layer_named(
|
||||
pdata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, totpoly, "material_index"));
|
||||
pdata, CD_PROP_INT32, CD_SET_DEFAULT, totpoly, "material_index"));
|
||||
}
|
||||
bool *sharp_faces = static_cast<bool *>(
|
||||
CustomData_get_layer_named_for_write(pdata, CD_PROP_BOOL, "sharp_face", totpoly));
|
||||
if (!sharp_faces) {
|
||||
sharp_faces = static_cast<bool *>(CustomData_add_layer_named(
|
||||
pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, totpoly, "sharp_face"));
|
||||
sharp_faces = static_cast<bool *>(
|
||||
CustomData_add_layer_named(pdata, CD_PROP_BOOL, CD_SET_DEFAULT, totpoly, "sharp_face"));
|
||||
}
|
||||
|
||||
numTex = CustomData_number_of_layers(fdata, CD_MTFACE);
|
||||
|
@ -463,7 +461,7 @@ static void convert_mfaces_to_mpolys(ID *id,
|
|||
totloop += mf->v4 ? 4 : 3;
|
||||
}
|
||||
|
||||
mloop = (MLoop *)CustomData_add_layer(ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, totloop);
|
||||
mloop = (MLoop *)CustomData_add_layer(ldata, CD_MLOOP, CD_SET_DEFAULT, totloop);
|
||||
|
||||
CustomData_to_bmeshpoly(fdata, ldata, totloop);
|
||||
|
||||
|
@ -625,28 +623,25 @@ static void add_mface_layers(Mesh &mesh, CustomData *fdata, CustomData *ldata, i
|
|||
|
||||
for (int i = 0; i < ldata->totlayer; i++) {
|
||||
if (ldata->layers[i].type == CD_PROP_FLOAT2) {
|
||||
CustomData_add_layer_named(
|
||||
fdata, CD_MTFACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
|
||||
CustomData_add_layer_named(fdata, CD_MTFACE, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
if (ldata->layers[i].type == CD_PROP_BYTE_COLOR) {
|
||||
CustomData_add_layer_named(
|
||||
fdata, CD_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
|
||||
CustomData_add_layer_named(fdata, CD_MCOL, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
else if (ldata->layers[i].type == CD_PREVIEW_MLOOPCOL) {
|
||||
CustomData_add_layer_named(
|
||||
fdata, CD_PREVIEW_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
|
||||
fdata, CD_PREVIEW_MCOL, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) {
|
||||
CustomData_add_layer_named(
|
||||
fdata, CD_ORIGSPACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
|
||||
fdata, CD_ORIGSPACE, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
else if (ldata->layers[i].type == CD_NORMAL) {
|
||||
CustomData_add_layer_named(
|
||||
fdata, CD_TESSLOOPNORMAL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
|
||||
fdata, CD_TESSLOOPNORMAL, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
else if (ldata->layers[i].type == CD_TANGENT) {
|
||||
CustomData_add_layer_named(
|
||||
fdata, CD_TANGENT, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
|
||||
CustomData_add_layer_named(fdata, CD_TANGENT, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1157,11 +1152,11 @@ static int mesh_tessface_calc(Mesh &mesh,
|
|||
sizeof(*mface_to_poly_map) * size_t(totface));
|
||||
}
|
||||
|
||||
CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
|
||||
CustomData_add_layer_with_data(fdata, CD_MFACE, mface, totface);
|
||||
|
||||
/* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons
|
||||
* they are directly tessellated from. */
|
||||
CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface);
|
||||
CustomData_add_layer_with_data(fdata, CD_ORIGINDEX, mface_to_poly_map, totface);
|
||||
add_mface_layers(mesh, fdata, ldata, totface);
|
||||
|
||||
/* NOTE: quad detection issue - fourth vertex-index vs fourth loop-index:
|
||||
|
@ -1314,8 +1309,8 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
|
|||
}
|
||||
}
|
||||
if (faceset_data != nullptr) {
|
||||
CustomData_add_layer_named(
|
||||
&mesh->pdata, CD_PROP_INT32, CD_ASSIGN, faceset_data, mesh->totpoly, ".sculpt_face_set");
|
||||
CustomData_add_layer_named_with_data(
|
||||
&mesh->pdata, CD_PROP_INT32, faceset_data, mesh->totpoly, ".sculpt_face_set");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1365,7 +1360,7 @@ void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh)
|
|||
const Span<MVert> verts(mesh->mvert, mesh->totvert);
|
||||
if (mesh->cd_flag & ME_CDFLAG_VERT_BWEIGHT) {
|
||||
float *weights = static_cast<float *>(
|
||||
CustomData_add_layer(&mesh->vdata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, verts.size()));
|
||||
CustomData_add_layer(&mesh->vdata, CD_BWEIGHT, CD_CONSTRUCT, verts.size()));
|
||||
for (const int i : verts.index_range()) {
|
||||
weights[i] = verts[i].bweight_legacy / 255.0f;
|
||||
}
|
||||
|
@ -1376,7 +1371,7 @@ void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh)
|
|||
if (!CustomData_has_layer(&mesh->edata, CD_BWEIGHT)) {
|
||||
if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
|
||||
float *weights = static_cast<float *>(
|
||||
CustomData_add_layer(&mesh->edata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, edges.size()));
|
||||
CustomData_add_layer(&mesh->edata, CD_BWEIGHT, CD_CONSTRUCT, edges.size()));
|
||||
for (const int i : edges.index_range()) {
|
||||
weights[i] = edges[i].bweight_legacy / 255.0f;
|
||||
}
|
||||
|
@ -1418,7 +1413,7 @@ void BKE_mesh_legacy_edge_crease_to_layers(Mesh *mesh)
|
|||
const Span<MEdge> edges = mesh->edges();
|
||||
if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) {
|
||||
float *creases = static_cast<float *>(
|
||||
CustomData_add_layer(&mesh->edata, CD_CREASE, CD_CONSTRUCT, nullptr, edges.size()));
|
||||
CustomData_add_layer(&mesh->edata, CD_CREASE, CD_CONSTRUCT, edges.size()));
|
||||
for (const int i : edges.index_range()) {
|
||||
creases[i] = edges[i].crease_legacy / 255.0f;
|
||||
}
|
||||
|
@ -1802,32 +1797,29 @@ void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
|
|||
});
|
||||
|
||||
CustomData_free_layer_named(&mesh->ldata, name.c_str(), mesh->totloop);
|
||||
CustomData_add_layer_named(
|
||||
&mesh->ldata, CD_PROP_FLOAT2, CD_ASSIGN, coords, mesh->totloop, name.c_str());
|
||||
CustomData_add_layer_named_with_data(
|
||||
&mesh->ldata, CD_PROP_FLOAT2, coords, mesh->totloop, name.c_str());
|
||||
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
if (vert_selection) {
|
||||
CustomData_add_layer_named(&mesh->ldata,
|
||||
CD_PROP_BOOL,
|
||||
CD_ASSIGN,
|
||||
vert_selection,
|
||||
mesh->totloop,
|
||||
BKE_uv_map_vert_select_name_get(name.c_str(), buffer));
|
||||
CustomData_add_layer_named_with_data(&mesh->ldata,
|
||||
CD_PROP_BOOL,
|
||||
vert_selection,
|
||||
mesh->totloop,
|
||||
BKE_uv_map_vert_select_name_get(name.c_str(), buffer));
|
||||
}
|
||||
if (edge_selection) {
|
||||
CustomData_add_layer_named(&mesh->ldata,
|
||||
CD_PROP_BOOL,
|
||||
CD_ASSIGN,
|
||||
edge_selection,
|
||||
mesh->totloop,
|
||||
BKE_uv_map_edge_select_name_get(name.c_str(), buffer));
|
||||
CustomData_add_layer_named_with_data(&mesh->ldata,
|
||||
CD_PROP_BOOL,
|
||||
edge_selection,
|
||||
mesh->totloop,
|
||||
BKE_uv_map_edge_select_name_get(name.c_str(), buffer));
|
||||
}
|
||||
if (pin) {
|
||||
CustomData_add_layer_named(&mesh->ldata,
|
||||
CD_PROP_BOOL,
|
||||
CD_ASSIGN,
|
||||
pin,
|
||||
mesh->totloop,
|
||||
BKE_uv_map_pin_name_get(name.c_str(), buffer));
|
||||
CustomData_add_layer_named_with_data(&mesh->ldata,
|
||||
CD_PROP_BOOL,
|
||||
pin,
|
||||
mesh->totloop,
|
||||
BKE_uv_map_pin_name_get(name.c_str(), buffer));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2000,7 +1992,7 @@ void BKE_mesh_legacy_convert_verts_to_positions(Mesh *mesh)
|
|||
mesh->totvert);
|
||||
MutableSpan<float3> positions(
|
||||
static_cast<float3 *>(CustomData_add_layer_named(
|
||||
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, mesh->totvert, "position")),
|
||||
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, mesh->totvert, "position")),
|
||||
mesh->totvert);
|
||||
threading::parallel_for(verts.index_range(), 2048, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
|
|
|
@ -100,46 +100,28 @@ static void add_v3_v3_atomic(float r[3], const float a[3])
|
|||
* Related to managing normals but not directly related to calculating normals.
|
||||
* \{ */
|
||||
|
||||
void BKE_mesh_normals_tag_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime->vert_normals_dirty = true;
|
||||
mesh->runtime->poly_normals_dirty = true;
|
||||
}
|
||||
|
||||
float (*BKE_mesh_vert_normals_for_write(Mesh *mesh))[3]
|
||||
{
|
||||
if (mesh->runtime->vert_normals == nullptr) {
|
||||
mesh->runtime->vert_normals = (float(*)[3])MEM_malloc_arrayN(
|
||||
mesh->totvert, sizeof(float[3]), __func__);
|
||||
}
|
||||
|
||||
BLI_assert(MEM_allocN_len(mesh->runtime->vert_normals) >= sizeof(float[3]) * mesh->totvert);
|
||||
|
||||
return mesh->runtime->vert_normals;
|
||||
mesh->runtime->vert_normals.reinitialize(mesh->totvert);
|
||||
return reinterpret_cast<float(*)[3]>(mesh->runtime->vert_normals.data());
|
||||
}
|
||||
|
||||
float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3]
|
||||
{
|
||||
if (mesh->runtime->poly_normals == nullptr) {
|
||||
mesh->runtime->poly_normals = (float(*)[3])MEM_malloc_arrayN(
|
||||
mesh->totpoly, sizeof(float[3]), __func__);
|
||||
}
|
||||
|
||||
BLI_assert(MEM_allocN_len(mesh->runtime->poly_normals) >= sizeof(float[3]) * mesh->totpoly);
|
||||
|
||||
return mesh->runtime->poly_normals;
|
||||
mesh->runtime->poly_normals.reinitialize(mesh->totpoly);
|
||||
return reinterpret_cast<float(*)[3]>(mesh->runtime->poly_normals.data());
|
||||
}
|
||||
|
||||
void BKE_mesh_vert_normals_clear_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime->vert_normals_dirty = false;
|
||||
BLI_assert(mesh->runtime->vert_normals || mesh->totvert == 0);
|
||||
BLI_assert(mesh->runtime->vert_normals.size() == mesh->totvert);
|
||||
}
|
||||
|
||||
void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime->poly_normals_dirty = false;
|
||||
BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0);
|
||||
BLI_assert(mesh->runtime->poly_normals.size() == mesh->totpoly);
|
||||
}
|
||||
|
||||
bool BKE_mesh_vert_normals_are_dirty(const Mesh *mesh)
|
||||
|
@ -345,83 +327,73 @@ void normals_calc_poly_vert(const Span<float3> positions,
|
|||
/** \name Mesh Normal Calculation
|
||||
* \{ */
|
||||
|
||||
const float (*BKE_mesh_vert_normals_ensure(const Mesh *mesh))[3]
|
||||
blender::Span<blender::float3> Mesh::vert_normals() const
|
||||
{
|
||||
if (!BKE_mesh_vert_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime->vert_normals != nullptr || mesh->totvert == 0);
|
||||
return mesh->runtime->vert_normals;
|
||||
if (!this->runtime->vert_normals_dirty) {
|
||||
BLI_assert(this->runtime->vert_normals.size() == this->totvert);
|
||||
return this->runtime->vert_normals;
|
||||
}
|
||||
|
||||
if (mesh->totvert == 0) {
|
||||
return nullptr;
|
||||
std::lock_guard lock{this->runtime->normals_mutex};
|
||||
if (!this->runtime->vert_normals_dirty) {
|
||||
BLI_assert(this->runtime->vert_normals.size() == this->totvert);
|
||||
return this->runtime->vert_normals;
|
||||
}
|
||||
|
||||
std::lock_guard lock{mesh->runtime->normals_mutex};
|
||||
if (!BKE_mesh_vert_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime->vert_normals != nullptr);
|
||||
return mesh->runtime->vert_normals;
|
||||
}
|
||||
|
||||
float(*vert_normals)[3];
|
||||
float(*poly_normals)[3];
|
||||
|
||||
/* Isolate task because a mutex is locked and computing normals is multi-threaded. */
|
||||
blender::threading::isolate_task([&]() {
|
||||
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
|
||||
const Span<float3> positions = mesh_mutable.vert_positions();
|
||||
const Span<MPoly> polys = mesh_mutable.polys();
|
||||
const Span<MLoop> loops = mesh_mutable.loops();
|
||||
const Span<float3> positions = this->vert_positions();
|
||||
const Span<MPoly> polys = this->polys();
|
||||
const Span<MLoop> loops = this->loops();
|
||||
|
||||
vert_normals = BKE_mesh_vert_normals_for_write(&mesh_mutable);
|
||||
poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable);
|
||||
this->runtime->vert_normals.reinitialize(positions.size());
|
||||
this->runtime->poly_normals.reinitialize(polys.size());
|
||||
blender::bke::mesh::normals_calc_poly_vert(
|
||||
positions,
|
||||
polys,
|
||||
loops,
|
||||
{reinterpret_cast<float3 *>(poly_normals), mesh->totpoly},
|
||||
{reinterpret_cast<float3 *>(vert_normals), mesh->totvert});
|
||||
positions, polys, loops, this->runtime->poly_normals, this->runtime->vert_normals);
|
||||
|
||||
BKE_mesh_vert_normals_clear_dirty(&mesh_mutable);
|
||||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
this->runtime->vert_normals_dirty = false;
|
||||
this->runtime->poly_normals_dirty = false;
|
||||
});
|
||||
|
||||
return vert_normals;
|
||||
return this->runtime->vert_normals;
|
||||
}
|
||||
|
||||
blender::Span<blender::float3> Mesh::poly_normals() const
|
||||
{
|
||||
if (!this->runtime->poly_normals_dirty) {
|
||||
BLI_assert(this->runtime->poly_normals.size() == this->totpoly);
|
||||
return this->runtime->poly_normals;
|
||||
}
|
||||
|
||||
std::lock_guard lock{this->runtime->normals_mutex};
|
||||
if (!this->runtime->poly_normals_dirty) {
|
||||
BLI_assert(this->runtime->poly_normals.size() == this->totpoly);
|
||||
return this->runtime->poly_normals;
|
||||
}
|
||||
|
||||
/* Isolate task because a mutex is locked and computing normals is multi-threaded. */
|
||||
blender::threading::isolate_task([&]() {
|
||||
const Span<float3> positions = this->vert_positions();
|
||||
const Span<MPoly> polys = this->polys();
|
||||
const Span<MLoop> loops = this->loops();
|
||||
|
||||
this->runtime->poly_normals.reinitialize(polys.size());
|
||||
blender::bke::mesh::normals_calc_polys(positions, polys, loops, this->runtime->poly_normals);
|
||||
|
||||
this->runtime->poly_normals_dirty = false;
|
||||
});
|
||||
|
||||
return this->runtime->poly_normals;
|
||||
}
|
||||
|
||||
const float (*BKE_mesh_vert_normals_ensure(const Mesh *mesh))[3]
|
||||
{
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->vert_normals().data());
|
||||
}
|
||||
|
||||
const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
|
||||
{
|
||||
if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime->poly_normals != nullptr || mesh->totpoly == 0);
|
||||
return mesh->runtime->poly_normals;
|
||||
}
|
||||
|
||||
if (mesh->totpoly == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::lock_guard lock{mesh->runtime->normals_mutex};
|
||||
if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime->poly_normals != nullptr);
|
||||
return mesh->runtime->poly_normals;
|
||||
}
|
||||
|
||||
float(*poly_normals)[3];
|
||||
|
||||
/* Isolate task because a mutex is locked and computing normals is multi-threaded. */
|
||||
blender::threading::isolate_task([&]() {
|
||||
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
|
||||
const Span<float3> positions = mesh_mutable.vert_positions();
|
||||
const Span<MPoly> polys = mesh_mutable.polys();
|
||||
const Span<MLoop> loops = mesh_mutable.loops();
|
||||
|
||||
poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable);
|
||||
blender::bke::mesh::normals_calc_polys(
|
||||
positions, polys, loops, {reinterpret_cast<float3 *>(poly_normals), mesh->totpoly});
|
||||
|
||||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
});
|
||||
|
||||
return poly_normals;
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->vert_normals().data());
|
||||
}
|
||||
|
||||
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
||||
|
@ -429,8 +401,8 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
|||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
BKE_mesh_vert_normals_ensure(mesh);
|
||||
BKE_mesh_poly_normals_ensure(mesh);
|
||||
mesh->vert_normals();
|
||||
mesh->poly_normals();
|
||||
break;
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
BMEditMesh *em = mesh->edit_mesh;
|
||||
|
@ -1850,7 +1822,7 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
|
|||
}
|
||||
else {
|
||||
clnors = (short(*)[2])CustomData_add_layer(
|
||||
&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, numloops);
|
||||
&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, numloops);
|
||||
}
|
||||
MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
|
||||
|
|
|
@ -571,7 +571,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
|
|||
const blender::Span<MPoly> polys_src = me_src->polys();
|
||||
const blender::Span<MLoop> loops_src = me_src->loops();
|
||||
float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr);
|
||||
const float(*vert_normals_dst)[3] = BKE_mesh_vert_normals_ensure(me_dst);
|
||||
const blender::Span<blender::float3> vert_normals_dst = me_dst->vert_normals();
|
||||
|
||||
size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE;
|
||||
float(*vcos)[3] = static_cast<float(*)[3]>(
|
||||
|
@ -937,7 +937,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
|
|||
|
||||
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2);
|
||||
|
||||
const float(*vert_normals_dst)[3] = BKE_mesh_vert_normals_ensure(me_dst);
|
||||
const blender::Span<blender::float3> vert_normals_dst = me_dst->vert_normals();
|
||||
|
||||
for (i = 0; i < numedges_dst; i++) {
|
||||
/* For each dst edge, we sample some rays from it (interpolated from its vertices)
|
||||
|
@ -1286,10 +1286,11 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
1) :
|
||||
0);
|
||||
|
||||
const float(*poly_nors_src)[3] = nullptr;
|
||||
const float(*loop_nors_src)[3] = nullptr;
|
||||
const float(*poly_nors_dst)[3] = nullptr;
|
||||
float(*loop_nors_dst)[3] = nullptr;
|
||||
blender::Span<blender::float3> poly_normals_src;
|
||||
blender::Span<blender::float3> loop_normals_src;
|
||||
|
||||
blender::Span<blender::float3> poly_normals_dst;
|
||||
blender::float3 *loop_normals_dst;
|
||||
|
||||
blender::Array<blender::float3> poly_cents_src;
|
||||
|
||||
|
@ -1345,22 +1346,23 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
const bool need_pnors_dst = need_lnors_dst || need_pnors_src;
|
||||
|
||||
if (need_pnors_dst) {
|
||||
poly_nors_dst = BKE_mesh_poly_normals_ensure(mesh_dst);
|
||||
poly_normals_dst = mesh_dst->poly_normals();
|
||||
}
|
||||
if (need_lnors_dst) {
|
||||
short(*custom_nors_dst)[2] = static_cast<short(*)[2]>(
|
||||
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, numloops_dst));
|
||||
|
||||
/* Cache loop normals into a temporary custom data layer. */
|
||||
loop_nors_dst = static_cast<float(*)[3]>(
|
||||
loop_normals_dst = static_cast<blender::float3 *>(
|
||||
CustomData_get_layer_for_write(ldata_dst, CD_NORMAL, numloops_dst));
|
||||
const bool do_loop_nors_dst = (loop_nors_dst == nullptr);
|
||||
if (!loop_nors_dst) {
|
||||
loop_nors_dst = static_cast<float(*)[3]>(
|
||||
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, nullptr, numloops_dst));
|
||||
|
||||
const bool do_loop_normals_dst = (loop_normals_dst == nullptr);
|
||||
if (!loop_normals_dst) {
|
||||
loop_normals_dst = static_cast<blender::float3 *>(
|
||||
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, numloops_dst));
|
||||
CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
if (dirty_nors_dst || do_loop_nors_dst) {
|
||||
if (dirty_nors_dst || do_loop_normals_dst) {
|
||||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh_dst->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
|
@ -1379,17 +1381,18 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
split_angle_dst,
|
||||
custom_nors_dst,
|
||||
nullptr,
|
||||
{reinterpret_cast<blender::float3 *>(loop_nors_dst), numloops_dst});
|
||||
{loop_normals_dst, numloops_dst});
|
||||
}
|
||||
}
|
||||
if (need_pnors_src || need_lnors_src) {
|
||||
if (need_pnors_src) {
|
||||
poly_nors_src = BKE_mesh_poly_normals_ensure(me_src);
|
||||
poly_normals_src = me_src->poly_normals();
|
||||
}
|
||||
if (need_lnors_src) {
|
||||
loop_nors_src = static_cast<const float(*)[3]>(
|
||||
CustomData_get_layer(&me_src->ldata, CD_NORMAL));
|
||||
BLI_assert(loop_nors_src != nullptr);
|
||||
loop_normals_src = {static_cast<const blender::float3 *>(
|
||||
CustomData_get_layer(&me_src->ldata, CD_NORMAL)),
|
||||
me_src->totloop};
|
||||
BLI_assert(loop_normals_src.data() != nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1583,7 +1586,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
bool pcent_dst_valid = false;
|
||||
|
||||
if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
|
||||
copy_v3_v3(pnor_dst, poly_nors_dst[pidx_dst]);
|
||||
copy_v3_v3(pnor_dst, poly_normals_dst[pidx_dst]);
|
||||
if (space_transform) {
|
||||
BLI_space_transform_apply_normal(space_transform, pnor_dst);
|
||||
}
|
||||
|
@ -1616,23 +1619,23 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
if (mesh_remap_bvhtree_query_nearest(
|
||||
tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
|
||||
float(*nor_dst)[3];
|
||||
const float(*nors_src)[3];
|
||||
blender::Span<blender::float3> nors_src;
|
||||
float best_nor_dot = -2.0f;
|
||||
float best_sqdist_fallback = FLT_MAX;
|
||||
int best_index_src = -1;
|
||||
|
||||
if (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) {
|
||||
copy_v3_v3(tmp_no, loop_nors_dst[plidx_dst + mp_dst->loopstart]);
|
||||
copy_v3_v3(tmp_no, loop_normals_dst[plidx_dst + mp_dst->loopstart]);
|
||||
if (space_transform) {
|
||||
BLI_space_transform_apply_normal(space_transform, tmp_no);
|
||||
}
|
||||
nor_dst = &tmp_no;
|
||||
nors_src = loop_nors_src;
|
||||
nors_src = loop_normals_src;
|
||||
vert_to_refelem_map_src = vert_to_loop_map_src;
|
||||
}
|
||||
else { /* if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { */
|
||||
nor_dst = &pnor_dst;
|
||||
nors_src = poly_nors_src;
|
||||
nors_src = poly_normals_src;
|
||||
vert_to_refelem_map_src = vert_to_poly_map_src;
|
||||
}
|
||||
|
||||
|
@ -1717,7 +1720,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
float w = 1.0f;
|
||||
|
||||
copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]);
|
||||
copy_v3_v3(tmp_no, loop_nors_dst[plidx_dst + mp_dst->loopstart]);
|
||||
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. */
|
||||
if (space_transform) {
|
||||
|
@ -2167,14 +2170,14 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
|
|||
{
|
||||
const float full_weight = 1.0f;
|
||||
const float max_dist_sq = max_dist * max_dist;
|
||||
const float(*poly_nors_dst)[3] = nullptr;
|
||||
blender::Span<blender::float3> poly_normals_dst;
|
||||
blender::float3 tmp_co, tmp_no;
|
||||
int i;
|
||||
|
||||
BLI_assert(mode & MREMAP_MODE_POLY);
|
||||
|
||||
if (mode & (MREMAP_USE_NORMAL | MREMAP_USE_NORPROJ)) {
|
||||
poly_nors_dst = BKE_mesh_poly_normals_ensure(mesh_dst);
|
||||
poly_normals_dst = mesh_dst->poly_normals();
|
||||
}
|
||||
|
||||
BKE_mesh_remap_init(r_map, numpolys_dst);
|
||||
|
@ -2220,15 +2223,13 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
|
|||
}
|
||||
}
|
||||
else if (mode == MREMAP_MODE_POLY_NOR) {
|
||||
BLI_assert(poly_nors_dst);
|
||||
|
||||
for (i = 0; i < numpolys_dst; i++) {
|
||||
const MPoly &poly = polys_dst[i];
|
||||
|
||||
tmp_co = blender::bke::mesh::poly_center_calc(
|
||||
{reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
|
||||
{&loops_dst[poly.loopstart], poly.totloop});
|
||||
copy_v3_v3(tmp_no, poly_nors_dst[i]);
|
||||
copy_v3_v3(tmp_no, poly_normals_dst[i]);
|
||||
|
||||
/* Convert the vertex to tree coordinates, if needed. */
|
||||
if (space_transform) {
|
||||
|
@ -2294,7 +2295,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
|
|||
{reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
|
||||
{&loops_dst[poly.loopstart], poly.totloop});
|
||||
|
||||
copy_v3_v3(tmp_no, poly_nors_dst[i]);
|
||||
copy_v3_v3(tmp_no, poly_normals_dst[i]);
|
||||
|
||||
/* We do our transform here, else it'd be redone by raycast helper for each ray, ugh! */
|
||||
if (space_transform) {
|
||||
|
|
|
@ -290,7 +290,7 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, const Mesh *source)
|
|||
}
|
||||
else {
|
||||
target_mask = (float *)CustomData_add_layer(
|
||||
&target->vdata, CD_PAINT_MASK, CD_CONSTRUCT, nullptr, target->totvert);
|
||||
&target->vdata, CD_PAINT_MASK, CD_CONSTRUCT, target->totvert);
|
||||
}
|
||||
|
||||
blender::threading::parallel_for(IndexRange(target->totvert), 4096, [&](const IndexRange range) {
|
||||
|
@ -384,7 +384,7 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
|
|||
int elem_num = domain == ATTR_DOMAIN_POINT ? target->totvert : target->totloop;
|
||||
|
||||
CustomData_add_layer_named(
|
||||
target_cdata, layer->type, CD_SET_DEFAULT, nullptr, elem_num, layer->name);
|
||||
target_cdata, eCustomDataType(layer->type), CD_SET_DEFAULT, elem_num, layer->name);
|
||||
layer_i = CustomData_get_named_layer_index(target_cdata, layer->type, layer->name);
|
||||
}
|
||||
|
||||
|
|
|
@ -78,10 +78,10 @@ static void free_bvh_cache(MeshRuntime &mesh_runtime)
|
|||
}
|
||||
}
|
||||
|
||||
static void free_normals(MeshRuntime &mesh_runtime)
|
||||
static void reset_normals(MeshRuntime &mesh_runtime)
|
||||
{
|
||||
MEM_SAFE_FREE(mesh_runtime.vert_normals);
|
||||
MEM_SAFE_FREE(mesh_runtime.poly_normals);
|
||||
mesh_runtime.vert_normals.clear_and_shrink();
|
||||
mesh_runtime.poly_normals.clear_and_shrink();
|
||||
mesh_runtime.vert_normals_dirty = true;
|
||||
mesh_runtime.poly_normals_dirty = true;
|
||||
}
|
||||
|
@ -101,7 +101,6 @@ MeshRuntime::~MeshRuntime()
|
|||
free_bvh_cache(*this);
|
||||
free_edit_data(*this);
|
||||
free_batch_cache(*this);
|
||||
free_normals(*this);
|
||||
if (this->shrinkwrap_data) {
|
||||
BKE_shrinkwrap_boundary_data_free(this->shrinkwrap_data);
|
||||
}
|
||||
|
@ -216,7 +215,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
|
|||
{
|
||||
/* Tagging shared caches dirty will free the allocated data if there is only one user. */
|
||||
free_bvh_cache(*mesh->runtime);
|
||||
free_normals(*mesh->runtime);
|
||||
reset_normals(*mesh->runtime);
|
||||
free_subdiv_ccg(*mesh->runtime);
|
||||
mesh->runtime->bounds_cache.tag_dirty();
|
||||
mesh->runtime->loose_edges_cache.tag_dirty();
|
||||
|
@ -234,7 +233,7 @@ void BKE_mesh_tag_edges_split(struct Mesh *mesh)
|
|||
* Face normals didn't change either, but tag those anyway, since there is no API function to
|
||||
* only tag vertex normals dirty. */
|
||||
free_bvh_cache(*mesh->runtime);
|
||||
free_normals(*mesh->runtime);
|
||||
reset_normals(*mesh->runtime);
|
||||
free_subdiv_ccg(*mesh->runtime);
|
||||
mesh->runtime->loose_edges_cache.tag_dirty();
|
||||
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
|
||||
|
@ -246,7 +245,8 @@ void BKE_mesh_tag_edges_split(struct Mesh *mesh)
|
|||
|
||||
void BKE_mesh_tag_positions_changed(Mesh *mesh)
|
||||
{
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
mesh->runtime->vert_normals_dirty = true;
|
||||
mesh->runtime->poly_normals_dirty = true;
|
||||
free_bvh_cache(*mesh->runtime);
|
||||
mesh->runtime->looptris_cache.tag_dirty();
|
||||
mesh->runtime->bounds_cache.tag_dirty();
|
||||
|
|
|
@ -311,8 +311,7 @@ void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data,
|
|||
{
|
||||
if (CustomData_get_named_layer_index(tan_data, CD_TANGENT, layer_name) == -1 &&
|
||||
CustomData_get_named_layer_index(uv_data, CD_PROP_FLOAT2, layer_name) != -1) {
|
||||
CustomData_add_layer_named(
|
||||
tan_data, CD_TANGENT, CD_SET_DEFAULT, nullptr, numLoopData, layer_name);
|
||||
CustomData_add_layer_named(tan_data, CD_TANGENT, CD_SET_DEFAULT, numLoopData, layer_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -442,7 +441,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
|||
if ((tangent_mask & DM_TANGENT_MASK_ORCO) &&
|
||||
CustomData_get_named_layer_index(loopdata, CD_TANGENT, "") == -1) {
|
||||
CustomData_add_layer_named(
|
||||
loopdata_out, CD_TANGENT, CD_SET_DEFAULT, nullptr, int(loopdata_out_len), "");
|
||||
loopdata_out, CD_TANGENT, CD_SET_DEFAULT, int(loopdata_out_len), "");
|
||||
}
|
||||
if (calc_act && act_uv_name[0]) {
|
||||
BKE_mesh_add_loop_tangent_named_layer_for_uv(
|
||||
|
@ -592,8 +591,8 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
|
|||
calc_active_tangent,
|
||||
tangent_names,
|
||||
tangent_names_len,
|
||||
BKE_mesh_vert_normals_ensure(me_eval),
|
||||
BKE_mesh_poly_normals_ensure(me_eval),
|
||||
reinterpret_cast<const float(*)[3]>(me_eval->vert_normals().data()),
|
||||
reinterpret_cast<const float(*)[3]>(me_eval->poly_normals().data()),
|
||||
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->ldata, CD_NORMAL)),
|
||||
/* may be nullptr */
|
||||
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->vdata, CD_ORCO)),
|
||||
|
|
|
@ -299,14 +299,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
|||
recalc_flag.edges = do_fixes;
|
||||
}
|
||||
|
||||
const float(*vert_normals)[3] = nullptr;
|
||||
if (!BKE_mesh_vert_normals_are_dirty(mesh)) {
|
||||
vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
}
|
||||
|
||||
for (i = 0; i < totvert; i++) {
|
||||
bool fix_normal = true;
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
if (!isfinite(vert_positions[i][j])) {
|
||||
PRINT_ERR("\tVertex %u: has invalid coordinate", i);
|
||||
|
@ -317,31 +310,6 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
|||
fix_flag.verts = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (vert_normals && vert_normals[i][j] != 0.0f) {
|
||||
fix_normal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (vert_normals && fix_normal) {
|
||||
/* If the vertex normal accumulates to zero or isn't part of a face, the location is used.
|
||||
* When the location is also zero, a zero normal warning should not be raised.
|
||||
* since this is the expected behavior of normal calculation.
|
||||
*
|
||||
* This avoids false positives but isn't foolproof as it's possible the vertex
|
||||
* is part of a polygon that has a normal which this vertex should be using,
|
||||
* although it's also possible degenerate/opposite faces accumulate to a zero vector.
|
||||
* To detect this a full normal recalculation would be needed, which is out of scope
|
||||
* for a basic validity check (see "Vertex Normal" in the doc-string). */
|
||||
if (!is_zero_v3(vert_positions[i])) {
|
||||
PRINT_ERR("\tVertex %u: has zero normal, assuming Z-up normal", i);
|
||||
if (do_fixes) {
|
||||
float *normal = (float *)vert_normals[i];
|
||||
normal[2] = 1.0f;
|
||||
fix_flag.verts = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1146,13 +1114,6 @@ bool BKE_mesh_is_valid(Mesh *me)
|
|||
do_fixes,
|
||||
&changed);
|
||||
|
||||
if (!me->runtime->vert_normals_dirty) {
|
||||
BLI_assert(me->runtime->vert_normals || me->totvert == 0);
|
||||
}
|
||||
if (!me->runtime->poly_normals_dirty) {
|
||||
BLI_assert(me->runtime->poly_normals || me->totpoly == 0);
|
||||
}
|
||||
|
||||
BLI_assert(changed == false);
|
||||
|
||||
return is_valid;
|
||||
|
@ -1352,8 +1313,8 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh)
|
|||
/* write new edges into a temporary CustomData */
|
||||
CustomData edgeData;
|
||||
CustomData_reset(&edgeData);
|
||||
CustomData_add_layer(&edgeData, CD_MEDGE, CD_SET_DEFAULT, nullptr, numEdges);
|
||||
CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, numEdges);
|
||||
CustomData_add_layer(&edgeData, CD_MEDGE, CD_SET_DEFAULT, numEdges);
|
||||
CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_SET_DEFAULT, numEdges);
|
||||
|
||||
MEdge *ege = (MEdge *)CustomData_get_layer_for_write(&edgeData, CD_MEDGE, mesh->totedge);
|
||||
int *index = (int *)CustomData_get_layer_for_write(&edgeData, CD_ORIGINDEX, mesh->totedge);
|
||||
|
|
|
@ -993,7 +993,7 @@ static void multiresModifier_disp_run(
|
|||
if (!mdisps) {
|
||||
if (op == CALC_DISPLACEMENTS) {
|
||||
mdisps = static_cast<MDisps *>(
|
||||
CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, me->totloop));
|
||||
CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, me->totloop));
|
||||
}
|
||||
else {
|
||||
return;
|
||||
|
@ -1528,7 +1528,7 @@ void multires_ensure_external_read(struct Mesh *mesh, int top_level)
|
|||
CustomData_get_layer_for_write(&mesh->ldata, CD_MDISPS, mesh->totloop));
|
||||
if (mdisps == nullptr) {
|
||||
mdisps = static_cast<MDisps *>(
|
||||
CustomData_add_layer(&mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, mesh->totloop));
|
||||
CustomData_add_layer(&mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, mesh->totloop));
|
||||
}
|
||||
|
||||
const int totloop = mesh->totloop;
|
||||
|
|
|
@ -179,8 +179,7 @@ void multiresModifier_subdivide_to_level(Object *object,
|
|||
* are allocated at a proper level and return. */
|
||||
const bool has_mdisps = CustomData_has_layer(&coarse_mesh->ldata, CD_MDISPS);
|
||||
if (!has_mdisps) {
|
||||
CustomData_add_layer(
|
||||
&coarse_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, coarse_mesh->totloop);
|
||||
CustomData_add_layer(&coarse_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, coarse_mesh->totloop);
|
||||
}
|
||||
|
||||
/* NOTE: Subdivision happens from the top level of the existing multires modifier. If it is set
|
||||
|
|
|
@ -74,8 +74,7 @@ void multires_subdivide_create_tangent_displacement_linear_grids(Object *object,
|
|||
|
||||
const bool has_mdisps = CustomData_has_layer(&coarse_mesh->ldata, CD_MDISPS);
|
||||
if (!has_mdisps) {
|
||||
CustomData_add_layer(
|
||||
&coarse_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, coarse_mesh->totloop);
|
||||
CustomData_add_layer(&coarse_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, coarse_mesh->totloop);
|
||||
}
|
||||
|
||||
if (new_top_level == 1) {
|
||||
|
|
|
@ -903,10 +903,10 @@ static void multires_unsubdivide_add_original_index_datalayers(Mesh *mesh)
|
|||
multires_unsubdivide_free_original_datalayers(mesh);
|
||||
|
||||
int *l_index = static_cast<int *>(CustomData_add_layer_named(
|
||||
&mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, mesh->totloop, lname));
|
||||
&mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, lname));
|
||||
|
||||
int *v_index = static_cast<int *>(CustomData_add_layer_named(
|
||||
&mesh->vdata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, mesh->totvert, vname));
|
||||
&mesh->vdata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totvert, vname));
|
||||
|
||||
/* Initialize these data-layer with the indices in the current mesh. */
|
||||
for (int i = 0; i < mesh->totloop; i++) {
|
||||
|
@ -1186,8 +1186,8 @@ static void multires_create_grids_in_unsubdivided_base_mesh(MultiresUnsubdivideC
|
|||
if (CustomData_has_layer(&base_mesh->ldata, CD_MDISPS)) {
|
||||
CustomData_free_layers(&base_mesh->ldata, CD_MDISPS, base_mesh->totloop);
|
||||
}
|
||||
MDisps *mdisps = static_cast<MDisps *>(CustomData_add_layer(
|
||||
&base_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, base_mesh->totloop));
|
||||
MDisps *mdisps = static_cast<MDisps *>(
|
||||
CustomData_add_layer(&base_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, base_mesh->totloop));
|
||||
|
||||
const int totdisp = pow_i(BKE_ccg_gridsize(context->num_total_levels), 2);
|
||||
const int totloop = base_mesh->totloop;
|
||||
|
|
|
@ -1672,7 +1672,8 @@ static void copy_ccg_data(Mesh *mesh_destination, Mesh *mesh_source, int layer_t
|
|||
const int layer_index = CustomData_get_layer_index(data_destination, layer_type);
|
||||
CustomData_free_layer(data_destination, layer_type, num_elements, layer_index);
|
||||
BLI_assert(!CustomData_has_layer(data_destination, layer_type));
|
||||
CustomData_add_layer(data_destination, layer_type, CD_SET_DEFAULT, nullptr, num_elements);
|
||||
CustomData_add_layer(
|
||||
data_destination, eCustomDataType(layer_type), CD_SET_DEFAULT, num_elements);
|
||||
BLI_assert(CustomData_has_layer(data_destination, layer_type));
|
||||
CustomData_copy_layer_type_data(data_source, data_destination, layer_type, 0, 0, num_elements);
|
||||
}
|
||||
|
|
|
@ -554,7 +554,7 @@ struct VertexDupliData_Mesh {
|
|||
|
||||
int totvert;
|
||||
Span<float3> vert_positions;
|
||||
const float (*vert_normals)[3];
|
||||
Span<float3> vert_normals;
|
||||
|
||||
const float (*orco)[3];
|
||||
};
|
||||
|
@ -735,7 +735,7 @@ static void make_duplis_verts(const DupliContext *ctx)
|
|||
vdd.params = vdd_params;
|
||||
vdd.totvert = me_eval->totvert;
|
||||
vdd.vert_positions = me_eval->vert_positions();
|
||||
vdd.vert_normals = BKE_mesh_vert_normals_ensure(me_eval);
|
||||
vdd.vert_normals = me_eval->vert_normals();
|
||||
vdd.orco = (const float(*)[3])CustomData_get_layer(&me_eval->vdata, CD_ORCO);
|
||||
|
||||
make_child_duplis(ctx, &vdd, make_child_duplis_verts_from_mesh);
|
||||
|
|
|
@ -1582,7 +1582,7 @@ static MultiresModifierData *sculpt_multires_modifier_get(const Scene *scene,
|
|||
|
||||
if (mmd->sculptlvl > 0 && !(mmd->flags & eMultiresModifierFlag_UseSculptBaseMesh)) {
|
||||
if (need_mdisps) {
|
||||
CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, me->totloop);
|
||||
CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, me->totloop);
|
||||
}
|
||||
|
||||
return mmd;
|
||||
|
@ -1976,7 +1976,7 @@ bool *BKE_sculpt_hide_poly_ensure(Mesh *mesh)
|
|||
return hide_poly;
|
||||
}
|
||||
return static_cast<bool *>(CustomData_add_layer_named(
|
||||
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, mesh->totpoly, ".hide_poly"));
|
||||
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totpoly, ".hide_poly"));
|
||||
}
|
||||
|
||||
int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
||||
|
@ -2001,8 +2001,8 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
|||
int gridarea = gridsize * gridsize;
|
||||
int i, j;
|
||||
|
||||
gmask = static_cast<GridPaintMask *>(CustomData_add_layer(
|
||||
&me->ldata, CD_GRID_PAINT_MASK, CD_SET_DEFAULT, nullptr, me->totloop));
|
||||
gmask = static_cast<GridPaintMask *>(
|
||||
CustomData_add_layer(&me->ldata, CD_GRID_PAINT_MASK, CD_SET_DEFAULT, me->totloop));
|
||||
|
||||
for (i = 0; i < me->totloop; i++) {
|
||||
GridPaintMask *gpm = &gmask[i];
|
||||
|
@ -2050,7 +2050,7 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
|||
|
||||
/* Create vertex paint mask layer if there isn't one already. */
|
||||
if (!paint_mask) {
|
||||
CustomData_add_layer(&me->vdata, CD_PAINT_MASK, CD_SET_DEFAULT, nullptr, me->totvert);
|
||||
CustomData_add_layer(&me->vdata, CD_PAINT_MASK, CD_SET_DEFAULT, me->totvert);
|
||||
/* The evaluated mesh must be updated to contain the new data. */
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
ret |= SCULPT_MASK_LAYER_CALC_VERT;
|
||||
|
@ -2512,7 +2512,7 @@ static bool sculpt_attribute_create(SculptSession *ss,
|
|||
|
||||
BLI_assert(CustomData_get_named_layer_index(cdata, proptype, name) == -1);
|
||||
|
||||
CustomData_add_layer_named(cdata, proptype, CD_SET_DEFAULT, nullptr, totelem, name);
|
||||
CustomData_add_layer_named(cdata, proptype, CD_SET_DEFAULT, totelem, name);
|
||||
int index = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (!permanent) {
|
||||
|
|
|
@ -2160,7 +2160,7 @@ void psys_particle_on_dm(Mesh *mesh_final,
|
|||
}
|
||||
|
||||
orcodata = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh_final->vdata, CD_ORCO));
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh_final);
|
||||
const blender::Span<blender::float3> vert_normals = mesh_final->vert_normals();
|
||||
|
||||
if (from == PART_FROM_VERT) {
|
||||
const float(*vert_positions)[3] = BKE_mesh_vert_positions(mesh_final);
|
||||
|
@ -2203,7 +2203,7 @@ void psys_particle_on_dm(Mesh *mesh_final,
|
|||
if (from == PART_FROM_VOLUME) {
|
||||
psys_interpolate_face(mesh_final,
|
||||
vert_positions,
|
||||
vert_normals,
|
||||
reinterpret_cast<const float(*)[3]>(vert_normals.data()),
|
||||
mface,
|
||||
mtface,
|
||||
orcodata,
|
||||
|
@ -2226,7 +2226,7 @@ void psys_particle_on_dm(Mesh *mesh_final,
|
|||
else {
|
||||
psys_interpolate_face(mesh_final,
|
||||
vert_positions,
|
||||
vert_normals,
|
||||
reinterpret_cast<const float(*)[3]>(vert_normals.data()),
|
||||
mface,
|
||||
mtface,
|
||||
orcodata,
|
||||
|
|
|
@ -845,7 +845,8 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
|
|||
pbvh->mloop = mloop;
|
||||
pbvh->looptri = looptri;
|
||||
pbvh->vert_positions = vert_positions;
|
||||
BKE_mesh_vert_normals_ensure(mesh);
|
||||
/* Make sure cached normals start out calculated. */
|
||||
mesh->vert_normals();
|
||||
pbvh->vert_normals = BKE_mesh_vert_normals_for_write(mesh);
|
||||
pbvh->hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->vdata, CD_PROP_BOOL, ".hide_vert", mesh->totvert));
|
||||
|
@ -3518,12 +3519,8 @@ bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh)
|
|||
if (pbvh->hide_vert) {
|
||||
return pbvh->hide_vert;
|
||||
}
|
||||
pbvh->hide_vert = static_cast<bool *>(CustomData_add_layer_named(&pbvh->mesh->vdata,
|
||||
CD_PROP_BOOL,
|
||||
CD_SET_DEFAULT,
|
||||
nullptr,
|
||||
pbvh->mesh->totvert,
|
||||
".hide_vert"));
|
||||
pbvh->hide_vert = static_cast<bool *>(CustomData_add_layer_named(
|
||||
&pbvh->mesh->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, pbvh->mesh->totvert, ".hide_vert"));
|
||||
return pbvh->hide_vert;
|
||||
}
|
||||
|
||||
|
@ -3889,7 +3886,7 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
|
|||
|
||||
if (!hide_poly) {
|
||||
hide_poly = static_cast<bool *>(CustomData_add_layer_named(
|
||||
&mesh->pdata, CD_PROP_BOOL, CD_CONSTRUCT, nullptr, mesh->totpoly, ".hide_poly"));
|
||||
&mesh->pdata, CD_PROP_BOOL, CD_CONSTRUCT, mesh->totpoly, ".hide_poly"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -290,5 +290,4 @@ void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
|
|||
|
||||
void pbvh_node_pixels_free(PBVHNode *node);
|
||||
void pbvh_pixels_free(PBVH *pbvh);
|
||||
void pbvh_pixels_free_brush_test(PBVHNode *node);
|
||||
void pbvh_free_draw_buffers(PBVH *pbvh, PBVHNode *node);
|
||||
|
|
|
@ -65,7 +65,6 @@ static void pointcloud_init_data(ID *id)
|
|||
CustomData_add_layer_named(&pointcloud->pdata,
|
||||
CD_PROP_FLOAT3,
|
||||
CD_SET_DEFAULT,
|
||||
nullptr,
|
||||
pointcloud->totpoint,
|
||||
POINTCLOUD_ATTR_POSITION);
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ struct ShrinkwrapCalcData {
|
|||
Object *ob; /* object we are applying shrinkwrap to */
|
||||
|
||||
float (*vert_positions)[3]; /* Array of verts being projected. */
|
||||
const float (*vert_normals)[3];
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
/* Vertices being shrink-wrapped. */
|
||||
float (*vertexCos)[3];
|
||||
int numVerts;
|
||||
|
@ -115,7 +115,7 @@ bool BKE_shrinkwrap_init_tree(
|
|||
|
||||
data->mesh = mesh;
|
||||
data->polys = mesh->polys().data();
|
||||
data->vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
data->vert_normals = reinterpret_cast<const float(*)[3]>(mesh->vert_normals().data()),
|
||||
data->sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_face"));
|
||||
|
||||
|
@ -136,7 +136,7 @@ bool BKE_shrinkwrap_init_tree(
|
|||
}
|
||||
|
||||
if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) {
|
||||
data->poly_normals = BKE_mesh_poly_normals_ensure(mesh);
|
||||
data->poly_normals = reinterpret_cast<const float(*)[3]>(mesh->poly_normals().data());
|
||||
if ((mesh->flag & ME_AUTOSMOOTH) != 0) {
|
||||
data->clnors = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
|
|||
MEM_freeN(vert_status);
|
||||
|
||||
/* Finalize average direction and compute normal. */
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
const blender::Span<blender::float3> vert_normals = mesh->vert_normals();
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
int bidx = vert_boundary_id[i];
|
||||
|
||||
|
@ -1409,7 +1409,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
|
|||
if (mesh != nullptr && smd->shrinkType == MOD_SHRINKWRAP_PROJECT) {
|
||||
/* Setup arrays to get vertex positions, normals and deform weights */
|
||||
calc.vert_positions = BKE_mesh_vert_positions_for_write(mesh);
|
||||
calc.vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
calc.vert_normals = mesh->vert_normals();
|
||||
|
||||
/* Using vertices positions/normals as if a subsurface was applied */
|
||||
if (smd->subsurfLevels) {
|
||||
|
@ -1570,7 +1570,7 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object
|
|||
calc.smd = &ssmd;
|
||||
calc.numVerts = src_me->totvert;
|
||||
calc.vertexCos = vertexCos;
|
||||
calc.vert_normals = BKE_mesh_vert_normals_ensure(src_me);
|
||||
calc.vert_normals = src_me->vert_normals();
|
||||
calc.vgroup = -1;
|
||||
calc.target = target_me;
|
||||
calc.keepDist = ssmd.keepDist;
|
||||
|
|
|
@ -1180,8 +1180,8 @@ static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
|
|||
|
||||
BLI_rw_mutex_lock(&ccgdm->origindex_cache_rwlock, THREAD_LOCK_WRITE);
|
||||
|
||||
origindex = static_cast<int *>(CustomData_add_layer(
|
||||
&dm->vertData, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, dm->numVertData));
|
||||
origindex = static_cast<int *>(
|
||||
CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_SET_DEFAULT, dm->numVertData));
|
||||
|
||||
totorig = ccgSubSurf_getNumVerts(ss);
|
||||
totnone = dm->numVertData - totorig;
|
||||
|
@ -1219,8 +1219,8 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
|
|||
return origindex;
|
||||
}
|
||||
|
||||
origindex = static_cast<int *>(CustomData_add_layer(
|
||||
&dm->edgeData, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, dm->numEdgeData));
|
||||
origindex = static_cast<int *>(
|
||||
CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_SET_DEFAULT, dm->numEdgeData));
|
||||
|
||||
totedge = ccgSubSurf_getNumEdges(ss);
|
||||
totorig = totedge * (edgeSize - 1);
|
||||
|
@ -1262,8 +1262,8 @@ static void *ccgDM_get_poly_data_layer(DerivedMesh *dm, int type)
|
|||
return origindex;
|
||||
}
|
||||
|
||||
origindex = static_cast<int *>(CustomData_add_layer(
|
||||
&dm->polyData, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, dm->numPolyData));
|
||||
origindex = static_cast<int *>(
|
||||
CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_SET_DEFAULT, dm->numPolyData));
|
||||
|
||||
totface = ccgSubSurf_getNumFaces(ss);
|
||||
|
||||
|
|
|
@ -309,7 +309,7 @@ template<typename T> struct AngleCartesianBase {
|
|||
math::sqrt((T(1) - a.cos_) / T(2))};
|
||||
/* Recover sign only for sine. Cosine of half angle is given to be positive or 0 since the
|
||||
* angle stored in #AngleCartesianBase is in the range [-pi..pi]. */
|
||||
/* TODO(fclem): Could use copysign here. */
|
||||
/* TODO(fclem): Could use `copysign` here. */
|
||||
if (a.sin_ < T(0)) {
|
||||
result.sin_ = -result.sin_;
|
||||
}
|
||||
|
|
|
@ -156,7 +156,29 @@ template<size_t Size, size_t Alignment> class AlignedBuffer {
|
|||
*/
|
||||
template<typename T, int64_t Size = 1> class TypedBuffer {
|
||||
private:
|
||||
BLI_NO_UNIQUE_ADDRESS AlignedBuffer<sizeof(T) * size_t(Size), alignof(T)> 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<get_size(), get_alignment()> buffer_;
|
||||
|
||||
public:
|
||||
operator T *()
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue