UI: Asset Shelf (Experimental Feature) #104831

Closed
Julian Eisel wants to merge 399 commits from asset-shelf into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
309 changed files with 3677 additions and 2790 deletions
Showing only changes of commit 8b253cdb8b - Show all commits

View File

@ -517,6 +517,7 @@ mark_as_advanced(WITH_CYCLES_LOGGING)
mark_as_advanced(WITH_CYCLES_DEBUG_NAN)
mark_as_advanced(WITH_CYCLES_NATIVE_ONLY)
mark_as_advanced(WITH_CYCLES_PRECOMPUTE)
mark_as_advanced(CYCLES_TEST_DEVICES)
# NVIDIA CUDA & OptiX
if(NOT APPLE)
@ -1292,6 +1293,9 @@ if(WITH_OPENMP)
add_definitions("${OpenMP_C_FLAGS}")
find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
mark_as_advanced(
OpenMP_LIBRARIES
)
endif()
endif()

View File

@ -119,5 +119,7 @@ ELSE()
ENDIF()
MARK_AS_ADVANCED(
_SYCL_INCLUDE_PARENT_DIR
SYCL_COMPILER
SYCL_INCLUDE_DIR
SYCL_LIBRARY
)

View File

@ -33,6 +33,7 @@ function(list_assert_duplicates
# message(STATUS "list data: ${list_id}")
list(REMOVE_ITEM list_id "PUBLIC" "PRIVATE" "INTERFACE")
list(LENGTH list_id _len_before)
list(REMOVE_DUPLICATES list_id)
list(LENGTH list_id _len_after)

View File

@ -444,10 +444,15 @@ endif()
if(WITH_COMPILER_CCACHE)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode")
find_program(CCACHE_PROGRAM ccache)
mark_as_advanced(CCACHE_PROGRAM)
if(CCACHE_PROGRAM)
# Makefiles and ninja
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" CACHE STRING "" FORCE)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" CACHE STRING "" FORCE)
mark_as_advanced(
CMAKE_C_COMPILER_LAUNCHER
CMAKE_CXX_COMPILER_LAUNCHER
)
else()
message(WARNING "Ccache NOT found, disabling WITH_COMPILER_CCACHE")
set(WITH_COMPILER_CCACHE OFF)

View File

@ -172,6 +172,7 @@ endif()
if(WITH_COMPILER_CCACHE)
if(CMAKE_GENERATOR STREQUAL "Xcode")
find_program(CCACHE_PROGRAM ccache)
mark_as_advanced(CCACHE_PROGRAM)
if(CCACHE_PROGRAM)
get_filename_component(ccompiler "${CMAKE_C_COMPILER}" NAME)
get_filename_component(cxxcompiler "${CMAKE_CXX_COMPILER}" NAME)

View File

@ -321,11 +321,13 @@ endif()
if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
set(CYCLES_LEVEL_ZERO ${LIBDIR}/level-zero CACHE PATH "Path to Level Zero installation")
mark_as_advanced(CYCLES_LEVEL_ZERO)
if(EXISTS ${CYCLES_LEVEL_ZERO} AND NOT LEVEL_ZERO_ROOT_DIR)
set(LEVEL_ZERO_ROOT_DIR ${CYCLES_LEVEL_ZERO})
endif()
set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to oneAPI DPC++ compiler")
mark_as_advanced(CYCLES_SYCL)
if(EXISTS ${CYCLES_SYCL} AND NOT SYCL_ROOT_DIR)
set(SYCL_ROOT_DIR ${CYCLES_SYCL})
endif()
@ -990,10 +992,15 @@ endif()
if(WITH_COMPILER_CCACHE)
find_program(CCACHE_PROGRAM ccache)
mark_as_advanced(CCACHE_PROGRAM)
if(CCACHE_PROGRAM)
# Makefiles and ninja
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" CACHE STRING "" FORCE)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" CACHE STRING "" FORCE)
mark_as_advanced(
CMAKE_C_COMPILER_LAUNCHER
CMAKE_CXX_COMPILER_LAUNCHER
)
else()
message(WARNING "Ccache NOT found, disabling WITH_COMPILER_CCACHE")
set(WITH_COMPILER_CCACHE OFF)

View File

@ -1103,6 +1103,7 @@ set(ZSTD_LIBRARIES ${LIBDIR}/zstd/lib/zstd_static.lib)
if(WITH_CYCLES AND (WITH_CYCLES_DEVICE_ONEAPI OR (WITH_CYCLES_EMBREE AND EMBREE_SYCL_SUPPORT)))
set(LEVEL_ZERO_ROOT_DIR ${LIBDIR}/level_zero)
set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to oneAPI DPC++ compiler")
mark_as_advanced(CYCLES_SYCL)
if(EXISTS ${CYCLES_SYCL} AND NOT SYCL_ROOT_DIR)
set(SYCL_ROOT_DIR ${CYCLES_SYCL})
endif()

View File

@ -10,7 +10,9 @@ set(INC_SYS
)
add_library(bf_intern_atomic INTERFACE)
target_include_directories(bf_intern_atomic INTERFACE .)
add_library(bf::intern::atomic ALIAS bf_intern_atomic)
# CMake 3.19+ allows one to populate the interface library with
# source files to show in the IDE, for people on older CMake versions

View File

@ -31,7 +31,8 @@ static void attr_create_motion(PointCloud *pointcloud,
const int num_points = pointcloud->get_points().size();
/* Find or add attribute */
float3 *P = &pointcloud->get_points()[0];
float3 *P = pointcloud->get_points().data();
float *radius = pointcloud->get_radius().data();
Attribute *attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (!attr_mP) {
@ -42,10 +43,11 @@ static void attr_create_motion(PointCloud *pointcloud,
float motion_times[2] = {-1.0f, 1.0f};
for (int step = 0; step < 2; step++) {
const float relative_time = motion_times[step] * 0.5f * motion_scale;
float3 *mP = attr_mP->data_float3() + step * num_points;
float4 *mP = attr_mP->data_float4() + step * num_points;
for (int i = 0; i < num_points; i++) {
mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
float3 Pi = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
mP[i] = make_float4(Pi.x, Pi.y, Pi.z, radius[i]);
}
}
}

View File

@ -89,7 +89,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
if (b_ob_info.is_real_object_data()) {
if (mesh) {
/* Make a copy to split faces if we use autosmooth, otherwise not needed.
/* Make a copy to split faces if we use auto-smooth, otherwise not needed.
* Also in edit mode do we need to make a copy, to ensure data layers like
* UV are not empty. */
if (mesh.is_editmode() ||

View File

@ -271,7 +271,7 @@ void BVHBuild::add_reference_points(BoundBox &root,
const float3 *points_data = &pointcloud->points[0];
const float *radius_data = &pointcloud->radius[0];
const size_t num_points = pointcloud->num_points();
const float3 *motion_data = (point_attr_mP) ? point_attr_mP->data_float3() : NULL;
const float4 *motion_data = (point_attr_mP) ? point_attr_mP->data_float4() : NULL;
const size_t num_steps = pointcloud->get_motion_steps();
if (point_attr_mP == NULL) {
@ -298,7 +298,7 @@ void BVHBuild::add_reference_points(BoundBox &root,
BoundBox bounds = BoundBox::empty;
point.bounds_grow(points_data, radius_data, bounds);
for (size_t step = 0; step < num_steps - 1; step++) {
point.bounds_grow(motion_data + step * num_points, radius_data, bounds);
point.bounds_grow(motion_data[step * num_points + j], bounds);
}
if (bounds.valid()) {
references.push_back(BVHReference(bounds, j, i, PRIMITIVE_MOTION_POINT));
@ -318,7 +318,7 @@ void BVHBuild::add_reference_points(BoundBox &root,
for (uint j = 0; j < num_points; j++) {
const PointCloud::Point point = pointcloud->get_point(j);
const size_t num_steps = pointcloud->get_motion_steps();
const float3 *point_steps = point_attr_mP->data_float3();
const float4 *point_steps = point_attr_mP->data_float4();
/* Calculate bounding box of the previous time step.
* Will be reused later to avoid duplicated work on

View File

@ -471,20 +471,6 @@ void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, c
}
}
/**
* Pack the motion points into a float4 as [x y z radius]
*/
template<typename T>
void pack_motion_points(size_t num_points, const T *verts, const float *radius, float4 *rtc_verts)
{
for (size_t j = 0; j < num_points; ++j) {
rtc_verts[j].x = verts[j].x;
rtc_verts[j].y = verts[j].y;
rtc_verts[j].z = verts[j].z;
rtc_verts[j].w = radius[j];
}
}
void BVHEmbree::set_point_vertex_buffer(RTCGeometry geom_id,
const PointCloud *pointcloud,
const bool update)
@ -520,13 +506,20 @@ void BVHEmbree::set_point_vertex_buffer(RTCGeometry geom_id,
assert(rtc_verts);
if (rtc_verts) {
if (t == t_mid || attr_mP == NULL) {
/* Pack the motion points into a float4 as [x y z radius]. */
const float3 *verts = pointcloud->get_points().data();
pack_motion_points<float3>(num_points, verts, radius, rtc_verts);
for (size_t j = 0; j < num_points; ++j) {
rtc_verts[j].x = verts[j].x;
rtc_verts[j].y = verts[j].y;
rtc_verts[j].z = verts[j].z;
rtc_verts[j].w = radius[j];
}
}
else {
/* Motion blur is already packed as [x y z radius]. */
int t_ = (t > t_mid) ? (t - 1) : t;
const float4 *verts = &attr_mP->data_float4()[t_ * num_points];
pack_motion_points<float4>(num_points, verts, radius, rtc_verts);
memcpy(rtc_verts, verts, sizeof(float4) * num_points);
}
}

View File

@ -618,7 +618,7 @@ hiprtGeometryBuildInput HIPRTDevice::prepare_point_blas(BVHHIPRT *bvh, PointClou
const float3 *points_data = pointcloud->get_points().data();
const float *radius_data = pointcloud->get_radius().data();
const size_t num_points = pointcloud->num_points();
const float3 *motion_data = (point_attr_mP) ? point_attr_mP->data_float3() : NULL;
const float4 *motion_data = (point_attr_mP) ? point_attr_mP->data_float4() : NULL;
const size_t num_steps = pointcloud->get_motion_steps();
int num_bounds = 0;
@ -646,7 +646,7 @@ hiprtGeometryBuildInput HIPRTDevice::prepare_point_blas(BVHHIPRT *bvh, PointClou
BoundBox bounds = BoundBox::empty;
point.bounds_grow(points_data, radius_data, bounds);
for (size_t step = 0; step < num_steps - 1; step++) {
point.bounds_grow(motion_data + step * num_points, radius_data, bounds);
point.bounds_grow(motion_data[step * num_points + j], bounds);
}
if (bounds.valid()) {
bvh->custom_primitive_bound[num_bounds] = bounds;
@ -666,7 +666,7 @@ hiprtGeometryBuildInput HIPRTDevice::prepare_point_blas(BVHHIPRT *bvh, PointClou
for (uint j = 0; j < num_points; j++) {
const PointCloud::Point point = pointcloud->get_point(j);
const size_t num_steps = pointcloud->get_motion_steps();
const float3 *point_steps = point_attr_mP->data_float3();
const float4 *point_steps = point_attr_mP->data_float4();
float4 prev_key = point.motion_key(
points_data, radius_data, point_steps, num_points, num_steps, 0.0f, j);

View File

@ -516,20 +516,31 @@ bool BVHMetal::build_BLAS_pointcloud(Progress &progress,
/* Get AABBs for each motion step */
size_t center_step = (num_motion_steps - 1) / 2;
for (size_t step = 0; step < num_motion_steps; ++step) {
/* The center step for motion vertices is not stored in the attribute */
if (step != center_step) {
size_t attr_offset = (step > center_step) ? step - 1 : step;
points = motion_keys->data_float3() + attr_offset * num_points;
if (step == center_step) {
/* The center step for motion vertices is not stored in the attribute */
for (size_t j = 0; j < num_points; ++j) {
const PointCloud::Point point = pointcloud->get_point(j);
BoundBox bounds = BoundBox::empty;
point.bounds_grow(points, radius, bounds);
const size_t index = step * num_points + j;
aabb_data[index].min = (MTLPackedFloat3 &)bounds.min;
aabb_data[index].max = (MTLPackedFloat3 &)bounds.max;
}
}
else {
size_t attr_offset = (step > center_step) ? step - 1 : step;
float4 *motion_points = motion_keys->data_float4() + attr_offset * num_points;
for (size_t j = 0; j < num_points; ++j) {
const PointCloud::Point point = pointcloud->get_point(j);
BoundBox bounds = BoundBox::empty;
point.bounds_grow(points, radius, bounds);
for (size_t j = 0; j < num_points; ++j) {
const PointCloud::Point point = pointcloud->get_point(j);
BoundBox bounds = BoundBox::empty;
point.bounds_grow(motion_points[j], bounds);
const size_t index = step * num_points + j;
aabb_data[index].min = (MTLPackedFloat3 &)bounds.min;
aabb_data[index].max = (MTLPackedFloat3 &)bounds.max;
const size_t index = step * num_points + j;
aabb_data[index].min = (MTLPackedFloat3 &)bounds.min;
aabb_data[index].max = (MTLPackedFloat3 &)bounds.max;
}
}
}

View File

@ -1395,27 +1395,43 @@ void OptiXDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
/* Get AABBs for each motion step. */
for (size_t step = 0; step < num_motion_steps; ++step) {
/* The center step for motion vertices is not stored in the attribute. */
const float3 *points = pointcloud->get_points().data();
const float *radius = pointcloud->get_radius().data();
size_t center_step = (num_motion_steps - 1) / 2;
if (step != center_step) {
size_t attr_offset = (step > center_step) ? step - 1 : step;
/* Technically this is a float4 array, but sizeof(float3) == sizeof(float4). */
points = motion_points->data_float3() + attr_offset * num_points;
if (step == center_step) {
const float3 *points = pointcloud->get_points().data();
const float *radius = pointcloud->get_radius().data();
for (size_t i = 0; i < num_points; ++i) {
const PointCloud::Point point = pointcloud->get_point(i);
BoundBox bounds = BoundBox::empty;
point.bounds_grow(points, radius, bounds);
const size_t index = step * num_points + i;
aabb_data[index].minX = bounds.min.x;
aabb_data[index].minY = bounds.min.y;
aabb_data[index].minZ = bounds.min.z;
aabb_data[index].maxX = bounds.max.x;
aabb_data[index].maxY = bounds.max.y;
aabb_data[index].maxZ = bounds.max.z;
}
}
else {
size_t attr_offset = (step > center_step) ? step - 1 : step;
const float4 *points = motion_points->data_float4() + attr_offset * num_points;
for (size_t i = 0; i < num_points; ++i) {
const PointCloud::Point point = pointcloud->get_point(i);
BoundBox bounds = BoundBox::empty;
point.bounds_grow(points, radius, bounds);
for (size_t i = 0; i < num_points; ++i) {
const PointCloud::Point point = pointcloud->get_point(i);
BoundBox bounds = BoundBox::empty;
point.bounds_grow(points[i], bounds);
const size_t index = step * num_points + i;
aabb_data[index].minX = bounds.min.x;
aabb_data[index].minY = bounds.min.y;
aabb_data[index].minZ = bounds.min.z;
aabb_data[index].maxX = bounds.max.x;
aabb_data[index].maxY = bounds.max.y;
aabb_data[index].maxZ = bounds.max.z;
const size_t index = step * num_points + i;
aabb_data[index].minX = bounds.min.x;
aabb_data[index].minY = bounds.min.y;
aabb_data[index].minZ = bounds.min.z;
aabb_data[index].maxX = bounds.max.x;
aabb_data[index].maxY = bounds.max.y;
aabb_data[index].maxZ = bounds.max.z;
}
}
}

View File

@ -94,6 +94,15 @@ void HdCyclesLight::Sync(HdSceneDelegate *sceneDelegate,
strength *= value.Get<float>();
}
if (_lightType == HdPrimTypeTokens->distantLight) {
/* Unclear why, but approximately matches Karma. */
strength *= 4.0f;
}
else {
/* Convert from intensity to radiant flux. */
strength *= M_PI;
}
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->normalize);
_light->set_normalize(value.IsHolding<bool>() && value.UncheckedGet<bool>());
@ -133,9 +142,15 @@ void HdCyclesLight::Sync(HdSceneDelegate *sceneDelegate,
}
}
else if (_lightType == HdPrimTypeTokens->sphereLight) {
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->radius);
if (!value.IsEmpty()) {
_light->set_size(value.Get<float>());
value = sceneDelegate->GetLightParamValue(id, TfToken("treatAsPoint"));
if (!value.IsEmpty() && value.Get<bool>()) {
_light->set_size(0.0f);
}
else {
value = sceneDelegate->GetLightParamValue(id, HdLightTokens->radius);
if (!value.IsEmpty()) {
_light->set_size(value.Get<float>());
}
}
bool shaping = false;

View File

@ -116,6 +116,15 @@ void HdCyclesSession::UpdateScene()
if (!background_light) {
scene->background->set_shader(scene->default_background);
scene->background->set_transparent(true);
/* Set background color depending to non-zero value if there are no
* lights in the scene, to match behavior of other renderers. */
for (ShaderNode *node : scene->default_background->graph->nodes) {
if (node->is_a(BackgroundNode::get_node_type())) {
BackgroundNode *bgNode = static_cast<BackgroundNode *>(node);
bgNode->set_color((scene->lights.size() == 0) ? make_float3(0.5f) : zero_float3());
}
}
}
else {
scene->background->set_shader(background_light->get_shader());

View File

@ -832,6 +832,8 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
)
set(SYCL_OFFLINE_COMPILER_PARALLEL_JOBS 1 CACHE STRING "Number of parallel compiler instances to use for device binaries compilation (expect ~8GB peak memory usage per instance).")
mark_as_advanced(SYCL_OFFLINE_COMPILER_PARALLEL_JOBS)
if(WITH_CYCLES_ONEAPI_BINARIES)
message(STATUS "${SYCL_OFFLINE_COMPILER_PARALLEL_JOBS} instance(s) of oneAPI offline compiler will be used.")
endif()
@ -865,6 +867,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
endif()
if(NOT DEFINED CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen)
set(CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen "${CYCLES_ONEAPI_SYCL_OPTIONS_spir64}" CACHE STRING "Extra build options for spir64_gen target")
mark_as_advanced(CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen)
endif()
# Enable zebin, a graphics binary format with improved compatibility.
string(PREPEND CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen "--format zebin ")

View File

@ -188,13 +188,13 @@ using uchar = unsigned char;
using sycl::half;
/* math functions */
ccl_device_forceinline float __uint_as_float(uint x)
ccl_device_forceinline float __uint_as_float(unsigned int x)
{
return sycl::bit_cast<float>(x);
}
ccl_device_forceinline uint __float_as_uint(float x)
ccl_device_forceinline unsigned int __float_as_uint(float x)
{
return sycl::bit_cast<uint>(x);
return sycl::bit_cast<unsigned int>(x);
}
ccl_device_forceinline float __int_as_float(int x)
{

View File

@ -290,7 +290,8 @@ ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight,
ls->D = normalize_len(*light_P - ray_P, &ls->t);
}
ls->eval_fac = 0.25f * invarea;
/* Convert radiant flux to radiance. */
ls->eval_fac = M_1_PI_F * invarea;
if (klight->area.normalize_spread > 0) {
/* Area Light spread angle attenuation */

View File

@ -10,28 +10,42 @@
CCL_NAMESPACE_BEGIN
ccl_device_inline void distant_light_uv(const ccl_global KernelLight *klight,
const float3 D,
ccl_private float *u,
ccl_private float *v)
{
/* Map direction (x, y, z) to disk [-0.5, 0.5]^2:
* r^2 = (1 - z) / (1 - cos(klight->distant.angle))
* u_ = 0.5 * x * r / sin_angle(D, -klight->co)
* v_ = 0.5 * y * r / sin_angle(D, -klight->co) */
const float fac = klight->distant.half_inv_sin_half_angle / len(D - klight->co);
/* Get u axis and v axis. */
const Transform itfm = klight->itfm;
const float u_ = dot(D, float4_to_float3(itfm.x)) * fac;
const float v_ = dot(D, float4_to_float3(itfm.y)) * fac;
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
*u = v_ + 0.5f;
*v = -u_ - v_;
}
ccl_device_inline bool distant_light_sample(const ccl_global KernelLight *klight,
const float2 rand,
ccl_private LightSample *ls)
{
/* distant light */
float3 lightD = klight->co;
float3 D = lightD;
float radius = klight->distant.radius;
float invarea = klight->distant.invarea;
float unused;
sample_uniform_cone_concentric(
klight->co, klight->distant.one_minus_cosangle, rand, &unused, &ls->Ng, &ls->pdf);
if (radius > 0.0f) {
D = normalize(D + disk_light_sample(D, rand) * radius);
}
ls->P = D;
ls->Ng = D;
ls->D = -D;
ls->P = ls->Ng;
ls->D = -ls->Ng;
ls->t = FLT_MAX;
float costheta = dot(lightD, D);
ls->pdf = invarea / (costheta * costheta * costheta);
ls->eval_fac = ls->pdf;
ls->eval_fac = klight->distant.eval_fac;
distant_light_uv(klight, ls->D, &ls->u, &ls->v);
return true;
}
@ -50,15 +64,11 @@ ccl_device bool distant_light_intersect(const ccl_global KernelLight *klight,
{
kernel_assert(klight->type == LIGHT_DISTANT);
if (klight->distant.radius == 0.0f) {
if (klight->distant.angle == 0.0f) {
return false;
}
const float3 lightD = klight->co;
const float costheta = dot(-lightD, ray->D);
const float cosangle = klight->distant.cosangle;
if (costheta < cosangle) {
if (vector_angle(-klight->co, ray->D) > klight->distant.angle) {
return false;
}
@ -76,7 +86,6 @@ ccl_device bool distant_light_sample_from_intersection(KernelGlobals kg,
{
ccl_global const KernelLight *klight = &kernel_data_fetch(lights, lamp);
const int shader = klight->shader_id;
const float radius = klight->distant.radius;
const LightType type = (LightType)klight->type;
if (type != LIGHT_DISTANT) {
@ -85,37 +94,19 @@ ccl_device bool distant_light_sample_from_intersection(KernelGlobals kg,
if (!(shader & SHADER_USE_MIS)) {
return false;
}
if (radius == 0.0f) {
if (klight->distant.angle == 0.0f) {
return false;
}
/* a distant light is infinitely far away, but equivalent to a disk
* shaped light exactly 1 unit away from the current shading point.
*
* radius t^2/cos(theta)
* <----------> t = sqrt(1^2 + tan(theta)^2)
* tan(th) area = radius*radius*pi
* <----->
* \ | (1 + tan(theta)^2)/cos(theta)
* \ | (1 + tan(acos(cos(theta)))^2)/cos(theta)
* t \th| 1 simplifies to
* \-| 1/(cos(theta)^3)
* \| magic!
* P
*/
float3 lightD = klight->co;
float costheta = dot(-lightD, ray_D);
float cosangle = klight->distant.cosangle;
/* Workaround to prevent a hang in the classroom scene with AMD HIP drivers 22.10,
* Remove when a compiler fix is available. */
#ifdef __HIP__
ls->shader = klight->shader_id;
#endif
if (costheta < cosangle)
if (vector_angle(-klight->co, ray_D) > klight->distant.angle) {
return false;
}
ls->type = type;
#ifndef __HIP__
@ -124,19 +115,16 @@ ccl_device bool distant_light_sample_from_intersection(KernelGlobals kg,
ls->object = PRIM_NONE;
ls->prim = PRIM_NONE;
ls->lamp = lamp;
/* todo: missing texture coordinates */
ls->u = 0.0f;
ls->v = 0.0f;
ls->t = FLT_MAX;
ls->P = -ray_D;
ls->Ng = -ray_D;
ls->D = ray_D;
ls->group = lamp_lightgroup(kg, lamp);
/* compute pdf */
float invarea = klight->distant.invarea;
ls->pdf = invarea / (costheta * costheta * costheta);
ls->eval_fac = ls->pdf;
ls->pdf = klight->distant.pdf;
ls->eval_fac = klight->distant.eval_fac;
distant_light_uv(klight, ray_D, &ls->u, &ls->v);
return true;
}

View File

@ -147,7 +147,7 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
ls->eval_fac = 1.0f;
}
else if (type == LIGHT_SPOT) {
if (!spot_light_sample<in_volume_segment>(klight, rand, P, ls)) {
if (!spot_light_sample<in_volume_segment>(klight, rand, P, N, shader_flags, ls)) {
return false;
}
}
@ -462,14 +462,13 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
ls->object = isect->object;
ls->prim = isect->prim;
ls->lamp = lamp;
/* todo: missing texture coordinates */
ls->t = isect->t;
ls->P = ray_P + ray_D * ls->t;
ls->D = ray_D;
ls->group = lamp_lightgroup(kg, lamp);
if (type == LIGHT_SPOT) {
if (!spot_light_sample_from_intersection(klight, isect, ray_P, ray_D, ls)) {
if (!spot_light_sample_from_intersection(klight, isect, ray_P, ray_D, N, path_flag, ls)) {
return false;
}
}

View File

@ -44,7 +44,7 @@ ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
ls->P = P + ls->D * ls->t;
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
ls->eval_fac = klight->spot.eval_fac;
if (r_sq == 0) {
/* Use intensity instead of radiance for point light. */
ls->eval_fac /= sqr(ls->t);
@ -100,7 +100,7 @@ ccl_device_forceinline void point_light_mnee_sample_update(const ccl_global Kern
ls->Ng = normalize(ls->P - klight->co);
}
else {
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
ls->eval_fac = klight->spot.eval_fac;
ls->Ng = -ls->D;
@ -136,7 +136,7 @@ ccl_device_inline bool point_light_sample_from_intersection(
const uint32_t path_flag,
ccl_private LightSample *ccl_restrict ls)
{
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
ls->eval_fac = klight->spot.eval_fac;
const float radius = klight->spot.radius;

View File

@ -381,7 +381,7 @@ ccl_device_forceinline void light_sample_update(KernelGlobals kg,
point_light_mnee_sample_update(klight, ls, P, N, path_flag);
}
else if (ls->type == LIGHT_SPOT) {
spot_light_mnee_sample_update(klight, ls, P);
spot_light_mnee_sample_update(klight, ls, P, N, path_flag);
}
else if (ls->type == LIGHT_AREA) {
area_light_mnee_sample_update(klight, ls, P);

View File

@ -8,96 +8,187 @@
CCL_NAMESPACE_BEGIN
ccl_device float spot_light_attenuation(const ccl_global KernelSpotLight *spot, float3 ray)
/* Transform vector to spot light's local coordinate system. */
ccl_device float3 spot_light_to_local(const ccl_global KernelSpotLight *spot, const float3 ray)
{
const float3 scaled_ray = safe_normalize(make_float3(dot(ray, spot->scaled_axis_u),
dot(ray, spot->scaled_axis_v),
dot(ray, spot->dir * spot->inv_len_z)));
return safe_normalize(make_float3(dot(ray, spot->scaled_axis_u),
dot(ray, spot->scaled_axis_v),
dot(ray, spot->dir * spot->inv_len_z)));
}
return smoothstepf((scaled_ray.z - spot->cos_half_spot_angle) * spot->spot_smooth);
/* Compute spot light attenuation of a ray given in local coordinate system. */
ccl_device float spot_light_attenuation(const ccl_global KernelSpotLight *spot, const float3 ray)
{
return smoothstepf((ray.z - spot->cos_half_spot_angle) * spot->spot_smooth);
}
ccl_device void spot_light_uv(const float3 ray,
const float half_cot_half_spot_angle,
ccl_private float *u,
ccl_private float *v)
{
/* Ensures that the spot light projects the full image regardless of the spot angle. */
const float factor = half_cot_half_spot_angle / ray.z;
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
*u = ray.y * factor + 0.5f;
*v = -(ray.x + ray.y) * factor;
}
template<bool in_volume_segment>
ccl_device_inline bool spot_light_sample(const ccl_global KernelLight *klight,
const float2 rand,
const float3 P,
const float3 N,
const int shader_flags,
ccl_private LightSample *ls)
{
ls->P = klight->co;
const float radius = klight->spot.radius;
const float r_sq = sqr(klight->spot.radius);
const float3 center = klight->co;
const float radius = klight->spot.radius;
/* disk oriented normal */
const float3 lightN = normalize(P - center);
ls->P = center;
if (radius > 0.0f) {
/* disk light */
ls->P += disk_light_sample(lightN, rand) * radius;
float3 lightN = P - center;
const float d_sq = len_squared(lightN);
const float d = sqrtf(d_sq);
lightN /= d;
float cos_theta;
ls->t = FLT_MAX;
if (d_sq > r_sq) {
const float one_minus_cos_half_spot_spread = 1.0f - klight->spot.cos_half_spot_angle;
const float one_minus_cos_half_angle = sin_sqr_to_one_minus_cos(r_sq / d_sq);
if (in_volume_segment || one_minus_cos_half_angle < one_minus_cos_half_spot_spread) {
/* Sample visible part of the sphere. */
sample_uniform_cone_concentric(
-lightN, one_minus_cos_half_angle, rand, &cos_theta, &ls->D, &ls->pdf);
}
else {
/* Sample spread cone. */
sample_uniform_cone_concentric(
-klight->spot.dir, one_minus_cos_half_spot_spread, rand, &cos_theta, &ls->D, &ls->pdf);
if (!ray_sphere_intersect(P, ls->D, 0.0f, FLT_MAX, center, radius, &ls->P, &ls->t)) {
/* Sampled direction does not intersect with the light. */
return false;
}
}
}
else {
const bool has_transmission = (shader_flags & SD_BSDF_HAS_TRANSMISSION);
if (has_transmission) {
ls->D = sample_uniform_sphere(rand);
ls->pdf = M_1_2PI_F * 0.5f;
}
else {
sample_cos_hemisphere(N, rand, &ls->D, &ls->pdf);
}
cos_theta = -dot(ls->D, lightN);
}
const float invarea = klight->spot.invarea;
ls->pdf = invarea;
if (ls->t == FLT_MAX) {
/* Law of cosines. */
ls->t = d * cos_theta -
copysignf(safe_sqrtf(r_sq - d_sq + d_sq * sqr(cos_theta)), d_sq - r_sq);
ls->P = P + ls->D * ls->t;
}
else {
/* Already computed when sampling the spread cone. */
}
ls->D = normalize_len(ls->P - P, &ls->t);
/* we set the light normal to the outgoing direction to support texturing */
ls->Ng = -ls->D;
const float3 local_ray = spot_light_to_local(&klight->spot, -ls->D);
ls->eval_fac = klight->spot.eval_fac;
if (d_sq > r_sq) {
ls->eval_fac *= spot_light_attenuation(&klight->spot, local_ray);
}
ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
/* spot light attenuation */
ls->eval_fac *= spot_light_attenuation(&klight->spot, -ls->D);
if (!in_volume_segment && ls->eval_fac == 0.0f) {
return false;
}
float2 uv = map_to_sphere(ls->Ng);
ls->u = uv.x;
ls->v = uv.y;
if (r_sq == 0) {
/* Use intensity instead of radiance when the radius is zero. */
ls->eval_fac /= sqr(ls->t);
/* `ls->Ng` is not well-defined when the radius is zero, use the incoming direction instead. */
ls->Ng = -ls->D;
}
else {
ls->Ng = normalize(ls->P - center);
/* Remap sampled point onto the sphere to prevent precision issues with small radius. */
ls->P = ls->Ng * radius + center;
}
spot_light_uv(local_ray, klight->spot.half_cot_half_spot_angle, &ls->u, &ls->v);
ls->pdf *= lamp_light_pdf(lightN, -ls->D, ls->t);
return true;
}
ccl_device_forceinline float spot_light_pdf(const float cos_half_spread,
const float d_sq,
const float r_sq,
const float3 N,
const float3 D,
const uint32_t path_flag)
{
if (d_sq > r_sq) {
return M_1_2PI_F / min(sin_sqr_to_one_minus_cos(r_sq / d_sq), 1.0f - cos_half_spread);
}
const bool has_transmission = (path_flag & PATH_RAY_MIS_HAD_TRANSMISSION);
return has_transmission ? M_1_2PI_F * 0.5f : pdf_cos_hemisphere(N, D);
}
ccl_device_forceinline void spot_light_mnee_sample_update(const ccl_global KernelLight *klight,
ccl_private LightSample *ls,
const float3 P)
const float3 P,
const float3 N,
const uint32_t path_flag)
{
ls->D = normalize_len(ls->P - P, &ls->t);
ls->Ng = -ls->D;
float2 uv = map_to_sphere(ls->Ng);
ls->u = uv.x;
ls->v = uv.y;
const float3 local_ray = spot_light_to_local(&klight->spot, -ls->D);
ls->eval_fac = klight->spot.eval_fac;
float invarea = klight->spot.invarea;
ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
/* NOTE : preserve pdf in area measure. */
ls->pdf = invarea;
const float radius = klight->spot.radius;
/* spot light attenuation */
ls->eval_fac *= spot_light_attenuation(&klight->spot, ls->Ng);
if (radius > 0) {
const float d_sq = len_squared(P - klight->co);
const float r_sq = sqr(radius);
const float t_sq = sqr(ls->t);
ls->pdf = spot_light_pdf(klight->spot.cos_half_spot_angle, d_sq, r_sq, N, ls->D, path_flag);
/* NOTE : preserve pdf in area measure. */
ls->pdf *= 0.5f * fabsf(d_sq - r_sq - t_sq) / (radius * ls->t * t_sq);
ls->Ng = normalize(ls->P - klight->co);
if (d_sq > r_sq) {
ls->eval_fac *= spot_light_attenuation(&klight->spot, local_ray);
}
}
else {
ls->Ng = -ls->D;
ls->eval_fac *= spot_light_attenuation(&klight->spot, local_ray);
/* PDF does not change. */
}
spot_light_uv(local_ray, klight->spot.half_cot_half_spot_angle, &ls->u, &ls->v);
}
ccl_device_inline bool spot_light_intersect(const ccl_global KernelLight *klight,
const ccl_private Ray *ccl_restrict ray,
ccl_private float *t)
{
/* Spot/Disk light. */
const float3 lightP = klight->co;
const float radius = klight->spot.radius;
if (radius == 0.0f) {
return false;
}
/* disk oriented normal */
const float3 lightN = normalize(ray->P - lightP);
/* One sided. */
if (dot(ray->D, lightN) >= 0.0f) {
if (dot(ray->D, ray->P - klight->co) >= 0.0f) {
return false;
}
float3 P;
return ray_disk_intersect(ray->P, ray->D, ray->tmin, ray->tmax, lightP, lightN, radius, &P, t);
return point_light_intersect(klight, ray, t);
}
ccl_device_inline bool spot_light_sample_from_intersection(
@ -105,35 +196,27 @@ ccl_device_inline bool spot_light_sample_from_intersection(
ccl_private const Intersection *ccl_restrict isect,
const float3 ray_P,
const float3 ray_D,
const float3 N,
const uint32_t path_flag,
ccl_private LightSample *ccl_restrict ls)
{
/* the normal of the oriented disk */
const float3 lightN = normalize(ray_P - klight->co);
/* We set the light normal to the outgoing direction to support texturing. */
ls->Ng = -ls->D;
const float d_sq = len_squared(ray_P - klight->co);
const float r_sq = sqr(klight->spot.radius);
float invarea = klight->spot.invarea;
ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
ls->pdf = invarea;
ls->pdf = spot_light_pdf(klight->spot.cos_half_spot_angle, d_sq, r_sq, N, ray_D, path_flag);
/* spot light attenuation */
ls->eval_fac *= spot_light_attenuation(&klight->spot, -ls->D);
if (ls->eval_fac == 0.0f) {
const float3 local_ray = spot_light_to_local(&klight->spot, -ray_D);
ls->eval_fac = klight->spot.eval_fac;
if (d_sq > r_sq) {
ls->eval_fac *= spot_light_attenuation(&klight->spot, local_ray);
}
if (ls->eval_fac == 0) {
return false;
}
float2 uv = map_to_sphere(ls->Ng);
ls->u = uv.x;
ls->v = uv.y;
ls->Ng = r_sq > 0 ? normalize(ls->P - klight->co) : -ray_D;
/* compute pdf */
if (ls->t != FLT_MAX) {
ls->pdf *= lamp_light_pdf(lightN, -ls->D, ls->t);
}
else {
ls->pdf = 0.f;
}
spot_light_uv(local_ray, klight->spot.half_cot_half_spot_angle, &ls->u, &ls->v);
return true;
}
@ -146,18 +229,20 @@ ccl_device_forceinline bool spot_light_tree_parameters(const ccl_global KernelLi
ccl_private float2 &distance,
ccl_private float3 &point_to_centroid)
{
float min_distance;
const float3 point_to_centroid_ = safe_normalize_len(centroid - P, &min_distance);
float dist_point_to_centroid;
const float3 point_to_centroid_ = safe_normalize_len(centroid - P, &dist_point_to_centroid);
const float radius = klight->spot.radius;
const float hypotenus = sqrtf(sqr(radius) + sqr(min_distance));
cos_theta_u = min_distance / hypotenus;
cos_theta_u = (dist_point_to_centroid > radius) ? cos_from_sin(radius / dist_point_to_centroid) :
-1.0f;
if (in_volume_segment) {
return true;
}
distance = make_float2(hypotenus, min_distance);
distance = (dist_point_to_centroid > radius) ?
dist_point_to_centroid * make_float2(1.0f / cos_theta_u, 1.0f) :
one_float2() * radius / M_SQRT2_F;
point_to_centroid = point_to_centroid_;
return true;

View File

@ -75,7 +75,7 @@
float fractal_voronoi_distance_to_edge(VoronoiParams params, T coord) \
{ \
float amplitude = 1.0; \
float max_amplitude = 0.5 + 0.5 * params.randomness; \
float max_amplitude = params.max_distance; \
float scale = 1.0; \
float distance = 8.0; \
\
@ -89,7 +89,7 @@
break; \
} \
else if (i <= params.detail) { \
max_amplitude = mix(max_amplitude, (0.5 + 0.5 * params.randomness) / scale, amplitude); \
max_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude); \
distance = mix(distance, min(distance, octave_distance / scale), amplitude); \
scale *= params.lacunarity; \
amplitude *= params.roughness; \
@ -97,8 +97,7 @@
else { \
float remainder = params.detail - floor(params.detail); \
if (remainder != 0.0) { \
float lerp_amplitude = mix( \
max_amplitude, (0.5 + 0.5 * params.randomness) / scale, amplitude); \
float lerp_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude); \
max_amplitude = mix(max_amplitude, lerp_amplitude, remainder); \
float lerp_distance = mix(distance, min(distance, octave_distance / scale), amplitude); \
distance = mix(distance, min(distance, lerp_distance), remainder); \

View File

@ -53,6 +53,7 @@ shader node_voronoi_texture(
coord *= Scale;
if (feature == "distance_to_edge") {
params.max_distance = 0.5 + 0.5 * params.randomness;
if (dimensions == "1D") {
Distance = fractal_voronoi_distance_to_edge(params, w);
}

View File

@ -133,14 +133,35 @@ ccl_device_inline void sample_uniform_cone_concentric(const float3 N,
ccl_private float *pdf)
{
if (one_minus_cos_angle > 0) {
/* Map random number from 2D to 1D. */
/* Remap radius to get a uniform distribution w.r.t. solid angle on the cone.
* The logic to derive this mapping is as follows:
*
* Sampling a cone is comparable to sampling the hemisphere, we just restrict theta. Therefore,
* the same trick of first sampling the unit disk and the projecting the result up towards the
* hemisphere by calculating the appropriate z coordinate still works.
*
* However, by itself this results in cosine-weighted hemisphere sampling, so we need some kind
* of remapping. Cosine-weighted hemisphere and uniform cone sampling have the same conditional
* PDF for phi (both are constant), so we only need to think about theta, which corresponds
* directly to the radius.
*
* To find this mapping, we consider the simplest sampling strategies for cosine-weighted
* hemispheres and uniform cones. In both, phi is chosen as 2pi * random(). For the former,
* r_disk(rand) = sqrt(rand). This is just naive disk sampling, since the projection to the
* hemisphere doesn't change the radius. For the latter, r_cone(rand) =
* sin_from_cos(mix(cos_angle, 1, rand)).
*
* So, to remap, we just invert r_disk `(-> rand(r_disk) = r_disk^2)` and insert it into
* r_cone: `r_cone(r_disk) = r_cone(rand(r_disk)) = sin_from_cos(mix(cos_angle, 1, r_disk^2))`.
* In practice, we need to replace `rand` with `1 - rand` to preserve the stratification,
* but since it's uniform, that's fine. */
float2 xy = concentric_sample_disk(rand);
const float r2 = len_squared(xy);
/* Equivalent to `mix(cos_angle, 1.0f, 1.0f - r2)` */
*cos_theta = 1.0f - r2 * one_minus_cos_angle;
/* Equivalent to `xy *= sin_theta / sqrt(r2); */
/* Remap disk radius to cone radius, equivalent to `xy *= sin_theta / sqrt(r2); */
xy *= safe_sqrtf(one_minus_cos_angle * (2.0f - one_minus_cos_angle * r2));
float3 T, B;

View File

@ -926,7 +926,7 @@ ccl_device float fractal_voronoi_distance_to_edge(ccl_private const VoronoiParam
const T coord)
{
float amplitude = 1.0f;
float max_amplitude = 0.5f + 0.5f * params.randomness;
float max_amplitude = params.max_distance;
float scale = 1.0f;
float distance = 8.0f;
@ -941,7 +941,7 @@ ccl_device float fractal_voronoi_distance_to_edge(ccl_private const VoronoiParam
break;
}
else if (i <= params.detail) {
max_amplitude = mix(max_amplitude, (0.5f + 0.5f * params.randomness) / scale, amplitude);
max_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude);
distance = mix(distance, min(distance, octave_distance / scale), amplitude);
scale *= params.lacunarity;
amplitude *= params.roughness;
@ -949,8 +949,7 @@ ccl_device float fractal_voronoi_distance_to_edge(ccl_private const VoronoiParam
else {
float remainder = params.detail - floorf(params.detail);
if (remainder != 0.0f) {
float lerp_amplitude = mix(
max_amplitude, (0.5f + 0.5f * params.randomness) / scale, amplitude);
float lerp_amplitude = mix(max_amplitude, params.max_distance / scale, amplitude);
max_amplitude = mix(max_amplitude, lerp_amplitude, remainder);
float lerp_distance = mix(distance, min(distance, octave_distance / scale), amplitude);
distance = mix(distance, min(distance, lerp_distance), remainder);
@ -1053,6 +1052,7 @@ ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg,
switch (params.feature) {
case NODE_VORONOI_DISTANCE_TO_EDGE: {
float distance = 0.0f;
params.max_distance = 0.5f + 0.5f * params.randomness;
switch (dimensions) {
case 1:
distance = fractal_voronoi_distance_to_edge(params, w);

View File

@ -1353,12 +1353,13 @@ typedef struct KernelSpotLight {
packed_float3 scaled_axis_u;
float radius;
packed_float3 scaled_axis_v;
float invarea;
float eval_fac;
packed_float3 dir;
float cos_half_spot_angle;
float half_cot_half_spot_angle;
float inv_len_z;
float spot_smooth;
float pad[2];
float pad;
} KernelSpotLight;
/* PointLight is SpotLight with only radius and invarea being used. */
@ -1376,10 +1377,12 @@ typedef struct KernelAreaLight {
} KernelAreaLight;
typedef struct KernelDistantLight {
float radius;
float cosangle;
float invarea;
float pad;
float angle;
float one_minus_cosangle;
float half_inv_sin_half_angle;
float pdf;
float eval_fac;
float pad[3];
} KernelDistantLight;
typedef struct KernelLight {

View File

@ -1152,9 +1152,13 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
float3 axis_v = normalize_len(extentv, &len_v);
float area = len_u * len_v;
if (light->ellipse) {
area *= -M_PI_4_F;
area *= M_PI_4_F;
}
float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
if (light->ellipse) {
/* Negative inverse area indicates ellipse. */
invarea = -invarea;
}
float3 dir = light->dir;
dir = safe_normalize(dir);
@ -1210,42 +1214,46 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
klights[light_index].strength[1] = light->strength.y;
klights[light_index].strength[2] = light->strength.z;
if (light->light_type == LIGHT_POINT) {
if (light->light_type == LIGHT_POINT || light->light_type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT;
float radius = light->size;
/* TODO: `invarea` was used for disk sampling, with the current solid angle sampling this
* becomes unnecessary. We could store `eval_fac` instead, but currently it shares the same
* #KernelSpotLight type with #LIGHT_SPOT, so keep it know until refactor for spot light. */
float invarea = (light->normalize && radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) :
1.0f;
float invarea = (radius == 0.0f) ? 1.0f / 4.0f :
(light->normalize) ? 1.0f / (4.0f * M_PI_F * radius * radius) :
1.0f;
/* Convert radiant flux to radiance or radiant intensity. */
float eval_fac = invarea * M_1_PI_F;
if (light->use_mis && radius > 0.0f)
shader_id |= SHADER_USE_MIS;
klights[light_index].co = co;
klights[light_index].spot.radius = radius;
klights[light_index].spot.invarea = invarea;
klights[light_index].spot.eval_fac = eval_fac;
}
else if (light->light_type == LIGHT_DISTANT) {
shader_id &= ~SHADER_AREA_LIGHT;
float3 dir = safe_normalize(light->dir);
float angle = light->angle / 2.0f;
float radius = tanf(angle);
float cosangle = cosf(angle);
float area = M_PI_F * radius * radius;
float invarea = (light->normalize && area > 0.0f) ? 1.0f / area : 1.0f;
float3 dir = light->dir;
dir = safe_normalize(dir);
if (light->use_mis && area > 0.0f)
if (light->use_mis && angle > 0.0f) {
shader_id |= SHADER_USE_MIS;
}
const float one_minus_cosangle = 2.0f * sqr(sinf(0.5f * angle));
const float pdf = (angle > 0.0f) ? (M_1_2PI_F / one_minus_cosangle) : 1.0f;
klights[light_index].co = dir;
klights[light_index].distant.invarea = invarea;
klights[light_index].distant.radius = radius;
klights[light_index].distant.cosangle = cosangle;
klights[light_index].distant.angle = angle;
klights[light_index].distant.one_minus_cosangle = one_minus_cosangle;
klights[light_index].distant.pdf = pdf;
klights[light_index].distant.eval_fac = (light->normalize && angle > 0) ?
M_1_PI_F / sqr(sinf(angle)) :
1.0f;
klights[light_index].distant.half_inv_sin_half_angle = 0.5f / sinf(0.5f * angle);
}
else if (light->light_type == LIGHT_BACKGROUND) {
uint visibility = scene->background->get_visibility();
@ -1277,9 +1285,13 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
float3 axis_v = normalize_len(extentv, &len_v);
float area = len_u * len_v;
if (light->ellipse) {
area *= -M_PI_4_F;
area *= M_PI_4_F;
}
float invarea = (light->normalize && area != 0.0f) ? 1.0f / area : 1.0f;
if (light->ellipse) {
/* Negative inverse area indicates ellipse. */
invarea = -invarea;
}
float3 dir = light->dir;
const float half_spread = 0.5f * light->spread;
@ -1306,9 +1318,7 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
klights[light_index].area.tan_half_spread = tan_half_spread;
klights[light_index].area.normalize_spread = normalize_spread;
}
else if (light->light_type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT;
if (light->light_type == LIGHT_SPOT) {
/* Scale axes to accommodate non-uniform scaling. */
float3 scaled_axis_u = light->axisu / len_squared(light->axisu);
float3 scaled_axis_v = light->axisv / len_squared(light->axisv);
@ -1316,22 +1326,14 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
/* Keep direction normalized. */
float3 dir = safe_normalize_len(light->dir, &len_z);
float radius = light->size;
float invarea = (light->normalize && radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) :
1.0f;
float cos_half_spot_angle = cosf(light->spot_angle * 0.5f);
float spot_smooth = 1.0f / ((1.0f - cos_half_spot_angle) * light->spot_smooth);
if (light->use_mis && radius > 0.0f)
shader_id |= SHADER_USE_MIS;
klights[light_index].co = co;
klights[light_index].spot.scaled_axis_u = scaled_axis_u;
klights[light_index].spot.radius = radius;
klights[light_index].spot.scaled_axis_v = scaled_axis_v;
klights[light_index].spot.invarea = invarea;
klights[light_index].spot.dir = dir;
klights[light_index].spot.cos_half_spot_angle = cos_half_spot_angle;
klights[light_index].spot.half_cot_half_spot_angle = 0.5f / tanf(light->spot_angle * 0.5f);
klights[light_index].spot.inv_len_z = 1.0f / len_z;
klights[light_index].spot.spot_smooth = spot_smooth;
}

View File

@ -76,6 +76,7 @@ class Light : public Node {
NODE_SOCKET_API(uint64_t, light_set_membership);
NODE_SOCKET_API(uint64_t, shadow_set_membership);
/* Normalize power by the surface area of the light. */
NODE_SOCKET_API(bool, normalize)
void tag_update(Scene *scene);

View File

@ -167,7 +167,8 @@ LightTreeEmitter::LightTreeEmitter(Scene *scene,
measure.bbox.grow(centroid - half_extentu + half_extentv);
measure.bbox.grow(centroid - half_extentu - half_extentv);
strength *= 0.25f; /* eval_fac scaling in `area.h` */
/* Convert irradiance to radiance. */
strength *= M_1_PI_F;
}
else if (type == LIGHT_POINT) {
measure.bcone.theta_o = M_PI_F;

View File

@ -34,7 +34,7 @@ void PointCloud::Point::bounds_grow(const float4 &point, BoundBox &bounds) const
float4 PointCloud::Point::motion_key(const float3 *points,
const float *radius,
const float3 *point_steps,
const float4 *point_steps,
size_t num_points,
size_t num_steps,
float time,
@ -56,7 +56,7 @@ float4 PointCloud::Point::motion_key(const float3 *points,
float4 PointCloud::Point::point_for_step(const float3 *points,
const float *radius,
const float3 *point_steps,
const float4 *point_steps,
size_t num_points,
size_t num_steps,
size_t step,
@ -73,10 +73,7 @@ float4 PointCloud::Point::point_for_step(const float3 *points,
step--;
}
const size_t offset = step * num_points;
return make_float4(point_steps[offset + p].x,
point_steps[offset + p].y,
point_steps[offset + p].z,
radius[offset + p]);
return point_steps[offset + p];
}
}
@ -189,10 +186,10 @@ void PointCloud::compute_bounds()
Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if (use_motion_blur && attr) {
size_t steps_size = points.size() * (motion_steps - 1);
float3 *point_steps = attr->data_float3();
float4 *point_steps = attr->data_float4();
for (size_t i = 0; i < steps_size; i++)
bnds.grow(point_steps[i]);
bnds.grow(float4_to_float3(point_steps[i]), point_steps[i].w);
}
if (!bnds.valid()) {
@ -204,10 +201,10 @@ void PointCloud::compute_bounds()
if (use_motion_blur && attr) {
size_t steps_size = points.size() * (motion_steps - 1);
float3 *point_steps = attr->data_float3();
float4 *point_steps = attr->data_float4();
for (size_t i = 0; i < steps_size; i++)
bnds.grow_safe(point_steps[i]);
bnds.grow_safe(float4_to_float3(point_steps[i]), point_steps[i].w);
}
}
}

View File

@ -28,14 +28,14 @@ class PointCloud : public Geometry {
float4 motion_key(const float3 *points,
const float *radius,
const float3 *point_steps,
const float4 *point_steps,
size_t num_points,
size_t num_steps,
float time,
size_t p) const;
float4 point_for_step(const float3 *points,
const float *radius,
const float3 *point_steps,
const float4 *point_steps,
size_t num_points,
size_t num_steps,
size_t step,

View File

@ -774,39 +774,38 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
if (shader->reference_count()) {
CompilerState state(graph);
if (clin->link) {
bool generate = false;
switch (type) {
case SHADER_TYPE_SURFACE: /* generate surface shader */
generate = true;
switch (type) {
case SHADER_TYPE_SURFACE: /* generate surface shader */
find_aov_nodes_and_dependencies(state.aov_nodes, graph, &state);
if (clin->link || state.aov_nodes.size() > 0) {
shader->has_surface = true;
state.node_feature_mask = KERNEL_FEATURE_NODE_MASK_SURFACE;
break;
case SHADER_TYPE_VOLUME: /* generate volume shader */
generate = true;
}
break;
case SHADER_TYPE_VOLUME: /* generate volume shader */
if (clin->link) {
shader->has_volume = true;
state.node_feature_mask = KERNEL_FEATURE_NODE_MASK_VOLUME;
break;
case SHADER_TYPE_DISPLACEMENT: /* generate displacement shader */
generate = true;
}
break;
case SHADER_TYPE_DISPLACEMENT: /* generate displacement shader */
if (clin->link) {
shader->has_displacement = true;
state.node_feature_mask = KERNEL_FEATURE_NODE_MASK_DISPLACEMENT;
break;
case SHADER_TYPE_BUMP: /* generate bump shader */
generate = true;
state.node_feature_mask = KERNEL_FEATURE_NODE_MASK_BUMP;
break;
default:
break;
}
if (generate) {
if (type == SHADER_TYPE_SURFACE) {
find_aov_nodes_and_dependencies(state.aov_nodes, graph, &state);
}
generate_multi_closure(clin->link->parent, clin->link->parent, &state);
}
break;
case SHADER_TYPE_BUMP: /* generate bump shader */
if (clin->link) {
state.node_feature_mask = KERNEL_FEATURE_NODE_MASK_BUMP;
}
break;
default:
break;
}
if (clin->link) {
generate_multi_closure(clin->link->parent, clin->link->parent, &state);
}
/* compile output node */

View File

@ -336,6 +336,12 @@ ccl_device float fast_atan2f(float y, float x)
return copysignf(r, y);
}
/* Same as precise_angle, but using fast_atan2f. Still much better that acos(dot(a, b)). */
ccl_device_inline float vector_angle(float3 a, float3 b)
{
return 2.0f * fast_atan2f(len(a - b), len(a + b));
}
/* Based on:
*
* https://github.com/LiraNuna/glsl-sse2/blob/master/source/vec4.h

View File

@ -97,8 +97,12 @@ GHOST_TSuccess GHOST_DisplayManager::findMatch(uint8_t display,
GHOST_ASSERT(m_settingsInitialized,
"GHOST_DisplayManager::findMatch(): m_settingsInitialized=false");
int criteria[4] = {
int(setting.xPixels), int(setting.yPixels), int(setting.bpp), int(setting.frequency)};
const int criteria[4] = {
int(setting.xPixels),
int(setting.yPixels),
int(setting.bpp),
int(setting.frequency),
};
int capabilities[4];
double field, score;
double best = 1e12; /* A big number. */

View File

@ -6097,8 +6097,8 @@ static GHOST_TSuccess getCursorPositionClientRelative_impl(
y = wl_fixed_to_int(win->wl_fixed_to_window(xy_wrap[1]));
}
else {
x = win->wl_fixed_to_window(seat_state_pointer->xy[0]);
y = win->wl_fixed_to_window(seat_state_pointer->xy[1]);
x = wl_fixed_to_int(win->wl_fixed_to_window(seat_state_pointer->xy[0]));
y = wl_fixed_to_int(win->wl_fixed_to_window(seat_state_pointer->xy[1]));
}
return GHOST_kSuccess;

View File

@ -35,7 +35,7 @@ set(SRC
)
set(LIB
PRIVATE bf_intern_atomic
PRIVATE bf::intern::atomic
)
if(WIN32 AND NOT UNIX)

View File

@ -564,8 +564,7 @@ class CLIP_OT_setup_tracking_scene(Operator):
world = bpy.data.worlds.new(name="World")
scene.world = world
# Having AO enabled is nice for shadow catcher.
world.light_settings.use_ambient_occlusion = True
# Setup ambient occlusion parameters for convenience.
world.light_settings.distance = 1.0
if hasattr(scene, "cycles"):
world.light_settings.ao_factor = 0.05

View File

@ -111,6 +111,10 @@ class DATA_PT_lightprobe_eevee_next(DataButtonsPanel, Panel):
col.prop(probe, "grid_bake_samples")
col.prop(probe, "surfel_density")
elif probe.type == 'CUBEMAP':
col = layout.column()
col.prop(probe, "resolution")
elif probe.type == 'PLANAR':
# Currently unsupported
pass

View File

@ -124,7 +124,7 @@ class MESH_UL_shape_keys(UIList):
row = split.row(align=True)
row.emboss = 'NONE_OR_STATUS'
if key_block.mute or (obj.mode == 'EDIT' and not (obj.use_shape_key_edit_mode and obj.type == 'MESH')):
row.active = False
split.active = False
if not item.id_data.use_relative:
row.prop(key_block, "frame", text="")
elif index > 0:

View File

@ -148,6 +148,27 @@ class EEVEE_WORLD_PT_volume(WorldButtonsPanel, Panel):
layout.label(text="No output node")
class EEVEE_WORLD_PT_probe(WorldButtonsPanel, Panel):
bl_label = "Probe"
bl_translation_context = i18n_contexts.id_id
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE_NEXT'}
@classmethod
def poll(cls, context):
engine = context.engine
world = context.world
return world and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
world = context.world
layout.use_property_split = True
layout.prop(world, "probe_resolution")
class WORLD_PT_viewport_display(WorldButtonsPanel, Panel):
bl_label = "Viewport Display"
bl_options = {'DEFAULT_CLOSED'}
@ -169,6 +190,7 @@ classes = (
EEVEE_WORLD_PT_surface,
EEVEE_WORLD_PT_volume,
EEVEE_WORLD_PT_mist,
EEVEE_WORLD_PT_probe,
WORLD_PT_viewport_display,
WORLD_PT_custom_props,
)

View File

@ -246,7 +246,7 @@ struct Mesh *editbmesh_get_eval_cage_from_orig(struct Depsgraph *depsgraph,
struct Object *obedit,
const struct CustomData_MeshMasks *dataMask);
float (*editbmesh_vert_coords_alloc(struct BMEditMesh *em, int *r_vert_len))[3];
float (*editbmesh_vert_coords_alloc(struct BMEditMesh *em))[3];
bool editbmesh_modifier_is_enabled(const struct Scene *scene,
const struct Object *ob,
struct ModifierData *md,

View File

@ -40,8 +40,9 @@ struct bAction *BKE_action_add(struct Main *bmain, const char name[]);
/* Action API ----------------- */
/* types of transforms applied to the given item
* - these are the return flags for action_get_item_transforms()
/**
* Types of transforms applied to the given item:
* - these are the return flags for #BKE_action_get_item_transform_flags()
*/
typedef enum eAction_TransformFlags {
/* location */
@ -69,24 +70,29 @@ typedef enum eAction_TransformFlags {
* - if 'curves' is provided, a list of links to these curves are also returned
* whose nodes WILL NEED FREEING.
*/
short action_get_item_transforms(struct bAction *act,
struct Object *ob,
struct bPoseChannel *pchan,
ListBase *curves);
eAction_TransformFlags BKE_action_get_item_transform_flags(struct bAction *act,
struct Object *ob,
struct bPoseChannel *pchan,
ListBase *curves);
/**
* Calculate the extents of given action.
*/
void calc_action_range(const struct bAction *act, float *start, float *end, short incl_modifiers);
void BKE_action_frame_range_calc(const struct bAction *act,
bool include_modifiers,
float *r_start,
float *r_end);
/* Retrieve the intended playback frame range, using the manually set range if available,
* or falling back to scanning F-Curves for their first & last frames otherwise. */
void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float *r_end);
/**
* Retrieve the intended playback frame range, using the manually set range if available,
* or falling back to scanning F-Curves for their first & last frames otherwise.
*/
void BKE_action_frame_range_get(const struct bAction *act, float *r_start, float *r_end);
/**
* Check if the given action has any keyframes.
*/
bool action_has_motion(const struct bAction *act);
bool BKE_action_has_motion(const struct bAction *act);
/**
* Is the action configured as cyclic.

View File

@ -27,7 +27,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 8
#define BLENDER_FILE_SUBVERSION 9
/* 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

View File

@ -1,40 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*/
#ifdef __cplusplus
extern "C" {
#endif
struct BMEditMesh;
typedef struct EditMeshData {
/** when set, \a vertexNos, polyNos are lazy initialized */
const float (*vertexCos)[3];
/** lazy initialize (when \a vertexCos is set) */
float const (*vertexNos)[3];
float const (*polyNos)[3];
/** also lazy init but don't depend on \a vertexCos */
const float (*polyCos)[3];
} EditMeshData;
void BKE_editmesh_cache_ensure_poly_normals(struct BMEditMesh *em, EditMeshData *emd);
void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, EditMeshData *emd);
void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, EditMeshData *emd);
bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em,
EditMeshData *emd,
float min[3],
float max[3]);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,29 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*/
struct BMEditMesh;
struct EditMeshData {
/** when set, \a vertexNos, polyNos are lazy initialized */
float (*vertexCos)[3];
/** lazy initialize (when \a vertexCos is set) */
float const (*vertexNos)[3];
float const (*polyNos)[3];
/** also lazy init but don't depend on \a vertexCos */
const float (*polyCos)[3];
};
void BKE_editmesh_cache_ensure_poly_normals(BMEditMesh *em, EditMeshData *emd);
void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh *em, EditMeshData *emd);
void BKE_editmesh_cache_ensure_poly_centers(BMEditMesh *em, EditMeshData *emd);
bool BKE_editmesh_cache_calc_minmax(BMEditMesh *em, EditMeshData *emd, float min[3], float max[3]);

View File

@ -133,6 +133,11 @@ class TreeNode : public ::GreasePencilLayerTreeNode {
* \note This results in undefined behavior if the node is not a Layer.
*/
Layer &as_layer_for_write();
/**
* \returns the parent layer group or nullptr for the root group.
*/
LayerGroup *parent_group() const;
};
/**
@ -296,6 +301,12 @@ class LayerGroup : public ::GreasePencilLayerTreeGroup {
bool is_visible() const;
bool is_locked() const;
/**
* \returns the group as a `TreeNode`.
*/
const TreeNode &as_node() const;
TreeNode &as_node();
/**
* Adds a group at the end of this group.
*/
@ -317,14 +328,14 @@ class LayerGroup : public ::GreasePencilLayerTreeGroup {
/**
* Adds a layer before \a link and returns it.
*/
Layer &add_layer_before(Layer *layer, Layer *link);
Layer &add_layer_before(StringRefNull name, Layer *link);
Layer &add_layer_before(Layer *layer, TreeNode *link);
Layer &add_layer_before(StringRefNull name, TreeNode *link);
/**
* Adds a layer after \a link and returns it.
*/
Layer &add_layer_after(Layer *layer, Layer *link);
Layer &add_layer_after(StringRefNull name, Layer *link);
Layer &add_layer_after(Layer *layer, TreeNode *link);
Layer &add_layer_after(StringRefNull name, TreeNode *link);
/**
* Returns the number of direct nodes in this group.
@ -340,7 +351,7 @@ class LayerGroup : public ::GreasePencilLayerTreeGroup {
* Tries to unlink the layer from the list of nodes in this group.
* \returns true, if the layer was successfully unlinked.
*/
bool unlink_layer(Layer *link);
bool unlink_node(TreeNode *link);
/**
* Returns a `Span` of pointers to all the `TreeNode`s in this group.
@ -382,6 +393,15 @@ class LayerGroup : public ::GreasePencilLayerTreeGroup {
void tag_nodes_cache_dirty() const;
};
inline const TreeNode &LayerGroup::as_node() const
{
return *reinterpret_cast<const TreeNode *>(this);
}
inline TreeNode &LayerGroup::as_node()
{
return *reinterpret_cast<TreeNode *>(this);
}
inline const TreeNode &Layer::as_node() const
{
return *reinterpret_cast<const TreeNode *>(this);

View File

@ -50,7 +50,7 @@ enum {
IDWALK_CB_DIRECT_WEAK_LINK = (1 << 3),
/**
* That ID is used as mere sub-data by its owner (only case currently: those root nodetrees in
* That ID is used as mere sub-data by its owner (only case currently: those root node-trees in
* materials etc., and the Scene's master collections).
* This means callback shall not *do* anything, only use this as informative data if it needs it.
*/

View File

@ -15,11 +15,6 @@ struct Mesh;
extern "C" {
#endif
struct Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(
struct BMEditMesh *em,
const struct CustomData_MeshMasks *cd_mask_extra,
const float (*vert_coords)[3],
const struct Mesh *me_settings);
struct Mesh *BKE_mesh_wrapper_from_editmesh(struct BMEditMesh *em,
const struct CustomData_MeshMasks *cd_mask_extra,
const struct Mesh *me_settings);
@ -31,6 +26,20 @@ int BKE_mesh_wrapper_edge_len(const struct Mesh *me);
int BKE_mesh_wrapper_loop_len(const struct Mesh *me);
int BKE_mesh_wrapper_poly_len(const struct Mesh *me);
/**
* Return a contiguous array of vertex position values, if available.
* Otherwise, vertex positions are stored in BMesh vertices.
*/
const float (*BKE_mesh_wrapper_vert_coords(const struct Mesh *mesh))[3];
/**
* Return a contiguous array of face normal values, if available.
* Otherwise, normals are stored in BMesh faces.
*/
const float (*BKE_mesh_wrapper_poly_normals(struct Mesh *mesh))[3];
void BKE_mesh_wrapper_tag_positions_changed(struct Mesh *mesh);
void BKE_mesh_wrapper_vert_coords_copy(const struct Mesh *me,
float (*vert_coords)[3],
int vert_coords_len);

View File

@ -187,10 +187,9 @@ typedef struct ModifierTypeInfo {
/********************* Deform modifier functions *********************/
/**
* Only for deform types, should apply the deformation
* to the given vertex array. If the deformer requires information from
* the object it can obtain it from the mesh argument if non-NULL,
* and otherwise the ob argument.
* Apply a deformation to the positions in the \a vertexCos array. If the \a mesh argument is
* non-null, if will contain proper (not wrapped) mesh data. The \a vertexCos array may or may
* not be the same as the mesh's position attribute.
*/
void (*deformVerts)(struct ModifierData *md,
const struct ModifierEvalContext *ctx,
@ -208,7 +207,8 @@ typedef struct ModifierTypeInfo {
float (*defMats)[3][3],
int numVerts);
/**
* Like deformVerts but called during editmode (for supporting modifiers)
* Like deformVerts but called during edit-mode if supported. The \a mesh argument might be a
* wrapper around edit BMesh data.
*/
void (*deformVertsEM)(struct ModifierData *md,
const struct ModifierEvalContext *ctx,

View File

@ -818,7 +818,9 @@ void node_type_storage(struct bNodeType *ntype,
/** \} */
/* ************** COMMON NODES *************** */
/* -------------------------------------------------------------------- */
/** \name Common Node Types
* \{ */
#define NODE_UNDEFINED -2 /* node type is not registered */
#define NODE_CUSTOM -1 /* for dynamically registered custom types */
@ -845,7 +847,7 @@ void node_type_storage(struct bNodeType *ntype,
*
* - nodetree:
* The actual bNodeTree data block.
* Check nodetree->idname or nodetree->typeinfo to use only specific types.
* Check `nodetree->idname` or `nodetree->typeinfo` to use only specific types.
*
* - id:
* The owner of the bNodeTree data block.

View File

@ -271,8 +271,15 @@ bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
/**
* For orthographic cameras, project the far away ray segment points to the root node so
* we can have better precision.
*
* Note: the interval is not guaranteed to lie between ray_start and ray_end; this is
* not necessary for orthographic views and is impossible anyhow due to the necessity of
* projecting the far clipping plane into the local object space. This works out to
* dividing view3d->clip_end by the object scale, which for small object and large
* clip_end's can easily lead to floating-point overflows.
*
*/
void BKE_pbvh_raycast_project_ray_root(
void BKE_pbvh_clip_ray_ortho(
PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]);
void BKE_pbvh_find_nearest_to_ray(PBVH *pbvh,

View File

@ -47,7 +47,7 @@ set(INC
set(INC_SYS
${ZLIB_INCLUDE_DIRS}
# For `vfontdata_freetype.c`.
# For `vfontdata_freetype.cc`.
${FREETYPE_INCLUDE_DIRS}
)
@ -306,8 +306,8 @@ set(SRC
intern/type_conversions.cc
intern/undo_system.cc
intern/unit.c
intern/vfont.c
intern/vfontdata_freetype.c
intern/vfont.cc
intern/vfontdata_freetype.cc
intern/viewer_path.cc
intern/volume.cc
intern/volume_render.cc
@ -379,7 +379,7 @@ set(SRC
BKE_editlattice.h
BKE_editmesh.h
BKE_editmesh_bvh.h
BKE_editmesh_cache.h
BKE_editmesh_cache.hh
BKE_editmesh_tangent.h
BKE_effect.h
BKE_fcurve.h
@ -557,7 +557,7 @@ set(LIB
bf_shader_fx
bf_simulation
extern_fmtlib
PRIVATE bf_intern_atomic
PRIVATE bf::intern::atomic
# For `vfontdata_freetype.c`.
${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES}
)

View File

@ -36,7 +36,7 @@
#include "BKE_colorband.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_cache.hh"
#include "BKE_geometry_set.hh"
#include "BKE_geometry_set_instances.hh"
#include "BKE_key.h"
@ -543,12 +543,10 @@ static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md,
* some point. */
BKE_mesh_wrapper_ensure_mdata(input_mesh);
/* Adds a new mesh component to the geometry set based on the #input_mesh. */
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
/* Replace only the mesh rather than the whole component, because the entire #MeshComponent
* might have been replaced by data from a different object in the node tree, which means the
* component contains vertex group name data for that object that should not be removed. */
mesh_component.replace(input_mesh, GeometryOwnershipType::Editable);
geometry_set.replace_mesh(input_mesh, GeometryOwnershipType::Editable);
/* Let the modifier change the geometry set. */
mti->modifyGeometrySet(md, &mectx, &geometry_set);
@ -1053,15 +1051,13 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
}
}
float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3]
float (*editbmesh_vert_coords_alloc(BMEditMesh *em))[3]
{
BMIter iter;
BMVert *eve;
float(*cos)[3];
int i;
*r_vert_len = em->bm->totvert;
cos = (float(*)[3])MEM_malloc_arrayN(em->bm->totvert, sizeof(float[3]), "vertexcos");
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
@ -1135,6 +1131,21 @@ static void editbmesh_calc_modifier_final_normals_or_defer(
editbmesh_calc_modifier_final_normals(mesh_final, final_datamask);
}
static float (*mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh))[3]
{
switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
if (mesh->runtime->edit_data->vertexCos == nullptr) {
mesh->runtime->edit_data->vertexCos = editbmesh_vert_coords_alloc(mesh->edit_mesh);
}
return mesh->runtime->edit_data->vertexCos;
case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD:
return reinterpret_cast<float(*)[3]>(mesh->vert_positions_for_write().data());
}
return nullptr;
}
static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
@ -1145,21 +1156,11 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
Mesh **r_final,
GeometrySet **r_geometry_set)
{
/* Input and final mesh. Final mesh is only created the moment the first
* constructive modifier is executed, or a deform modifier needs normals
* or certain data layers. */
Mesh *mesh_input = (Mesh *)ob->data;
Mesh *mesh_final = nullptr;
Mesh *mesh_cage = nullptr;
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
GeometrySet geometry_set_final;
/* TODO: Remove use of `deformed_verts` in mesh modifier stack
* since mesh positions are now stored in a contiguous array. */
float(*deformed_verts)[3] = nullptr;
int num_deformed_verts = 0;
bool isPrevDeform = false;
/* Mesh with constructive modifiers but no deformation applied. Tracked
* along with final mesh if undeformed / orco coordinates are requested
* for texturing. */
@ -1189,11 +1190,11 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
CDMaskLink *md_datamask = datamasks;
CustomData_MeshMasks append_mask = CD_MASK_BAREMESH;
/* Evaluate modifiers up to certain index to get the mesh cage. */
Mesh *mesh_final = BKE_mesh_wrapper_from_editmesh(em_input, &final_datamask, mesh_input);
int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, true);
if (r_cage && cageIndex == -1) {
mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input, &final_datamask, nullptr, mesh_input);
mesh_cage = mesh_final;
}
/* The mesh from edit mode should not have any original index layers already, since those
@ -1206,24 +1207,21 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
BKE_modifiers_clear_errors(ob);
if (ob->modifier_flag & OB_MODIFIER_FLAG_ADD_REST_POSITION) {
if (mesh_final == nullptr) {
mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, nullptr, mesh_input);
ASSERT_IS_VALID_MESH(mesh_final);
}
BKE_mesh_wrapper_ensure_mdata(mesh_final);
set_rest_position(*mesh_final);
}
bool non_deform_modifier_applied = false;
for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
if (!editbmesh_modifier_is_enabled(scene, ob, md, mesh_final != nullptr)) {
if (!editbmesh_modifier_is_enabled(scene, ob, md, non_deform_modifier_applied)) {
continue;
}
blender::bke::ScopedModifierTimer modifier_timer{*md};
/* Add an orco mesh as layer if needed by this modifier. */
if (mesh_final && mesh_orco && mti->requiredDataMask) {
if (mesh_orco && mti->requiredDataMask) {
CustomData_MeshMasks mask = {0};
mti->requiredDataMask(md, &mask);
if (mask.vmask & CD_MASK_ORCO) {
@ -1231,61 +1229,41 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
}
}
/* How to apply modifier depends on (a) what we already have as
* a result of previous modifiers (could be a mesh or just
* deformed vertices) and (b) what type the modifier is. */
if (mti->type == eModifierTypeType_OnlyDeform) {
/* No existing verts to deform, need to build them. */
if (!deformed_verts) {
if (mesh_final) {
/* Deforming a derived mesh, read the vertex locations
* out of the mesh and deform them. Once done with this
* run of deformers verts will be written back. */
deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts);
}
else {
deformed_verts = editbmesh_vert_coords_alloc(em_input, &num_deformed_verts);
}
}
else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
if (mesh_final == nullptr) {
mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, nullptr, mesh_input);
BKE_mesh_ensure_default_orig_index_customdata(mesh_final);
ASSERT_IS_VALID_MESH(mesh_final);
}
BLI_assert(deformed_verts != nullptr);
BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
if (mesh_final == mesh_cage) {
/* If the cage mesh has already been assigned, we have passed the cage index in the modifier
* list. If the cage and final meshes are still the same, duplicate the final mesh so the
* cage mesh isn't modified anymore. */
mesh_final = BKE_mesh_copy_for_eval(mesh_final);
if (mesh_cage->edit_mesh) {
mesh_final->edit_mesh = static_cast<BMEditMesh *>(MEM_dupallocN(mesh_cage->edit_mesh));
mesh_final->edit_mesh->is_shallow_copy = true;
mesh_final->runtime->is_original_bmesh = true;
BKE_mesh_runtime_ensure_edit_data(mesh_final);
}
}
if (mti->type == eModifierTypeType_OnlyDeform) {
if (mti->deformVertsEM) {
BKE_modifier_deform_vertsEM(
md, &mectx, em_input, mesh_final, deformed_verts, num_deformed_verts);
BKE_modifier_deform_vertsEM(md,
&mectx,
em_input,
mesh_final,
mesh_wrapper_vert_coords_ensure_for_write(mesh_final),
BKE_mesh_wrapper_vert_len(mesh_final));
BKE_mesh_wrapper_tag_positions_changed(mesh_final);
}
else {
BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
BKE_mesh_wrapper_ensure_mdata(mesh_final);
BKE_modifier_deform_verts(md,
&mectx,
mesh_final,
BKE_mesh_vert_positions_for_write(mesh_final),
mesh_final->totvert);
BKE_mesh_tag_positions_changed(mesh_final);
}
}
else {
/* apply vertex coordinates or build a DerivedMesh as necessary */
if (mesh_final) {
if (deformed_verts) {
Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final);
if (mesh_final != mesh_cage) {
BKE_id_free(nullptr, mesh_final);
}
mesh_final = mesh_tmp;
BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
else if (mesh_final == mesh_cage) {
/* 'me' may be changed by this modifier, so we need to copy it. */
mesh_final = BKE_mesh_copy_for_eval(mesh_final);
}
}
else {
mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input, nullptr, deformed_verts, mesh_input);
deformed_verts = nullptr;
}
non_deform_modifier_applied = true;
/* create an orco derivedmesh in parallel */
CustomData_MeshMasks mask = md_datamask->mask;
@ -1336,77 +1314,21 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
ASSERT_IS_VALID_MESH(mesh_next);
if (mesh_next) {
if (mesh_final && mesh_final != mesh_next) {
if (mesh_final != mesh_next) {
BKE_id_free(nullptr, mesh_final);
}
mesh_final = mesh_next;
if (deformed_verts) {
MEM_freeN(deformed_verts);
deformed_verts = nullptr;
}
}
mesh_final->runtime->deformed_only = false;
}
if (r_cage && i == cageIndex) {
if (mesh_final && deformed_verts) {
mesh_cage = BKE_mesh_copy_for_eval(mesh_final);
BKE_mesh_vert_coords_apply(mesh_cage, deformed_verts);
}
else if (mesh_final) {
mesh_cage = mesh_final;
}
else {
Mesh *me_orig = mesh_input;
/* Modifying the input mesh is weak, however as there can only be one object in edit mode
* even if multiple are sharing the same mesh this should be thread safe. */
if ((me_orig->id.tag & LIB_TAG_COPIED_ON_WRITE) && (ob->mode & OB_MODE_EDIT)) {
if (!BKE_mesh_runtime_ensure_edit_data(me_orig)) {
BKE_mesh_runtime_reset_edit_data(me_orig);
}
me_orig->runtime->edit_data->vertexCos = (const float(*)[3])MEM_dupallocN(
deformed_verts);
}
mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input,
&final_datamask,
deformed_verts ? (const float(*)[3])MEM_dupallocN(deformed_verts) : nullptr,
mesh_input);
}
mesh_cage = mesh_final;
}
isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
}
BLI_linklist_free((LinkNode *)datamasks, nullptr);
/* Yay, we are done. If we have a DerivedMesh and deformed vertices need
* to apply these back onto the DerivedMesh. If we have no DerivedMesh
* then we need to build one. */
if (mesh_final) {
if (deformed_verts) {
if (mesh_final == mesh_cage) {
mesh_final = BKE_mesh_copy_for_eval(mesh_final);
}
BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
}
else if (!deformed_verts && mesh_cage) {
/* cage should already have up to date normals */
mesh_final = mesh_cage;
}
else {
/* this is just a copy of the editmesh, no need to calc normals */
mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input, &final_datamask, deformed_verts, mesh_input);
deformed_verts = nullptr;
}
if (deformed_verts) {
MEM_freeN(deformed_verts);
}
/* Add orco coordinates to final and deformed mesh if requested. */
if (final_datamask.vmask & CD_MASK_ORCO) {
/* FIXME(@ideasman42): avoid the need to convert to mesh data just to add an orco layer. */

View File

@ -108,7 +108,7 @@ static void action_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src,
for (fcurve_src = action_src->curves.first; fcurve_src; fcurve_src = fcurve_src->next) {
/* Duplicate F-Curve. */
/* XXX TODO: pass subdata flag?
/* XXX TODO: pass sub-data flag?
* But surprisingly does not seem to be doing any ID reference-counting. */
fcurve_dst = BKE_fcurve_copy(fcurve_src);
@ -1334,7 +1334,7 @@ void BKE_pose_remove_group_index(bPose *pose, const int index)
/* ************** F-Curve Utilities for Actions ****************** */
bool action_has_motion(const bAction *act)
bool BKE_action_has_motion(const bAction *act)
{
FCurve *fcu;
@ -1392,7 +1392,10 @@ bool BKE_action_has_single_frame(const bAction *act)
return found_key;
}
void calc_action_range(const bAction *act, float *start, float *end, short incl_modifiers)
void BKE_action_frame_range_calc(const bAction *act,
bool include_modifiers,
float *r_start,
float *r_end)
{
FCurve *fcu;
float min = 999999999.0f, max = -999999999.0f;
@ -1419,10 +1422,10 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
foundvert = 1;
}
/* if incl_modifiers is enabled, need to consider modifiers too
/* if include_modifiers is enabled, need to consider modifiers too
* - only really care about the last modifier
*/
if ((incl_modifiers) && (fcu->modifiers.last)) {
if ((include_modifiers) && (fcu->modifiers.last)) {
FModifier *fcm = fcu->modifiers.last;
/* only use the maximum sensible limits of the modifiers if they are more extreme */
@ -1470,23 +1473,23 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
max += 1.0f;
}
*start = max_ff(min, MINAFRAMEF);
*end = min_ff(max, MAXFRAMEF);
*r_start = max_ff(min, MINAFRAMEF);
*r_end = min_ff(max, MAXFRAMEF);
}
else {
*start = 0.0f;
*end = 1.0f;
*r_start = 0.0f;
*r_end = 1.0f;
}
}
void BKE_action_get_frame_range(const bAction *act, float *r_start, float *r_end)
void BKE_action_frame_range_get(const bAction *act, float *r_start, float *r_end)
{
if (act && (act->flag & ACT_FRAME_RANGE)) {
*r_start = act->frame_start;
*r_end = act->frame_end;
}
else {
calc_action_range(act, r_start, r_end, false);
BKE_action_frame_range_calc(act, r_start, r_end, false);
}
/* Ensure that action is at least 1 frame long (for NLA strips to have a valid length). */
@ -1500,7 +1503,10 @@ bool BKE_action_is_cyclic(const bAction *act)
return act && (act->flag & ACT_FRAME_RANGE) && (act->flag & ACT_CYCLIC);
}
short action_get_item_transforms(bAction *act, Object *ob, bPoseChannel *pchan, ListBase *curves)
eAction_TransformFlags BKE_action_get_item_transform_flags(bAction *act,
Object *ob,
bPoseChannel *pchan,
ListBase *curves)
{
PointerRNA ptr;
FCurve *fcu;

View File

@ -1352,7 +1352,7 @@ void BKE_animdata_fix_paths_rename_all_ex(Main *bmain,
} \
(void)0
/* another version of this macro for nodetrees */
/* Another version of this macro for node-trees. */
#define RENAMEFIX_ANIM_NODETREE_IDS(first, NtId_Type) \
for (id = first; id; id = id->next) { \
AnimData *adt = BKE_animdata_from_id(id); \

View File

@ -3237,7 +3237,8 @@ static void animsys_create_action_track_strip(const AnimData *adt,
/* Action range is calculated taking F-Modifiers into account
* (which making new strips doesn't do due to the troublesome nature of that). */
calc_action_range(r_action_strip->act, &r_action_strip->actstart, &r_action_strip->actend, 1);
BKE_action_frame_range_calc(
r_action_strip->act, true, &r_action_strip->actstart, &r_action_strip->actend);
r_action_strip->start = r_action_strip->actstart;
r_action_strip->end = IS_EQF(r_action_strip->actstart, r_action_strip->actend) ?
(r_action_strip->actstart + 1.0f) :
@ -4002,11 +4003,11 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float
} \
(void)0
/* another macro for the "embedded" nodetree cases
* - this is like EVAL_ANIM_IDS, but this handles the case "embedded nodetrees"
* (i.e. scene/material/texture->nodetree) which we need a special exception
* for, otherwise they'd get skipped
* - 'ntp' stands for "node tree parent" = data-block where node tree stuff resides
/* Another macro for the "embedded" node-tree cases
* - This is like #EVAL_ANIM_IDS, but this handles the case "embedded node-trees"
* (i.e. `scene/material/texture->nodetree`) which we need a special exception
* for, otherwise they'd get skipped.
* - `ntp` stands for "node tree parent" = data-block where node tree stuff resides.
*/
#define EVAL_ANIM_NODETREE_IDS(first, NtId_Type, aflag) \
for (id = first; id; id = id->next) { \

View File

@ -989,9 +989,10 @@ void BKE_pchan_bbone_spline_params_get(bPoseChannel *pchan,
/* Transform previous point inside this bone space. */
if (bone->bbone_prev_type == BBONE_HANDLE_RELATIVE) {
/* Use delta movement (from restpose), and apply this relative to the current bone's head. */
/* Use delta movement (from rest-pose),
* and apply this relative to the current bone's head. */
if (rest) {
/* In restpose, arm_head == pose_head */
/* In rest-pose, arm_head == pose_head */
zero_v3(param->prev_h);
done = true;
}
@ -1043,9 +1044,10 @@ void BKE_pchan_bbone_spline_params_get(bPoseChannel *pchan,
/* Transform next point inside this bone space. */
if (bone->bbone_next_type == BBONE_HANDLE_RELATIVE) {
/* Use delta movement (from restpose), and apply this relative to the current bone's tail. */
/* Use delta movement (from rest-pose),
* and apply this relative to the current bone's tail. */
if (rest) {
/* In restpose, arm_head == pose_head */
/* In rest-pose, arm_head == pose_head */
copy_v3_fl3(param->next_h, 0.0f, param->length, 0.0);
done = true;
}
@ -1091,12 +1093,12 @@ void BKE_pchan_bbone_spline_params_get(bPoseChannel *pchan,
* - These properties allow users to hand-animate the
* bone curve/shape, without having to resort to using
* extra bones
* - The "bone" level offsets are for defining the restpose
* - The "bone" level offsets are for defining the rest-pose
* shape of the bone (e.g. for curved eyebrows for example).
* -> In the viewport, it's needed to define what the rest pose
* looks like
* -> For "rest == 0", we also still need to have it present
* so that we can "cancel out" this restpose when it comes
* so that we can "cancel out" this rest-pose when it comes
* time to deform some geometry, it won't cause double transforms.
* - The "pchan" level offsets are the ones that animators actually
* end up animating

View File

@ -415,10 +415,7 @@ void BKE_camera_params_compute_viewplane(
/* the window matrix is used for clipping, and not changed during OSA steps */
/* using an offset of +0.5 here would give clip errors on edges */
viewplane.xmin *= pixsize;
viewplane.xmax *= pixsize;
viewplane.ymin *= pixsize;
viewplane.ymax *= pixsize;
BLI_rctf_mul(&viewplane, pixsize);
/* Used for rendering (offset by near-clip with perspective views), passed to RE_SetPixelSize.
* For viewport drawing 'RegionView3D.pixsize'. */

View File

@ -1439,7 +1439,7 @@ static int followpath_get_tars(bConstraint *con, ListBase *list)
bFollowPathConstraint *data = con->data;
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints without subtargets */
/* Standard target-getting macro for single-target constraints without sub-targets. */
SINGLETARGETNS_GET_TARS(con, data->tar, ct, list);
return 1;
@ -3787,7 +3787,7 @@ static int clampto_get_tars(bConstraint *con, ListBase *list)
bClampToConstraint *data = con->data;
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints without subtargets */
/* Standard target-getting macro for single-target constraints without sub-targets. */
SINGLETARGETNS_GET_TARS(con, data->tar, ct, list);
return 1;
@ -4609,7 +4609,7 @@ static int splineik_get_tars(bConstraint *con, ListBase *list)
bSplineIKConstraint *data = con->data;
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints without subtargets */
/* Standard target-getting macro for single-target constraints without sub-targets. */
SINGLETARGETNS_GET_TARS(con, data->tar, ct, list);
return 1;

View File

@ -247,7 +247,8 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Depsgraph *depsgraph,
ModifierData *md;
Mesh *me_input = static_cast<Mesh *>(ob->data);
Mesh *me = nullptr;
int i, a, modifiers_left_num = 0, verts_num = 0;
int i, a, modifiers_left_num = 0;
const int verts_num = em->bm->totvert;
int cageIndex = BKE_modifiers_get_cage_index(scene, ob, nullptr, true);
float(*defmats)[3][3] = nullptr, (*deformedVerts)[3] = nullptr;
VirtualModifierData virtualModifierData;
@ -276,8 +277,8 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Depsgraph *depsgraph,
cd_mask_extra = datamasks->mask;
BLI_linklist_free((LinkNode *)datamasks, nullptr);
me = BKE_mesh_wrapper_from_editmesh_with_coords(em, &cd_mask_extra, nullptr, me_input);
deformedVerts = editbmesh_vert_coords_alloc(em, &verts_num);
me = BKE_mesh_wrapper_from_editmesh(em, &cd_mask_extra, me_input);
deformedVerts = editbmesh_vert_coords_alloc(em);
defmats = static_cast<float(*)[3][3]>(
MEM_mallocN(sizeof(*defmats) * verts_num, "defmats"));

View File

@ -62,7 +62,7 @@ static void init_curve_deform(const Object *ob_curve, const Object *ob_target, C
static bool calc_curve_deform(
const Object *ob_curve, float co[3], const short axis, const CurveDeform *cd, float r_quat[4])
{
Curve *cu = ob_curve->data;
const Curve *cu = ob_curve->data;
float fac, loc[4], dir[3], new_quat[4], radius;
short index;
const bool is_neg_axis = (axis > 2);

View File

@ -1029,31 +1029,31 @@ void BKE_curveprofile_evaluate_length_portion(const CurveProfile *profile,
/* Find the last point along the path with a lower length portion than the input. */
int i = 0;
float length_travelled = 0.0f;
while (length_travelled < requested_length) {
float length_traveled = 0.0f;
while (length_traveled < requested_length) {
/* Check if we reached the last point before the final one. */
if (i == BKE_curveprofile_table_size(profile) - 2) {
break;
}
float new_length = curveprofile_distance_to_next_table_point(profile, i);
if (length_travelled + new_length >= requested_length) {
if (length_traveled + new_length >= requested_length) {
break;
}
length_travelled += new_length;
length_traveled += new_length;
i++;
}
/* Now travel the remaining distance of length portion down the path to the next point and
* find the location where we stop. */
float distance_to_next_point = curveprofile_distance_to_next_table_point(profile, i);
float lerp_factor = (requested_length - length_travelled) / distance_to_next_point;
float lerp_factor = (requested_length - length_traveled) / distance_to_next_point;
#ifdef DEBUG_CURVEPROFILE_EVALUATE
printf("CURVEPROFILE EVALUATE\n");
printf(" length portion input: %f\n", double(length_portion));
printf(" requested path length: %f\n", double(requested_length));
printf(" distance to next point: %f\n", double(distance_to_next_point));
printf(" length travelled: %f\n", double(length_travelled));
printf(" length traveled: %f\n", double(length_traveled));
printf(" lerp-factor: %f\n", double(lerp_factor));
printf(" ith point (%f, %f)\n", double(profile->path[i].x), double(profile->path[i].y));
printf(" next point(%f, %f)\n", double(profile->path[i + 1].x), double(profile->path[i + 1].y));

View File

@ -60,8 +60,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, this->point_num, ATTR_POSITION.c_str());
this->attributes_for_write().add<float3>(
"position", ATTR_DOMAIN_POINT, AttributeInitConstruct());
this->runtime = MEM_new<CurvesGeometryRuntime>(__func__);

View File

@ -105,7 +105,7 @@ bool CustomData_MeshMasks_are_matching(const CustomData_MeshMasks *mask_ref,
/** \} */
/* -------------------------------------------------------------------- */
/** \name Layer Type Information
/** \name Layer Type Information Struct
* \{ */
struct LayerTypeInfo {
@ -1557,6 +1557,10 @@ static void layerDefault_propquaternion(void *data, const int count)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Layer Type Information (#LAYERTYPEINFO)
* \{ */
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */ /* DEPRECATED */
{sizeof(MVert), "MVert", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},

View File

@ -18,7 +18,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_cache.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_iterators.h"
@ -230,9 +230,9 @@ const float (*BKE_editmesh_vert_coords_when_deformed(Depsgraph *depsgraph,
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object_eval);
if ((me->runtime->edit_data != nullptr) && (me->runtime->edit_data->vertexCos != nullptr)) {
if (BKE_mesh_wrapper_vert_coords(me) != nullptr) {
/* Deformed, and we have deformed coords already. */
coords = me->runtime->edit_data->vertexCos;
coords = BKE_mesh_wrapper_vert_coords(me);
}
else if ((editmesh_eval_final != nullptr) &&
(editmesh_eval_final->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH))

View File

@ -17,7 +17,7 @@
#include "DNA_mesh_types.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h" /* own include */
#include "BKE_editmesh_cache.hh" /* own include */
/* -------------------------------------------------------------------- */
/** \name Ensure Data (derived from coords)

View File

@ -295,13 +295,11 @@ static void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
const IndexRange poly = polys[poly_index];
/* For every edge, mix values from the two adjacent corners (the current and next corner). */
for (const int i : IndexRange(poly.size())) {
const int next_i = (i + 1) % poly.size();
const int loop_i = poly.start() + i;
const int next_loop_i = poly.start() + next_i;
const int edge_index = corner_edges[loop_i];
mixer.mix_in(edge_index, old_values[loop_i]);
mixer.mix_in(edge_index, old_values[next_loop_i]);
for (const int corner : poly) {
const int next_corner = mesh::poly_corner_next(poly, corner);
const int edge_index = corner_edges[corner];
mixer.mix_in(edge_index, old_values[corner]);
mixer.mix_in(edge_index, old_values[next_corner]);
}
}
@ -322,13 +320,10 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
for (const int poly_index : polys.index_range()) {
const IndexRange poly = polys[poly_index];
for (const int i : IndexRange(poly.size())) {
const int next_i = (i + 1) % poly.size();
const int loop_i = poly[i];
const int next_loop_i = poly[next_i];
const int edge_index = corner_edges[loop_i];
if (!old_values[loop_i] || !old_values[next_loop_i]) {
for (const int corner : poly) {
const int next_corner = mesh::poly_corner_next(poly, corner);
const int edge_index = corner_edges[corner];
if (!old_values[corner] || !old_values[next_corner]) {
r_values[edge_index] = false;
}
}

View File

@ -28,12 +28,12 @@
#include "MEM_guardedalloc.h"
namespace blender::bke {
/* -------------------------------------------------------------------- */
/** \name Geometry Component
* \{ */
namespace blender::bke {
GeometryComponent::GeometryComponent(Type type) : type_(type) {}
GeometryComponentPtr GeometryComponent::create(Type component_type)
@ -390,20 +390,14 @@ bool GeometrySet::is_empty() const
GeometrySet GeometrySet::create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership)
{
GeometrySet geometry_set;
if (mesh != nullptr) {
MeshComponent &component = geometry_set.get_component_for_write<MeshComponent>();
component.replace(mesh, ownership);
}
geometry_set.replace_mesh(mesh, ownership);
return geometry_set;
}
GeometrySet GeometrySet::create_with_volume(Volume *volume, GeometryOwnershipType ownership)
{
GeometrySet geometry_set;
if (volume != nullptr) {
VolumeComponent &component = geometry_set.get_component_for_write<VolumeComponent>();
component.replace(volume, ownership);
}
geometry_set.replace_volume(volume, ownership);
return geometry_set;
}
@ -411,20 +405,14 @@ GeometrySet GeometrySet::create_with_pointcloud(PointCloud *pointcloud,
GeometryOwnershipType ownership)
{
GeometrySet geometry_set;
if (pointcloud != nullptr) {
PointCloudComponent &component = geometry_set.get_component_for_write<PointCloudComponent>();
component.replace(pointcloud, ownership);
}
geometry_set.replace_pointcloud(pointcloud, ownership);
return geometry_set;
}
GeometrySet GeometrySet::create_with_curves(Curves *curves, GeometryOwnershipType ownership)
{
GeometrySet geometry_set;
if (curves != nullptr) {
CurveComponent &component = geometry_set.get_component_for_write<CurveComponent>();
component.replace(curves, ownership);
}
geometry_set.replace_curves(curves, ownership);
return geometry_set;
}
@ -729,6 +717,6 @@ bool object_has_geometry_set_instances(const Object &object)
return false;
}
} // namespace blender::bke
/** \} */
} // namespace blender::bke

View File

@ -401,6 +401,11 @@ Layer &TreeNode::as_layer_for_write()
return *reinterpret_cast<Layer *>(this);
}
LayerGroup *TreeNode::parent_group() const
{
return &this->parent->wrap();
}
LayerMask::LayerMask()
{
this->layer_name = nullptr;
@ -738,7 +743,7 @@ Layer &LayerGroup::add_layer(Layer *layer)
return *layer;
}
Layer &LayerGroup::add_layer_before(Layer *layer, Layer *link)
Layer &LayerGroup::add_layer_before(Layer *layer, TreeNode *link)
{
BLI_assert(layer != nullptr && link != nullptr);
BLI_insertlinkbefore(&this->children,
@ -749,7 +754,7 @@ Layer &LayerGroup::add_layer_before(Layer *layer, Layer *link)
return *layer;
}
Layer &LayerGroup::add_layer_after(Layer *layer, Layer *link)
Layer &LayerGroup::add_layer_after(Layer *layer, TreeNode *link)
{
BLI_assert(layer != nullptr && link != nullptr);
BLI_insertlinkafter(&this->children,
@ -766,13 +771,13 @@ Layer &LayerGroup::add_layer(StringRefNull name)
return this->add_layer(new_layer);
}
Layer &LayerGroup::add_layer_before(StringRefNull name, Layer *link)
Layer &LayerGroup::add_layer_before(StringRefNull name, TreeNode *link)
{
Layer *new_layer = MEM_new<Layer>(__func__, name);
return this->add_layer_before(new_layer, link);
}
Layer &LayerGroup::add_layer_after(StringRefNull name, Layer *link)
Layer &LayerGroup::add_layer_after(StringRefNull name, TreeNode *link)
{
Layer *new_layer = MEM_new<Layer>(__func__, name);
return this->add_layer_after(new_layer, link);
@ -789,11 +794,11 @@ int64_t LayerGroup::num_nodes_total() const
return this->runtime->nodes_cache_.size();
}
bool LayerGroup::unlink_layer(Layer *link)
bool LayerGroup::unlink_node(TreeNode *link)
{
if (BLI_remlink_safe(&this->children, link)) {
this->tag_nodes_cache_dirty();
link->base.parent = nullptr;
link->parent = nullptr;
return true;
}
return false;
@ -1434,14 +1439,14 @@ blender::bke::greasepencil::Layer &GreasePencil::add_layer(
blender::bke::greasepencil::Layer &GreasePencil::add_layer_after(
blender::bke::greasepencil::LayerGroup &group,
blender::bke::greasepencil::Layer *layer,
blender::bke::greasepencil::TreeNode *link,
const blender::StringRefNull name)
{
using namespace blender;
VectorSet<StringRefNull> names = get_node_names(*this);
std::string unique_name(name.c_str());
unique_layer_name(names, unique_name.data());
return group.add_layer_after(unique_name, layer);
return group.add_layer_after(unique_name, link);
}
blender::bke::greasepencil::Layer &GreasePencil::add_layer(const blender::StringRefNull name)
@ -1551,7 +1556,7 @@ void GreasePencil::remove_layer(blender::bke::greasepencil::Layer &layer)
}
/* Unlink the layer from the parent group. */
layer.parent_group().unlink_layer(&layer);
layer.parent_group().unlink_node(&layer.as_node());
/* Remove drawings. */
/* TODO: In the future this should only remove drawings when the user count hits zero. */

View File

@ -466,7 +466,7 @@ void BKE_idtype_id_foreach_cache(ID *id,
type_info = BKE_idtype_get_info_from_id(&nodetree->id);
if (type_info == NULL) {
/* Very old .blend file seem to have empty names for their embedded node trees, see
* `blo_do_versions_250()`. Assume those are nodetrees then. */
* `blo_do_versions_250()`. Assume those are node-trees then. */
type_info = BKE_idtype_get_info_from_idcode(ID_NT);
}
if (type_info->foreach_cache != NULL) {

View File

@ -1098,7 +1098,7 @@ static char *get_rna_access(ID *id,
propname = "eval_time";
break;
/* XXX problematic blocktypes */
/* XXX problematic block-types. */
case ID_SEQ: /* sequencer strip */
/* SEQ_FAC1: */
switch (adrcode) {

View File

@ -593,7 +593,7 @@ static int id_copy_libmanagement_cb(LibraryIDLinkCallbackData *cb_data)
/* Remap self-references to new copied ID. */
if (id == data->id_src) {
/* We cannot use self_id here, it is not *always* id_dst (thanks to $£!+@#&/? nodetrees). */
/* We cannot use self_id here, it is not *always* id_dst (thanks to confounded node-trees!). */
id = *id_pointer = data->id_dst;
}
@ -713,15 +713,15 @@ ID *BKE_id_copy_for_duplicate(Main *bmain,
ID_NEW_SET(key, key_new);
}
/* NOTE: embedded data (root nodetrees and master collections) should never be referenced by
/* NOTE: embedded data (root node-trees and master collections) should never be referenced by
* anything else, so we do not need to set their newid pointer and flag. */
BKE_animdata_duplicate_id_action(bmain, id_new, duplicate_flags);
if (key_new != NULL) {
BKE_animdata_duplicate_id_action(bmain, key_new, duplicate_flags);
}
/* Note that actions of embedded data (root nodetrees and master collections) are handled
* by `BKE_animdata_duplicate_id_action` as well. */
/* Note that actions of embedded data (root node-trees and master collections) are handled
* by #BKE_animdata_duplicate_id_action as well. */
}
return id->newid;
}
@ -1436,7 +1436,7 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
/* the duplicate should get a copy of the animdata */
if ((flag & LIB_ID_COPY_NO_ANIMDATA) == 0) {
/* Note that even though horrors like root nodetrees are not in bmain, the actions they use
/* Note that even though horrors like root node-trees are not in bmain, the actions they use
* in their anim data *are* in bmain... super-mega-hooray. */
BLI_assert((copy_data_flag & LIB_ID_COPY_ACTIONS) == 0 ||
(copy_data_flag & LIB_ID_CREATE_NO_MAIN) == 0);
@ -1837,7 +1837,7 @@ void BKE_library_make_local(Main *bmain,
BLI_linklist_prepend_arena(&todo_ids, id, linklist_mem);
id->tag |= LIB_TAG_DOIT;
/* Tag those nasty non-ID nodetrees,
/* Tag those nasty non-ID node-trees,
* but do not add them to todo list, making them local is handled by 'owner' ID.
* This is needed for library_make_local_copying_check() to work OK at step 2. */
if (ntree != NULL) {

View File

@ -722,7 +722,7 @@ static bool lib_query_unused_ids_tag_recurse(Main *bmain,
if (ELEM(GS(id->name), ID_IM)) {
/* Images which have a 'viewer' source (e.g. render results) should not be considered as
* orphaned/unused data. */
Image *image = (Image *)id;
const Image *image = (Image *)id;
if (image->source == IMA_SRC_VIEWER) {
id_relations->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED;
return false;

View File

@ -185,7 +185,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
IDRemap *id_remap_data = cb_data->user_data;
/* Those asserts ensure the general sanity of ID tags regarding 'embedded' ID data (root
* nodetrees and co). */
* node-trees and co). */
BLI_assert(id_owner == id_remap_data->id_owner);
BLI_assert(id_self == id_owner || (id_self->flag & LIB_EMBEDDED_DATA) != 0);

View File

@ -117,6 +117,12 @@ static void light_blend_write(BlendWriter *writer, ID *id, const void *id_addres
{
Light *la = (Light *)id;
/* Forward compatibility for energy. */
la->energy_deprecated = la->energy;
if (la->type == LA_AREA) {
la->energy_deprecated /= M_PI_4;
}
/* write LibData */
BLO_write_id_struct(writer, Light, id_address, &la->id);
BKE_id_blend_write(writer, &la->id);

View File

@ -160,7 +160,7 @@ static void material_free_data(ID *id)
static void material_foreach_id(ID *id, LibraryForeachIDData *data)
{
Material *material = (Material *)id;
/* Nodetrees **are owned by IDs**, treat them as mere sub-data and not real ID! */
/* Node-trees **are owned by IDs**, treat them as mere sub-data and not real ID! */
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
data, BKE_library_foreach_ID_embedded(data, (ID **)&material->nodetree));
if (material->texpaintslot != nullptr) {

View File

@ -78,7 +78,7 @@ static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata);
static void mesh_init_data(ID *id)
{
Mesh *mesh = (Mesh *)id;
Mesh *mesh = reinterpret_cast<Mesh *>(id);
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mesh, id));
@ -97,8 +97,8 @@ static void mesh_init_data(ID *id)
static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
{
Mesh *mesh_dst = (Mesh *)id_dst;
const Mesh *mesh_src = (const Mesh *)id_src;
Mesh *mesh_dst = reinterpret_cast<Mesh *>(id_dst);
const Mesh *mesh_src = reinterpret_cast<const Mesh *>(id_src);
mesh_dst->runtime = new blender::bke::MeshRuntime();
mesh_dst->runtime->deformed_only = mesh_src->runtime->deformed_only;
@ -197,7 +197,7 @@ void BKE_mesh_free_editmesh(Mesh *mesh)
static void mesh_free_data(ID *id)
{
Mesh *mesh = (Mesh *)id;
Mesh *mesh = reinterpret_cast<Mesh *>(id);
BKE_mesh_free_editmesh(mesh);
@ -209,7 +209,7 @@ static void mesh_free_data(ID *id)
static void mesh_foreach_id(ID *id, LibraryForeachIDData *data)
{
Mesh *mesh = (Mesh *)id;
Mesh *mesh = reinterpret_cast<Mesh *>(id);
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, mesh->texcomesh, IDWALK_CB_NEVER_SELF);
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, mesh->key, IDWALK_CB_USER);
for (int i = 0; i < mesh->totcol; i++) {
@ -219,7 +219,7 @@ static void mesh_foreach_id(ID *id, LibraryForeachIDData *data)
static void mesh_foreach_path(ID *id, BPathForeachPathData *bpath_data)
{
Mesh *me = (Mesh *)id;
Mesh *me = reinterpret_cast<Mesh *>(id);
if (me->ldata.external) {
BKE_bpath_foreach_path_fixed_process(
bpath_data, me->ldata.external->filepath, sizeof(me->ldata.external->filepath));
@ -229,16 +229,15 @@ static void mesh_foreach_path(ID *id, BPathForeachPathData *bpath_data)
static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
using namespace blender;
Mesh *mesh = (Mesh *)id;
Mesh *mesh = reinterpret_cast<Mesh *>(id);
const bool is_undo = BLO_write_is_undo(writer);
Vector<CustomDataLayer, 16> vert_layers;
Vector<CustomDataLayer, 16> edge_layers;
Vector<CustomDataLayer, 16> loop_layers;
Vector<CustomDataLayer, 16> poly_layers;
blender::ResourceScope temp_arrays_for_legacy_format;
/* cache only - don't write */
/* Cache only - don't write. */
mesh->mface = nullptr;
mesh->totface = 0;
memset(&mesh->fdata, 0, sizeof(mesh->fdata));
@ -270,7 +269,6 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
BLO_write_id_struct(writer, Mesh, id_address, &mesh->id);
BKE_id_blend_write(writer, &mesh->id);
/* direct data */
if (mesh->adt) {
BKE_animdata_blend_write(writer, mesh->adt);
}
@ -286,7 +284,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
writer, &mesh->vdata, vert_layers, mesh->totvert, CD_MASK_MESH.vmask, &mesh->id);
CustomData_blend_write(
writer, &mesh->edata, edge_layers, mesh->totedge, CD_MASK_MESH.emask, &mesh->id);
/* fdata is really a dummy - written so slots align */
/* `fdata` is cleared above but written so slots align. */
CustomData_blend_write(writer, &mesh->fdata, {}, mesh->totface, CD_MASK_MESH.fmask, &mesh->id);
CustomData_blend_write(
writer, &mesh->ldata, loop_layers, mesh->totloop, CD_MASK_MESH.lmask, &mesh->id);
@ -300,7 +298,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
{
Mesh *mesh = (Mesh *)id;
Mesh *mesh = reinterpret_cast<Mesh *>(id);
BLO_read_pointer_array(reader, (void **)&mesh->mat);
/* Deprecated pointers to custom data layers are read here for backward compatibility
@ -315,7 +313,6 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_data_address(reader, &mesh->mselect);
/* animdata */
BLO_read_data_address(reader, &mesh->adt);
BKE_animdata_blend_read_data(reader, mesh->adt);
@ -345,7 +342,6 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
mesh->poly_offset_indices);
}
/* happens with old files */
if (mesh->mselect == nullptr) {
mesh->totselect = 0;
}
@ -360,8 +356,8 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
static void mesh_blend_read_lib(BlendLibReader *reader, ID *id)
{
Mesh *me = (Mesh *)id;
/* this check added for python created meshes */
Mesh *me = reinterpret_cast<Mesh *>(id);
/* This check added for python created meshes. */
if (me->mat) {
for (int i = 0; i < me->totcol; i++) {
BLO_read_id_address(reader, id, &me->mat[i]);
@ -378,7 +374,7 @@ static void mesh_blend_read_lib(BlendLibReader *reader, ID *id)
static void mesh_read_expand(BlendExpander *expander, ID *id)
{
Mesh *me = (Mesh *)id;
Mesh *me = reinterpret_cast<Mesh *>(id);
for (int a = 0; a < me->totcol; a++) {
BLO_expand(expander, me->mat[a]);
}
@ -911,9 +907,7 @@ static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
Mesh *BKE_mesh_add(Main *bmain, const char *name)
{
Mesh *me = (Mesh *)BKE_id_new(bmain, ID_ME, name);
return me;
return static_cast<Mesh *>(BKE_id_new(bmain, ID_ME, name));
}
void BKE_mesh_poly_offsets_ensure_alloc(Mesh *mesh)
@ -1045,7 +1039,7 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
/* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */
const bool do_tessface = (tessface_num || ((me_src->totface != 0) && (me_src->totpoly == 0)));
Mesh *me_dst = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
Mesh *me_dst = static_cast<Mesh *>(BKE_id_new_nomain(ID_ME, nullptr));
me_dst->mselect = (MSelect *)MEM_dupallocN(me_src->mselect);
@ -1139,7 +1133,7 @@ Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm,
const Mesh *me_settings)
{
BLI_assert(params->calc_object_remap == false);
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
Mesh *mesh = static_cast<Mesh *>(BKE_id_new_nomain(ID_ME, nullptr));
BM_mesh_bm_to_me(nullptr, bm, mesh, params);
BKE_mesh_copy_parameters_for_eval(mesh, me_settings);
return mesh;
@ -1149,7 +1143,7 @@ Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm,
const CustomData_MeshMasks *cd_mask_extra,
const Mesh *me_settings)
{
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
Mesh *mesh = static_cast<Mesh *>(BKE_id_new_nomain(ID_ME, nullptr));
BM_mesh_bm_to_me_for_eval(bm, mesh, cd_mask_extra);
BKE_mesh_copy_parameters_for_eval(mesh, me_settings);
return mesh;
@ -1182,7 +1176,7 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob)
/* This is Object-level data access,
* DO NOT touch to Mesh's bb, would be totally thread-unsafe. */
if (ob->runtime.bb == nullptr || ob->runtime.bb->flag & BOUNDBOX_DIRTY) {
Mesh *me = (Mesh *)ob->data;
Mesh *me = static_cast<Mesh *>(ob->data);
float min[3], max[3];
INIT_MINMAX(min, max);
@ -1279,7 +1273,7 @@ void BKE_mesh_texspace_get_reference(Mesh *me,
float (*BKE_mesh_orco_verts_get(Object *ob))[3]
{
Mesh *me = (Mesh *)ob->data;
Mesh *me = static_cast<Mesh *>(ob->data);
Mesh *tme = me->texcomesh ? me->texcomesh : me;
/* Get appropriate vertex coordinates */
@ -1335,7 +1329,7 @@ Mesh *BKE_mesh_from_object(Object *ob)
return nullptr;
}
if (ob->type == OB_MESH) {
return (Mesh *)ob->data;
return static_cast<Mesh *>(ob->data);
}
return nullptr;
@ -1352,7 +1346,7 @@ void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *me)
multires_force_sculpt_rebuild(ob);
if (ob->type == OB_MESH) {
old = (Mesh *)ob->data;
old = static_cast<Mesh *>(ob->data);
if (old) {
id_us_min(&old->id);
}
@ -1841,7 +1835,7 @@ void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
mesh->runtime->mesh_eval = nullptr;
}
if (DEG_is_active(depsgraph)) {
Mesh *mesh_orig = (Mesh *)DEG_get_original_id(&mesh->id);
Mesh *mesh_orig = reinterpret_cast<Mesh *>(DEG_get_original_id(&mesh->id));
if (mesh->texspace_flag & ME_TEXSPACE_FLAG_AUTO_EVALUATED) {
mesh_orig->texspace_flag |= ME_TEXSPACE_FLAG_AUTO_EVALUATED;
copy_v3_v3(mesh_orig->texspace_location, mesh->texspace_location);

View File

@ -205,10 +205,8 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select
}
/* Create new edges. */
if (!CustomData_has_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge")) {
CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totloop, ".corner_edge");
}
MutableAttributeAccessor attributes = mesh->attributes_for_write();
attributes.add<int>(".corner_edge", ATTR_DOMAIN_CORNER, AttributeInitConstruct());
MutableSpan<int2> new_edges{
static_cast<int2 *>(MEM_calloc_arrayN(new_totedge, sizeof(int2), __func__)), new_totedge};
calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, new_edges);
@ -221,9 +219,8 @@ 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_named_with_data(
&mesh->edata, CD_PROP_INT32_2D, new_edges.data(), new_totedge, ".edge_verts", nullptr);
mesh->totedge = new_totedge;
attributes.add<int2>(".edge_verts", ATTR_DOMAIN_EDGE, AttributeInitMoveArray(new_edges.data()));
if (select_new_edges) {
MutableAttributeAccessor attributes = mesh->attributes_for_write();

View File

@ -69,6 +69,7 @@ static CLG_LogRef LOG = {"bke.mesh_convert"};
static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispbase)
{
using namespace blender;
using namespace blender::bke;
int a, b, ofs;
const bool conv_polys = (
@ -127,9 +128,9 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
"material_index", ATTR_DOMAIN_FACE);
SpanAttributeWriter<bool> sharp_faces = attributes.lookup_or_add_for_write_span<bool>(
"sharp_face", ATTR_DOMAIN_FACE);
blender::float2 *mloopuv = static_cast<blender::float2 *>(CustomData_add_layer_named(
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, mesh->totloop, DATA_("UVMap")));
SpanAttributeWriter<float2> uv_attribute = attributes.lookup_or_add_for_write_span<float2>(
DATA_("UVMap"), ATTR_DOMAIN_CORNER);
MutableSpan<float2> uv_map = uv_attribute.span;
int dst_vert = 0;
int dst_edge = 0;
@ -203,11 +204,9 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
poly_offsets[dst_poly] = dst_loop;
material_indices.span[dst_poly] = dl->col;
if (mloopuv) {
for (int i = 0; i < 3; i++, mloopuv++) {
(*mloopuv)[0] = (corner_verts[dst_loop + i] - startvert) / float(dl->nr - 1);
(*mloopuv)[1] = 0.0f;
}
for (int i = 0; i < 3; i++) {
uv_map[dst_loop + i][0] = (corner_verts[dst_loop + i] - startvert) / float(dl->nr - 1);
uv_map[dst_loop + i][1] = 0.0f;
}
sharp_faces.span[dst_poly] = !is_smooth;
@ -260,35 +259,33 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
poly_offsets[dst_poly] = dst_loop;
material_indices.span[dst_poly] = dl->col;
if (mloopuv) {
int orco_sizeu = dl->nr - 1;
int orco_sizev = dl->parts - 1;
int orco_sizeu = dl->nr - 1;
int orco_sizev = dl->parts - 1;
/* exception as handled in convertblender.c too */
if (dl->flag & DL_CYCL_U) {
orco_sizeu++;
if (dl->flag & DL_CYCL_V) {
orco_sizev++;
}
}
else if (dl->flag & DL_CYCL_V) {
/* exception as handled in convertblender.c too */
if (dl->flag & DL_CYCL_U) {
orco_sizeu++;
if (dl->flag & DL_CYCL_V) {
orco_sizev++;
}
}
else if (dl->flag & DL_CYCL_V) {
orco_sizev++;
}
for (int i = 0; i < 4; i++, mloopuv++) {
/* find uv based on vertex index into grid array */
int v = corner_verts[dst_loop + i] - startvert;
for (int i = 0; i < 4; i++) {
/* find uv based on vertex index into grid array */
int v = corner_verts[dst_loop + i] - startvert;
(*mloopuv)[0] = (v / dl->nr) / float(orco_sizev);
(*mloopuv)[1] = (v % dl->nr) / float(orco_sizeu);
uv_map[dst_loop + i][0] = (v / dl->nr) / float(orco_sizev);
uv_map[dst_loop + i][1] = (v % dl->nr) / float(orco_sizeu);
/* cyclic correction */
if (ELEM(i, 1, 2) && (*mloopuv)[0] == 0.0f) {
(*mloopuv)[0] = 1.0f;
}
if (ELEM(i, 0, 1) && (*mloopuv)[1] == 0.0f) {
(*mloopuv)[1] = 1.0f;
}
/* cyclic correction */
if (ELEM(i, 1, 2) && uv_map[dst_loop + i][0] == 0.0f) {
uv_map[dst_loop + i][0] = 1.0f;
}
if (ELEM(i, 0, 1) && uv_map[dst_loop + i][1] == 0.0f) {
uv_map[dst_loop + i][1] = 1.0f;
}
}
@ -311,6 +308,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
material_indices.finish();
sharp_faces.finish();
uv_attribute.finish();
return mesh;
}

View File

@ -13,7 +13,7 @@
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_cache.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_iterators.h"

View File

@ -30,7 +30,7 @@
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_cache.hh"
#include "BKE_global.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h"
@ -366,10 +366,11 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
break;
case ME_WRAPPER_TYPE_BMESH: {
BMEditMesh *em = mesh->edit_mesh;
EditMeshData *emd = mesh->runtime->edit_data;
if (emd->vertexCos) {
BKE_editmesh_cache_ensure_vert_normals(em, emd);
BKE_editmesh_cache_ensure_poly_normals(em, emd);
if (EditMeshData *emd = mesh->runtime->edit_data) {
if (emd->vertexCos) {
BKE_editmesh_cache_ensure_vert_normals(em, emd);
BKE_editmesh_cache_ensure_poly_normals(em, emd);
}
}
return;
}

View File

@ -19,7 +19,7 @@
#include "BLI_timeit.hh"
#include "BKE_bvhutils.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_cache.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h"

View File

@ -34,8 +34,9 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BKE_DerivedMesh.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_cache.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h"
@ -52,10 +53,9 @@
using blender::float3;
using blender::Span;
Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
const CustomData_MeshMasks *cd_mask_extra,
const float (*vert_coords)[3],
const Mesh *me_settings)
Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
const CustomData_MeshMasks *cd_mask_extra,
const Mesh *me_settings)
{
Mesh *me = static_cast<Mesh *>(BKE_id_new_nomain(ID_ME, nullptr));
BKE_mesh_copy_parameters_for_eval(me, me_settings);
@ -85,18 +85,9 @@ Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
me->totloop = 0;
#endif
EditMeshData *edit_data = me->runtime->edit_data;
edit_data->vertexCos = vert_coords;
return me;
}
Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
const CustomData_MeshMasks *cd_mask_extra,
const Mesh *me_settings)
{
return BKE_mesh_wrapper_from_editmesh_with_coords(em, cd_mask_extra, nullptr, me_settings);
}
void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
{
std::lock_guard lock{me->runtime->eval_mutex};
@ -138,6 +129,8 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
BKE_mesh_vert_coords_apply(me, edit_data->vertexCos);
me->runtime->is_original_bmesh = false;
}
BKE_mesh_runtime_reset_edit_data(me);
MEM_SAFE_FREE(me->runtime->edit_data);
break;
}
}
@ -176,6 +169,48 @@ bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3])
/** \name Mesh Coordinate Access
* \{ */
const float (*BKE_mesh_wrapper_vert_coords(const Mesh *mesh))[3]
{
switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
return mesh->runtime->edit_data->vertexCos;
case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD:
return reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data());
}
return nullptr;
}
const float (*BKE_mesh_wrapper_poly_normals(Mesh *mesh))[3]
{
switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
BKE_editmesh_cache_ensure_poly_normals(mesh->edit_mesh, mesh->runtime->edit_data);
return mesh->runtime->edit_data->polyNos;
case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD:
return reinterpret_cast<const float(*)[3]>(mesh->poly_normals().data());
}
return nullptr;
}
void BKE_mesh_wrapper_tag_positions_changed(Mesh *mesh)
{
switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
if (mesh->runtime->edit_data) {
MEM_SAFE_FREE(mesh->runtime->edit_data->vertexNos);
MEM_SAFE_FREE(mesh->runtime->edit_data->polyCos);
MEM_SAFE_FREE(mesh->runtime->edit_data->polyNos);
}
break;
case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD:
BKE_mesh_tag_positions_changed(mesh);
break;
}
}
void BKE_mesh_wrapper_vert_coords_copy(const Mesh *me,
float (*vert_coords)[3],
int vert_coords_len)

View File

@ -47,7 +47,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_appdir.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_cache.hh"
#include "BKE_effect.h"
#include "BKE_fluid.h"
#include "BKE_global.h"

View File

@ -481,7 +481,7 @@ NlaStrip *BKE_nlastrip_new(bAction *act)
/* determine initial range
* - strip length cannot be 0... ever...
*/
BKE_action_get_frame_range(strip->act, &strip->actstart, &strip->actend);
BKE_action_frame_range_get(strip->act, &strip->actstart, &strip->actend);
strip->start = strip->actstart;
strip->end = IS_EQF(strip->actstart, strip->actend) ? (strip->actstart + 1.0f) : strip->actend;
@ -1580,7 +1580,7 @@ void BKE_nlastrip_recalculate_bounds_sync_action(NlaStrip *strip)
prev_actstart = strip->actstart;
BKE_action_get_frame_range(strip->act, &strip->actstart, &strip->actend);
BKE_action_frame_range_get(strip->act, &strip->actstart, &strip->actend);
/* Set start such that key's do not visually move, to preserve the overall animation result. */
strip->start += (strip->actstart - prev_actstart) * strip->scale;
@ -2113,7 +2113,7 @@ void BKE_nla_action_pushdown(AnimData *adt, const bool is_liboverride)
* as that will cause us grief down the track
*/
/* TODO: what about modifiers? */
if (action_has_motion(adt->action) == 0) {
if (BKE_action_has_motion(adt->action) == 0) {
CLOG_ERROR(&LOG, "action has no data");
return;
}

View File

@ -82,7 +82,7 @@
#include "BKE_displist.h"
#include "BKE_duplilist.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_cache.hh"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_fcurve_driver.h"

View File

@ -37,7 +37,7 @@
#include "BKE_collection.h"
#include "BKE_duplilist.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_editmesh_cache.hh"
#include "BKE_geometry_set.hh"
#include "BKE_geometry_set_instances.hh"
#include "BKE_global.h"

View File

@ -881,22 +881,22 @@ bool BKE_ocean_init(Ocean *o,
o->_Lz = 0.001f;
}
/* the +ve components and DC */
/* The +VE components and DC. */
for (i = 0; i <= o->_M / 2; i++) {
o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx;
}
/* the -ve components */
/* The -VE components. */
for (i = o->_M - 1, ii = 0; i > o->_M / 2; i--, ii++) {
o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx;
}
/* the +ve components and DC */
/* The +VE components and DC. */
for (i = 0; i <= o->_N / 2; i++) {
o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz;
}
/* the -ve components */
/* The -VE components. */
for (i = o->_N - 1, ii = 0; i > o->_N / 2; i--, ii++) {
o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz;
}

View File

@ -55,12 +55,6 @@ static void psys_path_iter_get(ParticlePathIterator *iter,
}
}
typedef struct ParticlePathModifier {
struct ParticlePathModifier *next, *prev;
void (*apply)(ParticleCacheKey *keys, int totkeys, ParticleCacheKey *parent_keys);
} ParticlePathModifier;
/* ------------------------------------------------------------------------- */
static void do_kink_spiral_deform(ParticleKey *state,
@ -303,13 +297,11 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx,
const bool draw_col_ma = (part->draw_col == PART_DRAW_COL_MAT);
const bool use_length_check = !ELEM(part->kink, PART_KINK_SPIRAL);
// ParticlePathModifier *mod;
ParticleCacheKey *key;
int totkeys, k;
float max_length;
/* TODO: for the future: use true particle modifiers that work on the whole curve.
* `modifiers` & `mod` are unused. */
/* TODO: for the future: use true particle modifiers that work on the whole curve. */
if (part->kink == PART_KINK_SPIRAL) {
do_kink_spiral(

View File

@ -42,8 +42,6 @@
#include "pbvh_intern.hh"
#include <cmath>
using blender::float3;
using blender::MutableSpan;
using blender::Span;
@ -2683,7 +2681,7 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
return hit;
}
void BKE_pbvh_raycast_project_ray_root(
void BKE_pbvh_clip_ray_ortho(
PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
{
if (pbvh->nodes) {
@ -2691,9 +2689,8 @@ void BKE_pbvh_raycast_project_ray_root(
float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3];
IsectRayAABB_Precalc ray;
float ray_normal_inv[3];
const float margin = 1e-3;
float offset = 1.0f + margin;
const float offset_vec[3] = {margin, margin, margin};
float offset = 1.0f + 1e-3f;
const float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f};
if (original) {
BKE_pbvh_node_get_original_BB(pbvh->nodes, bb_min_root, bb_max_root);
@ -2702,42 +2699,66 @@ void BKE_pbvh_raycast_project_ray_root(
BKE_pbvh_node_get_BB(pbvh->nodes, bb_min_root, bb_max_root);
}
/* Calc rough clipping to avoid overflow later. See #109555. */
float mat[3][3];
axis_dominant_v3_to_m3(mat, ray_normal);
float a[3], b[3], min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {FLT_MIN, FLT_MIN, FLT_MIN};
/* Compute AABB bounds rotated along ray_normal.*/
copy_v3_v3(a, bb_min_root);
copy_v3_v3(b, bb_max_root);
mul_m3_v3(mat, a);
mul_m3_v3(mat, b);
minmax_v3v3_v3(min, max, a);
minmax_v3v3_v3(min, max, b);
float cent[3];
/* Find midpoint of aabb on ray. */
mid_v3_v3v3(cent, bb_min_root, bb_max_root);
float t = line_point_factor_v3(cent, ray_start, ray_end);
interp_v3_v3v3(cent, ray_start, ray_end, t);
/* Compute rough interval. */
float dist = max[2] - min[2];
madd_v3_v3v3fl(ray_start, cent, ray_normal, -dist);
madd_v3_v3v3fl(ray_end, cent, ray_normal, dist);
/* Slightly offset min and max in case we have a zero width node
* (due to a plane mesh for instance), or faces very close to the bounding box boundary. */
mid_v3_v3v3(bb_center, bb_max_root, bb_min_root);
/* diff should be same for both min/max since it's calculated from center */
/* Diff should be same for both min/max since it's calculated from center. */
sub_v3_v3v3(bb_diff, bb_max_root, bb_center);
/* handles case of zero width bb */
/* Handles case of zero width bb. */
add_v3_v3(bb_diff, offset_vec);
madd_v3_v3v3fl(bb_max_root, bb_center, bb_diff, offset);
madd_v3_v3v3fl(bb_min_root, bb_center, bb_diff, -offset);
/* first project start ray */
/* Final projection of start ray. */
isect_ray_aabb_v3_precalc(&ray, ray_start, ray_normal);
if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_start)) {
return;
}
/* then the end ray */
/* Final projection of end ray. */
mul_v3_v3fl(ray_normal_inv, ray_normal, -1.0);
isect_ray_aabb_v3_precalc(&ray, ray_end, ray_normal_inv);
/* unlikely to fail exiting if entering succeeded, still keep this here */
/* Unlikely to fail exiting if entering succeeded, still keep this here. */
if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_end)) {
return;
}
if (rootmin_end <= rootmin_start) {
/* Small object sizes can led to floating-point overflow
* when trying to add a reasonably small margin, e.g. 1e-3.
* This happens when initializing rays by the viewport clipping
* bounds, which are then divided by the object's scale.
* So if the clip end if 10000 and we divide by 0.00001 we
* get a really large number that we canned add 1e-3 (0.001) to.
*
* To solve this, we compute a margin using the next possible floating
* point value after ray start. */
float epsilon = std::nextafterf(rootmin_start, rootmin_start + 1.0f) - rootmin_start;
rootmin_end = rootmin_start + epsilon * 500.0f;
/*
* As a last-ditch effort to correct floating point overflow compute
* and add an epsilon if rootmin_start == rootmin_end.
*/
float epsilon = (std::nextafter(rootmin_start, rootmin_start + 1000.0f) - rootmin_start) *
5000.0f;
if (rootmin_start == rootmin_end) {
rootmin_start -= epsilon;
rootmin_end += epsilon;
}
madd_v3_v3v3fl(ray_start, ray_start, ray_normal, rootmin_start);

View File

@ -64,11 +64,8 @@ static void pointcloud_init_data(ID *id)
MEMCPY_STRUCT_AFTER(pointcloud, DNA_struct_default_get(PointCloud), id);
CustomData_reset(&pointcloud->pdata);
CustomData_add_layer_named(&pointcloud->pdata,
CD_PROP_FLOAT3,
CD_CONSTRUCT,
pointcloud->totpoint,
POINTCLOUD_ATTR_POSITION);
pointcloud->attributes_for_write().add<float3>(
"position", ATTR_DOMAIN_POINT, blender::bke::AttributeInitConstruct());
pointcloud->runtime = new blender::bke::PointCloudRuntime();
}

View File

@ -1023,7 +1023,7 @@ static void ccgDM_release(DerivedMesh *dm)
if (ccgdm->multires.modified_flags) {
/* Check that mmd still exists */
if (!ccgdm->multires.local_mmd &&
BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) < 0)
BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) == -1)
{
ccgdm->multires.mmd = nullptr;
}

View File

@ -21,6 +21,7 @@
#include "BLI_math.h"
#include "BLI_math_base_safe.h"
#include "BLI_path_util.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_threads.h"
@ -75,10 +76,7 @@ static void vfont_init_data(ID *id)
}
}
static void vfont_copy_data(Main *UNUSED(bmain),
ID *id_dst,
const ID *UNUSED(id_src),
const int flag)
static void vfont_copy_data(Main * /*bmain*/, ID *id_dst, const ID * /*id_src*/, const int flag)
{
VFont *vfont_dst = (VFont *)id_dst;
@ -86,7 +84,7 @@ static void vfont_copy_data(Main *UNUSED(bmain),
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
/* Just to be sure, should not have any value actually after reading time. */
vfont_dst->temp_pf = NULL;
vfont_dst->temp_pf = nullptr;
if (vfont_dst->packedfile) {
vfont_dst->packedfile = BKE_packedfile_duplicate(vfont_dst->packedfile);
@ -105,7 +103,7 @@ static void vfont_free_data(ID *id)
if (vfont->packedfile) {
BKE_packedfile_free(vfont->packedfile);
vfont->packedfile = NULL;
vfont->packedfile = nullptr;
}
}
@ -113,7 +111,8 @@ static void vfont_foreach_path(ID *id, BPathForeachPathData *bpath_data)
{
VFont *vfont = (VFont *)id;
if (vfont->packedfile != NULL && (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
if ((vfont->packedfile != nullptr) &&
(bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
return;
}
@ -130,12 +129,12 @@ static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_addres
const bool is_undo = BLO_write_is_undo(writer);
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
vf->data = NULL;
vf->temp_pf = NULL;
vf->data = nullptr;
vf->temp_pf = nullptr;
/* Do not store packed files in case this is a library override ID. */
if (ID_IS_OVERRIDE_LIBRARY(vf) && !is_undo) {
vf->packedfile = NULL;
vf->packedfile = nullptr;
}
/* write LibData */
@ -149,39 +148,39 @@ static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_addres
static void vfont_blend_read_data(BlendDataReader *reader, ID *id)
{
VFont *vf = (VFont *)id;
vf->data = NULL;
vf->temp_pf = NULL;
vf->data = nullptr;
vf->temp_pf = nullptr;
BKE_packedfile_blend_read(reader, &vf->packedfile);
}
IDTypeInfo IDType_ID_VF = {
.id_code = ID_VF,
.id_filter = FILTER_ID_VF,
.main_listbase_index = INDEX_ID_VF,
.struct_size = sizeof(VFont),
.name = "Font",
.name_plural = "fonts",
.translation_context = BLT_I18NCONTEXT_ID_VFONT,
.flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE,
.asset_type_info = NULL,
/*id_code*/ ID_VF,
/*id_filter*/ FILTER_ID_VF,
/*main_listbase_index*/ INDEX_ID_VF,
/*struct_size*/ sizeof(VFont),
/*name*/ "Font",
/*name_plural*/ "fonts",
/*translation_context*/ BLT_I18NCONTEXT_ID_VFONT,
/*flags*/ IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE,
/*asset_type_info*/ nullptr,
.init_data = vfont_init_data,
.copy_data = vfont_copy_data,
.free_data = vfont_free_data,
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
.foreach_path = vfont_foreach_path,
.owner_pointer_get = NULL,
/*init_data*/ vfont_init_data,
/*copy_data*/ vfont_copy_data,
/*free_data*/ vfont_free_data,
/*make_local*/ nullptr,
/*foreach_id*/ nullptr,
/*foreach_cache*/ nullptr,
/*foreach_path*/ vfont_foreach_path,
/*owner_pointer_get*/ nullptr,
.blend_write = vfont_blend_write,
.blend_read_data = vfont_blend_read_data,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
/*blend_write*/ vfont_blend_write,
/*blend_read_data*/ vfont_blend_read_data,
/*blend_read_lib*/ nullptr,
/*blend_read_expand*/ nullptr,
.blend_read_undo_preserve = NULL,
/*blend_read_undo_preserve*/ nullptr,
.lib_override_apply_post = NULL,
/*lib_override_apply_post*/ nullptr,
};
/***************************** VFont *******************************/
@ -192,10 +191,10 @@ void BKE_vfont_free_data(VFont *vfont)
if (vfont->data->characters) {
GHashIterator gh_iter;
GHASH_ITER (gh_iter, vfont->data->characters) {
VChar *che = BLI_ghashIterator_getValue(&gh_iter);
VChar *che = static_cast<VChar *>(BLI_ghashIterator_getValue(&gh_iter));
while (che->nurbsbase.first) {
Nurb *nu = che->nurbsbase.first;
Nurb *nu = static_cast<Nurb *>(che->nurbsbase.first);
if (nu->bezt) {
MEM_freeN(nu->bezt);
}
@ -205,20 +204,20 @@ void BKE_vfont_free_data(VFont *vfont)
MEM_freeN(che);
}
BLI_ghash_free(vfont->data->characters, NULL, NULL);
BLI_ghash_free(vfont->data->characters, nullptr, nullptr);
}
MEM_freeN(vfont->data);
vfont->data = NULL;
vfont->data = nullptr;
}
if (vfont->temp_pf) {
BKE_packedfile_free(vfont->temp_pf); /* NULL when the font file can't be found on disk */
vfont->temp_pf = NULL;
BKE_packedfile_free(vfont->temp_pf); /* Null when the font file can't be found on disk. */
vfont->temp_pf = nullptr;
}
}
static const void *builtin_font_data = NULL;
static const void *builtin_font_data = nullptr;
static int builtin_font_size = 0;
bool BKE_vfont_is_builtin(const VFont *vfont)
@ -237,7 +236,7 @@ static PackedFile *get_builtin_packedfile(void)
if (!builtin_font_data) {
CLOG_ERROR(&LOG, "Internal error, builtin font not loaded");
return NULL;
return nullptr;
}
void *mem = MEM_mallocN(builtin_font_size, "vfd_builtin");
@ -249,8 +248,8 @@ static PackedFile *get_builtin_packedfile(void)
static VFontData *vfont_get_data(VFont *vfont)
{
if (vfont == NULL) {
return NULL;
if (vfont == nullptr) {
return nullptr;
}
/* And then set the data */
@ -277,16 +276,16 @@ static VFontData *vfont_get_data(VFont *vfont)
pf = vfont->packedfile;
/* We need to copy a tmp font to memory unless it is already there */
if (vfont->temp_pf == NULL) {
if (vfont->temp_pf == nullptr) {
vfont->temp_pf = BKE_packedfile_duplicate(pf);
}
}
else {
pf = BKE_packedfile_new(NULL, vfont->filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
pf = BKE_packedfile_new(nullptr, vfont->filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
if (vfont->temp_pf == NULL) {
if (vfont->temp_pf == nullptr) {
vfont->temp_pf = BKE_packedfile_new(
NULL, vfont->filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
nullptr, vfont->filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
}
}
if (!pf) {
@ -317,7 +316,7 @@ static VFontData *vfont_get_data(VFont *vfont)
VFont *BKE_vfont_load(Main *bmain, const char *filepath)
{
char filename[FILE_MAXFILE];
VFont *vfont = NULL;
VFont *vfont = nullptr;
PackedFile *pf;
bool is_builtin;
@ -329,7 +328,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath)
}
else {
BLI_path_split_file_part(filepath, filename, sizeof(filename));
pf = BKE_packedfile_new(NULL, filepath, BKE_main_blendfile_path(bmain));
pf = BKE_packedfile_new(nullptr, filepath, BKE_main_blendfile_path(bmain));
is_builtin = false;
}
@ -340,7 +339,8 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath)
vfd = BKE_vfontdata_from_freetypefont(pf);
if (vfd) {
/* If there's a font name, use it for the ID name. */
vfont = BKE_libblock_alloc(bmain, ID_VF, vfd->name[0] ? vfd->name : filename, 0);
vfont = static_cast<VFont *>(
BKE_libblock_alloc(bmain, ID_VF, vfd->name[0] ? vfd->name : filename, 0));
vfont->data = vfd;
STRNCPY(vfont->filepath, filepath);
@ -351,7 +351,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath)
/* Do not add #FO_BUILTIN_NAME to temporary list-base. */
if (!STREQ(filename, FO_BUILTIN_NAME)) {
vfont->temp_pf = BKE_packedfile_new(NULL, filepath, BKE_main_blendfile_path(bmain));
vfont->temp_pf = BKE_packedfile_new(nullptr, filepath, BKE_main_blendfile_path(bmain));
}
}
@ -366,14 +366,13 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath)
VFont *BKE_vfont_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
{
VFont *vfont;
char filepath_abs[FILE_MAX], filepath_test[FILE_MAX];
STRNCPY(filepath_abs, filepath);
BLI_path_abs(filepath_abs, BKE_main_blendfile_path(bmain));
/* first search an identical filepath */
for (vfont = bmain->fonts.first; vfont; vfont = vfont->id.next) {
LISTBASE_FOREACH (VFont *, vfont, &bmain->fonts) {
STRNCPY(filepath_test, vfont->filepath);
BLI_path_abs(filepath_test, ID_BLEND_PATH(bmain, &vfont->id));
@ -394,7 +393,7 @@ VFont *BKE_vfont_load_exists_ex(Main *bmain, const char *filepath, bool *r_exist
VFont *BKE_vfont_load_exists(Main *bmain, const char *filepath)
{
return BKE_vfont_load_exists_ex(bmain, filepath, NULL);
return BKE_vfont_load_exists_ex(bmain, filepath, nullptr);
}
static VFont *which_vfont(Curve *cu, CharInfo *info)
@ -413,9 +412,7 @@ static VFont *which_vfont(Curve *cu, CharInfo *info)
VFont *BKE_vfont_builtin_get(void)
{
VFont *vfont;
for (vfont = G_MAIN->fonts.first; vfont; vfont = vfont->id.next) {
LISTBASE_FOREACH (VFont *, vfont, &G_MAIN->fonts) {
if (BKE_vfont_is_builtin(vfont)) {
return vfont;
}
@ -423,7 +420,7 @@ VFont *BKE_vfont_builtin_get(void)
/* Newly loaded ID's have a user by default, in this case the caller is responsible
* for assigning a user, otherwise an additional user would be added, see: #100819. */
vfont = BKE_vfont_load(G_MAIN, FO_BUILTIN_NAME);
VFont *vfont = BKE_vfont_load(G_MAIN, FO_BUILTIN_NAME);
id_us_min(&vfont->id);
BLI_assert(vfont->id.us == 0);
return vfont;
@ -431,7 +428,7 @@ VFont *BKE_vfont_builtin_get(void)
static VChar *find_vfont_char(VFontData *vfd, uint character)
{
return BLI_ghash_lookup(vfd->characters, POINTER_FROM_UINT(character));
return static_cast<VChar *>(BLI_ghash_lookup(vfd->characters, POINTER_FROM_UINT(character)));
}
static void build_underline(Curve *cu,
@ -448,8 +445,8 @@ static void build_underline(Curve *cu,
nu2 = (Nurb *)MEM_callocN(sizeof(Nurb), "underline_nurb");
nu2->resolu = cu->resolu;
nu2->bezt = NULL;
nu2->knotsu = nu2->knotsv = NULL;
nu2->bezt = nullptr;
nu2->knotsu = nu2->knotsv = nullptr;
nu2->charidx = charidx + 1000;
if (mat_nr > 0) {
nu2->mat_nr = mat_nr - 1;
@ -521,9 +518,9 @@ void BKE_vfont_build_char(Curve *cu,
VChar *che = find_vfont_char(vfd, character);
/* Select the glyph data */
Nurb *nu1 = NULL;
Nurb *nu1 = nullptr;
if (che) {
nu1 = che->nurbsbase.first;
nu1 = static_cast<Nurb *>(che->nurbsbase.first);
}
/* Create the character */
@ -531,13 +528,13 @@ void BKE_vfont_build_char(Curve *cu,
BezTriple *bezt1 = nu1->bezt;
if (bezt1) {
Nurb *nu2 = (Nurb *)MEM_mallocN(sizeof(Nurb), "duplichar_nurb");
if (nu2 == NULL) {
if (nu2 == nullptr) {
break;
}
memcpy(nu2, nu1, sizeof(Nurb));
*nu2 = blender::dna::shallow_copy(*nu1);
nu2->resolu = cu->resolu;
nu2->bp = NULL;
nu2->knotsu = nu2->knotsv = NULL;
nu2->bp = nullptr;
nu2->knotsu = nu2->knotsv = nullptr;
nu2->flag = CU_SMOOTH;
nu2->charidx = charidx;
if (info->mat_nr > 0) {
@ -546,12 +543,12 @@ void BKE_vfont_build_char(Curve *cu,
else {
nu2->mat_nr = 0;
}
/* nu2->trim.first = 0; */
/* nu2->trim.last = 0; */
// nu2->trim.first = 0;
// nu2->trim.last = 0;
int u = nu2->pntsu;
BezTriple *bezt2 = (BezTriple *)MEM_malloc_arrayN(u, sizeof(BezTriple), "duplichar_bezt2");
if (bezt2 == NULL) {
if (bezt2 == nullptr) {
MEM_freeN(nu2);
break;
}
@ -623,11 +620,11 @@ void BKE_vfont_build_char(Curve *cu,
int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end)
{
Curve *cu = ob->data;
Curve *cu = static_cast<Curve *>(ob->data);
EditFont *ef = cu->editfont;
int start, end, direction;
if ((ob->type != OB_FONT) || (ef == NULL)) {
if ((ob->type != OB_FONT) || (ef == nullptr)) {
return 0;
}
@ -663,7 +660,7 @@ int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end)
void BKE_vfont_select_clamp(Object *ob)
{
Curve *cu = ob->data;
Curve *cu = static_cast<Curve *>(ob->data);
EditFont *ef = cu->editfont;
BLI_assert((ob->type == OB_FONT) && ef);
@ -676,7 +673,7 @@ void BKE_vfont_select_clamp(Object *ob)
static float char_width(Curve *cu, VChar *che, CharInfo *info)
{
/* The character wasn't found, probably ascii = 0, then the width shall be 0 as well */
if (che == NULL) {
if (che == nullptr) {
return 0.0f;
}
if (info->flag & CU_CHINFO_SMALLCAPS_CHECK) {
@ -752,8 +749,6 @@ typedef struct VFontCursor_Params {
int r_string_offset;
} VFontCursor_Params;
/** \} */
enum {
VFONT_TO_CURVE_INIT = 0,
VFONT_TO_CURVE_BISECT,
@ -818,14 +813,14 @@ static bool vfont_to_curve(Object *ob,
struct CharTrans **r_chartransdata)
{
EditFont *ef = cu->editfont;
EditFontSelBox *selboxes = NULL;
EditFontSelBox *selboxes = nullptr;
VFont *vfont, *oldvfont;
VFontData *vfd = NULL;
CharInfo *info = NULL, *custrinfo;
VFontData *vfd = nullptr;
CharInfo *info = nullptr, *custrinfo;
TextBox tb_scale;
bool use_textbox;
VChar *che;
struct CharTrans *chartransdata = NULL, *ct;
CharTrans *chartransdata = nullptr, *ct;
struct TempLineInfo *lineinfo;
float xof, yof, xtrax, linedist;
float twidth = 0, maxlen = 0;
@ -833,7 +828,7 @@ static bool vfont_to_curve(Object *ob,
int curbox;
int selstart = 0, selend = 0;
int cnr = 0, lnr = 0, wsnr = 0;
const char32_t *mem = NULL;
const char32_t *mem = nullptr;
char32_t ascii;
bool ok = false;
const float font_size = cu->fsize * iter_data->scale_to_fit;
@ -849,8 +844,8 @@ static bool vfont_to_curve(Object *ob,
/* Text at the beginning of the last used text-box (use for y-axis alignment).
* We over-allocate by one to simplify logic of getting last char. */
int *i_textbox_array = MEM_callocN(sizeof(*i_textbox_array) * (cu->totbox + 1),
"TextBox initial char index");
int *i_textbox_array = static_cast<int *>(
MEM_callocN(sizeof(*i_textbox_array) * (cu->totbox + 1), "TextBox initial char index"));
#define MARGIN_X_MIN (xof_scale + tb_scale.x)
#define MARGIN_Y_MIN (yof_scale + tb_scale.y)
@ -858,15 +853,15 @@ static bool vfont_to_curve(Object *ob,
/* NOTE: do calculations including the trailing '\0' of a string
* because the cursor can be at that location. */
BLI_assert(ob == NULL || ob->type == OB_FONT);
BLI_assert(ob == nullptr || ob->type == OB_FONT);
/* Set font data */
vfont = cu->vfont;
if (cu->str == NULL) {
if (cu->str == nullptr) {
return ok;
}
if (vfont == NULL) {
if (vfont == nullptr) {
return ok;
}
@ -887,15 +882,17 @@ static bool vfont_to_curve(Object *ob,
slen = cu->len_char32;
/* Create unicode string */
mem_tmp = MEM_malloc_arrayN((slen + 1), sizeof(*mem_tmp), "convertedmem");
mem_tmp = static_cast<char32_t *>(
MEM_malloc_arrayN((slen + 1), sizeof(*mem_tmp), "convertedmem"));
if (!mem_tmp) {
return ok;
}
BLI_str_utf8_as_utf32(mem_tmp, cu->str, slen + 1);
if (cu->strinfo == NULL) { /* old file */
cu->strinfo = MEM_calloc_arrayN((slen + 4), sizeof(CharInfo), "strinfo compat");
if (cu->strinfo == nullptr) { /* old file */
cu->strinfo = static_cast<CharInfo *>(
MEM_calloc_arrayN((slen + 4), sizeof(CharInfo), "strinfo compat"));
}
custrinfo = cu->strinfo;
if (!custrinfo) {
@ -905,32 +902,36 @@ static bool vfont_to_curve(Object *ob,
mem = mem_tmp;
}
if (cu->tb == NULL) {
cu->tb = MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "TextBox compat");
if (cu->tb == nullptr) {
cu->tb = static_cast<TextBox *>(
MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "TextBox compat"));
}
if (ef != NULL && ob != NULL) {
if (ef != nullptr && ob != nullptr) {
if (ef->selboxes) {
MEM_freeN(ef->selboxes);
}
if (BKE_vfont_select_get(ob, &selstart, &selend)) {
ef->selboxes_len = (selend - selstart) + 1;
ef->selboxes = MEM_calloc_arrayN(ef->selboxes_len, sizeof(EditFontSelBox), "font selboxes");
ef->selboxes = static_cast<EditFontSelBox *>(
MEM_calloc_arrayN(ef->selboxes_len, sizeof(EditFontSelBox), "font selboxes"));
}
else {
ef->selboxes_len = 0;
ef->selboxes = NULL;
ef->selboxes = nullptr;
}
selboxes = ef->selboxes;
}
/* calc offset and rotation of each char */
ct = chartransdata = MEM_calloc_arrayN((slen + 1), sizeof(struct CharTrans), "buildtext");
ct = chartransdata = static_cast<CharTrans *>(
MEM_calloc_arrayN((slen + 1), sizeof(CharTrans), "buildtext"));
/* We assume the worst case: 1 character per line (is freed at end anyway) */
lineinfo = MEM_malloc_arrayN((slen * 2 + 1), sizeof(*lineinfo), "lineinfo");
lineinfo = static_cast<TempLineInfo *>(
MEM_malloc_arrayN((slen * 2 + 1), sizeof(*lineinfo), "lineinfo"));
linedist = cu->linedist;
@ -943,17 +944,17 @@ static bool vfont_to_curve(Object *ob,
xtrax = 0.5f * cu->spacing - 0.5f;
oldvfont = NULL;
oldvfont = nullptr;
for (i = 0; i < slen; i++) {
custrinfo[i].flag &= ~(CU_CHINFO_WRAP | CU_CHINFO_SMALLCAPS_CHECK | CU_CHINFO_OVERFLOW);
}
TextBoxBounds_ForCursor *tb_bounds_for_cursor = NULL;
if (cursor_params != NULL) {
if (cu->textoncurve == NULL && (cu->totbox > 1) && (slen > 0)) {
tb_bounds_for_cursor = MEM_malloc_arrayN(
cu->totbox, sizeof(TextBoxBounds_ForCursor), "TextboxBounds_Cursor");
TextBoxBounds_ForCursor *tb_bounds_for_cursor = nullptr;
if (cursor_params != nullptr) {
if (cu->textoncurve == nullptr && (cu->totbox > 1) && (slen > 0)) {
tb_bounds_for_cursor = static_cast<TextBoxBounds_ForCursor *>(
MEM_malloc_arrayN(cu->totbox, sizeof(TextBoxBounds_ForCursor), "TextboxBounds_Cursor"));
for (curbox = 0; curbox < cu->totbox; curbox++) {
TextBoxBounds_ForCursor *tb_bounds = &tb_bounds_for_cursor[curbox];
tb_bounds->char_index_last = -1;
@ -980,7 +981,7 @@ static bool vfont_to_curve(Object *ob,
vfont = which_vfont(cu, info);
if (vfont == NULL) {
if (vfont == nullptr) {
break;
}
@ -992,7 +993,7 @@ static bool vfont_to_curve(Object *ob,
/* VFont Data for VFont couldn't be found */
if (!vfd) {
MEM_freeN(chartransdata);
chartransdata = NULL;
chartransdata = nullptr;
MEM_freeN(lineinfo);
goto finally;
}
@ -1005,21 +1006,21 @@ static bool vfont_to_curve(Object *ob,
/* The character wasn't in the current curve base so load it.
* But if the font is built-in then do not try loading since
* whole font is in the memory already. */
if (che == NULL && BKE_vfont_is_builtin(vfont) == false) {
if (che == nullptr && BKE_vfont_is_builtin(vfont) == false) {
BLI_rw_mutex_lock(&vfont_rwlock, THREAD_LOCK_WRITE);
/* Check it once again, char might have been already load
* between previous #BLI_rw_mutex_unlock() and this #BLI_rw_mutex_lock().
*
* Such a check should not be a bottleneck since it wouldn't
* happen often once all the chars are load. */
if ((che = find_vfont_char(vfd, ascii)) == NULL) {
if ((che = find_vfont_char(vfd, ascii)) == nullptr) {
che = BKE_vfontdata_char_from_freetypefont(vfont, ascii);
}
BLI_rw_mutex_unlock(&vfont_rwlock);
}
}
else {
che = NULL;
che = nullptr;
}
twidth = char_width(cu, che, info);
@ -1105,7 +1106,7 @@ static bool vfont_to_curve(Object *ob,
CLAMP_MIN(maxlen, lineinfo[lnr].x_min);
if (tb_bounds_for_cursor != NULL) {
if (tb_bounds_for_cursor != nullptr) {
tb_bounds_for_cursor[curbox].char_index_last = i;
}
@ -1152,7 +1153,7 @@ static bool vfont_to_curve(Object *ob,
xof = MARGIN_X_MIN + tabfac;
}
else {
EditFontSelBox *sb = NULL;
EditFontSelBox *sb = nullptr;
float wsfac;
ct->xof = xof;
@ -1244,7 +1245,7 @@ static bool vfont_to_curve(Object *ob,
li->x_min = ((li->x_max - li->x_min) + xof_scale);
if (li->char_nr > 1) {
li->x_min /= (float)(li->char_nr - 1);
li->x_min /= float(li->char_nr - 1);
}
}
for (i = 0; i <= slen; i++) {
@ -1272,7 +1273,7 @@ static bool vfont_to_curve(Object *ob,
struct TempLineInfo *li;
li = &lineinfo[ct->linenr];
curofs += ((li->x_max - li->x_min) + xof_scale) / (float)li->wspace_nr;
curofs += ((li->x_max - li->x_min) + xof_scale) / float(li->wspace_nr);
}
ct->xof += curofs;
}
@ -1368,7 +1369,7 @@ static bool vfont_to_curve(Object *ob,
}
}
}
if (tb_bounds_for_cursor != NULL) {
if (tb_bounds_for_cursor != nullptr) {
int char_beg_next = 0;
for (curbox = 0; curbox < cu->totbox; curbox++) {
TextBoxBounds_ForCursor *tb_bounds = &tb_bounds_for_cursor[curbox];
@ -1398,10 +1399,7 @@ static bool vfont_to_curve(Object *ob,
char_idx_offset += line->char_nr + 1;
}
/* Move the bounds into a space compatible with `cursor_location`. */
bounds->xmin *= font_size;
bounds->xmax *= font_size;
bounds->ymin *= font_size;
bounds->ymax *= font_size;
BLI_rctf_mul(bounds, font_size);
char_beg_next = tb_bounds->char_index_last + 1;
}
@ -1413,15 +1411,15 @@ static bool vfont_to_curve(Object *ob,
/* TEXT ON CURVE */
/* NOTE: Only #OB_CURVES_LEGACY objects could have a path. */
if (cu->textoncurve && cu->textoncurve->type == OB_CURVES_LEGACY) {
BLI_assert(cu->textoncurve->runtime.curve_cache != NULL);
if (cu->textoncurve->runtime.curve_cache != NULL &&
cu->textoncurve->runtime.curve_cache->anim_path_accum_length != NULL)
BLI_assert(cu->textoncurve->runtime.curve_cache != nullptr);
if (cu->textoncurve->runtime.curve_cache != nullptr &&
cu->textoncurve->runtime.curve_cache->anim_path_accum_length != nullptr)
{
float distfac, imat[4][4], imat3[3][3], cmat[3][3];
float minx, maxx;
float timeofs, sizefac;
if (ob != NULL) {
if (ob != nullptr) {
invert_m4_m4(imat, ob->object_to_world);
}
else {
@ -1505,12 +1503,13 @@ static bool vfont_to_curve(Object *ob,
/* Calculate the right loc AND the right rot separately. */
/* `vec` needs 4 items. */
BKE_where_on_path(cu->textoncurve, ctime, vec, NULL, NULL, NULL, NULL);
BKE_where_on_path(cu->textoncurve, ctime + dtime, NULL, rotvec, NULL, NULL, NULL);
BKE_where_on_path(cu->textoncurve, ctime, vec, nullptr, nullptr, nullptr, nullptr);
BKE_where_on_path(
cu->textoncurve, ctime + dtime, nullptr, rotvec, nullptr, nullptr, nullptr);
mul_v3_fl(vec, sizefac);
ct->rot = (float)M_PI - atan2f(rotvec[1], rotvec[0]);
ct->rot = float(M_PI) - atan2f(rotvec[1], rotvec[0]);
si = sinf(ct->rot);
co = cosf(ct->rot);
@ -1660,7 +1659,7 @@ static bool vfont_to_curve(Object *ob,
if (mode == FO_SELCHANGE) {
MEM_freeN(chartransdata);
chartransdata = NULL;
chartransdata = nullptr;
}
else if (mode == FO_EDIT) {
/* Make NURBS-data. */
@ -1668,7 +1667,7 @@ static bool vfont_to_curve(Object *ob,
ct = chartransdata;
for (i = 0; i < slen; i++) {
uint cha = (uint)mem[i];
uint cha = uint(mem[i]);
info = &(custrinfo[i]);
if ((cu->overflow == CU_OVERFLOW_TRUNCATE) && (ob && ob->mode != OB_MODE_EDIT) &&
@ -1683,7 +1682,7 @@ static bool vfont_to_curve(Object *ob,
/* Only do that check in case we do have an object, otherwise all materials get erased every
* time that code is called without an object. */
if (ob != NULL && (info->mat_nr > (ob->totcol))) {
if (ob != nullptr && (info->mat_nr > (ob->totcol))) {
// CLOG_ERROR(
// &LOG, "Illegal material index (%d) in text object, setting to 0", info->mat_nr);
info->mat_nr = 0;
@ -1828,7 +1827,7 @@ static bool vfont_to_curve(Object *ob,
if (slen == 0) {
cursor_params->r_string_offset = -1;
}
else if (cu->textoncurve != NULL) {
else if (cu->textoncurve != nullptr) {
int closest_char = -1;
float closest_dist_sq = FLT_MAX;
@ -1852,7 +1851,7 @@ static bool vfont_to_curve(Object *ob,
int char_beg = 0;
int char_end = slen;
if (tb_bounds_for_cursor != NULL) {
if (tb_bounds_for_cursor != nullptr) {
/* Search for the closest box. */
int closest_box = -1;
float closest_dist_sq = FLT_MAX;
@ -1881,7 +1880,7 @@ static bool vfont_to_curve(Object *ob,
char_end = tb_bounds_for_cursor[closest_box].char_index_last;
}
MEM_freeN(tb_bounds_for_cursor);
tb_bounds_for_cursor = NULL; /* Safety only. */
tb_bounds_for_cursor = nullptr; /* Safety only. */
}
const float interline_offset = ((linedist - 0.5f) / 2.0f) * font_size;
/* Loop until find the line where `cursor_location` is over. */
@ -1920,21 +1919,21 @@ static bool vfont_to_curve(Object *ob,
cursor_params->r_string_offset = i;
}
/* Must be cleared & freed. */
BLI_assert(tb_bounds_for_cursor == NULL);
BLI_assert(tb_bounds_for_cursor == nullptr);
}
/* Scale to fit only works for single text box layouts. */
if (ELEM(iter_data->status, VFONT_TO_CURVE_SCALE_ONCE, VFONT_TO_CURVE_BISECT)) {
/* Always cleanup before going to the scale-to-fit repetition. */
if (r_nubase != NULL) {
if (r_nubase != nullptr) {
BKE_nurbList_free(r_nubase);
}
if (chartransdata != NULL) {
if (chartransdata != nullptr) {
MEM_freeN(chartransdata);
}
if (ef == NULL) {
if (ef == nullptr) {
MEM_freeN((void *)mem);
}
return true;
@ -1945,10 +1944,10 @@ finally:
if (r_text) {
*r_text = mem;
*r_text_len = slen;
*r_text_free = (ef == NULL);
*r_text_free = (ef == nullptr);
}
else {
if (ef == NULL) {
if (ef == nullptr) {
MEM_freeN((void *)mem);
}
}
@ -1983,17 +1982,16 @@ bool BKE_vfont_to_curve_ex(Object *ob,
bool *r_text_free,
struct CharTrans **r_chartransdata)
{
VFontToCurveIter data = {
.iteraction = cu->totbox * FONT_TO_CURVE_SCALE_ITERATIONS,
.scale_to_fit = 1.0f,
.word_wrap = true,
.ok = true,
.status = VFONT_TO_CURVE_INIT,
};
VFontToCurveIter data = {};
data.iteraction = cu->totbox * FONT_TO_CURVE_SCALE_ITERATIONS;
data.scale_to_fit = 1.0f;
data.word_wrap = true;
data.ok = true;
data.status = VFONT_TO_CURVE_INIT;
do {
data.ok &= vfont_to_curve(
ob, cu, mode, &data, NULL, r_nubase, r_text, r_text_len, r_text_free, r_chartransdata);
ob, cu, mode, &data, nullptr, r_nubase, r_text, r_text_len, r_text_free, r_chartransdata);
} while (data.ok && ELEM(data.status, VFONT_TO_CURVE_SCALE_ONCE, VFONT_TO_CURVE_BISECT));
return data.ok;
@ -2005,23 +2003,21 @@ int BKE_vfont_cursor_to_text_index(Object *ob, float cursor_location[2])
ListBase *r_nubase = &cu->nurb;
/* TODO: iterating to calculate the scale can be avoided. */
VFontToCurveIter data = {};
data.iteraction = cu->totbox * FONT_TO_CURVE_SCALE_ITERATIONS;
data.scale_to_fit = 1.0f;
data.word_wrap = true;
data.ok = true;
data.status = VFONT_TO_CURVE_INIT;
VFontToCurveIter data = {
.iteraction = cu->totbox * FONT_TO_CURVE_SCALE_ITERATIONS,
.scale_to_fit = 1.0f,
.word_wrap = true,
.ok = true,
.status = VFONT_TO_CURVE_INIT,
};
VFontCursor_Params cursor_params = {
.cursor_location = {cursor_location[0], cursor_location[1]},
.r_string_offset = -1,
};
VFontCursor_Params cursor_params = {};
cursor_params.cursor_location[0] = cursor_location[0];
cursor_params.cursor_location[1] = cursor_location[1];
cursor_params.r_string_offset = -1;
do {
data.ok &= vfont_to_curve(
ob, cu, FO_CURS, &data, &cursor_params, r_nubase, NULL, NULL, NULL, NULL);
ob, cu, FO_CURS, &data, &cursor_params, r_nubase, nullptr, nullptr, nullptr, nullptr);
} while (data.ok && ELEM(data.status, VFONT_TO_CURVE_SCALE_ONCE, VFONT_TO_CURVE_BISECT));
return cursor_params.r_string_offset;
@ -2034,14 +2030,16 @@ bool BKE_vfont_to_curve_nubase(Object *ob, const eEditFontMode mode, ListBase *r
{
BLI_assert(ob->type == OB_FONT);
return BKE_vfont_to_curve_ex(ob, ob->data, mode, r_nubase, NULL, NULL, NULL, NULL);
return BKE_vfont_to_curve_ex(
ob, static_cast<Curve *>(ob->data), mode, r_nubase, nullptr, nullptr, nullptr, nullptr);
}
bool BKE_vfont_to_curve(Object *ob, const eEditFontMode mode)
{
Curve *cu = ob->data;
Curve *cu = static_cast<Curve *>(ob->data);
return BKE_vfont_to_curve_ex(ob, ob->data, mode, &cu->nurb, NULL, NULL, NULL, NULL);
return BKE_vfont_to_curve_ex(
ob, static_cast<Curve *>(ob->data), mode, &cu->nurb, nullptr, nullptr, nullptr, nullptr);
}
/* -------------------------------------------------------------------- */
@ -2053,7 +2051,7 @@ static struct {
CharInfo *info_buffer;
size_t len_utf32;
size_t len_utf8;
} g_vfont_clipboard = {NULL};
} g_vfont_clipboard = {nullptr};
void BKE_vfont_clipboard_free(void)
{
@ -2071,13 +2069,13 @@ void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf,
/* Clean previous buffers. */
BKE_vfont_clipboard_free();
text = MEM_malloc_arrayN((len + 1), sizeof(*text), __func__);
if (text == NULL) {
text = static_cast<char32_t *>(MEM_malloc_arrayN((len + 1), sizeof(*text), __func__));
if (text == nullptr) {
return;
}
info = MEM_malloc_arrayN(len, sizeof(CharInfo), __func__);
if (info == NULL) {
info = static_cast<struct CharInfo *>(MEM_malloc_arrayN(len, sizeof(CharInfo), __func__));
if (info == nullptr) {
MEM_freeN(text);
return;
}

View File

@ -209,7 +209,7 @@ static VChar *freetypechar_to_vchar(FT_Face face, FT_ULong charcode, const VFont
{
FT_UInt glyph_index = FT_Get_Char_Index(face, charcode);
if (FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) != FT_Err_Ok) {
return NULL;
return nullptr;
}
VChar *che = (VChar *)MEM_callocN(sizeof(VChar), "objfnt_char");
@ -223,16 +223,16 @@ static VChar *freetypechar_to_vchar(FT_Face face, FT_ULong charcode, const VFont
static FT_Face vfont_face_load_from_packed_file(FT_Library library, PackedFile *pf)
{
FT_Face face = NULL;
FT_New_Memory_Face(library, pf->data, pf->size, 0, &face);
FT_Face face = nullptr;
FT_New_Memory_Face(library, static_cast<const FT_Byte *>(pf->data), pf->size, 0, &face);
if (!face) {
return NULL;
return nullptr;
}
/* Font must contain vectors, not bitmaps. */
if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
FT_Done_Face(face);
return NULL;
return nullptr;
}
/* Select a character map. */
@ -245,7 +245,7 @@ static FT_Face vfont_face_load_from_packed_file(FT_Library library, PackedFile *
}
if (err) {
FT_Done_Face(face);
return NULL;
return nullptr;
}
/* Test that we can load glyphs from this font. */
@ -255,7 +255,7 @@ static FT_Face vfont_face_load_from_packed_file(FT_Library library, PackedFile *
FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) != FT_Err_Ok)
{
FT_Done_Face(face);
return NULL;
return nullptr;
}
return face;
@ -263,19 +263,19 @@ static FT_Face vfont_face_load_from_packed_file(FT_Library library, PackedFile *
VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf)
{
FT_Library library = NULL;
FT_Library library = nullptr;
if (FT_Init_FreeType(&library) != FT_Err_Ok) {
return NULL;
return nullptr;
}
FT_Face face = vfont_face_load_from_packed_file(library, pf);
if (!face) {
FT_Done_FreeType(library);
return NULL;
return nullptr;
}
/* allocate blender font */
VFontData *vfd = MEM_callocN(sizeof(*vfd), "FTVFontData");
VFontData *vfd = static_cast<VFontData *>(MEM_callocN(sizeof(*vfd), "FTVFontData"));
/* Get the name. */
if (face->family_name) {
@ -290,7 +290,7 @@ VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf)
if (complete_font) {
/* We can get descender as well, but we simple store descender in relation to the ascender.
* Also note that descender is stored as a negative number. */
vfd->ascender = (float)face->ascender / (face->ascender - face->descender);
vfd->ascender = float(face->ascender) / (face->ascender - face->descender);
}
else {
vfd->ascender = 0.8f;
@ -299,10 +299,10 @@ VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf)
/* Adjust font size */
if (face->bbox.yMax != face->bbox.yMin) {
vfd->scale = (float)(1.0 / (double)(face->bbox.yMax - face->bbox.yMin));
vfd->scale = float(1.0 / double(face->bbox.yMax - face->bbox.yMin));
if (complete_font) {
vfd->em_height = (float)(face->ascender - face->descender) /
vfd->em_height = float(face->ascender - face->descender) /
(face->bbox.yMax - face->bbox.yMin);
}
}
@ -332,16 +332,16 @@ VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf)
static void *vfontdata_copy_characters_value_cb(const void *src)
{
return BKE_vfontdata_char_copy(src);
return BKE_vfontdata_char_copy(static_cast<const VChar *>(src));
}
VFontData *BKE_vfontdata_copy(const VFontData *vfont_src, const int UNUSED(flag))
VFontData *BKE_vfontdata_copy(const VFontData *vfont_src, const int /*flag*/)
{
VFontData *vfont_dst = MEM_dupallocN(vfont_src);
VFontData *vfont_dst = static_cast<VFontData *>(MEM_dupallocN(vfont_src));
if (vfont_src->characters != NULL) {
if (vfont_src->characters != nullptr) {
vfont_dst->characters = BLI_ghash_copy(
vfont_src->characters, NULL, vfontdata_copy_characters_value_cb);
vfont_src->characters, nullptr, vfontdata_copy_characters_value_cb);
}
return vfont_dst;
@ -350,21 +350,21 @@ VFontData *BKE_vfontdata_copy(const VFontData *vfont_src, const int UNUSED(flag)
VChar *BKE_vfontdata_char_from_freetypefont(VFont *vfont, ulong character)
{
if (!vfont) {
return NULL;
return nullptr;
}
/* Init Freetype */
FT_Library library = NULL;
FT_Library library = nullptr;
FT_Error err = FT_Init_FreeType(&library);
if (err) {
/* XXX error("Failed to load the Freetype font library"); */
return NULL;
return nullptr;
}
FT_Face face = vfont_face_load_from_packed_file(library, vfont->temp_pf);
if (!face) {
FT_Done_FreeType(library);
return NULL;
return nullptr;
}
/* Load the character */
@ -379,7 +379,7 @@ VChar *BKE_vfontdata_char_from_freetypefont(VFont *vfont, ulong character)
VChar *BKE_vfontdata_char_copy(const VChar *vchar_src)
{
VChar *vchar_dst = MEM_dupallocN(vchar_src);
VChar *vchar_dst = static_cast<VChar *>(MEM_dupallocN(vchar_src));
BLI_listbase_clear(&vchar_dst->nurbsbase);
BKE_nurbList_duplicate(&vchar_dst->nurbsbase, &vchar_src->nurbsbase);

View File

@ -70,6 +70,8 @@ void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, floa
void BLI_rctf_translate(struct rctf *rect, float x, float y);
void BLI_rcti_translate(struct rcti *rect, int x, int y);
void BLI_rctf_mul(struct rctf *rect, float factor);
void BLI_rcti_mul(struct rcti *rect, int factor);
void BLI_rcti_recenter(struct rcti *rect, int x, int y);
void BLI_rctf_recenter(struct rctf *rect, float x, float y);
void BLI_rcti_resize(struct rcti *rect, int x, int y);

View File

@ -393,7 +393,7 @@ set(LIB
bf_intern_eigen
bf_intern_guardedalloc
extern_wcwidth
PRIVATE bf_intern_atomic
PRIVATE bf::intern::atomic
${ZLIB_LIBRARIES}
${ZSTD_LIBRARIES}
)

Some files were not shown because too many files have changed in this diff Show More