UI: Asset Shelf (Experimental Feature) #104831
|
@ -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()
|
||||
|
||||
|
|
|
@ -119,5 +119,7 @@ ELSE()
|
|||
ENDIF()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
_SYCL_INCLUDE_PARENT_DIR
|
||||
SYCL_COMPILER
|
||||
SYCL_INCLUDE_DIR
|
||||
SYCL_LIBRARY
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() ||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 ")
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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); \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -35,7 +35,7 @@ set(SRC
|
|||
)
|
||||
|
||||
set(LIB
|
||||
PRIVATE bf_intern_atomic
|
||||
PRIVATE bf::intern::atomic
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT UNIX)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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]);
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}
|
||||
)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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); \
|
||||
|
|
|
@ -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) { \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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__);
|
||||
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue