Animation: NLA Vertical Reorder #107990
@ -521,7 +521,8 @@ endif()
|
||||
if(NOT APPLE)
|
||||
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON)
|
||||
option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
|
||||
set(CYCLES_HIP_BINARIES_ARCH gfx900 gfx906 gfx90c gfx902 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 gfx1100 gfx1101 gfx1102 CACHE STRING "AMD HIP architectures to build binaries for")
|
||||
# Radeon VII (gfx906) not currently working with HIP SDK, so left out of the list.
|
||||
set(CYCLES_HIP_BINARIES_ARCH gfx900 gfx90c gfx902 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 gfx1100 gfx1101 gfx1102 CACHE STRING "AMD HIP architectures to build binaries for")
|
||||
mark_as_advanced(WITH_CYCLES_DEVICE_HIP)
|
||||
mark_as_advanced(CYCLES_HIP_BINARIES_ARCH)
|
||||
endif()
|
||||
@ -1580,6 +1581,8 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_NORETURN -Wno-missing-noreturn)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_BUT_SET_VARIABLE -Wno-unused-but-set-variable)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_STRICT_PROTOTYPES -Wno-strict-prototypes)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_BITWISE_INSTEAD_OF_LOGICAL -Wno-bitwise-instead-of-logical)
|
||||
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PRIVATE_FIELD -Wno-unused-private-field)
|
||||
@ -1593,6 +1596,7 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNDEFINED_VAR_TEMPLATE -Wno-undefined-var-template)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_INSTANTIATION_AFTER_SPECIALIZATION -Wno-instantiation-after-specialization)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_MISLEADING_INDENTATION -Wno-misleading-indentation)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_BITWISE_INSTEAD_OF_LOGICAL -Wno-bitwise-instead-of-logical)
|
||||
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
|
||||
|
||||
|
@ -113,8 +113,14 @@ add_dependencies(
|
||||
|
||||
if(BUILD_MODE STREQUAL Release AND WIN32)
|
||||
ExternalProject_Add_Step(external_dpcpp after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${LIBDIR}/dpcpp/bin/clang-cl.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${LIBDIR}/dpcpp/bin/clang-cpp.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/dpcpp ${HARVEST_TARGET}/dpcpp
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/clang-cl.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/clang-cpp.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/clang.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/ld.lld.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/ld64.lld.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/lld.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/lld-link.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/wasm-ld.exe
|
||||
)
|
||||
endif()
|
||||
|
@ -37,18 +37,24 @@ elseif(HIP_HIPCC_EXECUTABLE)
|
||||
set(HIP_VERSION_MINOR 0)
|
||||
set(HIP_VERSION_PATCH 0)
|
||||
|
||||
if(WIN32)
|
||||
set(_hipcc_executable ${HIP_HIPCC_EXECUTABLE}.bat)
|
||||
else()
|
||||
set(_hipcc_executable ${HIP_HIPCC_EXECUTABLE})
|
||||
endif()
|
||||
|
||||
# Get version from the output.
|
||||
execute_process(COMMAND ${HIP_HIPCC_EXECUTABLE} --version
|
||||
OUTPUT_VARIABLE HIP_VERSION_RAW
|
||||
execute_process(COMMAND ${_hipcc_executable} --version
|
||||
OUTPUT_VARIABLE _hip_version_raw
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
# Parse parts.
|
||||
if(HIP_VERSION_RAW MATCHES "HIP version: .*")
|
||||
if(_hip_version_raw MATCHES "HIP version: .*")
|
||||
# Strip the HIP prefix and get list of individual version components.
|
||||
string(REGEX REPLACE
|
||||
".*HIP version: ([.0-9]+).*" "\\1"
|
||||
HIP_SEMANTIC_VERSION "${HIP_VERSION_RAW}")
|
||||
HIP_SEMANTIC_VERSION "${_hip_version_raw}")
|
||||
string(REPLACE "." ";" HIP_VERSION_PARTS "${HIP_SEMANTIC_VERSION}")
|
||||
list(LENGTH HIP_VERSION_PARTS NUM_HIP_VERSION_PARTS)
|
||||
|
||||
@ -71,7 +77,13 @@ elseif(HIP_HIPCC_EXECUTABLE)
|
||||
|
||||
# Construct full semantic version.
|
||||
set(HIP_VERSION "${HIP_VERSION_MAJOR}.${HIP_VERSION_MINOR}.${HIP_VERSION_PATCH}")
|
||||
unset(HIP_VERSION_RAW)
|
||||
unset(_hip_version_raw)
|
||||
unset(_hipcc_executable)
|
||||
else()
|
||||
set(HIP_FOUND FALSE)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(HIP
|
||||
REQUIRED_VARS HIP_HIPCC_EXECUTABLE
|
||||
VERSION_VAR HIP_VERSION)
|
||||
|
@ -82,7 +82,7 @@ if(NOT APPLE)
|
||||
set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_CUBIN_COMPILER OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_HIP_BINARIES OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_HIP_BINARIES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_DEVICE_ONEAPI ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_ONEAPI_BINARIES ON CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
@ -174,7 +174,7 @@ if(SYSTEMSTUBS_LIBRARY)
|
||||
list(APPEND PLATFORM_LINKLIBS SystemStubs)
|
||||
endif()
|
||||
|
||||
string(APPEND PLATFORM_CFLAGS " -pipe -funsigned-char -fno-strict-aliasing")
|
||||
string(APPEND PLATFORM_CFLAGS " -pipe -funsigned-char -fno-strict-aliasing -ffp-contract=off")
|
||||
set(PLATFORM_LINKFLAGS
|
||||
"-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Cocoa -framework Carbon -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework Metal -framework QuartzCore"
|
||||
)
|
||||
|
@ -803,8 +803,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
# Automatically turned on when building with "-march=native". This is
|
||||
# explicitly turned off here as it will make floating point math give a bit
|
||||
# different results. This will lead to automated test failures. So disable
|
||||
# this until we support it. Seems to default to off in clang and the intel
|
||||
# compiler.
|
||||
# this until we support it.
|
||||
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -ffp-contract=off")
|
||||
|
||||
# `maybe-uninitialized` is unreliable in release builds, but fine in debug builds.
|
||||
@ -892,7 +891,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
# CLang is the same as GCC for now.
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
|
||||
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -ffp-contract=off")
|
||||
|
||||
if(WITH_LINKER_MOLD AND _IS_LINKER_DEFAULT)
|
||||
find_program(MOLD_BIN "mold")
|
||||
|
@ -9,7 +9,7 @@ buildbot:
|
||||
cuda11:
|
||||
version: '11.4.1'
|
||||
hip:
|
||||
version: '5.3.22480'
|
||||
version: '5.5.30571'
|
||||
optix:
|
||||
version: '7.3.0'
|
||||
ocloc:
|
||||
|
@ -572,7 +572,7 @@ template<class T> inline bool cmpMinMax(T &minv, T &maxv, const T &val)
|
||||
}
|
||||
template<> inline bool cmpMinMax<Vec3>(Vec3 &minv, Vec3 &maxv, const Vec3 &val)
|
||||
{
|
||||
return (cmpMinMax(minv.x, maxv.x, val.x) | cmpMinMax(minv.y, maxv.y, val.y) |
|
||||
return (cmpMinMax(minv.x, maxv.x, val.x) || cmpMinMax(minv.y, maxv.y, val.y) ||
|
||||
cmpMinMax(minv.z, maxv.z, val.z));
|
||||
}
|
||||
|
||||
|
@ -1683,9 +1683,6 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
||||
col.label(text=iface_("and NVIDIA driver version %s or newer") % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
elif device_type == 'HIP':
|
||||
if True:
|
||||
col.label(text="HIP temporarily disabled due to compiler bugs", icon='BLANK1')
|
||||
else:
|
||||
import sys
|
||||
if sys.platform[:3] == "win":
|
||||
driver_version = "21.Q4"
|
||||
@ -1693,6 +1690,9 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
||||
col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
elif sys.platform.startswith("linux"):
|
||||
if True:
|
||||
col.label(text="HIP temporarily disabled due to compiler bugs", icon='BLANK1')
|
||||
else:
|
||||
driver_version = "22.10"
|
||||
col.label(text="Requires AMD GPU with Vega or RDNA architecture", icon='BLANK1')
|
||||
col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1',
|
||||
|
@ -1061,7 +1061,7 @@ void BlenderSession::ensure_display_driver_if_needed()
|
||||
unique_ptr<BlenderDisplayDriver> display_driver = make_unique<BlenderDisplayDriver>(
|
||||
b_engine, b_scene, background);
|
||||
display_driver_ = display_driver.get();
|
||||
session->set_display_driver(move(display_driver));
|
||||
session->set_display_driver(std::move(display_driver));
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@ -606,7 +606,7 @@ void BVH2::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
|
||||
int4 *bvh_nodes = &bvh->pack.nodes[0];
|
||||
size_t bvh_nodes_size = bvh->pack.nodes.size();
|
||||
|
||||
for (size_t i = 0, j = 0; i < bvh_nodes_size; j++) {
|
||||
for (size_t i = 0; i < bvh_nodes_size;) {
|
||||
size_t nsize, nsize_bbox;
|
||||
if (bvh_nodes[i].x & PATH_RAY_NODE_UNALIGNED) {
|
||||
nsize = BVH_UNALIGNED_NODE_SIZE;
|
||||
|
@ -42,15 +42,19 @@ endif()
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
|
||||
if(UNIX)
|
||||
# Disabled until there is a HIP 5.5 release for Linux.
|
||||
set(WITH_CYCLES_HIP_BINARIES OFF)
|
||||
message(STATUS "HIP temporarily disabled due to compiler bugs")
|
||||
else()
|
||||
# Need at least HIP 5.5 to solve compiler bug affecting the kernel.
|
||||
find_package(HIP 5.5.0)
|
||||
set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES)
|
||||
|
||||
# find_package(HIP)
|
||||
# set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES)
|
||||
|
||||
# if(HIP_FOUND)
|
||||
# message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})")
|
||||
# endif()
|
||||
if(HIP_FOUND)
|
||||
message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT WITH_HIP_DYNLOAD)
|
||||
|
@ -137,7 +137,7 @@ void device_hip_info(vector<DeviceInfo> &devices)
|
||||
info.num = num;
|
||||
|
||||
info.has_nanovdb = true;
|
||||
info.has_light_tree = false;
|
||||
info.has_light_tree = true;
|
||||
info.denoisers = 0;
|
||||
|
||||
info.has_gpu_queue = true;
|
||||
|
@ -866,9 +866,9 @@ char *OneapiDevice::device_capabilities()
|
||||
|
||||
sycl::id<3> max_work_item_sizes =
|
||||
device.get_info<sycl::info::device::max_work_item_sizes<3>>();
|
||||
WRITE_ATTR("max_work_item_sizes_dim0", ((size_t)max_work_item_sizes.get(0)))
|
||||
WRITE_ATTR("max_work_item_sizes_dim1", ((size_t)max_work_item_sizes.get(1)))
|
||||
WRITE_ATTR("max_work_item_sizes_dim2", ((size_t)max_work_item_sizes.get(2)))
|
||||
WRITE_ATTR(max_work_item_sizes_dim0, ((size_t)max_work_item_sizes.get(0)))
|
||||
WRITE_ATTR(max_work_item_sizes_dim1, ((size_t)max_work_item_sizes.get(1)))
|
||||
WRITE_ATTR(max_work_item_sizes_dim2, ((size_t)max_work_item_sizes.get(2)))
|
||||
|
||||
GET_NUM_ATTR(max_work_group_size)
|
||||
GET_NUM_ATTR(max_num_sub_groups)
|
||||
@ -891,7 +891,7 @@ char *OneapiDevice::device_capabilities()
|
||||
GET_NUM_ATTR(native_vector_width_half)
|
||||
|
||||
size_t max_clock_frequency = device.get_info<sycl::info::device::max_clock_frequency>();
|
||||
WRITE_ATTR("max_clock_frequency", max_clock_frequency)
|
||||
WRITE_ATTR(max_clock_frequency, max_clock_frequency)
|
||||
|
||||
GET_NUM_ATTR(address_bits)
|
||||
GET_NUM_ATTR(max_mem_alloc_size)
|
||||
@ -900,7 +900,7 @@ char *OneapiDevice::device_capabilities()
|
||||
* supported so we always return false, even if device supports HW texture usage acceleration.
|
||||
*/
|
||||
bool image_support = false;
|
||||
WRITE_ATTR("image_support", (size_t)image_support)
|
||||
WRITE_ATTR(image_support, (size_t)image_support)
|
||||
|
||||
GET_NUM_ATTR(max_parameter_size)
|
||||
GET_NUM_ATTR(mem_base_addr_align)
|
||||
|
@ -574,7 +574,7 @@ void PathTrace::denoise(const RenderWork &render_work)
|
||||
|
||||
void PathTrace::set_output_driver(unique_ptr<OutputDriver> driver)
|
||||
{
|
||||
output_driver_ = move(driver);
|
||||
output_driver_ = std::move(driver);
|
||||
}
|
||||
|
||||
void PathTrace::set_display_driver(unique_ptr<DisplayDriver> driver)
|
||||
@ -585,7 +585,7 @@ void PathTrace::set_display_driver(unique_ptr<DisplayDriver> driver)
|
||||
destroy_gpu_resources();
|
||||
|
||||
if (driver) {
|
||||
display_ = make_unique<PathTraceDisplay>(move(driver));
|
||||
display_ = make_unique<PathTraceDisplay>(std::move(driver));
|
||||
}
|
||||
else {
|
||||
display_ = nullptr;
|
||||
|
@ -9,7 +9,9 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
PathTraceDisplay::PathTraceDisplay(unique_ptr<DisplayDriver> driver) : driver_(move(driver)) {}
|
||||
PathTraceDisplay::PathTraceDisplay(unique_ptr<DisplayDriver> driver) : driver_(std::move(driver))
|
||||
{
|
||||
}
|
||||
|
||||
void PathTraceDisplay::reset(const BufferParams &buffer_params, const bool reset_rendering)
|
||||
{
|
||||
|
@ -28,6 +28,7 @@ static size_t estimate_single_state_size(const uint kernel_features)
|
||||
#define KERNEL_STRUCT_ARRAY_MEMBER(parent_struct, type, name, feature) \
|
||||
state_size += (kernel_features & (feature)) ? sizeof(type) : 0;
|
||||
#define KERNEL_STRUCT_END(name) \
|
||||
(void)array_index; \
|
||||
break; \
|
||||
}
|
||||
#define KERNEL_STRUCT_END_ARRAY(name, cpu_array_size, gpu_array_size) \
|
||||
@ -139,6 +140,7 @@ void PathTraceWorkGPU::alloc_integrator_soa()
|
||||
integrator_state_gpu_.parent_struct[array_index].name = (type *)array->device_pointer; \
|
||||
}
|
||||
#define KERNEL_STRUCT_END(name) \
|
||||
(void)array_index; \
|
||||
break; \
|
||||
}
|
||||
#define KERNEL_STRUCT_END_ARRAY(name, cpu_array_size, gpu_array_size) \
|
||||
|
@ -51,8 +51,6 @@ ccl_device_inline
|
||||
int object = OBJECT_NONE;
|
||||
float isect_t = ray->tmax;
|
||||
|
||||
int num_hits_in_instance = 0;
|
||||
|
||||
uint num_hits = 0;
|
||||
isect_array->t = ray->tmax;
|
||||
|
||||
@ -152,7 +150,6 @@ ccl_device_inline
|
||||
/* Move on to next entry in intersections array. */
|
||||
isect_array++;
|
||||
num_hits++;
|
||||
num_hits_in_instance++;
|
||||
isect_array->t = isect_t;
|
||||
if (num_hits == max_hits) {
|
||||
return num_hits;
|
||||
@ -193,7 +190,6 @@ ccl_device_inline
|
||||
/* Move on to next entry in intersections array. */
|
||||
isect_array++;
|
||||
num_hits++;
|
||||
num_hits_in_instance++;
|
||||
isect_array->t = isect_t;
|
||||
if (num_hits == max_hits) {
|
||||
return num_hits;
|
||||
@ -219,7 +215,6 @@ ccl_device_inline
|
||||
bvh_instance_push(kg, object, ray, &P, &dir, &idir);
|
||||
#endif
|
||||
|
||||
num_hits_in_instance = 0;
|
||||
isect_array->t = isect_t;
|
||||
|
||||
++stack_ptr;
|
||||
|
@ -79,9 +79,8 @@ CCL_NAMESPACE_BEGIN
|
||||
#define __VISIBILITY_FLAG__
|
||||
#define __VOLUME__
|
||||
|
||||
/* TODO: solve internal compiler errors and enable light tree on HIP. */
|
||||
/* TODO: solve internal compiler perf issue and enable light tree on Metal/AMD. */
|
||||
#if defined(__KERNEL_HIP__) || defined(__KERNEL_METAL_AMD__)
|
||||
#if defined(__KERNEL_METAL_AMD__)
|
||||
# undef __LIGHT_TREE__
|
||||
#endif
|
||||
|
||||
|
@ -15,8 +15,12 @@ set(SRC
|
||||
camera.cpp
|
||||
colorspace.cpp
|
||||
constant_fold.cpp
|
||||
devicescene.cpp
|
||||
film.cpp
|
||||
geometry.cpp
|
||||
geometry_attributes.cpp
|
||||
geometry_bvh.cpp
|
||||
geometry_mesh.cpp
|
||||
hair.cpp
|
||||
image.cpp
|
||||
image_oiio.cpp
|
||||
@ -55,6 +59,7 @@ set(SRC_HEADERS
|
||||
camera.h
|
||||
colorspace.h
|
||||
constant_fold.h
|
||||
devicescene.h
|
||||
film.h
|
||||
geometry.h
|
||||
hair.h
|
||||
|
64
intern/cycles/scene/devicescene.cpp
Normal file
64
intern/cycles/scene/devicescene.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#include "scene/devicescene.h"
|
||||
#include "device/device.h"
|
||||
#include "device/memory.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
DeviceScene::DeviceScene(Device *device)
|
||||
: bvh_nodes(device, "bvh_nodes", MEM_GLOBAL),
|
||||
bvh_leaf_nodes(device, "bvh_leaf_nodes", MEM_GLOBAL),
|
||||
object_node(device, "object_node", MEM_GLOBAL),
|
||||
prim_type(device, "prim_type", MEM_GLOBAL),
|
||||
prim_visibility(device, "prim_visibility", MEM_GLOBAL),
|
||||
prim_index(device, "prim_index", MEM_GLOBAL),
|
||||
prim_object(device, "prim_object", MEM_GLOBAL),
|
||||
prim_time(device, "prim_time", MEM_GLOBAL),
|
||||
tri_verts(device, "tri_verts", MEM_GLOBAL),
|
||||
tri_shader(device, "tri_shader", MEM_GLOBAL),
|
||||
tri_vnormal(device, "tri_vnormal", MEM_GLOBAL),
|
||||
tri_vindex(device, "tri_vindex", MEM_GLOBAL),
|
||||
tri_patch(device, "tri_patch", MEM_GLOBAL),
|
||||
tri_patch_uv(device, "tri_patch_uv", MEM_GLOBAL),
|
||||
curves(device, "curves", MEM_GLOBAL),
|
||||
curve_keys(device, "curve_keys", MEM_GLOBAL),
|
||||
curve_segments(device, "curve_segments", MEM_GLOBAL),
|
||||
patches(device, "patches", MEM_GLOBAL),
|
||||
points(device, "points", MEM_GLOBAL),
|
||||
points_shader(device, "points_shader", MEM_GLOBAL),
|
||||
objects(device, "objects", MEM_GLOBAL),
|
||||
object_motion_pass(device, "object_motion_pass", MEM_GLOBAL),
|
||||
object_motion(device, "object_motion", MEM_GLOBAL),
|
||||
object_flag(device, "object_flag", MEM_GLOBAL),
|
||||
object_volume_step(device, "object_volume_step", MEM_GLOBAL),
|
||||
object_prim_offset(device, "object_prim_offset", MEM_GLOBAL),
|
||||
camera_motion(device, "camera_motion", MEM_GLOBAL),
|
||||
attributes_map(device, "attributes_map", MEM_GLOBAL),
|
||||
attributes_float(device, "attributes_float", MEM_GLOBAL),
|
||||
attributes_float2(device, "attributes_float2", MEM_GLOBAL),
|
||||
attributes_float3(device, "attributes_float3", MEM_GLOBAL),
|
||||
attributes_float4(device, "attributes_float4", MEM_GLOBAL),
|
||||
attributes_uchar4(device, "attributes_uchar4", MEM_GLOBAL),
|
||||
light_distribution(device, "light_distribution", MEM_GLOBAL),
|
||||
lights(device, "lights", MEM_GLOBAL),
|
||||
light_background_marginal_cdf(device, "light_background_marginal_cdf", MEM_GLOBAL),
|
||||
light_background_conditional_cdf(device, "light_background_conditional_cdf", MEM_GLOBAL),
|
||||
light_tree_nodes(device, "light_tree_nodes", MEM_GLOBAL),
|
||||
light_tree_emitters(device, "light_tree_emitters", MEM_GLOBAL),
|
||||
light_to_tree(device, "light_to_tree", MEM_GLOBAL),
|
||||
object_to_tree(device, "object_to_tree", MEM_GLOBAL),
|
||||
object_lookup_offset(device, "object_lookup_offset", MEM_GLOBAL),
|
||||
triangle_to_tree(device, "triangle_to_tree", MEM_GLOBAL),
|
||||
particles(device, "particles", MEM_GLOBAL),
|
||||
svm_nodes(device, "svm_nodes", MEM_GLOBAL),
|
||||
shaders(device, "shaders", MEM_GLOBAL),
|
||||
lookup_table(device, "lookup_table", MEM_GLOBAL),
|
||||
sample_pattern_lut(device, "sample_pattern_lut", MEM_GLOBAL),
|
||||
ies_lights(device, "ies", MEM_GLOBAL)
|
||||
{
|
||||
memset((void *)&data, 0, sizeof(data));
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
101
intern/cycles/scene/devicescene.h
Normal file
101
intern/cycles/scene/devicescene.h
Normal file
@ -0,0 +1,101 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#ifndef __DEVICESCENE_H__
|
||||
#define __DEVICESCENE_H__
|
||||
|
||||
#include "device/device.h"
|
||||
#include "device/memory.h"
|
||||
|
||||
#include "util/types.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class DeviceScene {
|
||||
public:
|
||||
/* BVH */
|
||||
device_vector<int4> bvh_nodes;
|
||||
device_vector<int4> bvh_leaf_nodes;
|
||||
device_vector<int> object_node;
|
||||
device_vector<int> prim_type;
|
||||
device_vector<uint> prim_visibility;
|
||||
device_vector<int> prim_index;
|
||||
device_vector<int> prim_object;
|
||||
device_vector<float2> prim_time;
|
||||
|
||||
/* mesh */
|
||||
device_vector<packed_float3> tri_verts;
|
||||
device_vector<uint> tri_shader;
|
||||
device_vector<packed_float3> tri_vnormal;
|
||||
device_vector<packed_uint3> tri_vindex;
|
||||
device_vector<uint> tri_patch;
|
||||
device_vector<float2> tri_patch_uv;
|
||||
|
||||
device_vector<KernelCurve> curves;
|
||||
device_vector<float4> curve_keys;
|
||||
device_vector<KernelCurveSegment> curve_segments;
|
||||
|
||||
device_vector<uint> patches;
|
||||
|
||||
/* point-cloud */
|
||||
device_vector<float4> points;
|
||||
device_vector<uint> points_shader;
|
||||
|
||||
/* objects */
|
||||
device_vector<KernelObject> objects;
|
||||
device_vector<Transform> object_motion_pass;
|
||||
device_vector<DecomposedTransform> object_motion;
|
||||
device_vector<uint> object_flag;
|
||||
device_vector<float> object_volume_step;
|
||||
device_vector<uint> object_prim_offset;
|
||||
|
||||
/* cameras */
|
||||
device_vector<DecomposedTransform> camera_motion;
|
||||
|
||||
/* attributes */
|
||||
device_vector<AttributeMap> attributes_map;
|
||||
device_vector<float> attributes_float;
|
||||
device_vector<float2> attributes_float2;
|
||||
device_vector<packed_float3> attributes_float3;
|
||||
device_vector<float4> attributes_float4;
|
||||
device_vector<uchar4> attributes_uchar4;
|
||||
|
||||
/* lights */
|
||||
device_vector<KernelLightDistribution> light_distribution;
|
||||
device_vector<KernelLight> lights;
|
||||
device_vector<float2> light_background_marginal_cdf;
|
||||
device_vector<float2> light_background_conditional_cdf;
|
||||
|
||||
/* light tree */
|
||||
device_vector<KernelLightTreeNode> light_tree_nodes;
|
||||
device_vector<KernelLightTreeEmitter> light_tree_emitters;
|
||||
device_vector<uint> light_to_tree;
|
||||
device_vector<uint> object_to_tree;
|
||||
device_vector<uint> object_lookup_offset;
|
||||
device_vector<uint> triangle_to_tree;
|
||||
|
||||
/* particles */
|
||||
device_vector<KernelParticle> particles;
|
||||
|
||||
/* shaders */
|
||||
device_vector<int4> svm_nodes;
|
||||
device_vector<KernelShader> shaders;
|
||||
|
||||
/* lookup tables */
|
||||
device_vector<float> lookup_table;
|
||||
|
||||
/* integrator */
|
||||
device_vector<float> sample_pattern_lut;
|
||||
|
||||
/* IES lights */
|
||||
device_vector<float> ies_lights;
|
||||
|
||||
KernelData data;
|
||||
|
||||
DeviceScene(Device *device);
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __DEVICESCENE_H__ */
|
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,38 @@ class Shader;
|
||||
class Volume;
|
||||
struct PackedBVH;
|
||||
|
||||
/* Set of flags used to help determining what data has been modified or needs reallocation, so we
|
||||
* can decide which device data to free or update. */
|
||||
enum {
|
||||
DEVICE_CURVE_DATA_MODIFIED = (1 << 0),
|
||||
DEVICE_MESH_DATA_MODIFIED = (1 << 1),
|
||||
DEVICE_POINT_DATA_MODIFIED = (1 << 2),
|
||||
|
||||
ATTR_FLOAT_MODIFIED = (1 << 3),
|
||||
ATTR_FLOAT2_MODIFIED = (1 << 4),
|
||||
ATTR_FLOAT3_MODIFIED = (1 << 5),
|
||||
ATTR_FLOAT4_MODIFIED = (1 << 6),
|
||||
ATTR_UCHAR4_MODIFIED = (1 << 7),
|
||||
|
||||
CURVE_DATA_NEED_REALLOC = (1 << 8),
|
||||
MESH_DATA_NEED_REALLOC = (1 << 9),
|
||||
POINT_DATA_NEED_REALLOC = (1 << 10),
|
||||
|
||||
ATTR_FLOAT_NEEDS_REALLOC = (1 << 11),
|
||||
ATTR_FLOAT2_NEEDS_REALLOC = (1 << 12),
|
||||
ATTR_FLOAT3_NEEDS_REALLOC = (1 << 13),
|
||||
ATTR_FLOAT4_NEEDS_REALLOC = (1 << 14),
|
||||
|
||||
ATTR_UCHAR4_NEEDS_REALLOC = (1 << 15),
|
||||
|
||||
ATTRS_NEED_REALLOC = (ATTR_FLOAT_NEEDS_REALLOC | ATTR_FLOAT2_NEEDS_REALLOC |
|
||||
ATTR_FLOAT3_NEEDS_REALLOC | ATTR_FLOAT4_NEEDS_REALLOC |
|
||||
ATTR_UCHAR4_NEEDS_REALLOC),
|
||||
DEVICE_MESH_DATA_NEEDS_REALLOC = (MESH_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC),
|
||||
DEVICE_POINT_DATA_NEEDS_REALLOC = (POINT_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC),
|
||||
DEVICE_CURVE_DATA_NEEDS_REALLOC = (CURVE_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC),
|
||||
};
|
||||
|
||||
/* Geometry
|
||||
*
|
||||
* Base class for geometric types like Mesh and Hair. */
|
||||
|
722
intern/cycles/scene/geometry_attributes.cpp
Normal file
722
intern/cycles/scene/geometry_attributes.cpp
Normal file
@ -0,0 +1,722 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#include "bvh/bvh.h"
|
||||
#include "bvh/bvh2.h"
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
#include "scene/attribute.h"
|
||||
#include "scene/camera.h"
|
||||
#include "scene/geometry.h"
|
||||
#include "scene/hair.h"
|
||||
#include "scene/light.h"
|
||||
#include "scene/mesh.h"
|
||||
#include "scene/object.h"
|
||||
#include "scene/pointcloud.h"
|
||||
#include "scene/scene.h"
|
||||
#include "scene/shader.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "scene/stats.h"
|
||||
#include "scene/volume.h"
|
||||
|
||||
#include "subd/patch_table.h"
|
||||
#include "subd/split.h"
|
||||
|
||||
#include "kernel/osl/globals.h"
|
||||
|
||||
#include "util/foreach.h"
|
||||
#include "util/log.h"
|
||||
#include "util/progress.h"
|
||||
#include "util/task.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
bool Geometry::need_attribute(Scene *scene, AttributeStandard std)
|
||||
{
|
||||
if (std == ATTR_STD_NONE)
|
||||
return false;
|
||||
|
||||
if (scene->need_global_attribute(std))
|
||||
return true;
|
||||
|
||||
foreach (Node *node, used_shaders) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
if (shader->attributes.find(std))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Geometry::need_attribute(Scene * /*scene*/, ustring name)
|
||||
{
|
||||
if (name == ustring())
|
||||
return false;
|
||||
|
||||
foreach (Node *node, used_shaders) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
if (shader->attributes.find(name))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AttributeRequestSet Geometry::needed_attributes()
|
||||
{
|
||||
AttributeRequestSet result;
|
||||
|
||||
foreach (Node *node, used_shaders) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
result.add(shader->attributes);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Geometry::has_voxel_attributes() const
|
||||
{
|
||||
foreach (const Attribute &attr, attributes.attributes) {
|
||||
if (attr.element == ATTR_ELEMENT_VOXEL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Generate a normal attribute map entry from an attribute descriptor. */
|
||||
static void emit_attribute_map_entry(AttributeMap *attr_map,
|
||||
size_t index,
|
||||
uint64_t id,
|
||||
TypeDesc type,
|
||||
const AttributeDescriptor &desc)
|
||||
{
|
||||
attr_map[index].id = id;
|
||||
attr_map[index].element = desc.element;
|
||||
attr_map[index].offset = as_uint(desc.offset);
|
||||
|
||||
if (type == TypeDesc::TypeFloat)
|
||||
attr_map[index].type = NODE_ATTR_FLOAT;
|
||||
else if (type == TypeDesc::TypeMatrix)
|
||||
attr_map[index].type = NODE_ATTR_MATRIX;
|
||||
else if (type == TypeFloat2)
|
||||
attr_map[index].type = NODE_ATTR_FLOAT2;
|
||||
else if (type == TypeFloat4)
|
||||
attr_map[index].type = NODE_ATTR_FLOAT4;
|
||||
else if (type == TypeRGBA)
|
||||
attr_map[index].type = NODE_ATTR_RGBA;
|
||||
else
|
||||
attr_map[index].type = NODE_ATTR_FLOAT3;
|
||||
|
||||
attr_map[index].flags = desc.flags;
|
||||
}
|
||||
|
||||
/* Generate an attribute map end marker, optionally including a link to another map.
|
||||
* Links are used to connect object attribute maps to mesh attribute maps. */
|
||||
static void emit_attribute_map_terminator(AttributeMap *attr_map,
|
||||
size_t index,
|
||||
bool chain,
|
||||
uint chain_link)
|
||||
{
|
||||
for (int j = 0; j < ATTR_PRIM_TYPES; j++) {
|
||||
attr_map[index + j].id = ATTR_STD_NONE;
|
||||
attr_map[index + j].element = chain; /* link is valid flag */
|
||||
attr_map[index + j].offset = chain ? chain_link + j : 0; /* link to the correct sub-entry */
|
||||
attr_map[index + j].type = 0;
|
||||
attr_map[index + j].flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate all necessary attribute map entries from the attribute request. */
|
||||
static void emit_attribute_mapping(
|
||||
AttributeMap *attr_map, size_t index, uint64_t id, AttributeRequest &req, Geometry *geom)
|
||||
{
|
||||
emit_attribute_map_entry(attr_map, index, id, req.type, req.desc);
|
||||
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
if (mesh->get_num_subd_faces()) {
|
||||
emit_attribute_map_entry(attr_map, index + 1, id, req.subd_type, req.subd_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryManager::update_svm_attributes(Device *,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
vector<AttributeRequestSet> &geom_attributes,
|
||||
vector<AttributeRequestSet> &object_attributes)
|
||||
{
|
||||
/* for SVM, the attributes_map table is used to lookup the offset of an
|
||||
* attribute, based on a unique shader attribute id. */
|
||||
|
||||
/* compute array stride */
|
||||
size_t attr_map_size = 0;
|
||||
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
geom->attr_map_offset = attr_map_size;
|
||||
|
||||
#ifdef WITH_OSL
|
||||
size_t attr_count = 0;
|
||||
foreach (AttributeRequest &req, geom_attributes[i].requests) {
|
||||
if (req.std != ATTR_STD_NONE &&
|
||||
scene->shader_manager->get_attribute_id(req.std) != (uint64_t)req.std)
|
||||
attr_count += 2;
|
||||
else
|
||||
attr_count += 1;
|
||||
}
|
||||
#else
|
||||
const size_t attr_count = geom_attributes[i].size();
|
||||
#endif
|
||||
|
||||
attr_map_size += (attr_count + 1) * ATTR_PRIM_TYPES;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
|
||||
/* only allocate a table for the object if it actually has attributes */
|
||||
if (object_attributes[i].size() == 0) {
|
||||
object->attr_map_offset = 0;
|
||||
}
|
||||
else {
|
||||
object->attr_map_offset = attr_map_size;
|
||||
attr_map_size += (object_attributes[i].size() + 1) * ATTR_PRIM_TYPES;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_map_size == 0)
|
||||
return;
|
||||
|
||||
if (!dscene->attributes_map.need_realloc()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* create attribute map */
|
||||
AttributeMap *attr_map = dscene->attributes_map.alloc(attr_map_size);
|
||||
memset(attr_map, 0, dscene->attributes_map.size() * sizeof(*attr_map));
|
||||
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
AttributeRequestSet &attributes = geom_attributes[i];
|
||||
|
||||
/* set geometry attributes */
|
||||
size_t index = geom->attr_map_offset;
|
||||
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
uint64_t id;
|
||||
if (req.std == ATTR_STD_NONE)
|
||||
id = scene->shader_manager->get_attribute_id(req.name);
|
||||
else
|
||||
id = scene->shader_manager->get_attribute_id(req.std);
|
||||
|
||||
emit_attribute_mapping(attr_map, index, id, req, geom);
|
||||
index += ATTR_PRIM_TYPES;
|
||||
|
||||
#ifdef WITH_OSL
|
||||
/* Some standard attributes are explicitly referenced via their standard ID, so add those
|
||||
* again in case they were added under a different attribute ID. */
|
||||
if (req.std != ATTR_STD_NONE && id != (uint64_t)req.std) {
|
||||
emit_attribute_mapping(attr_map, index, (uint64_t)req.std, req, geom);
|
||||
index += ATTR_PRIM_TYPES;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
emit_attribute_map_terminator(attr_map, index, false, 0);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
AttributeRequestSet &attributes = object_attributes[i];
|
||||
|
||||
/* set object attributes */
|
||||
if (attributes.size() > 0) {
|
||||
size_t index = object->attr_map_offset;
|
||||
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
uint64_t id;
|
||||
if (req.std == ATTR_STD_NONE)
|
||||
id = scene->shader_manager->get_attribute_id(req.name);
|
||||
else
|
||||
id = scene->shader_manager->get_attribute_id(req.std);
|
||||
|
||||
emit_attribute_mapping(attr_map, index, id, req, object->geometry);
|
||||
index += ATTR_PRIM_TYPES;
|
||||
}
|
||||
|
||||
emit_attribute_map_terminator(attr_map, index, true, object->geometry->attr_map_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy to device */
|
||||
dscene->attributes_map.copy_to_device();
|
||||
}
|
||||
|
||||
void GeometryManager::update_attribute_element_offset(Geometry *geom,
|
||||
device_vector<float> &attr_float,
|
||||
size_t &attr_float_offset,
|
||||
device_vector<float2> &attr_float2,
|
||||
size_t &attr_float2_offset,
|
||||
device_vector<packed_float3> &attr_float3,
|
||||
size_t &attr_float3_offset,
|
||||
device_vector<float4> &attr_float4,
|
||||
size_t &attr_float4_offset,
|
||||
device_vector<uchar4> &attr_uchar4,
|
||||
size_t &attr_uchar4_offset,
|
||||
Attribute *mattr,
|
||||
AttributePrimitive prim,
|
||||
TypeDesc &type,
|
||||
AttributeDescriptor &desc)
|
||||
{
|
||||
if (mattr) {
|
||||
/* store element and type */
|
||||
desc.element = mattr->element;
|
||||
desc.flags = mattr->flags;
|
||||
type = mattr->type;
|
||||
|
||||
/* store attribute data in arrays */
|
||||
size_t size = mattr->element_size(geom, prim);
|
||||
|
||||
AttributeElement &element = desc.element;
|
||||
int &offset = desc.offset;
|
||||
|
||||
if (mattr->element == ATTR_ELEMENT_VOXEL) {
|
||||
/* store slot in offset value */
|
||||
ImageHandle &handle = mattr->data_voxel();
|
||||
offset = handle.svm_slot();
|
||||
}
|
||||
else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
|
||||
uchar4 *data = mattr->data_uchar4();
|
||||
offset = attr_uchar4_offset;
|
||||
|
||||
assert(attr_uchar4.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_uchar4[offset + k] = data[k];
|
||||
}
|
||||
attr_uchar4.tag_modified();
|
||||
}
|
||||
attr_uchar4_offset += size;
|
||||
}
|
||||
else if (mattr->type == TypeDesc::TypeFloat) {
|
||||
float *data = mattr->data_float();
|
||||
offset = attr_float_offset;
|
||||
|
||||
assert(attr_float.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float[offset + k] = data[k];
|
||||
}
|
||||
attr_float.tag_modified();
|
||||
}
|
||||
attr_float_offset += size;
|
||||
}
|
||||
else if (mattr->type == TypeFloat2) {
|
||||
float2 *data = mattr->data_float2();
|
||||
offset = attr_float2_offset;
|
||||
|
||||
assert(attr_float2.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float2[offset + k] = data[k];
|
||||
}
|
||||
attr_float2.tag_modified();
|
||||
}
|
||||
attr_float2_offset += size;
|
||||
}
|
||||
else if (mattr->type == TypeDesc::TypeMatrix) {
|
||||
Transform *tfm = mattr->data_transform();
|
||||
offset = attr_float4_offset;
|
||||
|
||||
assert(attr_float4.size() >= offset + size * 3);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size * 3; k++) {
|
||||
attr_float4[offset + k] = (&tfm->x)[k];
|
||||
}
|
||||
attr_float4.tag_modified();
|
||||
}
|
||||
attr_float4_offset += size * 3;
|
||||
}
|
||||
else if (mattr->type == TypeFloat4 || mattr->type == TypeRGBA) {
|
||||
float4 *data = mattr->data_float4();
|
||||
offset = attr_float4_offset;
|
||||
|
||||
assert(attr_float4.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float4[offset + k] = data[k];
|
||||
}
|
||||
attr_float4.tag_modified();
|
||||
}
|
||||
attr_float4_offset += size;
|
||||
}
|
||||
else {
|
||||
float3 *data = mattr->data_float3();
|
||||
offset = attr_float3_offset;
|
||||
|
||||
assert(attr_float3.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float3[offset + k] = data[k];
|
||||
}
|
||||
attr_float3.tag_modified();
|
||||
}
|
||||
attr_float3_offset += size;
|
||||
}
|
||||
|
||||
/* mesh vertex/curve index is global, not per object, so we sneak
|
||||
* a correction for that in here */
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK &&
|
||||
desc.flags & ATTR_SUBDIVIDED) {
|
||||
/* Indices for subdivided attributes are retrieved
|
||||
* from patch table so no need for correction here. */
|
||||
}
|
||||
else if (element == ATTR_ELEMENT_VERTEX)
|
||||
offset -= mesh->vert_offset;
|
||||
else if (element == ATTR_ELEMENT_VERTEX_MOTION)
|
||||
offset -= mesh->vert_offset;
|
||||
else if (element == ATTR_ELEMENT_FACE) {
|
||||
if (prim == ATTR_PRIM_GEOMETRY)
|
||||
offset -= mesh->prim_offset;
|
||||
else
|
||||
offset -= mesh->face_offset;
|
||||
}
|
||||
else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
|
||||
if (prim == ATTR_PRIM_GEOMETRY)
|
||||
offset -= 3 * mesh->prim_offset;
|
||||
else
|
||||
offset -= mesh->corner_offset;
|
||||
}
|
||||
}
|
||||
else if (geom->is_hair()) {
|
||||
Hair *hair = static_cast<Hair *>(geom);
|
||||
if (element == ATTR_ELEMENT_CURVE)
|
||||
offset -= hair->prim_offset;
|
||||
else if (element == ATTR_ELEMENT_CURVE_KEY)
|
||||
offset -= hair->curve_key_offset;
|
||||
else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION)
|
||||
offset -= hair->curve_key_offset;
|
||||
}
|
||||
else if (geom->is_pointcloud()) {
|
||||
if (element == ATTR_ELEMENT_VERTEX)
|
||||
offset -= geom->prim_offset;
|
||||
else if (element == ATTR_ELEMENT_VERTEX_MOTION)
|
||||
offset -= geom->prim_offset;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* attribute not found */
|
||||
desc.element = ATTR_ELEMENT_NONE;
|
||||
desc.offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_attribute_element_size(Geometry *geom,
|
||||
Attribute *mattr,
|
||||
AttributePrimitive prim,
|
||||
size_t *attr_float_size,
|
||||
size_t *attr_float2_size,
|
||||
size_t *attr_float3_size,
|
||||
size_t *attr_float4_size,
|
||||
size_t *attr_uchar4_size)
|
||||
{
|
||||
if (mattr) {
|
||||
size_t size = mattr->element_size(geom, prim);
|
||||
|
||||
if (mattr->element == ATTR_ELEMENT_VOXEL) {
|
||||
/* pass */
|
||||
}
|
||||
else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
|
||||
*attr_uchar4_size += size;
|
||||
}
|
||||
else if (mattr->type == TypeDesc::TypeFloat) {
|
||||
*attr_float_size += size;
|
||||
}
|
||||
else if (mattr->type == TypeFloat2) {
|
||||
*attr_float2_size += size;
|
||||
}
|
||||
else if (mattr->type == TypeDesc::TypeMatrix) {
|
||||
*attr_float4_size += size * 4;
|
||||
}
|
||||
else if (mattr->type == TypeFloat4 || mattr->type == TypeRGBA) {
|
||||
*attr_float4_size += size;
|
||||
}
|
||||
else {
|
||||
*attr_float3_size += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryManager::device_update_attributes(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
progress.set_status("Updating Mesh", "Computing attributes");
|
||||
|
||||
/* gather per mesh requested attributes. as meshes may have multiple
|
||||
* shaders assigned, this merges the requested attributes that have
|
||||
* been set per shader by the shader manager */
|
||||
vector<AttributeRequestSet> geom_attributes(scene->geometry.size());
|
||||
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
|
||||
geom->index = i;
|
||||
scene->need_global_attributes(geom_attributes[i]);
|
||||
|
||||
foreach (Node *node, geom->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
geom_attributes[i].add(shader->attributes);
|
||||
}
|
||||
|
||||
if (geom->is_hair() && static_cast<Hair *>(geom)->need_shadow_transparency()) {
|
||||
geom_attributes[i].add(ATTR_STD_SHADOW_TRANSPARENCY);
|
||||
}
|
||||
}
|
||||
|
||||
/* convert object attributes to use the same data structures as geometry ones */
|
||||
vector<AttributeRequestSet> object_attributes(scene->objects.size());
|
||||
vector<AttributeSet> object_attribute_values;
|
||||
|
||||
object_attribute_values.reserve(scene->objects.size());
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
Geometry *geom = object->geometry;
|
||||
size_t geom_idx = geom->index;
|
||||
|
||||
assert(geom_idx < scene->geometry.size() && scene->geometry[geom_idx] == geom);
|
||||
|
||||
object_attribute_values.push_back(AttributeSet(geom, ATTR_PRIM_GEOMETRY));
|
||||
|
||||
AttributeRequestSet &geom_requests = geom_attributes[geom_idx];
|
||||
AttributeRequestSet &attributes = object_attributes[i];
|
||||
AttributeSet &values = object_attribute_values[i];
|
||||
|
||||
for (size_t j = 0; j < object->attributes.size(); j++) {
|
||||
ParamValue ¶m = object->attributes[j];
|
||||
|
||||
/* add attributes that are requested and not already handled by the mesh */
|
||||
if (geom_requests.find(param.name()) && !geom->attributes.find(param.name())) {
|
||||
attributes.add(param.name());
|
||||
|
||||
Attribute *attr = values.add(param.name(), param.type(), ATTR_ELEMENT_OBJECT);
|
||||
assert(param.datasize() == attr->buffer.size());
|
||||
memcpy(attr->buffer.data(), param.data(), param.datasize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* mesh attribute are stored in a single array per data type. here we fill
|
||||
* those arrays, and set the offset and element type to create attribute
|
||||
* maps next */
|
||||
|
||||
/* Pre-allocate attributes to avoid arrays re-allocation which would
|
||||
* take 2x of overall attribute memory usage.
|
||||
*/
|
||||
size_t attr_float_size = 0;
|
||||
size_t attr_float2_size = 0;
|
||||
size_t attr_float3_size = 0;
|
||||
size_t attr_float4_size = 0;
|
||||
size_t attr_uchar4_size = 0;
|
||||
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
AttributeRequestSet &attributes = geom_attributes[i];
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
Attribute *attr = geom->attributes.find(req);
|
||||
|
||||
update_attribute_element_size(geom,
|
||||
attr,
|
||||
ATTR_PRIM_GEOMETRY,
|
||||
&attr_float_size,
|
||||
&attr_float2_size,
|
||||
&attr_float3_size,
|
||||
&attr_float4_size,
|
||||
&attr_uchar4_size);
|
||||
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
Attribute *subd_attr = mesh->subd_attributes.find(req);
|
||||
|
||||
update_attribute_element_size(mesh,
|
||||
subd_attr,
|
||||
ATTR_PRIM_SUBD,
|
||||
&attr_float_size,
|
||||
&attr_float2_size,
|
||||
&attr_float3_size,
|
||||
&attr_float4_size,
|
||||
&attr_uchar4_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
|
||||
foreach (Attribute &attr, object_attribute_values[i].attributes) {
|
||||
update_attribute_element_size(object->geometry,
|
||||
&attr,
|
||||
ATTR_PRIM_GEOMETRY,
|
||||
&attr_float_size,
|
||||
&attr_float2_size,
|
||||
&attr_float3_size,
|
||||
&attr_float4_size,
|
||||
&attr_uchar4_size);
|
||||
}
|
||||
}
|
||||
|
||||
dscene->attributes_float.alloc(attr_float_size);
|
||||
dscene->attributes_float2.alloc(attr_float2_size);
|
||||
dscene->attributes_float3.alloc(attr_float3_size);
|
||||
dscene->attributes_float4.alloc(attr_float4_size);
|
||||
dscene->attributes_uchar4.alloc(attr_uchar4_size);
|
||||
|
||||
/* The order of those flags needs to match that of AttrKernelDataType. */
|
||||
const bool attributes_need_realloc[AttrKernelDataType::NUM] = {
|
||||
dscene->attributes_float.need_realloc(),
|
||||
dscene->attributes_float2.need_realloc(),
|
||||
dscene->attributes_float3.need_realloc(),
|
||||
dscene->attributes_float4.need_realloc(),
|
||||
dscene->attributes_uchar4.need_realloc(),
|
||||
};
|
||||
|
||||
size_t attr_float_offset = 0;
|
||||
size_t attr_float2_offset = 0;
|
||||
size_t attr_float3_offset = 0;
|
||||
size_t attr_float4_offset = 0;
|
||||
size_t attr_uchar4_offset = 0;
|
||||
|
||||
/* Fill in attributes. */
|
||||
for (size_t i = 0; i < scene->geometry.size(); i++) {
|
||||
Geometry *geom = scene->geometry[i];
|
||||
AttributeRequestSet &attributes = geom_attributes[i];
|
||||
|
||||
/* todo: we now store std and name attributes from requests even if
|
||||
* they actually refer to the same mesh attributes, optimize */
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
Attribute *attr = geom->attributes.find(req);
|
||||
|
||||
if (attr) {
|
||||
/* force a copy if we need to reallocate all the data */
|
||||
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
|
||||
}
|
||||
|
||||
update_attribute_element_offset(geom,
|
||||
dscene->attributes_float,
|
||||
attr_float_offset,
|
||||
dscene->attributes_float2,
|
||||
attr_float2_offset,
|
||||
dscene->attributes_float3,
|
||||
attr_float3_offset,
|
||||
dscene->attributes_float4,
|
||||
attr_float4_offset,
|
||||
dscene->attributes_uchar4,
|
||||
attr_uchar4_offset,
|
||||
attr,
|
||||
ATTR_PRIM_GEOMETRY,
|
||||
req.type,
|
||||
req.desc);
|
||||
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
Attribute *subd_attr = mesh->subd_attributes.find(req);
|
||||
|
||||
if (subd_attr) {
|
||||
/* force a copy if we need to reallocate all the data */
|
||||
subd_attr->modified |= attributes_need_realloc[Attribute::kernel_type(*subd_attr)];
|
||||
}
|
||||
|
||||
update_attribute_element_offset(mesh,
|
||||
dscene->attributes_float,
|
||||
attr_float_offset,
|
||||
dscene->attributes_float2,
|
||||
attr_float2_offset,
|
||||
dscene->attributes_float3,
|
||||
attr_float3_offset,
|
||||
dscene->attributes_float4,
|
||||
attr_float4_offset,
|
||||
dscene->attributes_uchar4,
|
||||
attr_uchar4_offset,
|
||||
subd_attr,
|
||||
ATTR_PRIM_SUBD,
|
||||
req.subd_type,
|
||||
req.subd_desc);
|
||||
}
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
Object *object = scene->objects[i];
|
||||
AttributeRequestSet &attributes = object_attributes[i];
|
||||
AttributeSet &values = object_attribute_values[i];
|
||||
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
Attribute *attr = values.find(req);
|
||||
|
||||
if (attr) {
|
||||
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
|
||||
}
|
||||
|
||||
update_attribute_element_offset(object->geometry,
|
||||
dscene->attributes_float,
|
||||
attr_float_offset,
|
||||
dscene->attributes_float2,
|
||||
attr_float2_offset,
|
||||
dscene->attributes_float3,
|
||||
attr_float3_offset,
|
||||
dscene->attributes_float4,
|
||||
attr_float4_offset,
|
||||
dscene->attributes_uchar4,
|
||||
attr_uchar4_offset,
|
||||
attr,
|
||||
ATTR_PRIM_GEOMETRY,
|
||||
req.type,
|
||||
req.desc);
|
||||
|
||||
/* object attributes don't care about subdivision */
|
||||
req.subd_type = req.type;
|
||||
req.subd_desc = req.desc;
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* create attribute lookup maps */
|
||||
if (scene->shader_manager->use_osl())
|
||||
update_osl_globals(device, scene);
|
||||
|
||||
update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes);
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
|
||||
/* copy to device */
|
||||
progress.set_status("Updating Mesh", "Copying Attributes to device");
|
||||
|
||||
dscene->attributes_float.copy_to_device_if_modified();
|
||||
dscene->attributes_float2.copy_to_device_if_modified();
|
||||
dscene->attributes_float3.copy_to_device_if_modified();
|
||||
dscene->attributes_float4.copy_to_device_if_modified();
|
||||
dscene->attributes_uchar4.copy_to_device_if_modified();
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
|
||||
/* After mesh attributes and patch tables have been copied to device memory,
|
||||
* we need to update offsets in the objects. */
|
||||
scene->object_manager->device_update_geom_offsets(device, dscene, scene);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
196
intern/cycles/scene/geometry_bvh.cpp
Normal file
196
intern/cycles/scene/geometry_bvh.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#include "bvh/bvh.h"
|
||||
#include "bvh/bvh2.h"
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
#include "scene/attribute.h"
|
||||
#include "scene/camera.h"
|
||||
#include "scene/geometry.h"
|
||||
#include "scene/hair.h"
|
||||
#include "scene/light.h"
|
||||
#include "scene/mesh.h"
|
||||
#include "scene/object.h"
|
||||
#include "scene/pointcloud.h"
|
||||
#include "scene/scene.h"
|
||||
#include "scene/shader.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "scene/stats.h"
|
||||
#include "scene/volume.h"
|
||||
|
||||
#include "subd/patch_table.h"
|
||||
#include "subd/split.h"
|
||||
|
||||
#include "kernel/osl/globals.h"
|
||||
|
||||
#include "util/foreach.h"
|
||||
#include "util/log.h"
|
||||
#include "util/progress.h"
|
||||
#include "util/task.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
void Geometry::compute_bvh(Device *device,
|
||||
DeviceScene *dscene,
|
||||
SceneParams *params,
|
||||
Progress *progress,
|
||||
size_t n,
|
||||
size_t total)
|
||||
{
|
||||
if (progress->get_cancel())
|
||||
return;
|
||||
|
||||
compute_bounds();
|
||||
|
||||
const BVHLayout bvh_layout = BVHParams::best_bvh_layout(
|
||||
params->bvh_layout, device->get_bvh_layout_mask(dscene->data.kernel_features));
|
||||
if (need_build_bvh(bvh_layout)) {
|
||||
string msg = "Updating Geometry BVH ";
|
||||
if (name.empty())
|
||||
msg += string_printf("%u/%u", (uint)(n + 1), (uint)total);
|
||||
else
|
||||
msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total);
|
||||
|
||||
Object object;
|
||||
|
||||
/* Ensure all visibility bits are set at the geometry level BVH. In
|
||||
* the object level BVH is where actual visibility is tested. */
|
||||
object.set_is_shadow_catcher(true);
|
||||
object.set_visibility(~0);
|
||||
|
||||
object.set_geometry(this);
|
||||
|
||||
vector<Geometry *> geometry;
|
||||
geometry.push_back(this);
|
||||
vector<Object *> objects;
|
||||
objects.push_back(&object);
|
||||
|
||||
if (bvh && !need_update_rebuild) {
|
||||
progress->set_status(msg, "Refitting BVH");
|
||||
|
||||
bvh->replace_geometry(geometry, objects);
|
||||
|
||||
device->build_bvh(bvh, *progress, true);
|
||||
}
|
||||
else {
|
||||
progress->set_status(msg, "Building BVH");
|
||||
|
||||
BVHParams bparams;
|
||||
bparams.use_spatial_split = params->use_bvh_spatial_split;
|
||||
bparams.use_compact_structure = params->use_bvh_compact_structure;
|
||||
bparams.bvh_layout = bvh_layout;
|
||||
bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
|
||||
params->use_bvh_unaligned_nodes;
|
||||
bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
|
||||
bparams.num_motion_curve_steps = params->num_bvh_time_steps;
|
||||
bparams.num_motion_point_steps = params->num_bvh_time_steps;
|
||||
bparams.bvh_type = params->bvh_type;
|
||||
bparams.curve_subdivisions = params->curve_subdivisions();
|
||||
|
||||
delete bvh;
|
||||
bvh = BVH::create(bparams, geometry, objects, device);
|
||||
MEM_GUARDED_CALL(progress, device->build_bvh, bvh, *progress, false);
|
||||
}
|
||||
}
|
||||
|
||||
need_update_rebuild = false;
|
||||
need_update_bvh_for_offset = false;
|
||||
}
|
||||
|
||||
void GeometryManager::device_update_bvh(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
/* bvh build */
|
||||
progress.set_status("Updating Scene BVH", "Building");
|
||||
|
||||
BVHParams bparams;
|
||||
bparams.top_level = true;
|
||||
bparams.bvh_layout = BVHParams::best_bvh_layout(
|
||||
scene->params.bvh_layout, device->get_bvh_layout_mask(dscene->data.kernel_features));
|
||||
bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
|
||||
bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
|
||||
scene->params.use_bvh_unaligned_nodes;
|
||||
bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
|
||||
bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
|
||||
bparams.num_motion_point_steps = scene->params.num_bvh_time_steps;
|
||||
bparams.bvh_type = scene->params.bvh_type;
|
||||
bparams.curve_subdivisions = scene->params.curve_subdivisions();
|
||||
|
||||
VLOG_INFO << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
|
||||
|
||||
const bool can_refit = scene->bvh != nullptr &&
|
||||
(bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX ||
|
||||
bparams.bvh_layout == BVHLayout::BVH_LAYOUT_METAL);
|
||||
|
||||
BVH *bvh = scene->bvh;
|
||||
if (!scene->bvh) {
|
||||
bvh = scene->bvh = BVH::create(bparams, scene->geometry, scene->objects, device);
|
||||
}
|
||||
|
||||
device->build_bvh(bvh, progress, can_refit);
|
||||
|
||||
if (progress.get_cancel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool has_bvh2_layout = (bparams.bvh_layout == BVH_LAYOUT_BVH2);
|
||||
|
||||
PackedBVH pack;
|
||||
if (has_bvh2_layout) {
|
||||
pack = std::move(static_cast<BVH2 *>(bvh)->pack);
|
||||
}
|
||||
else {
|
||||
pack.root_index = -1;
|
||||
}
|
||||
|
||||
/* copy to device */
|
||||
progress.set_status("Updating Scene BVH", "Copying BVH to device");
|
||||
|
||||
/* When using BVH2, we always have to copy/update the data as its layout is dependent on the
|
||||
* BVH's leaf nodes which may be different when the objects or vertices move. */
|
||||
|
||||
if (pack.nodes.size()) {
|
||||
dscene->bvh_nodes.steal_data(pack.nodes);
|
||||
dscene->bvh_nodes.copy_to_device();
|
||||
}
|
||||
if (pack.leaf_nodes.size()) {
|
||||
dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes);
|
||||
dscene->bvh_leaf_nodes.copy_to_device();
|
||||
}
|
||||
if (pack.object_node.size()) {
|
||||
dscene->object_node.steal_data(pack.object_node);
|
||||
dscene->object_node.copy_to_device();
|
||||
}
|
||||
if (pack.prim_type.size()) {
|
||||
dscene->prim_type.steal_data(pack.prim_type);
|
||||
dscene->prim_type.copy_to_device();
|
||||
}
|
||||
if (pack.prim_visibility.size()) {
|
||||
dscene->prim_visibility.steal_data(pack.prim_visibility);
|
||||
dscene->prim_visibility.copy_to_device();
|
||||
}
|
||||
if (pack.prim_index.size()) {
|
||||
dscene->prim_index.steal_data(pack.prim_index);
|
||||
dscene->prim_index.copy_to_device();
|
||||
}
|
||||
if (pack.prim_object.size()) {
|
||||
dscene->prim_object.steal_data(pack.prim_object);
|
||||
dscene->prim_object.copy_to_device();
|
||||
}
|
||||
if (pack.prim_time.size()) {
|
||||
dscene->prim_time.steal_data(pack.prim_time);
|
||||
dscene->prim_time.copy_to_device();
|
||||
}
|
||||
|
||||
dscene->data.bvh.root = pack.root_index;
|
||||
dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
|
||||
dscene->data.bvh.curve_subdivisions = scene->params.curve_subdivisions();
|
||||
/* The scene handle is set in 'CPUDevice::const_copy_to' and 'OptiXDevice::const_copy_to' */
|
||||
dscene->data.device_bvh = 0;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
223
intern/cycles/scene/geometry_mesh.cpp
Normal file
223
intern/cycles/scene/geometry_mesh.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#include "bvh/bvh.h"
|
||||
#include "bvh/bvh2.h"
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
#include "scene/attribute.h"
|
||||
#include "scene/camera.h"
|
||||
#include "scene/geometry.h"
|
||||
#include "scene/hair.h"
|
||||
#include "scene/light.h"
|
||||
#include "scene/mesh.h"
|
||||
#include "scene/object.h"
|
||||
#include "scene/osl.h"
|
||||
#include "scene/pointcloud.h"
|
||||
#include "scene/scene.h"
|
||||
#include "scene/shader.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "scene/stats.h"
|
||||
#include "scene/volume.h"
|
||||
|
||||
#include "subd/patch_table.h"
|
||||
#include "subd/split.h"
|
||||
|
||||
#ifdef WITH_OSL
|
||||
# include "kernel/osl/globals.h"
|
||||
#endif
|
||||
|
||||
#include "util/foreach.h"
|
||||
#include "util/log.h"
|
||||
#include "util/progress.h"
|
||||
#include "util/task.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
void GeometryManager::device_update_mesh(Device *,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
/* Count. */
|
||||
size_t vert_size = 0;
|
||||
size_t tri_size = 0;
|
||||
|
||||
size_t curve_key_size = 0;
|
||||
size_t curve_size = 0;
|
||||
size_t curve_segment_size = 0;
|
||||
|
||||
size_t point_size = 0;
|
||||
|
||||
size_t patch_size = 0;
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
|
||||
vert_size += mesh->verts.size();
|
||||
tri_size += mesh->num_triangles();
|
||||
|
||||
if (mesh->get_num_subd_faces()) {
|
||||
Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1);
|
||||
patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
|
||||
|
||||
/* patch tables are stored in same array so include them in patch_size */
|
||||
if (mesh->patch_table) {
|
||||
mesh->patch_table_offset = patch_size;
|
||||
patch_size += mesh->patch_table->total_size();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (geom->is_hair()) {
|
||||
Hair *hair = static_cast<Hair *>(geom);
|
||||
|
||||
curve_key_size += hair->get_curve_keys().size();
|
||||
curve_size += hair->num_curves();
|
||||
curve_segment_size += hair->num_segments();
|
||||
}
|
||||
else if (geom->is_pointcloud()) {
|
||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
||||
point_size += pointcloud->num_points();
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in all the arrays. */
|
||||
if (tri_size != 0) {
|
||||
/* normals */
|
||||
progress.set_status("Updating Mesh", "Computing normals");
|
||||
|
||||
packed_float3 *tri_verts = dscene->tri_verts.alloc(vert_size);
|
||||
uint *tri_shader = dscene->tri_shader.alloc(tri_size);
|
||||
packed_float3 *vnormal = dscene->tri_vnormal.alloc(vert_size);
|
||||
packed_uint3 *tri_vindex = dscene->tri_vindex.alloc(tri_size);
|
||||
uint *tri_patch = dscene->tri_patch.alloc(tri_size);
|
||||
float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
|
||||
|
||||
const bool copy_all_data = dscene->tri_shader.need_realloc() ||
|
||||
dscene->tri_vindex.need_realloc() ||
|
||||
dscene->tri_vnormal.need_realloc() ||
|
||||
dscene->tri_patch.need_realloc() ||
|
||||
dscene->tri_patch_uv.need_realloc();
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
|
||||
if (mesh->shader_is_modified() || mesh->smooth_is_modified() ||
|
||||
mesh->triangles_is_modified() || copy_all_data) {
|
||||
mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]);
|
||||
}
|
||||
|
||||
if (mesh->verts_is_modified() || copy_all_data) {
|
||||
mesh->pack_normals(&vnormal[mesh->vert_offset]);
|
||||
}
|
||||
|
||||
if (mesh->verts_is_modified() || mesh->triangles_is_modified() ||
|
||||
mesh->vert_patch_uv_is_modified() || copy_all_data) {
|
||||
mesh->pack_verts(&tri_verts[mesh->vert_offset],
|
||||
&tri_vindex[mesh->prim_offset],
|
||||
&tri_patch[mesh->prim_offset],
|
||||
&tri_patch_uv[mesh->vert_offset]);
|
||||
}
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* vertex coordinates */
|
||||
progress.set_status("Updating Mesh", "Copying Mesh to device");
|
||||
|
||||
dscene->tri_verts.copy_to_device_if_modified();
|
||||
dscene->tri_shader.copy_to_device_if_modified();
|
||||
dscene->tri_vnormal.copy_to_device_if_modified();
|
||||
dscene->tri_vindex.copy_to_device_if_modified();
|
||||
dscene->tri_patch.copy_to_device_if_modified();
|
||||
dscene->tri_patch_uv.copy_to_device_if_modified();
|
||||
}
|
||||
|
||||
if (curve_segment_size != 0) {
|
||||
progress.set_status("Updating Mesh", "Copying Curves to device");
|
||||
|
||||
float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size);
|
||||
KernelCurve *curves = dscene->curves.alloc(curve_size);
|
||||
KernelCurveSegment *curve_segments = dscene->curve_segments.alloc(curve_segment_size);
|
||||
|
||||
const bool copy_all_data = dscene->curve_keys.need_realloc() ||
|
||||
dscene->curves.need_realloc() ||
|
||||
dscene->curve_segments.need_realloc();
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->is_hair()) {
|
||||
Hair *hair = static_cast<Hair *>(geom);
|
||||
|
||||
bool curve_keys_co_modified = hair->curve_radius_is_modified() ||
|
||||
hair->curve_keys_is_modified();
|
||||
bool curve_data_modified = hair->curve_shader_is_modified() ||
|
||||
hair->curve_first_key_is_modified();
|
||||
|
||||
if (!curve_keys_co_modified && !curve_data_modified && !copy_all_data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hair->pack_curves(scene,
|
||||
&curve_keys[hair->curve_key_offset],
|
||||
&curves[hair->prim_offset],
|
||||
&curve_segments[hair->curve_segment_offset]);
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dscene->curve_keys.copy_to_device_if_modified();
|
||||
dscene->curves.copy_to_device_if_modified();
|
||||
dscene->curve_segments.copy_to_device_if_modified();
|
||||
}
|
||||
|
||||
if (point_size != 0) {
|
||||
progress.set_status("Updating Mesh", "Copying Point clouds to device");
|
||||
|
||||
float4 *points = dscene->points.alloc(point_size);
|
||||
uint *points_shader = dscene->points_shader.alloc(point_size);
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->is_pointcloud()) {
|
||||
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
||||
pointcloud->pack(
|
||||
scene, &points[pointcloud->prim_offset], &points_shader[pointcloud->prim_offset]);
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dscene->points.copy_to_device();
|
||||
dscene->points_shader.copy_to_device();
|
||||
}
|
||||
|
||||
if (patch_size != 0 && dscene->patches.need_realloc()) {
|
||||
progress.set_status("Updating Mesh", "Copying Patches to device");
|
||||
|
||||
uint *patch_data = dscene->patches.alloc(patch_size);
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
mesh->pack_patches(&patch_data[mesh->patch_offset]);
|
||||
|
||||
if (mesh->patch_table) {
|
||||
mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset],
|
||||
mesh->patch_table_offset);
|
||||
}
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dscene->patches.copy_to_device();
|
||||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
@ -24,6 +24,7 @@
|
||||
#include "scene/svm.h"
|
||||
#include "scene/tables.h"
|
||||
#include "scene/volume.h"
|
||||
#include "scene/devicescene.h"
|
||||
#include "session/session.h"
|
||||
|
||||
#include "util/foreach.h"
|
||||
@ -33,59 +34,7 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
DeviceScene::DeviceScene(Device *device)
|
||||
: bvh_nodes(device, "bvh_nodes", MEM_GLOBAL),
|
||||
bvh_leaf_nodes(device, "bvh_leaf_nodes", MEM_GLOBAL),
|
||||
object_node(device, "object_node", MEM_GLOBAL),
|
||||
prim_type(device, "prim_type", MEM_GLOBAL),
|
||||
prim_visibility(device, "prim_visibility", MEM_GLOBAL),
|
||||
prim_index(device, "prim_index", MEM_GLOBAL),
|
||||
prim_object(device, "prim_object", MEM_GLOBAL),
|
||||
prim_time(device, "prim_time", MEM_GLOBAL),
|
||||
tri_verts(device, "tri_verts", MEM_GLOBAL),
|
||||
tri_shader(device, "tri_shader", MEM_GLOBAL),
|
||||
tri_vnormal(device, "tri_vnormal", MEM_GLOBAL),
|
||||
tri_vindex(device, "tri_vindex", MEM_GLOBAL),
|
||||
tri_patch(device, "tri_patch", MEM_GLOBAL),
|
||||
tri_patch_uv(device, "tri_patch_uv", MEM_GLOBAL),
|
||||
curves(device, "curves", MEM_GLOBAL),
|
||||
curve_keys(device, "curve_keys", MEM_GLOBAL),
|
||||
curve_segments(device, "curve_segments", MEM_GLOBAL),
|
||||
patches(device, "patches", MEM_GLOBAL),
|
||||
points(device, "points", MEM_GLOBAL),
|
||||
points_shader(device, "points_shader", MEM_GLOBAL),
|
||||
objects(device, "objects", MEM_GLOBAL),
|
||||
object_motion_pass(device, "object_motion_pass", MEM_GLOBAL),
|
||||
object_motion(device, "object_motion", MEM_GLOBAL),
|
||||
object_flag(device, "object_flag", MEM_GLOBAL),
|
||||
object_volume_step(device, "object_volume_step", MEM_GLOBAL),
|
||||
object_prim_offset(device, "object_prim_offset", MEM_GLOBAL),
|
||||
camera_motion(device, "camera_motion", MEM_GLOBAL),
|
||||
attributes_map(device, "attributes_map", MEM_GLOBAL),
|
||||
attributes_float(device, "attributes_float", MEM_GLOBAL),
|
||||
attributes_float2(device, "attributes_float2", MEM_GLOBAL),
|
||||
attributes_float3(device, "attributes_float3", MEM_GLOBAL),
|
||||
attributes_float4(device, "attributes_float4", MEM_GLOBAL),
|
||||
attributes_uchar4(device, "attributes_uchar4", MEM_GLOBAL),
|
||||
light_distribution(device, "light_distribution", MEM_GLOBAL),
|
||||
lights(device, "lights", MEM_GLOBAL),
|
||||
light_background_marginal_cdf(device, "light_background_marginal_cdf", MEM_GLOBAL),
|
||||
light_background_conditional_cdf(device, "light_background_conditional_cdf", MEM_GLOBAL),
|
||||
light_tree_nodes(device, "light_tree_nodes", MEM_GLOBAL),
|
||||
light_tree_emitters(device, "light_tree_emitters", MEM_GLOBAL),
|
||||
light_to_tree(device, "light_to_tree", MEM_GLOBAL),
|
||||
object_to_tree(device, "object_to_tree", MEM_GLOBAL),
|
||||
object_lookup_offset(device, "object_lookup_offset", MEM_GLOBAL),
|
||||
triangle_to_tree(device, "triangle_to_tree", MEM_GLOBAL),
|
||||
particles(device, "particles", MEM_GLOBAL),
|
||||
svm_nodes(device, "svm_nodes", MEM_GLOBAL),
|
||||
shaders(device, "shaders", MEM_GLOBAL),
|
||||
lookup_table(device, "lookup_table", MEM_GLOBAL),
|
||||
sample_pattern_lut(device, "sample_pattern_lut", MEM_GLOBAL),
|
||||
ies_lights(device, "ies", MEM_GLOBAL)
|
||||
{
|
||||
memset((void *)&data, 0, sizeof(data));
|
||||
}
|
||||
|
||||
|
||||
Scene::Scene(const SceneParams ¶ms_, Device *device)
|
||||
: name("Scene"),
|
||||
|
@ -6,20 +6,16 @@
|
||||
|
||||
#include "bvh/params.h"
|
||||
|
||||
#include "scene/devicescene.h"
|
||||
#include "scene/film.h"
|
||||
#include "scene/image.h"
|
||||
#include "scene/shader.h"
|
||||
|
||||
#include "device/device.h"
|
||||
#include "device/memory.h"
|
||||
|
||||
#include "util/param.h"
|
||||
#include "util/string.h"
|
||||
#include "util/system.h"
|
||||
#include "util/texture.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/types.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@ -54,92 +50,6 @@ class RenderStats;
|
||||
class SceneUpdateStats;
|
||||
class Volume;
|
||||
|
||||
/* Scene Device Data */
|
||||
|
||||
class DeviceScene {
|
||||
public:
|
||||
/* BVH */
|
||||
device_vector<int4> bvh_nodes;
|
||||
device_vector<int4> bvh_leaf_nodes;
|
||||
device_vector<int> object_node;
|
||||
device_vector<int> prim_type;
|
||||
device_vector<uint> prim_visibility;
|
||||
device_vector<int> prim_index;
|
||||
device_vector<int> prim_object;
|
||||
device_vector<float2> prim_time;
|
||||
|
||||
/* mesh */
|
||||
device_vector<packed_float3> tri_verts;
|
||||
device_vector<uint> tri_shader;
|
||||
device_vector<packed_float3> tri_vnormal;
|
||||
device_vector<packed_uint3> tri_vindex;
|
||||
device_vector<uint> tri_patch;
|
||||
device_vector<float2> tri_patch_uv;
|
||||
|
||||
device_vector<KernelCurve> curves;
|
||||
device_vector<float4> curve_keys;
|
||||
device_vector<KernelCurveSegment> curve_segments;
|
||||
|
||||
device_vector<uint> patches;
|
||||
|
||||
/* point-cloud */
|
||||
device_vector<float4> points;
|
||||
device_vector<uint> points_shader;
|
||||
|
||||
/* objects */
|
||||
device_vector<KernelObject> objects;
|
||||
device_vector<Transform> object_motion_pass;
|
||||
device_vector<DecomposedTransform> object_motion;
|
||||
device_vector<uint> object_flag;
|
||||
device_vector<float> object_volume_step;
|
||||
device_vector<uint> object_prim_offset;
|
||||
|
||||
/* cameras */
|
||||
device_vector<DecomposedTransform> camera_motion;
|
||||
|
||||
/* attributes */
|
||||
device_vector<AttributeMap> attributes_map;
|
||||
device_vector<float> attributes_float;
|
||||
device_vector<float2> attributes_float2;
|
||||
device_vector<packed_float3> attributes_float3;
|
||||
device_vector<float4> attributes_float4;
|
||||
device_vector<uchar4> attributes_uchar4;
|
||||
|
||||
/* lights */
|
||||
device_vector<KernelLightDistribution> light_distribution;
|
||||
device_vector<KernelLight> lights;
|
||||
device_vector<float2> light_background_marginal_cdf;
|
||||
device_vector<float2> light_background_conditional_cdf;
|
||||
|
||||
/* light tree */
|
||||
device_vector<KernelLightTreeNode> light_tree_nodes;
|
||||
device_vector<KernelLightTreeEmitter> light_tree_emitters;
|
||||
device_vector<uint> light_to_tree;
|
||||
device_vector<uint> object_to_tree;
|
||||
device_vector<uint> object_lookup_offset;
|
||||
device_vector<uint> triangle_to_tree;
|
||||
|
||||
/* particles */
|
||||
device_vector<KernelParticle> particles;
|
||||
|
||||
/* shaders */
|
||||
device_vector<int4> svm_nodes;
|
||||
device_vector<KernelShader> shaders;
|
||||
|
||||
/* lookup tables */
|
||||
device_vector<float> lookup_table;
|
||||
|
||||
/* integrator */
|
||||
device_vector<float> sample_pattern_lut;
|
||||
|
||||
/* IES lights */
|
||||
device_vector<float> ies_lights;
|
||||
|
||||
KernelData data;
|
||||
|
||||
DeviceScene(Device *device);
|
||||
};
|
||||
|
||||
/* Scene Parameters */
|
||||
|
||||
class SceneParams {
|
||||
|
@ -621,12 +621,12 @@ void Session::set_pause(bool pause)
|
||||
|
||||
void Session::set_output_driver(unique_ptr<OutputDriver> driver)
|
||||
{
|
||||
path_trace_->set_output_driver(move(driver));
|
||||
path_trace_->set_output_driver(std::move(driver));
|
||||
}
|
||||
|
||||
void Session::set_display_driver(unique_ptr<DisplayDriver> driver)
|
||||
{
|
||||
path_trace_->set_display_driver(move(driver));
|
||||
path_trace_->set_display_driver(std::move(driver));
|
||||
}
|
||||
|
||||
double Session::get_estimated_remaining_time() const
|
||||
|
@ -285,7 +285,7 @@ static bool configure_image_spec_from_buffer(ImageSpec *image_spec,
|
||||
*image_spec = ImageSpec(
|
||||
buffer_params.width, buffer_params.height, num_channels, TypeDesc::FLOAT);
|
||||
|
||||
image_spec->channelnames = move(channel_names);
|
||||
image_spec->channelnames = std::move(channel_names);
|
||||
|
||||
if (!buffer_params_to_image_spec_atttributes(image_spec, buffer_params)) {
|
||||
return false;
|
||||
|
@ -809,7 +809,7 @@ static string path_source_replace_includes_recursive(const string &_source,
|
||||
const size_t source_length = source.length();
|
||||
size_t index = 0;
|
||||
/* Information about where we are in the source. */
|
||||
size_t line_number = 0, column_number = 1;
|
||||
size_t column_number = 1;
|
||||
/* Currently gathered non-preprocessor token.
|
||||
* Store as start/length rather than token itself to avoid overhead of
|
||||
* memory re-allocations on each character concatenation.
|
||||
@ -842,7 +842,6 @@ static string path_source_replace_includes_recursive(const string &_source,
|
||||
preprocessor_line = "";
|
||||
}
|
||||
column_number = 0;
|
||||
++line_number;
|
||||
}
|
||||
else if (ch == '#' && column_number == 1 && !inside_preprocessor) {
|
||||
/* Append all possible non-preprocessor token to the result. */
|
||||
|
@ -897,12 +897,10 @@ void Octree::printPath(PathElement *path)
|
||||
void Octree::printPaths(PathList *path)
|
||||
{
|
||||
PathList *iter = path;
|
||||
int i = 0;
|
||||
while (iter != NULL) {
|
||||
dc_printf("Path %d:\n", i);
|
||||
printPath(iter);
|
||||
iter = iter->next;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1256,7 +1254,6 @@ Node *Octree::connectFace(
|
||||
|
||||
updateParent(&newnode->internal, len, st);
|
||||
|
||||
int flag = 0;
|
||||
// Add the cells to the rings and fill in the patch
|
||||
PathElement *newEleN;
|
||||
if (curEleN->pos[0] != stN[0] || curEleN->pos[1] != stN[1] || curEleN->pos[2] != stN[2]) {
|
||||
@ -1286,7 +1283,6 @@ Node *Octree::connectFace(
|
||||
alpha);
|
||||
|
||||
curEleN = newEleN;
|
||||
flag++;
|
||||
}
|
||||
|
||||
PathElement *newEleP;
|
||||
@ -1316,7 +1312,6 @@ Node *Octree::connectFace(
|
||||
alpha);
|
||||
|
||||
curEleP = newEleP;
|
||||
flag++;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1543,6 +1538,8 @@ void Octree::getFacePoint(PathElement *leaf, int dir, int &x, int &y, float &p,
|
||||
float off[3];
|
||||
int num = 0, num2 = 0;
|
||||
|
||||
(void)num2; // Unused in release builds.
|
||||
|
||||
LeafNode *leafnode = locateLeaf(leaf->pos);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int edgeind = faceMap[dir * 2][i];
|
||||
|
@ -61,7 +61,7 @@ extern const char *GHOST_getBinaryDir(void);
|
||||
/**
|
||||
* Add the file to the operating system most recently used files
|
||||
*/
|
||||
extern void GHOST_addToSystemRecentFiles(const char *filename);
|
||||
extern void GHOST_addToSystemRecentFiles(const char *filepath);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -57,4 +57,4 @@ class GHOST_IXrGraphicsBinding {
|
||||
};
|
||||
|
||||
std::unique_ptr<GHOST_IXrGraphicsBinding> GHOST_XrGraphicsBindingCreateFromType(
|
||||
GHOST_TXrGraphicsBinding type, GHOST_Context &ghost_ctx);
|
||||
GHOST_TXrGraphicsBinding type, GHOST_Context &context);
|
||||
|
@ -5586,8 +5586,6 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background)
|
||||
# endif
|
||||
display_destroy_and_free_all();
|
||||
throw std::runtime_error("Wayland: unable to find libdecor!");
|
||||
|
||||
use_libdecor = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -5610,7 +5608,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background)
|
||||
(void)background;
|
||||
#endif
|
||||
{
|
||||
GWL_XDG_Decor_System &decor = *display_->xdg_decor;
|
||||
const GWL_XDG_Decor_System &decor = *display_->xdg_decor;
|
||||
if (!decor.shell) {
|
||||
display_destroy_and_free_all();
|
||||
throw std::runtime_error("Wayland: unable to access xdg_shell!");
|
||||
@ -6071,11 +6069,9 @@ static GHOST_TSuccess getCursorPositionClientRelative_impl(
|
||||
/* As the cursor is restored at the warped location,
|
||||
* apply warping when requesting the cursor location. */
|
||||
GHOST_Rect wrap_bounds{};
|
||||
if (win->getCursorGrabModeIsWarp()) {
|
||||
if (win->getCursorGrabBounds(wrap_bounds) == GHOST_kFailure) {
|
||||
win->getClientBounds(wrap_bounds);
|
||||
}
|
||||
}
|
||||
int xy_wrap[2] = {
|
||||
seat_state_pointer->xy[0],
|
||||
seat_state_pointer->xy[1],
|
||||
@ -6680,10 +6676,9 @@ GHOST_TSuccess GHOST_SystemWayland::cursor_shape_custom_set(uint8_t *bitmap,
|
||||
static constexpr uint32_t transparent = 0x00000000;
|
||||
|
||||
uint8_t datab = 0, maskb = 0;
|
||||
uint32_t *pixel;
|
||||
|
||||
for (int y = 0; y < sizey; ++y) {
|
||||
pixel = &static_cast<uint32_t *>(cursor->custom_data)[y * sizex];
|
||||
uint32_t *pixel = &static_cast<uint32_t *>(cursor->custom_data)[y * sizex];
|
||||
for (int x = 0; x < sizex; ++x) {
|
||||
if ((x % 8) == 0) {
|
||||
datab = *bitmap++;
|
||||
|
@ -37,15 +37,15 @@ bool ghost_wl_output_own(const struct wl_output *wl_output);
|
||||
void ghost_wl_output_tag(struct wl_output *wl_output);
|
||||
struct GWL_Output *ghost_wl_output_user_data(struct wl_output *wl_output);
|
||||
|
||||
bool ghost_wl_surface_own(const struct wl_surface *surface);
|
||||
void ghost_wl_surface_tag(struct wl_surface *surface);
|
||||
GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *surface);
|
||||
bool ghost_wl_surface_own(const struct wl_surface *wl_surface);
|
||||
void ghost_wl_surface_tag(struct wl_surface *wl_surface);
|
||||
GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *wl_surface);
|
||||
|
||||
bool ghost_wl_surface_own_cursor_pointer(const struct wl_surface *surface);
|
||||
void ghost_wl_surface_tag_cursor_pointer(struct wl_surface *surface);
|
||||
bool ghost_wl_surface_own_cursor_pointer(const struct wl_surface *wl_surface);
|
||||
void ghost_wl_surface_tag_cursor_pointer(struct wl_surface *wl_surface);
|
||||
|
||||
bool ghost_wl_surface_own_cursor_tablet(const struct wl_surface *surface);
|
||||
void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *surface);
|
||||
bool ghost_wl_surface_own_cursor_tablet(const struct wl_surface *wl_surface);
|
||||
void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *wl_surface);
|
||||
|
||||
/* Scaling to: translates from WAYLAND into GHOST (viewport local) coordinates.
|
||||
* Scaling from: performs the reverse translation.
|
||||
|
@ -85,7 +85,7 @@ static uchar bit_is_on(const uchar *ptr, int bit)
|
||||
|
||||
static GHOST_TKey ghost_key_from_keysym(const KeySym key);
|
||||
static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCode keycode);
|
||||
static GHOST_TKey ghost_key_from_keysym_or_keycode(const KeySym key,
|
||||
static GHOST_TKey ghost_key_from_keysym_or_keycode(const KeySym key_sym,
|
||||
const XkbDescPtr xkb_descr,
|
||||
const KeyCode keycode);
|
||||
|
||||
@ -1776,11 +1776,11 @@ bool GHOST_SystemX11::generateWindowExposeEvents()
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
static GHOST_TKey ghost_key_from_keysym_or_keycode(const KeySym keysym,
|
||||
static GHOST_TKey ghost_key_from_keysym_or_keycode(const KeySym key_sym,
|
||||
XkbDescPtr xkb_descr,
|
||||
const KeyCode keycode)
|
||||
{
|
||||
GHOST_TKey type = ghost_key_from_keysym(keysym);
|
||||
GHOST_TKey type = ghost_key_from_keysym(key_sym);
|
||||
if (type == GHOST_kKeyUnknown) {
|
||||
if (xkb_descr) {
|
||||
type = ghost_key_from_keycode(xkb_descr, keycode);
|
||||
|
@ -31,7 +31,7 @@
|
||||
#endif
|
||||
|
||||
/* generic error handlers */
|
||||
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent);
|
||||
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *event);
|
||||
int GHOST_X11_ApplicationIOErrorHandler(Display *display);
|
||||
|
||||
#define GHOST_X11_ERROR_HANDLERS_OVERRIDE(var) \
|
||||
|
@ -155,7 +155,7 @@ class GHOST_Window : public GHOST_IWindow {
|
||||
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) const override;
|
||||
|
||||
void getCursorGrabState(GHOST_TGrabCursorMode &mode,
|
||||
GHOST_TAxisFlag &axis_flag,
|
||||
GHOST_TAxisFlag &wrap_axis,
|
||||
GHOST_Rect &bounds,
|
||||
bool &use_software_cursor) override;
|
||||
/**
|
||||
|
@ -89,11 +89,13 @@ class GHOST_XrAction {
|
||||
const XrTime &predicted_display_time);
|
||||
void applyHapticFeedback(XrSession session,
|
||||
const char *action_name,
|
||||
const char *subaction_path,
|
||||
const char *subaction_path_str,
|
||||
const int64_t &duration,
|
||||
const float &frequency,
|
||||
const float &litude);
|
||||
void stopHapticFeedback(XrSession session, const char *action_name, const char *subaction_path);
|
||||
void stopHapticFeedback(XrSession session,
|
||||
const char *action_name,
|
||||
const char *subaction_path_str);
|
||||
|
||||
void *getCustomdata();
|
||||
void getBindings(std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings) const;
|
||||
|
@ -74,7 +74,7 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *> &tasks)
|
||||
return false;
|
||||
|
||||
// compute task ids and assign weights to task
|
||||
int primary_size = 0, primary = 0;
|
||||
int primary_size = 0;
|
||||
int secondary_size = 0, secondary = 0;
|
||||
double primary_weight = 0.0, secondary_weight = 0.0;
|
||||
std::list<IK_QTask *>::iterator task;
|
||||
@ -86,7 +86,6 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *> &tasks)
|
||||
qtask->SetId(primary_size);
|
||||
primary_size += qtask->Size();
|
||||
primary_weight += qtask->Weight();
|
||||
primary++;
|
||||
}
|
||||
else {
|
||||
qtask->SetId(secondary_size);
|
||||
|
@ -283,15 +283,13 @@ void AutoTrack::DetectAndTrack(const DetectAndTrackOptions& options) {
|
||||
|
||||
// Find tracks in the previous frame that are not in this one.
|
||||
vector<Marker*> previous_frame_markers_to_track;
|
||||
int num_skipped = 0;
|
||||
for (int i = 0; i < previous_frame_markers.size(); ++i) {
|
||||
if (std::binary_search(tracks_in_this_frame.begin(),
|
||||
tracks_in_this_frame.end(),
|
||||
previous_frame_markers[i].track)) {
|
||||
num_skipped++;
|
||||
} else {
|
||||
previous_frame_markers_to_track.push_back(&previous_frame_markers[i]);
|
||||
continue;
|
||||
}
|
||||
previous_frame_markers_to_track.push_back(&previous_frame_markers[i]);
|
||||
}
|
||||
|
||||
// Finally track the markers from the last frame into this one.
|
||||
|
@ -140,7 +140,6 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks& _tracks,
|
||||
|
||||
int max_image = filtered_tracks.MaxImage();
|
||||
int next_keyframe = 1;
|
||||
int number_keyframes = 0;
|
||||
|
||||
// Limit correspondence ratio from both sides.
|
||||
// On the one hand if number of correspondent features is too low,
|
||||
@ -162,7 +161,6 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks& _tracks,
|
||||
|
||||
LG << "Found keyframe " << next_keyframe;
|
||||
|
||||
number_keyframes++;
|
||||
next_keyframe = -1;
|
||||
|
||||
for (int candidate_image = current_keyframe + 1;
|
||||
@ -406,7 +404,6 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks& _tracks,
|
||||
// However, it's just quick hack and smarter way to do this would be nice
|
||||
if (next_keyframe == -1) {
|
||||
next_keyframe = current_keyframe + 10;
|
||||
number_keyframes = 0;
|
||||
|
||||
if (next_keyframe >= max_image)
|
||||
break;
|
||||
|
@ -380,7 +380,7 @@ TopologyRefinerImpl *TopologyRefinerImpl::createFromConverter(
|
||||
TopologyRefinerImpl *topology_refiner_impl = new TopologyRefinerImpl();
|
||||
topology_refiner_impl->topology_refiner = topology_refiner;
|
||||
topology_refiner_impl->settings = settings;
|
||||
topology_refiner_impl->base_mesh_topology = move(base_mesh_topology);
|
||||
topology_refiner_impl->base_mesh_topology = std::move(base_mesh_topology);
|
||||
|
||||
return topology_refiner_impl;
|
||||
}
|
||||
|
BIN
release/datafiles/icons/ops.gpencil.sculpt_average.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_average.dat
Normal file
Binary file not shown.
BIN
release/datafiles/icons/ops.gpencil.sculpt_blur.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_blur.dat
Normal file
Binary file not shown.
BIN
release/datafiles/icons/ops.gpencil.sculpt_smear.dat
Normal file
BIN
release/datafiles/icons/ops.gpencil.sculpt_smear.dat
Normal file
Binary file not shown.
@ -204,6 +204,9 @@ _km_hierarchy = [
|
||||
('Grease Pencil Stroke Sculpt (Clone)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Weight Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Weight (Draw)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Weight (Blur)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Weight (Average)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Weight (Smear)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Vertex Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Vertex (Draw)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Vertex (Blur)', 'EMPTY', 'WINDOW', []),
|
||||
|
@ -869,10 +869,10 @@
|
||||
</space>
|
||||
<space_list>
|
||||
<ThemeSpaceListGeneric
|
||||
list="#181818"
|
||||
list_title="#ffffff"
|
||||
list_text="#ffffff"
|
||||
list_text_hi="#ffffff"
|
||||
list="#b3b3b3"
|
||||
list_title="#747474"
|
||||
list_text="#333333"
|
||||
list_text_hi="#747474"
|
||||
>
|
||||
</ThemeSpaceListGeneric>
|
||||
</space_list>
|
||||
@ -1240,7 +1240,7 @@
|
||||
title="#000000"
|
||||
text="#000000"
|
||||
text_hi="#ffffff"
|
||||
header="#727272ff"
|
||||
header="#b3b3b3ff"
|
||||
header_text="#000000"
|
||||
header_text_hi="#ffffff"
|
||||
button="#7272727f"
|
||||
@ -1317,7 +1317,7 @@
|
||||
title="#ffffff"
|
||||
text="#ffffff"
|
||||
text_hi="#ffffff"
|
||||
header="#999999ff"
|
||||
header="#b3b3b3ff"
|
||||
header_text="#1a1a1a"
|
||||
header_text_hi="#ffffff"
|
||||
button="#2f303500"
|
||||
|
@ -4178,6 +4178,9 @@ def km_grease_pencil_stroke_weight_mode(params):
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_weight_paint.brush.size')]}),
|
||||
# Brush weight
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_weight_paint.brush.weight')]}),
|
||||
# Increase/Decrease brush size
|
||||
("brush.scale_size", {"type": 'LEFT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 0.9)]}),
|
||||
@ -4197,6 +4200,10 @@ def km_grease_pencil_stroke_weight_mode(params):
|
||||
op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}),
|
||||
# Context menu
|
||||
*_template_items_context_panel("VIEW3D_PT_gpencil_weight_context_menu", params.context_menu_event),
|
||||
# Toggle Add/Subtract for weight draw tool
|
||||
("gpencil.weight_toggle_direction", {"type": 'D', "value": 'PRESS'}, None),
|
||||
# Weight sample
|
||||
("gpencil.weight_sample", {"type": params.action_mouse, "value": 'PRESS', "ctrl": True}, None),
|
||||
])
|
||||
|
||||
if params.select_mouse == 'LEFTMOUSE':
|
||||
@ -4220,6 +4227,59 @@ def km_grease_pencil_stroke_weight_draw(_params):
|
||||
# Draw
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_blur(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Blur)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Blur
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_average(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Average)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Average
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_smear(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Smear)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Smear
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
@ -5579,6 +5639,10 @@ def km_font(params):
|
||||
{"properties": [("type", 'PREVIOUS_PAGE')]}),
|
||||
("font.move", {"type": 'PAGE_DOWN', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("type", 'NEXT_PAGE')]}),
|
||||
("font.move", {"type": 'HOME', "value": 'PRESS', "ctrl": True, "repeat": True},
|
||||
{"properties": [("type", 'TEXT_BEGIN')]}),
|
||||
("font.move", {"type": 'END', "value": 'PRESS', "ctrl": True, "repeat": True},
|
||||
{"properties": [("type", 'TEXT_END')]}),
|
||||
("font.move_select", {"type": 'HOME', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("type", 'LINE_BEGIN')]}),
|
||||
("font.move_select", {"type": 'END', "value": 'PRESS', "shift": True},
|
||||
@ -5599,6 +5663,10 @@ def km_font(params):
|
||||
{"properties": [("type", 'PREVIOUS_PAGE')]}),
|
||||
("font.move_select", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True},
|
||||
{"properties": [("type", 'NEXT_PAGE')]}),
|
||||
("font.move_select", {"type": 'HOME', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True},
|
||||
{"properties": [("type", 'TEXT_BEGIN')]}),
|
||||
("font.move_select", {"type": 'END', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True},
|
||||
{"properties": [("type", 'TEXT_END')]}),
|
||||
("font.change_spacing", {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
|
||||
{"properties": [("delta", -1.0)]}),
|
||||
("font.change_spacing", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
|
||||
@ -8107,6 +8175,9 @@ def generate_keymaps(params=None):
|
||||
km_grease_pencil_stroke_sculpt_clone(params),
|
||||
km_grease_pencil_stroke_weight_mode(params),
|
||||
km_grease_pencil_stroke_weight_draw(params),
|
||||
km_grease_pencil_stroke_weight_blur(params),
|
||||
km_grease_pencil_stroke_weight_average(params),
|
||||
km_grease_pencil_stroke_weight_smear(params),
|
||||
km_grease_pencil_stroke_vertex_mode(params),
|
||||
km_grease_pencil_stroke_vertex_draw(params),
|
||||
km_grease_pencil_stroke_vertex_blur(params),
|
||||
|
@ -2777,6 +2777,56 @@ def km_grease_pencil_stroke_weight_draw(_params):
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_blur(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Blur)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_average(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Average)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_smear(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Smear)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
@ -3775,6 +3825,10 @@ def km_font(params):
|
||||
{"properties": [("type", 'PREVIOUS_PAGE')]}),
|
||||
("font.move", {"type": 'PAGE_DOWN', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("type", 'NEXT_PAGE')]}),
|
||||
("font.move", {"type": 'HOME', "value": 'PRESS', "ctrl": True, "repeat": True},
|
||||
{"properties": [("type", 'TEXT_BEGIN')]}),
|
||||
("font.move", {"type": 'END', "value": 'PRESS', "ctrl": True, "repeat": True},
|
||||
{"properties": [("type", 'TEXT_END')]}),
|
||||
("font.move_select", {"type": 'HOME', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("type", 'LINE_BEGIN')]}),
|
||||
("font.move_select", {"type": 'END', "value": 'PRESS', "shift": True},
|
||||
@ -3795,6 +3849,10 @@ def km_font(params):
|
||||
{"properties": [("type", 'PREVIOUS_PAGE')]}),
|
||||
("font.move_select", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True},
|
||||
{"properties": [("type", 'NEXT_PAGE')]}),
|
||||
("font.move_select", {"type": 'HOME', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True},
|
||||
{"properties": [("type", 'TEXT_BEGIN')]}),
|
||||
("font.move_select", {"type": 'END', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": True},
|
||||
{"properties": [("type", 'TEXT_END')]}),
|
||||
("font.change_spacing", {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
|
||||
{"properties": [("delta", -1)]}),
|
||||
("font.change_spacing", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
|
||||
@ -4187,6 +4245,9 @@ def generate_keymaps_impl(params=None):
|
||||
km_grease_pencil_stroke_sculpt_clone(params),
|
||||
km_grease_pencil_stroke_weight_mode(params),
|
||||
km_grease_pencil_stroke_weight_draw(params),
|
||||
km_grease_pencil_stroke_weight_blur(params),
|
||||
km_grease_pencil_stroke_weight_average(params),
|
||||
km_grease_pencil_stroke_weight_smear(params),
|
||||
km_grease_pencil_stroke_vertex_mode(params),
|
||||
km_grease_pencil_stroke_vertex_draw(params),
|
||||
km_grease_pencil_stroke_vertex_blur(params),
|
||||
|
@ -371,10 +371,18 @@ class DATA_PT_font(CurveButtonsPanelText, Panel):
|
||||
row.prop(char, "use_small_caps", toggle=True)
|
||||
else:
|
||||
row = layout.row(align=True)
|
||||
row.operator("font.style_toggle", text="Bold", icon='BOLD' , depress = text.is_select_bold).style = 'BOLD'
|
||||
row.operator("font.style_toggle", text="Italic", icon='ITALIC' , depress = text.is_select_italic).style = 'ITALIC'
|
||||
row.operator("font.style_toggle", text="Underline", icon='UNDERLINE' , depress = text.is_select_underline).style = 'UNDERLINE'
|
||||
row.operator("font.style_toggle", text="Small Caps", icon='SMALL_CAPS' , depress = text.is_select_smallcaps).style = 'SMALL_CAPS'
|
||||
row.operator(
|
||||
"font.style_toggle", text="Bold", icon='BOLD', depress=text.is_select_bold,
|
||||
).style = 'BOLD'
|
||||
row.operator(
|
||||
"font.style_toggle", text="Italic", icon='ITALIC', depress=text.is_select_italic,
|
||||
).style = 'ITALIC'
|
||||
row.operator(
|
||||
"font.style_toggle", text="Underline", icon='UNDERLINE', depress=text.is_select_underline,
|
||||
).style = 'UNDERLINE'
|
||||
row.operator(
|
||||
"font.style_toggle", text="Small Caps", icon='SMALL_CAPS', depress=text.is_select_smallcaps,
|
||||
).style = 'SMALL_CAPS'
|
||||
|
||||
|
||||
class DATA_PT_font_transform(CurveButtonsPanelText, Panel):
|
||||
|
@ -1415,8 +1415,12 @@ def brush_basic_gpencil_weight_settings(layout, _context, brush, *, compact=Fals
|
||||
row.prop(brush, "strength", slider=True)
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
|
||||
if brush.gpencil_weight_tool in {'WEIGHT'}:
|
||||
layout.prop(brush, "weight", slider=True)
|
||||
|
||||
gp_settings = brush.gpencil_settings
|
||||
layout.prop(gp_settings, "direction", expand=True, text="" if compact else "Direction")
|
||||
|
||||
|
||||
def brush_basic_gpencil_vertex_settings(layout, _context, brush, *, compact=False):
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
@ -706,6 +706,15 @@ class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
|
||||
bl_label = "Asset Metadata"
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
|
||||
@staticmethod
|
||||
def metadata_prop(layout, asset_data, propname):
|
||||
"""
|
||||
Only display properties that are either set or can be modified (i.e. the
|
||||
asset is in the current file). Empty, non-editable fields are not really useful.
|
||||
"""
|
||||
if getattr(asset_data, propname) or not asset_data.is_property_readonly(propname):
|
||||
layout.prop(asset_data, propname)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
wm = context.window_manager
|
||||
@ -745,10 +754,11 @@ class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
|
||||
row.prop(wm, "asset_path_dummy", text="Source", icon='CURRENT_FILE' if is_local_asset else 'NONE')
|
||||
row.operator("asset.open_containing_blend_file", text="", icon='TOOL_SETTINGS')
|
||||
|
||||
layout.prop(asset_file_handle.asset_data, "description")
|
||||
layout.prop(asset_file_handle.asset_data, "license")
|
||||
layout.prop(asset_file_handle.asset_data, "copyright")
|
||||
layout.prop(asset_file_handle.asset_data, "author")
|
||||
asset_data = asset_file_handle.asset_data
|
||||
self.metadata_prop(layout, asset_data, "description")
|
||||
self.metadata_prop(layout, asset_data, "license")
|
||||
self.metadata_prop(layout, asset_data, "copyright")
|
||||
self.metadata_prop(layout, asset_data, "author")
|
||||
|
||||
|
||||
class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
|
||||
|
@ -903,7 +903,10 @@ class NodeTreeInterfacePanel(Panel):
|
||||
props = property_row.operator_menu_enum(
|
||||
"node.tree_socket_change_subtype",
|
||||
"socket_subtype",
|
||||
text=active_socket.bl_subtype_label if active_socket.bl_subtype_label else active_socket.bl_idname
|
||||
text=(
|
||||
active_socket.bl_subtype_label if active_socket.bl_subtype_label else
|
||||
active_socket.bl_idname
|
||||
),
|
||||
)
|
||||
|
||||
layout.use_property_split = True
|
||||
|
@ -68,6 +68,7 @@ def generate_from_enum_ex(
|
||||
dict(
|
||||
idname=idname_prefix + name,
|
||||
label=name,
|
||||
description=enum.description,
|
||||
icon=icon,
|
||||
cursor=cursor,
|
||||
data_block=idname,
|
||||
|
@ -8,6 +8,7 @@ from bpy.types import (
|
||||
from bl_ui.properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
brush_basic_texpaint_settings,
|
||||
brush_basic_gpencil_weight_settings,
|
||||
)
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
AnnotationDataPanel,
|
||||
@ -414,11 +415,13 @@ class _draw_tool_settings_context_mode:
|
||||
paint = context.tool_settings.gpencil_weight_paint
|
||||
brush = paint.brush
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_weight_settings,
|
||||
)
|
||||
layout.template_ID_preview(paint, "brush", rows=3, cols=8, hide_buttons=True)
|
||||
|
||||
brush_basic_gpencil_weight_settings(layout, context, brush, compact=True)
|
||||
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_weight_options", text="Options")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_weight_falloff", text="Falloff")
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
@ -1803,6 +1806,11 @@ class VIEW3D_MT_select_edit_text(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("font.move_select", text="Top").type = 'TEXT_BEGIN'
|
||||
layout.operator("font.move_select", text="Bottom").type = 'TEXT_END'
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("font.move_select", text="Previous Block").type = 'PREVIOUS_PAGE'
|
||||
layout.operator("font.move_select", text="Next Block").type = 'NEXT_PAGE'
|
||||
|
||||
@ -7657,12 +7665,10 @@ class VIEW3D_PT_gpencil_weight_context_menu(Panel):
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_weight_paint
|
||||
brush = settings.brush
|
||||
|
||||
layout = self.layout
|
||||
|
||||
layout.prop(brush, "size", slider=True)
|
||||
layout.prop(brush, "strength")
|
||||
layout.prop(brush, "weight")
|
||||
# Weight settings
|
||||
brush_basic_gpencil_weight_settings(layout, context, brush)
|
||||
|
||||
# Layers
|
||||
draw_gpencil_layer_active(context, layout)
|
||||
|
@ -2021,6 +2021,9 @@ class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel, Gr
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
def draw(self, context):
|
||||
if self.is_popover:
|
||||
return
|
||||
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
@ -2029,7 +2032,6 @@ class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel, Gr
|
||||
settings = tool_settings.gpencil_weight_paint
|
||||
brush = settings.brush
|
||||
|
||||
if not self.is_popover:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_weight_settings,
|
||||
)
|
||||
@ -2038,6 +2040,7 @@ class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel, Gr
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_weight_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel):
|
||||
bl_context = ".greasepencil_weight"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_weight_paint_settings'
|
||||
bl_label = "Falloff"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@ -2049,6 +2052,20 @@ class VIEW3D_PT_tools_grease_pencil_brush_weight_falloff(GreasePencilBrushFallof
|
||||
return (brush and brush.curve)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_options(Panel, View3DPanel, GreasePencilWeightPanel):
|
||||
bl_label = "Options"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
tool_settings = context.scene.tool_settings
|
||||
|
||||
col = layout.column()
|
||||
col.prop(tool_settings, "use_auto_normalize", text="Auto Normalize")
|
||||
|
||||
|
||||
# Grease Pencil vertex painting tools
|
||||
class GreasePencilVertexPanel:
|
||||
bl_context = ".greasepencil_vertex"
|
||||
@ -2425,6 +2442,7 @@ classes = (
|
||||
VIEW3D_PT_tools_grease_pencil_sculpt_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_paint_select,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_paint_settings,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_options,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_vertex_paint_select,
|
||||
VIEW3D_PT_tools_grease_pencil_vertex_paint_settings,
|
||||
|
@ -260,6 +260,7 @@ void AssetCatalogService::update_catalog_path(const CatalogID catalog_id,
|
||||
}
|
||||
cat->path = new_path;
|
||||
cat->simple_name_refresh();
|
||||
this->tag_has_unsaved_changes(cat);
|
||||
|
||||
/* TODO(Sybren): go over all assets that are assigned to this catalog, defined in the current
|
||||
* blend file, and update the catalog simple name stored there. */
|
||||
|
@ -86,6 +86,8 @@ struct AttributeInit {
|
||||
VArray,
|
||||
/** #AttributeInitMoveArray. */
|
||||
MoveArray,
|
||||
/** #AttributeInitShared. */
|
||||
Shared,
|
||||
};
|
||||
Type type;
|
||||
AttributeInit(const Type type) : type(type) {}
|
||||
@ -121,9 +123,6 @@ struct AttributeInitVArray : public AttributeInit {
|
||||
* Sometimes data is created before a geometry component is available. In that case, it's
|
||||
* preferable to move data directly to the created attribute to avoid a new allocation and a copy.
|
||||
*
|
||||
* Note that this will only have a benefit for attributes that are stored directly as contiguous
|
||||
* arrays, so not for some built-in attributes.
|
||||
*
|
||||
* The array must be allocated with MEM_*, since `attribute_try_create` will free the array if it
|
||||
* can't be used directly, and that is generally how Blender expects custom data to be allocated.
|
||||
*/
|
||||
@ -133,6 +132,20 @@ struct AttributeInitMoveArray : public AttributeInit {
|
||||
AttributeInitMoveArray(void *data) : AttributeInit(Type::MoveArray), data(data) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a shared attribute by adding a user to a shared data array.
|
||||
* The sharing info has ownership of the provided contiguous array.
|
||||
*/
|
||||
struct AttributeInitShared : public AttributeInit {
|
||||
const void *data = nullptr;
|
||||
const ImplicitSharingInfo *sharing_info = nullptr;
|
||||
|
||||
AttributeInitShared(const void *data, const ImplicitSharingInfo &sharing_info)
|
||||
: AttributeInit(Type::Shared), data(data), sharing_info(&sharing_info)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/* Returns false when the iteration should be stopped. */
|
||||
using AttributeForeachCallback =
|
||||
FunctionRef<bool(const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data)>;
|
||||
@ -151,6 +164,21 @@ template<typename T> struct AttributeReader {
|
||||
*/
|
||||
eAttrDomain domain;
|
||||
|
||||
/**
|
||||
* Information about shared ownership of the attribute array. This will only be provided
|
||||
* if the virtual array directly references the contiguous original attribute array.
|
||||
*/
|
||||
const ImplicitSharingInfo *sharing_info;
|
||||
|
||||
const VArray<T> &operator*() const
|
||||
{
|
||||
return this->varray;
|
||||
}
|
||||
VArray<T> &operator*()
|
||||
{
|
||||
return this->varray;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return this->varray;
|
||||
@ -270,15 +298,25 @@ template<typename T> struct SpanAttributeWriter {
|
||||
struct GAttributeReader {
|
||||
GVArray varray;
|
||||
eAttrDomain domain;
|
||||
const ImplicitSharingInfo *sharing_info;
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return this->varray;
|
||||
}
|
||||
|
||||
const GVArray &operator*() const
|
||||
{
|
||||
return this->varray;
|
||||
}
|
||||
GVArray &operator*()
|
||||
{
|
||||
return this->varray;
|
||||
}
|
||||
|
||||
template<typename T> AttributeReader<T> typed() const
|
||||
{
|
||||
return {varray.typed<T>(), domain};
|
||||
return {varray.typed<T>(), domain, sharing_info};
|
||||
}
|
||||
};
|
||||
|
||||
@ -457,7 +495,7 @@ class AttributeAccessor {
|
||||
* Get read-only access to the attribute. If necessary, the attribute is interpolated to the
|
||||
* given domain, and converted to the given type, in that order. The result may be empty.
|
||||
*/
|
||||
GVArray lookup(const AttributeIDRef &attribute_id,
|
||||
GAttributeReader lookup(const AttributeIDRef &attribute_id,
|
||||
const std::optional<eAttrDomain> domain,
|
||||
const std::optional<eCustomDataType> data_type) const;
|
||||
|
||||
@ -465,7 +503,7 @@ class AttributeAccessor {
|
||||
* Get read-only access to the attribute whereby the attribute is interpolated to the given
|
||||
* domain. The result may be empty.
|
||||
*/
|
||||
GVArray lookup(const AttributeIDRef &attribute_id, const eAttrDomain domain) const
|
||||
GAttributeReader lookup(const AttributeIDRef &attribute_id, const eAttrDomain domain) const
|
||||
{
|
||||
return this->lookup(attribute_id, domain, std::nullopt);
|
||||
}
|
||||
@ -474,7 +512,8 @@ class AttributeAccessor {
|
||||
* Get read-only access to the attribute whereby the attribute is converted to the given type.
|
||||
* The result may be empty.
|
||||
*/
|
||||
GVArray lookup(const AttributeIDRef &attribute_id, const eCustomDataType data_type) const
|
||||
GAttributeReader lookup(const AttributeIDRef &attribute_id,
|
||||
const eCustomDataType data_type) const
|
||||
{
|
||||
return this->lookup(attribute_id, std::nullopt, data_type);
|
||||
}
|
||||
@ -484,7 +523,7 @@ class AttributeAccessor {
|
||||
* given domain and then converted to the given type, in that order. The result may be empty.
|
||||
*/
|
||||
template<typename T>
|
||||
VArray<T> lookup(const AttributeIDRef &attribute_id,
|
||||
AttributeReader<T> lookup(const AttributeIDRef &attribute_id,
|
||||
const std::optional<eAttrDomain> domain = std::nullopt) const
|
||||
{
|
||||
const CPPType &cpp_type = CPPType::get<T>();
|
||||
@ -498,7 +537,7 @@ class AttributeAccessor {
|
||||
* If the attribute does not exist, a virtual array with the given default value is returned.
|
||||
* If the passed in default value is null, the default value of the type is used (generally 0).
|
||||
*/
|
||||
GVArray lookup_or_default(const AttributeIDRef &attribute_id,
|
||||
GAttributeReader lookup_or_default(const AttributeIDRef &attribute_id,
|
||||
const eAttrDomain domain,
|
||||
const eCustomDataType data_type,
|
||||
const void *default_value = nullptr) const;
|
||||
@ -507,14 +546,14 @@ class AttributeAccessor {
|
||||
* Same as the generic version above, but should be used when the type is known at compile time.
|
||||
*/
|
||||
template<typename T>
|
||||
VArray<T> lookup_or_default(const AttributeIDRef &attribute_id,
|
||||
AttributeReader<T> lookup_or_default(const AttributeIDRef &attribute_id,
|
||||
const eAttrDomain domain,
|
||||
const T &default_value) const
|
||||
{
|
||||
if (VArray<T> varray = this->lookup<T>(attribute_id, domain)) {
|
||||
if (AttributeReader<T> varray = this->lookup<T>(attribute_id, domain)) {
|
||||
return varray;
|
||||
}
|
||||
return VArray<T>::ForSingle(default_value, this->domain_size(domain));
|
||||
return {VArray<T>::ForSingle(default_value, this->domain_size(domain)), domain};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -626,6 +665,15 @@ class MutableAttributeAccessor : public AttributeAccessor {
|
||||
{
|
||||
return fn_->add(owner_, attribute_id, domain, data_type, initializer);
|
||||
}
|
||||
template<typename T>
|
||||
bool add(const AttributeIDRef &attribute_id,
|
||||
const eAttrDomain domain,
|
||||
const AttributeInit &initializer)
|
||||
{
|
||||
const CPPType &cpp_type = CPPType::get<T>();
|
||||
const eCustomDataType data_type = cpp_type_to_custom_data_type(cpp_type);
|
||||
return this->add(attribute_id, domain, data_type, initializer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an attribute with the given id, domain and data type. If it does not exist, create a new
|
||||
|
@ -28,7 +28,7 @@ bool BKE_curves_attribute_required(const struct Curves *curves, const char *name
|
||||
|
||||
/* Depsgraph */
|
||||
|
||||
struct Curves *BKE_curves_copy_for_eval(struct Curves *curves_src, bool reference);
|
||||
struct Curves *BKE_curves_copy_for_eval(struct Curves *curves_src);
|
||||
|
||||
void BKE_curves_data_update(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
|
@ -152,8 +152,6 @@ enum {
|
||||
LIB_ID_COPY_CACHES = 1 << 18,
|
||||
/** Don't copy `id->adt`, used by ID data-block localization routines. */
|
||||
LIB_ID_COPY_NO_ANIMDATA = 1 << 19,
|
||||
/** Mesh: Reference CD data layers instead of doing real copy - USE WITH CAUTION! */
|
||||
LIB_ID_COPY_CD_REFERENCE = 1 << 20,
|
||||
/** Do not copy id->override_library, used by ID data-block override routines. */
|
||||
LIB_ID_COPY_NO_LIB_OVERRIDE = 1 << 21,
|
||||
/** When copying local sub-data (like constraints or modifiers), do not set their "library
|
||||
|
@ -158,15 +158,15 @@ void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
|
||||
/** Add poly offsets to describe faces to a new mesh. */
|
||||
void BKE_mesh_poly_offsets_ensure_alloc(struct Mesh *mesh);
|
||||
|
||||
struct Mesh *BKE_mesh_new_nomain(int verts_len, int edges_len, int loops_len, int polys_len);
|
||||
struct Mesh *BKE_mesh_new_nomain(int verts_num, int edges_num, int polys_num, int loops_num);
|
||||
struct Mesh *BKE_mesh_new_nomain_from_template(
|
||||
const struct Mesh *me_src, int verts_len, int edges_len, int loops_len, int polys_len);
|
||||
const struct Mesh *me_src, int verts_num, int edges_num, int polys_num, int loops_num);
|
||||
struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src,
|
||||
int verts_len,
|
||||
int edges_len,
|
||||
int tessface_len,
|
||||
int loops_len,
|
||||
int polys_len,
|
||||
int verts_num,
|
||||
int edges_num,
|
||||
int tessface_num,
|
||||
int polys_num,
|
||||
int loops_num,
|
||||
struct CustomData_MeshMasks mask);
|
||||
|
||||
void BKE_mesh_eval_delete(struct Mesh *mesh_eval);
|
||||
@ -175,7 +175,7 @@ void BKE_mesh_eval_delete(struct Mesh *mesh_eval);
|
||||
* Performs copy for use during evaluation,
|
||||
* optional referencing original arrays to reduce memory.
|
||||
*/
|
||||
struct Mesh *BKE_mesh_copy_for_eval(const struct Mesh *source, bool reference);
|
||||
struct Mesh *BKE_mesh_copy_for_eval(const struct Mesh *source);
|
||||
|
||||
/**
|
||||
* These functions construct a new Mesh,
|
||||
|
@ -298,6 +298,12 @@ typedef struct bNodeType {
|
||||
void (*freefunc_api)(struct PointerRNA *ptr);
|
||||
void (*copyfunc_api)(struct PointerRNA *ptr, const struct bNode *src_node);
|
||||
|
||||
/**
|
||||
* An additional poll test for deciding whether nodes should be an option in search menus.
|
||||
* Potentially more strict poll than #poll(), but doesn't have to check the same things.
|
||||
*/
|
||||
bool (*add_ui_poll)(const struct bContext *C);
|
||||
|
||||
/**
|
||||
* Can this node type be added to a node tree?
|
||||
* \param r_disabled_hint: Hint to display in the UI when the poll fails.
|
||||
|
@ -70,8 +70,7 @@ void *BKE_pointcloud_add(struct Main *bmain, const char *name);
|
||||
void *BKE_pointcloud_add_default(struct Main *bmain, const char *name);
|
||||
struct PointCloud *BKE_pointcloud_new_nomain(int totpoint);
|
||||
void BKE_pointcloud_nomain_to_pointcloud(struct PointCloud *pointcloud_src,
|
||||
struct PointCloud *pointcloud_dst,
|
||||
bool take_ownership);
|
||||
struct PointCloud *pointcloud_dst);
|
||||
|
||||
struct BoundBox *BKE_pointcloud_boundbox_get(struct Object *ob);
|
||||
|
||||
@ -79,7 +78,7 @@ bool BKE_pointcloud_attribute_required(const struct PointCloud *pointcloud, cons
|
||||
|
||||
/* Dependency Graph */
|
||||
|
||||
struct PointCloud *BKE_pointcloud_copy_for_eval(struct PointCloud *pointcloud_src, bool reference);
|
||||
struct PointCloud *BKE_pointcloud_copy_for_eval(struct PointCloud *pointcloud_src);
|
||||
|
||||
void BKE_pointcloud_data_update(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
|
@ -53,8 +53,9 @@ typedef struct EditFont {
|
||||
int selstart, selend;
|
||||
|
||||
/**
|
||||
* Combined styles (#CharInfo.flag) for selected string. A flag will be
|
||||
* set only if ALL characters in the selected string have it.
|
||||
* Combined styles from #CharInfo.flag for the selected range selected
|
||||
* (only including values from #CU_CHINFO_STYLE_ALL).
|
||||
* A flag will be set only if ALL characters in the selected string have it.
|
||||
*/
|
||||
int select_char_info_flag;
|
||||
|
||||
|
@ -130,7 +130,7 @@ void BKE_volume_grid_transform_matrix_set(const struct Volume *volume,
|
||||
* file path. Grids are shared with the source data-block, not copied. */
|
||||
|
||||
struct Volume *BKE_volume_new_for_eval(const struct Volume *volume_src);
|
||||
struct Volume *BKE_volume_copy_for_eval(struct Volume *volume_src, bool reference);
|
||||
struct Volume *BKE_volume_copy_for_eval(struct Volume *volume_src);
|
||||
|
||||
struct VolumeGrid *BKE_volume_grid_add(struct Volume *volume,
|
||||
const char *name,
|
||||
|
@ -380,7 +380,7 @@ static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer)
|
||||
BKE_mesh_ensure_default_orig_index_customdata(mesh);
|
||||
}
|
||||
else {
|
||||
mesh = BKE_mesh_copy_for_eval(me, true);
|
||||
mesh = BKE_mesh_copy_for_eval(me);
|
||||
}
|
||||
|
||||
orco = get_orco_coords(ob, em, layer, &free);
|
||||
@ -654,15 +654,22 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
|
||||
if (ob->modifier_flag & OB_MODIFIER_FLAG_ADD_REST_POSITION) {
|
||||
if (mesh_final == nullptr) {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
|
||||
ASSERT_IS_VALID_MESH(mesh_final);
|
||||
}
|
||||
MutableAttributeAccessor attributes = mesh_final->attributes_for_write();
|
||||
SpanAttributeWriter<float3> rest_positions =
|
||||
attributes.lookup_or_add_for_write_only_span<float3>("rest_position", ATTR_DOMAIN_POINT);
|
||||
if (rest_positions && attributes.domain_size(ATTR_DOMAIN_POINT) > 0) {
|
||||
attributes.lookup<float3>("position").materialize(rest_positions.span);
|
||||
rest_positions.finish();
|
||||
const AttributeReader positions = attributes.lookup<float3>("position");
|
||||
if (positions) {
|
||||
if (positions.sharing_info && positions.varray.is_span()) {
|
||||
attributes.add<float3>("rest_position",
|
||||
ATTR_DOMAIN_POINT,
|
||||
AttributeInitShared(positions.varray.get_internal_span().data(),
|
||||
*positions.sharing_info));
|
||||
}
|
||||
else {
|
||||
attributes.add<float3>(
|
||||
"rest_position", ATTR_DOMAIN_POINT, AttributeInitVArray(positions.varray));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -678,7 +685,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
|
||||
blender::bke::ScopedModifierTimer modifier_timer{*md};
|
||||
if (!mesh_final) {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
|
||||
ASSERT_IS_VALID_MESH(mesh_final);
|
||||
}
|
||||
BKE_modifier_deform_verts(md,
|
||||
@ -696,12 +703,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
* places that wish to use the original mesh but with deformed
|
||||
* coordinates (like vertex paint). */
|
||||
if (r_deform) {
|
||||
if (mesh_final) {
|
||||
mesh_deform = BKE_mesh_copy_for_eval(mesh_final, false);
|
||||
}
|
||||
else {
|
||||
mesh_deform = BKE_mesh_copy_for_eval(mesh_input, false);
|
||||
}
|
||||
mesh_deform = BKE_mesh_copy_for_eval(mesh_final ? mesh_final : mesh_input);
|
||||
}
|
||||
}
|
||||
|
||||
@ -772,7 +774,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
|
||||
if (mti->type == eModifierTypeType_OnlyDeform) {
|
||||
if (!mesh_final) {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
|
||||
ASSERT_IS_VALID_MESH(mesh_final);
|
||||
}
|
||||
BKE_modifier_deform_verts(md,
|
||||
@ -791,7 +793,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
}
|
||||
}
|
||||
else {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
|
||||
ASSERT_IS_VALID_MESH(mesh_final);
|
||||
check_for_needs_mapping = true;
|
||||
}
|
||||
@ -959,7 +961,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
mesh_final = mesh_input;
|
||||
}
|
||||
else {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1004,7 +1006,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
/* Not yet finalized by any instance, do it now
|
||||
* Isolate since computing normals is multithreaded and we are holding a lock. */
|
||||
blender::threading::isolate_task([&] {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
|
||||
mesh_calc_modifier_final_normals(
|
||||
mesh_input, &final_datamask, sculpt_dyntopo, mesh_final);
|
||||
mesh_calc_finalize(mesh_input, mesh_final);
|
||||
@ -1019,7 +1021,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
else if (!mesh_has_modifier_final_normals(mesh_input, &final_datamask, runtime->mesh_eval)) {
|
||||
/* Modifier stack was (re-)evaluated with a request for additional normals
|
||||
* different than the instanced mesh, can't instance anymore now. */
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
|
||||
mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final);
|
||||
mesh_calc_finalize(mesh_input, mesh_final);
|
||||
}
|
||||
@ -1248,7 +1250,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
/* 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, false);
|
||||
Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final);
|
||||
if (mesh_final != mesh_cage) {
|
||||
BKE_id_free(nullptr, mesh_final);
|
||||
}
|
||||
@ -1257,7 +1259,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
}
|
||||
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, false);
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_final);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -1330,7 +1332,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
|
||||
if (r_cage && i == cageIndex) {
|
||||
if (mesh_final && deformed_verts) {
|
||||
mesh_cage = BKE_mesh_copy_for_eval(mesh_final, false);
|
||||
mesh_cage = BKE_mesh_copy_for_eval(mesh_final);
|
||||
BKE_mesh_vert_coords_apply(mesh_cage, deformed_verts);
|
||||
}
|
||||
else if (mesh_final) {
|
||||
@ -1366,7 +1368,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
if (mesh_final) {
|
||||
if (deformed_verts) {
|
||||
if (mesh_final == mesh_cage) {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_final, false);
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_final);
|
||||
}
|
||||
BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
|
||||
}
|
||||
|
@ -218,6 +218,12 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case AttributeInit::Type::Shared: {
|
||||
const AttributeInitShared &init = static_cast<const AttributeInitShared &>(initializer);
|
||||
const void *stored_data = CustomData_add_layer_with_data(
|
||||
&custom_data, data_type, const_cast<void *>(init.data), domain_num, init.sharing_info);
|
||||
return stored_data != nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
@ -293,6 +299,16 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
|
||||
custom_data, data_type, attribute_id, domain_num, data, nullptr);
|
||||
break;
|
||||
}
|
||||
case AttributeInit::Type::Shared: {
|
||||
const AttributeInitShared &init = static_cast<const AttributeInitShared &>(initializer);
|
||||
add_generic_custom_data_layer_with_existing_data(custom_data,
|
||||
data_type,
|
||||
attribute_id,
|
||||
domain_num,
|
||||
const_cast<void *>(init.data),
|
||||
init.sharing_info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return old_layer_num < custom_data.totlayer;
|
||||
}
|
||||
@ -314,7 +330,7 @@ bool BuiltinCustomDataLayerProvider::layer_exists(const CustomData &custom_data)
|
||||
return CustomData_has_layer(&custom_data, stored_type_);
|
||||
}
|
||||
|
||||
GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) const
|
||||
GAttributeReader BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) const
|
||||
{
|
||||
const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
|
||||
if (custom_data == nullptr) {
|
||||
@ -326,22 +342,23 @@ GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) cons
|
||||
const int element_num = custom_data_access_.get_element_num(owner);
|
||||
if (element_num == 0) {
|
||||
if (this->layer_exists(*custom_data)) {
|
||||
return GVArray::ForSpan({type, nullptr, 0});
|
||||
return {GVArray::ForSpan({type, nullptr, 0}), domain_, nullptr};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
const void *data = nullptr;
|
||||
int index;
|
||||
if (stored_as_named_attribute_) {
|
||||
data = CustomData_get_layer_named(custom_data, stored_type_, name_.c_str());
|
||||
index = CustomData_get_named_layer_index(custom_data, stored_type_, name_.c_str());
|
||||
}
|
||||
else {
|
||||
data = CustomData_get_layer(custom_data, stored_type_);
|
||||
index = CustomData_get_layer_index(custom_data, stored_type_);
|
||||
}
|
||||
if (data == nullptr) {
|
||||
if (index == -1) {
|
||||
return {};
|
||||
}
|
||||
return GVArray::ForSpan({type, data, element_num});
|
||||
const CustomDataLayer &layer = custom_data->layers[index];
|
||||
return {GVArray::ForSpan({type, layer.data, element_num}), domain_, layer.sharing_info};
|
||||
}
|
||||
|
||||
GAttributeWriter BuiltinCustomDataLayerProvider::try_get_for_write(void *owner) const
|
||||
@ -472,7 +489,7 @@ GAttributeReader CustomDataAttributeProvider::try_get_for_read(
|
||||
continue;
|
||||
}
|
||||
GSpan data{*type, layer.data, element_num};
|
||||
return {GVArray::ForSpan(data), domain_};
|
||||
return {GVArray::ForSpan(data), domain_, layer.sharing_info};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@ -729,7 +746,7 @@ static blender::GVArray try_adapt_data_type(blender::GVArray varray,
|
||||
return conversions.try_convert(std::move(varray), to_type);
|
||||
}
|
||||
|
||||
GVArray AttributeAccessor::lookup(const AttributeIDRef &attribute_id,
|
||||
GAttributeReader AttributeAccessor::lookup(const AttributeIDRef &attribute_id,
|
||||
const std::optional<eAttrDomain> domain,
|
||||
const std::optional<eCustomDataType> data_type) const
|
||||
{
|
||||
@ -737,42 +754,44 @@ GVArray AttributeAccessor::lookup(const AttributeIDRef &attribute_id,
|
||||
if (!attribute) {
|
||||
return {};
|
||||
}
|
||||
GVArray varray = std::move(attribute.varray);
|
||||
if (domain.has_value()) {
|
||||
if (attribute.domain != domain) {
|
||||
varray = this->adapt_domain(varray, attribute.domain, *domain);
|
||||
if (!varray) {
|
||||
attribute.varray = this->adapt_domain(attribute.varray, attribute.domain, *domain);
|
||||
attribute.domain = *domain;
|
||||
attribute.sharing_info = nullptr;
|
||||
if (!attribute.varray) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data_type.has_value()) {
|
||||
const CPPType &type = *custom_data_type_to_cpp_type(*data_type);
|
||||
if (varray.type() != type) {
|
||||
varray = try_adapt_data_type(std::move(varray), type);
|
||||
if (!varray) {
|
||||
if (attribute.varray.type() != type) {
|
||||
attribute.varray = try_adapt_data_type(std::move(attribute.varray), type);
|
||||
attribute.sharing_info = nullptr;
|
||||
if (!attribute.varray) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
return varray;
|
||||
return attribute;
|
||||
}
|
||||
|
||||
GVArray AttributeAccessor::lookup_or_default(const AttributeIDRef &attribute_id,
|
||||
GAttributeReader AttributeAccessor::lookup_or_default(const AttributeIDRef &attribute_id,
|
||||
const eAttrDomain domain,
|
||||
const eCustomDataType data_type,
|
||||
const void *default_value) const
|
||||
{
|
||||
GVArray varray = this->lookup(attribute_id, domain, data_type);
|
||||
if (varray) {
|
||||
return varray;
|
||||
GAttributeReader attribute = this->lookup(attribute_id, domain, data_type);
|
||||
if (attribute) {
|
||||
return attribute;
|
||||
}
|
||||
const CPPType &type = *custom_data_type_to_cpp_type(data_type);
|
||||
const int64_t domain_size = this->domain_size(domain);
|
||||
if (default_value == nullptr) {
|
||||
return GVArray::ForSingleRef(type, domain_size, type.default_value());
|
||||
return {GVArray::ForSingleRef(type, domain_size, type.default_value()), domain, nullptr};
|
||||
}
|
||||
return GVArray::ForSingle(type, domain_size, default_value);
|
||||
return {GVArray::ForSingle(type, domain_size, default_value), domain, nullptr};
|
||||
}
|
||||
|
||||
Set<AttributeIDRef> AttributeAccessor::all_ids() const
|
||||
@ -921,7 +940,7 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer(
|
||||
return true;
|
||||
}
|
||||
|
||||
GVArray src = src_attributes.lookup(id, meta_data.domain);
|
||||
GVArray src = *src_attributes.lookup(id, meta_data.domain);
|
||||
BLI_assert(src);
|
||||
bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
|
||||
id, meta_data.domain, meta_data.data_type);
|
||||
|
@ -66,7 +66,7 @@ class BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
virtual GVArray try_get_for_read(const void *owner) const = 0;
|
||||
virtual GAttributeReader try_get_for_read(const void *owner) const = 0;
|
||||
virtual GAttributeWriter try_get_for_write(void *owner) const = 0;
|
||||
virtual bool try_delete(void *owner) const = 0;
|
||||
virtual bool try_create(void *onwer, const AttributeInit &initializer) const = 0;
|
||||
@ -196,7 +196,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArray try_get_for_read(const void *owner) const final;
|
||||
GAttributeReader try_get_for_read(const void *owner) const final;
|
||||
GAttributeWriter try_get_for_write(void *owner) const final;
|
||||
bool try_delete(void *owner) const final;
|
||||
bool try_create(void *owner, const AttributeInit &initializer) const final;
|
||||
@ -279,7 +279,7 @@ inline GAttributeReader lookup(const void *owner, const AttributeIDRef &attribut
|
||||
const StringRef name = attribute_id.name();
|
||||
if (const BuiltinAttributeProvider *provider =
|
||||
providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {
|
||||
return {provider->try_get_for_read(owner), provider->domain()};
|
||||
return provider->try_get_for_read(owner);
|
||||
}
|
||||
}
|
||||
for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {
|
||||
|
@ -1276,14 +1276,57 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
|
||||
|
||||
break;
|
||||
}
|
||||
case GP_BRUSH_PRESET_DRAW_WEIGHT: {
|
||||
case GP_BRUSH_PRESET_WEIGHT_DRAW: {
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_WEIGHT;
|
||||
brush->gpencil_weight_tool = GPWEIGHT_TOOL_DRAW;
|
||||
|
||||
brush->size = 25.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
|
||||
|
||||
brush->gpencil_settings->draw_strength = 0.8f;
|
||||
brush->alpha = 0.3f;
|
||||
brush->gpencil_settings->draw_strength = 0.3f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE;
|
||||
brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
|
||||
|
||||
break;
|
||||
}
|
||||
case GP_BRUSH_PRESET_WEIGHT_BLUR: {
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_VERTEX_BLUR;
|
||||
brush->gpencil_weight_tool = GPWEIGHT_TOOL_BLUR;
|
||||
|
||||
brush->size = 50.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
|
||||
|
||||
brush->alpha = 0.3f;
|
||||
brush->gpencil_settings->draw_strength = 0.3f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE;
|
||||
brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
|
||||
|
||||
break;
|
||||
}
|
||||
case GP_BRUSH_PRESET_WEIGHT_AVERAGE: {
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_VERTEX_BLUR;
|
||||
brush->gpencil_weight_tool = GPWEIGHT_TOOL_AVERAGE;
|
||||
|
||||
brush->size = 50.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
|
||||
|
||||
brush->alpha = 0.3f;
|
||||
brush->gpencil_settings->draw_strength = 0.3f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE;
|
||||
brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
|
||||
|
||||
break;
|
||||
}
|
||||
case GP_BRUSH_PRESET_WEIGHT_SMEAR: {
|
||||
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_VERTEX_BLUR;
|
||||
brush->gpencil_weight_tool = GPWEIGHT_TOOL_SMEAR;
|
||||
|
||||
brush->size = 50.0f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
|
||||
|
||||
brush->alpha = 0.3f;
|
||||
brush->gpencil_settings->draw_strength = 0.3f;
|
||||
brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE;
|
||||
brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
|
||||
|
||||
@ -1569,13 +1612,32 @@ void BKE_brush_gpencil_weight_presets(Main *bmain, ToolSettings *ts, const bool
|
||||
Paint *weightpaint = &ts->gp_weightpaint->paint;
|
||||
Brush *brush_prev = weightpaint->brush;
|
||||
Brush *brush, *deft_weight;
|
||||
/* Vertex Draw brush. */
|
||||
brush = gpencil_brush_ensure(bmain, ts, "Draw Weight", OB_MODE_WEIGHT_GPENCIL, &r_new);
|
||||
|
||||
/* Weight Draw brush. */
|
||||
brush = gpencil_brush_ensure(bmain, ts, "Weight Draw", OB_MODE_WEIGHT_GPENCIL, &r_new);
|
||||
if ((reset) || (r_new)) {
|
||||
BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_DRAW_WEIGHT);
|
||||
BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_WEIGHT_DRAW);
|
||||
}
|
||||
deft_weight = brush; /* save default brush. */
|
||||
|
||||
/* Weight Blur brush. */
|
||||
brush = gpencil_brush_ensure(bmain, ts, "Weight Blur", OB_MODE_WEIGHT_GPENCIL, &r_new);
|
||||
if ((reset) || (r_new)) {
|
||||
BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_WEIGHT_BLUR);
|
||||
}
|
||||
|
||||
/* Weight Average brush. */
|
||||
brush = gpencil_brush_ensure(bmain, ts, "Weight Average", OB_MODE_WEIGHT_GPENCIL, &r_new);
|
||||
if ((reset) || (r_new)) {
|
||||
BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_WEIGHT_AVERAGE);
|
||||
}
|
||||
|
||||
/* Weight Smear brush. */
|
||||
brush = gpencil_brush_ensure(bmain, ts, "Weight Smear", OB_MODE_WEIGHT_GPENCIL, &r_new);
|
||||
if ((reset) || (r_new)) {
|
||||
BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_WEIGHT_SMEAR);
|
||||
}
|
||||
|
||||
/* Set default brush. */
|
||||
if (reset || brush_prev == nullptr) {
|
||||
BKE_paint_brush_set(weightpaint, deft_weight);
|
||||
|
@ -1280,7 +1280,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
|
||||
blender::bke::AttributeAccessor attributes = mesh->attributes();
|
||||
mask = looptri_no_hidden_map_get(
|
||||
mesh->polys(),
|
||||
attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false),
|
||||
*attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false),
|
||||
looptris.size(),
|
||||
&mask_bits_act_len);
|
||||
ATTR_FALLTHROUGH;
|
||||
|
@ -399,7 +399,7 @@ bool BKE_cachefile_filepath_get(const Main *bmain,
|
||||
const int frame = (int)BKE_cachefile_time_offset(cache_file, (double)ctime, fps);
|
||||
|
||||
char ext[32];
|
||||
BLI_path_frame_strip(r_filepath, ext);
|
||||
BLI_path_frame_strip(r_filepath, ext, sizeof(ext));
|
||||
BLI_path_frame(r_filepath, frame, frame_len);
|
||||
BLI_path_extension_ensure(r_filepath, FILE_MAX, ext);
|
||||
|
||||
|
@ -1176,7 +1176,7 @@ static void cloth_update_verts(Object *ob, ClothModifierData *clmd, Mesh *mesh)
|
||||
static Mesh *cloth_make_rest_mesh(ClothModifierData *clmd, Mesh *mesh)
|
||||
{
|
||||
using namespace blender;
|
||||
Mesh *new_mesh = BKE_mesh_copy_for_eval(mesh, false);
|
||||
Mesh *new_mesh = BKE_mesh_copy_for_eval(mesh);
|
||||
ClothVertex *verts = clmd->clothObject->verts;
|
||||
MutableSpan<float3> positions = mesh->vert_positions_for_write();
|
||||
|
||||
|
@ -389,7 +389,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
|
||||
if (defmats == nullptr) {
|
||||
/* NOTE: Evaluated object is re-set to its original un-deformed state. */
|
||||
Mesh *me = static_cast<Mesh *>(object_eval.data);
|
||||
me_eval = BKE_mesh_copy_for_eval(me, true);
|
||||
me_eval = BKE_mesh_copy_for_eval(me);
|
||||
crazyspace_init_verts_and_matrices(me_eval, &defmats, &deformedVerts);
|
||||
}
|
||||
|
||||
@ -470,7 +470,7 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
|
||||
}
|
||||
|
||||
if (mesh_eval == nullptr) {
|
||||
mesh_eval = BKE_mesh_copy_for_eval(mesh, true);
|
||||
mesh_eval = BKE_mesh_copy_for_eval(mesh);
|
||||
}
|
||||
|
||||
mti->deformVerts(md, &mectx, mesh_eval, deformedVerts, mesh_eval->totvert);
|
||||
|
@ -691,7 +691,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
||||
}
|
||||
|
||||
Mesh *mesh = BKE_mesh_new_nomain(
|
||||
offsets.vert.last(), offsets.edge.last(), offsets.loop.last(), offsets.poly.last());
|
||||
offsets.vert.last(), offsets.edge.last(), offsets.poly.last(), offsets.loop.last());
|
||||
mesh->flag |= ME_AUTOSMOOTH;
|
||||
mesh->smoothresh = DEG2RADF(180.0f);
|
||||
MutableSpan<float3> positions = mesh->vert_positions_for_write();
|
||||
@ -747,7 +747,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
||||
Span<float> radii = {};
|
||||
if (main_attributes.contains("radius")) {
|
||||
radii = evaluated_attribute_if_necessary(
|
||||
main_attributes.lookup_or_default<float>("radius", ATTR_DOMAIN_POINT, 1.0f),
|
||||
*main_attributes.lookup_or_default<float>("radius", ATTR_DOMAIN_POINT, 1.0f),
|
||||
main,
|
||||
main.curve_type_counts(),
|
||||
eval_buffer)
|
||||
@ -805,7 +805,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
||||
|
||||
const eAttrDomain src_domain = meta_data.domain;
|
||||
const eCustomDataType type = meta_data.data_type;
|
||||
GVArray src = main_attributes.lookup(id, src_domain, type);
|
||||
const GVArray src = *main_attributes.lookup(id, src_domain, type);
|
||||
|
||||
const eAttrDomain dst_domain = get_attribute_domain_for_mesh(mesh_attributes, id);
|
||||
GSpanAttributeWriter dst = mesh_attributes.lookup_or_add_for_write_only_span(
|
||||
@ -841,7 +841,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
||||
}
|
||||
const eAttrDomain src_domain = meta_data.domain;
|
||||
const eCustomDataType type = meta_data.data_type;
|
||||
GVArray src = profile_attributes.lookup(id, src_domain, type);
|
||||
const GVArray src = *profile_attributes.lookup(id, src_domain, type);
|
||||
|
||||
const eAttrDomain dst_domain = get_attribute_domain_for_mesh(mesh_attributes, id);
|
||||
GSpanAttributeWriter dst = mesh_attributes.lookup_or_add_for_write_only_span(
|
||||
|
@ -220,16 +220,10 @@ bool BKE_curves_attribute_required(const Curves * /*curves*/, const char *name)
|
||||
return STREQ(name, ATTR_POSITION);
|
||||
}
|
||||
|
||||
Curves *BKE_curves_copy_for_eval(Curves *curves_src, bool reference)
|
||||
Curves *BKE_curves_copy_for_eval(Curves *curves_src)
|
||||
{
|
||||
int flags = LIB_ID_COPY_LOCALIZE;
|
||||
|
||||
if (reference) {
|
||||
flags |= LIB_ID_COPY_CD_REFERENCE;
|
||||
}
|
||||
|
||||
Curves *result = (Curves *)BKE_id_copy_ex(nullptr, &curves_src->id, nullptr, flags);
|
||||
return result;
|
||||
return reinterpret_cast<Curves *>(
|
||||
BKE_id_copy_ex(nullptr, &curves_src->id, nullptr, LIB_ID_COPY_LOCALIZE));
|
||||
}
|
||||
|
||||
static void curves_evaluate_modifiers(struct Depsgraph *depsgraph,
|
||||
|
@ -1904,7 +1904,7 @@ static void dynamic_paint_apply_surface_wave_cb(void *__restrict userdata,
|
||||
*/
|
||||
static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *ob, Mesh *mesh)
|
||||
{
|
||||
Mesh *result = BKE_mesh_copy_for_eval(mesh, false);
|
||||
Mesh *result = BKE_mesh_copy_for_eval(mesh);
|
||||
|
||||
if (pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING) &&
|
||||
pmd->type == MOD_DYNAMICPAINT_TYPE_CANVAS) {
|
||||
@ -2049,7 +2049,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
|
||||
if (runtime_data->brush_mesh != nullptr) {
|
||||
BKE_id_free(nullptr, runtime_data->brush_mesh);
|
||||
}
|
||||
runtime_data->brush_mesh = BKE_mesh_copy_for_eval(result, false);
|
||||
runtime_data->brush_mesh = BKE_mesh_copy_for_eval(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -2070,7 +2070,7 @@ static void canvas_copyMesh(DynamicPaintCanvasSettings *canvas, Mesh *mesh)
|
||||
BKE_id_free(nullptr, runtime->canvas_mesh);
|
||||
}
|
||||
|
||||
runtime->canvas_mesh = BKE_mesh_copy_for_eval(mesh, false);
|
||||
runtime->canvas_mesh = BKE_mesh_copy_for_eval(mesh);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3796,7 +3796,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph,
|
||||
SUBFRAME_RECURSION,
|
||||
BKE_scene_ctime_get(scene),
|
||||
eModifierType_DynamicPaint);
|
||||
mesh_p = BKE_mesh_copy_for_eval(dynamicPaint_brush_mesh_get(brush), false);
|
||||
mesh_p = BKE_mesh_copy_for_eval(dynamicPaint_brush_mesh_get(brush));
|
||||
numOfVerts_p = mesh_p->totvert;
|
||||
|
||||
float(*positions_p)[3] = BKE_mesh_vert_positions_for_write(mesh_p);
|
||||
@ -4282,7 +4282,7 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
|
||||
Bounds3D mesh_bb = {{0}};
|
||||
VolumeGrid *grid = bData->grid;
|
||||
|
||||
mesh = BKE_mesh_copy_for_eval(brush_mesh, false);
|
||||
mesh = BKE_mesh_copy_for_eval(brush_mesh);
|
||||
float(*positions)[3] = BKE_mesh_vert_positions_for_write(mesh);
|
||||
const blender::Span<blender::float3> vert_normals = mesh->vert_normals();
|
||||
const blender::Span<int> corner_verts = mesh->corner_verts();
|
||||
|
@ -1003,7 +1003,7 @@ static void obstacles_from_mesh(Object *coll_ob,
|
||||
float *vert_vel = nullptr;
|
||||
bool has_velocity = false;
|
||||
|
||||
Mesh *me = BKE_mesh_copy_for_eval(fes->mesh, false);
|
||||
Mesh *me = BKE_mesh_copy_for_eval(fes->mesh);
|
||||
float(*positions)[3] = BKE_mesh_vert_positions_for_write(me);
|
||||
|
||||
int min[3], max[3], res[3];
|
||||
@ -2062,7 +2062,7 @@ static void emit_from_mesh(
|
||||
|
||||
/* Copy mesh for thread safety as we modify it.
|
||||
* Main issue is its VertArray being modified, then replaced and freed. */
|
||||
Mesh *me = BKE_mesh_copy_for_eval(ffs->mesh, false);
|
||||
Mesh *me = BKE_mesh_copy_for_eval(ffs->mesh);
|
||||
float(*positions)[3] = BKE_mesh_vert_positions_for_write(me);
|
||||
|
||||
const blender::Span<int> corner_verts = me->corner_verts();
|
||||
@ -3229,7 +3229,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
me = BKE_mesh_new_nomain(num_verts, 0, num_faces * 3, num_faces);
|
||||
me = BKE_mesh_new_nomain(num_verts, 0, num_faces, num_faces * 3);
|
||||
if (!me) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -3237,8 +3237,9 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
blender::MutableSpan<int> poly_offsets = me->poly_offsets_for_write();
|
||||
blender::MutableSpan<int> corner_verts = me->corner_verts_for_write();
|
||||
|
||||
const bool is_sharp = orgmesh->attributes().lookup_or_default<bool>(
|
||||
"sharp_face", ATTR_DOMAIN_FACE, false)[0];
|
||||
const bool is_sharp = orgmesh->attributes()
|
||||
.lookup_or_default<bool>("sharp_face", ATTR_DOMAIN_FACE, false)
|
||||
.varray[0];
|
||||
BKE_mesh_smooth_flag_set(me, !is_sharp);
|
||||
|
||||
/* Get size (dimension) but considering scaling. */
|
||||
@ -3363,10 +3364,10 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje
|
||||
|
||||
/* Just copy existing mesh if there is no content or if the adaptive domain is not being used. */
|
||||
if (fds->total_cells <= 1 || (fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) == 0) {
|
||||
return BKE_mesh_copy_for_eval(orgmesh, false);
|
||||
return BKE_mesh_copy_for_eval(orgmesh);
|
||||
}
|
||||
|
||||
result = BKE_mesh_new_nomain(num_verts, 0, num_faces * 4, num_faces);
|
||||
result = BKE_mesh_new_nomain(num_verts, 0, num_faces, num_faces * 4);
|
||||
float(*positions)[3] = BKE_mesh_vert_positions_for_write(result);
|
||||
blender::MutableSpan<int> poly_offsets = result->poly_offsets_for_write();
|
||||
blender::MutableSpan<int> corner_verts = result->corner_verts_for_write();
|
||||
@ -3589,7 +3590,7 @@ static void fluid_modifier_processFlow(FluidModifierData *fmd,
|
||||
if (fmd->flow->mesh) {
|
||||
BKE_id_free(nullptr, fmd->flow->mesh);
|
||||
}
|
||||
fmd->flow->mesh = BKE_mesh_copy_for_eval(me, false);
|
||||
fmd->flow->mesh = BKE_mesh_copy_for_eval(me);
|
||||
}
|
||||
|
||||
if (scene_framenr > fmd->time) {
|
||||
@ -3616,7 +3617,7 @@ static void fluid_modifier_processEffector(FluidModifierData *fmd,
|
||||
if (fmd->effector->mesh) {
|
||||
BKE_id_free(nullptr, fmd->effector->mesh);
|
||||
}
|
||||
fmd->effector->mesh = BKE_mesh_copy_for_eval(me, false);
|
||||
fmd->effector->mesh = BKE_mesh_copy_for_eval(me);
|
||||
}
|
||||
|
||||
if (scene_framenr > fmd->time) {
|
||||
@ -4124,7 +4125,7 @@ Mesh *BKE_fluid_modifier_do(
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
result = BKE_mesh_copy_for_eval(me, false);
|
||||
result = BKE_mesh_copy_for_eval(me);
|
||||
}
|
||||
else {
|
||||
BKE_mesh_copy_parameters_for_eval(result, me);
|
||||
|
@ -33,7 +33,7 @@ GeometryComponent *CurveComponent::copy() const
|
||||
{
|
||||
CurveComponent *new_component = new CurveComponent();
|
||||
if (curves_ != nullptr) {
|
||||
new_component->curves_ = BKE_curves_copy_for_eval(curves_, false);
|
||||
new_component->curves_ = BKE_curves_copy_for_eval(curves_);
|
||||
new_component->ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
return new_component;
|
||||
@ -87,7 +87,7 @@ Curves *CurveComponent::get_for_write()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ == GeometryOwnershipType::ReadOnly) {
|
||||
curves_ = BKE_curves_copy_for_eval(curves_, false);
|
||||
curves_ = BKE_curves_copy_for_eval(curves_);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
return curves_;
|
||||
@ -107,7 +107,7 @@ void CurveComponent::ensure_owns_direct_data()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ != GeometryOwnershipType::Owned) {
|
||||
curves_ = BKE_curves_copy_for_eval(curves_, false);
|
||||
curves_ = BKE_curves_copy_for_eval(curves_);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
}
|
||||
|
@ -131,14 +131,16 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
|
||||
{
|
||||
}
|
||||
|
||||
GVArray try_get_for_read(const void *owner) const final
|
||||
GAttributeReader try_get_for_read(const void *owner) const final
|
||||
{
|
||||
const Instances *instances = static_cast<const Instances *>(owner);
|
||||
if (instances == nullptr) {
|
||||
return {};
|
||||
}
|
||||
Span<float4x4> transforms = instances->transforms();
|
||||
return VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms);
|
||||
return {VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms),
|
||||
domain_,
|
||||
nullptr};
|
||||
}
|
||||
|
||||
GAttributeWriter try_get_for_write(void *owner) const final
|
||||
|
@ -36,7 +36,7 @@ GeometryComponent *MeshComponent::copy() const
|
||||
{
|
||||
MeshComponent *new_component = new MeshComponent();
|
||||
if (mesh_ != nullptr) {
|
||||
new_component->mesh_ = BKE_mesh_copy_for_eval(mesh_, false);
|
||||
new_component->mesh_ = BKE_mesh_copy_for_eval(mesh_);
|
||||
new_component->ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
return new_component;
|
||||
@ -83,7 +83,7 @@ Mesh *MeshComponent::get_for_write()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ == GeometryOwnershipType::ReadOnly) {
|
||||
mesh_ = BKE_mesh_copy_for_eval(mesh_, false);
|
||||
mesh_ = BKE_mesh_copy_for_eval(mesh_);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
return mesh_;
|
||||
@ -103,7 +103,7 @@ void MeshComponent::ensure_owns_direct_data()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ != GeometryOwnershipType::Owned) {
|
||||
mesh_ = BKE_mesh_copy_for_eval(mesh_, false);
|
||||
mesh_ = BKE_mesh_copy_for_eval(mesh_);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
}
|
||||
@ -1114,7 +1114,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_FLOAT3,
|
||||
CD_PROP_FLOAT3,
|
||||
BuiltinAttributeProvider::NonCreatable,
|
||||
BuiltinAttributeProvider::Creatable,
|
||||
BuiltinAttributeProvider::NonDeletable,
|
||||
point_access,
|
||||
tag_component_positions_changed);
|
||||
|
@ -23,7 +23,7 @@ GeometryComponent *PointCloudComponent::copy() const
|
||||
{
|
||||
PointCloudComponent *new_component = new PointCloudComponent();
|
||||
if (pointcloud_ != nullptr) {
|
||||
new_component->pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_, false);
|
||||
new_component->pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_);
|
||||
new_component->ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
return new_component;
|
||||
@ -70,7 +70,7 @@ PointCloud *PointCloudComponent::get_for_write()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ == GeometryOwnershipType::ReadOnly) {
|
||||
pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_, false);
|
||||
pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
return pointcloud_;
|
||||
@ -90,7 +90,7 @@ void PointCloudComponent::ensure_owns_direct_data()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ != GeometryOwnershipType::Owned) {
|
||||
pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_, false);
|
||||
pointcloud_ = BKE_pointcloud_copy_for_eval(pointcloud_);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
}
|
||||
@ -139,7 +139,7 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud()
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_FLOAT3,
|
||||
CD_PROP_FLOAT3,
|
||||
BuiltinAttributeProvider::NonCreatable,
|
||||
BuiltinAttributeProvider::Creatable,
|
||||
BuiltinAttributeProvider::NonDeletable,
|
||||
point_access,
|
||||
tag_component_positions_changed);
|
||||
|
@ -21,7 +21,7 @@ GeometryComponent *VolumeComponent::copy() const
|
||||
{
|
||||
VolumeComponent *new_component = new VolumeComponent();
|
||||
if (volume_ != nullptr) {
|
||||
new_component->volume_ = BKE_volume_copy_for_eval(volume_, false);
|
||||
new_component->volume_ = BKE_volume_copy_for_eval(volume_);
|
||||
new_component->ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
return new_component;
|
||||
@ -68,7 +68,7 @@ Volume *VolumeComponent::get_for_write()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ == GeometryOwnershipType::ReadOnly) {
|
||||
volume_ = BKE_volume_copy_for_eval(volume_, false);
|
||||
volume_ = BKE_volume_copy_for_eval(volume_);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
return volume_;
|
||||
@ -83,7 +83,7 @@ void VolumeComponent::ensure_owns_direct_data()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
if (ownership_ != GeometryOwnershipType::Owned) {
|
||||
volume_ = BKE_volume_copy_for_eval(volume_, false);
|
||||
volume_ = BKE_volume_copy_for_eval(volume_);
|
||||
ownership_ = GeometryOwnershipType::Owned;
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ GVArray AttributeFieldInput::get_varray_for_context(const GeometryFieldContext &
|
||||
{
|
||||
const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_);
|
||||
if (auto attributes = context.attributes()) {
|
||||
return attributes->lookup(name_, context.domain(), data_type);
|
||||
return *attributes->lookup(name_, context.domain(), data_type);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@ -304,7 +304,7 @@ GVArray IDAttributeFieldInput::get_varray_for_context(const GeometryFieldContext
|
||||
|
||||
const StringRef name = get_random_id_attribute_name(context.domain());
|
||||
if (auto attributes = context.attributes()) {
|
||||
if (GVArray attribute = attributes->lookup(name, context.domain(), CD_PROP_INT32)) {
|
||||
if (GVArray attribute = *attributes->lookup(name, context.domain(), CD_PROP_INT32)) {
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
@ -334,7 +334,7 @@ GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryField
|
||||
const IndexMask /*mask*/) const
|
||||
{
|
||||
const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_);
|
||||
return context.attributes()->lookup(*anonymous_id_, context.domain(), data_type);
|
||||
return *context.attributes()->lookup(*anonymous_id_, context.domain(), data_type);
|
||||
}
|
||||
|
||||
std::string AnonymousAttributeFieldInput::socket_inspection_name() const
|
||||
@ -474,7 +474,7 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
|
||||
}
|
||||
|
||||
attributes.remove(attribute_id);
|
||||
if (attributes.add(attribute_id, domain, data_type, bke::AttributeInitMoveArray{buffer})) {
|
||||
if (attributes.add(attribute_id, domain, data_type, bke::AttributeInitMoveArray(buffer))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2507,7 +2507,7 @@ static void gpencil_generate_edgeloops(Object *ob,
|
||||
const Span<MDeformVert> dverts = me->deform_verts();
|
||||
const blender::Span<blender::float3> vert_normals = me->vert_normals();
|
||||
const bke::AttributeAccessor attributes = me->attributes();
|
||||
const VArray<bool> uv_seams = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> uv_seams = *attributes.lookup_or_default<bool>(
|
||||
".uv_seam", ATTR_DOMAIN_EDGE, false);
|
||||
|
||||
/* Arrays for all edge vertices (forward and backward) that form a edge loop.
|
||||
@ -2753,7 +2753,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
|
||||
gpl_fill, scene->r.cfra + frame_offset, GP_GETFRAME_ADD_NEW);
|
||||
int i;
|
||||
|
||||
const VArray<int> mesh_material_indices = me_eval->attributes().lookup_or_default<int>(
|
||||
const VArray<int> mesh_material_indices = *me_eval->attributes().lookup_or_default<int>(
|
||||
"material_index", ATTR_DOMAIN_FACE, 0);
|
||||
for (i = 0; i < polys_len; i++) {
|
||||
const IndexRange poly = polys[i];
|
||||
|
@ -1451,18 +1451,17 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
|
||||
freepolygonize(&process);
|
||||
|
||||
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)ob->data)->name + 2);
|
||||
int corners_num = 0;
|
||||
for (uint i = 0; i < process.curindex; i++) {
|
||||
const int *indices = process.indices[i];
|
||||
const int count = indices[2] != indices[3] ? 4 : 3;
|
||||
corners_num += count;
|
||||
}
|
||||
|
||||
mesh->totvert = int(process.co.size());
|
||||
CustomData_add_layer_named(
|
||||
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, mesh->totvert, "position");
|
||||
Mesh *mesh = BKE_mesh_new_nomain(int(process.co.size()), 0, int(process.curindex), corners_num);
|
||||
mesh->vert_positions_for_write().copy_from(process.co);
|
||||
|
||||
mesh->totpoly = int(process.curindex);
|
||||
BKE_mesh_poly_offsets_ensure_alloc(mesh);
|
||||
blender::MutableSpan<int> poly_offsets = mesh->poly_offsets_for_write();
|
||||
int *corner_verts = static_cast<int *>(CustomData_add_layer_named(
|
||||
&mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totpoly * 4, ".corner_vert"));
|
||||
blender::MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
|
||||
|
||||
int loop_offset = 0;
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
@ -1490,9 +1489,6 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
sizeof(float[3]) * size_t(mesh->totvert));
|
||||
BKE_mesh_vert_normals_clear_dirty(mesh);
|
||||
|
||||
mesh->totloop = loop_offset;
|
||||
poly_offsets.last() = loop_offset;
|
||||
|
||||
BKE_mesh_calc_edges(mesh, false, false);
|
||||
|
||||
return mesh;
|
||||
|
@ -1032,23 +1032,19 @@ static void mesh_ensure_cdlayers_primary(Mesh &mesh)
|
||||
}
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_new_nomain(int verts_len, int edges_len, int loops_len, int polys_len)
|
||||
Mesh *BKE_mesh_new_nomain(const int verts_num,
|
||||
const int edges_num,
|
||||
const int polys_num,
|
||||
const int loops_num)
|
||||
{
|
||||
Mesh *mesh = (Mesh *)BKE_libblock_alloc(
|
||||
nullptr, ID_ME, BKE_idtype_idcode_to_name(ID_ME), LIB_ID_CREATE_LOCALIZE);
|
||||
Mesh *mesh = static_cast<Mesh *>(BKE_libblock_alloc(
|
||||
nullptr, ID_ME, BKE_idtype_idcode_to_name(ID_ME), LIB_ID_CREATE_LOCALIZE));
|
||||
BKE_libblock_init_empty(&mesh->id);
|
||||
|
||||
/* Don't use #CustomData_reset because we don't want to touch custom-data. */
|
||||
copy_vn_i(mesh->vdata.typemap, CD_NUMTYPES, -1);
|
||||
copy_vn_i(mesh->edata.typemap, CD_NUMTYPES, -1);
|
||||
copy_vn_i(mesh->fdata.typemap, CD_NUMTYPES, -1);
|
||||
copy_vn_i(mesh->ldata.typemap, CD_NUMTYPES, -1);
|
||||
copy_vn_i(mesh->pdata.typemap, CD_NUMTYPES, -1);
|
||||
|
||||
mesh->totvert = verts_len;
|
||||
mesh->totedge = edges_len;
|
||||
mesh->totloop = loops_len;
|
||||
mesh->totpoly = polys_len;
|
||||
mesh->totvert = verts_num;
|
||||
mesh->totedge = edges_num;
|
||||
mesh->totpoly = polys_num;
|
||||
mesh->totloop = loops_num;
|
||||
|
||||
mesh_ensure_cdlayers_primary(*mesh);
|
||||
BKE_mesh_poly_offsets_ensure_alloc(mesh);
|
||||
@ -1112,35 +1108,35 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
||||
int verts_len,
|
||||
int edges_len,
|
||||
int tessface_len,
|
||||
int loops_len,
|
||||
int polys_len,
|
||||
CustomData_MeshMasks mask)
|
||||
const int verts_num,
|
||||
const int edges_num,
|
||||
const int tessface_num,
|
||||
const int polys_num,
|
||||
const int loops_num,
|
||||
const CustomData_MeshMasks mask)
|
||||
{
|
||||
/* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */
|
||||
const bool do_tessface = (tessface_len || ((me_src->totface != 0) && (me_src->totpoly == 0)));
|
||||
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);
|
||||
|
||||
me_dst->mselect = (MSelect *)MEM_dupallocN(me_src->mselect);
|
||||
|
||||
me_dst->totvert = verts_len;
|
||||
me_dst->totedge = edges_len;
|
||||
me_dst->totface = tessface_len;
|
||||
me_dst->totloop = loops_len;
|
||||
me_dst->totpoly = polys_len;
|
||||
me_dst->totvert = verts_num;
|
||||
me_dst->totedge = edges_num;
|
||||
me_dst->totpoly = polys_num;
|
||||
me_dst->totloop = loops_num;
|
||||
me_dst->totface = tessface_num;
|
||||
|
||||
BKE_mesh_copy_parameters_for_eval(me_dst, me_src);
|
||||
|
||||
CustomData_copy_layout(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_SET_DEFAULT, verts_len);
|
||||
CustomData_copy_layout(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_len);
|
||||
CustomData_copy_layout(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_len);
|
||||
CustomData_copy_layout(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_len);
|
||||
CustomData_copy_layout(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_SET_DEFAULT, verts_num);
|
||||
CustomData_copy_layout(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_num);
|
||||
CustomData_copy_layout(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_num);
|
||||
CustomData_copy_layout(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_num);
|
||||
if (do_tessface) {
|
||||
CustomData_copy_layout(
|
||||
&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_len);
|
||||
&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_num);
|
||||
}
|
||||
else {
|
||||
mesh_tessface_clear_intern(me_dst, false);
|
||||
@ -1160,11 +1156,14 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
||||
return me_dst;
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_new_nomain_from_template(
|
||||
const Mesh *me_src, int verts_len, int edges_len, int loops_len, int polys_len)
|
||||
Mesh *BKE_mesh_new_nomain_from_template(const Mesh *me_src,
|
||||
const int verts_num,
|
||||
const int edges_num,
|
||||
const int polys_num,
|
||||
const int loops_num)
|
||||
{
|
||||
return BKE_mesh_new_nomain_from_template_ex(
|
||||
me_src, verts_len, edges_len, 0, loops_len, polys_len, CD_MASK_EVERYTHING);
|
||||
me_src, verts_num, edges_num, 0, polys_num, loops_num, CD_MASK_EVERYTHING);
|
||||
}
|
||||
|
||||
void BKE_mesh_eval_delete(struct Mesh *mesh_eval)
|
||||
@ -1176,16 +1175,10 @@ void BKE_mesh_eval_delete(struct Mesh *mesh_eval)
|
||||
MEM_freeN(mesh_eval);
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_copy_for_eval(const Mesh *source, bool reference)
|
||||
Mesh *BKE_mesh_copy_for_eval(const Mesh *source)
|
||||
{
|
||||
int flags = LIB_ID_COPY_LOCALIZE;
|
||||
|
||||
if (reference) {
|
||||
flags |= LIB_ID_COPY_CD_REFERENCE;
|
||||
}
|
||||
|
||||
Mesh *result = (Mesh *)BKE_id_copy_ex(nullptr, &source->id, nullptr, flags);
|
||||
return result;
|
||||
return reinterpret_cast<Mesh *>(
|
||||
BKE_id_copy_ex(nullptr, &source->id, nullptr, LIB_ID_COPY_LOCALIZE));
|
||||
}
|
||||
|
||||
BMesh *BKE_mesh_to_bmesh_ex(const Mesh *me,
|
||||
@ -1486,7 +1479,7 @@ bool BKE_mesh_material_index_used(Mesh *me, short index)
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
const AttributeAccessor attributes = me->attributes();
|
||||
const VArray<int> material_indices = attributes.lookup_or_default<int>(
|
||||
const VArray<int> material_indices = *attributes.lookup_or_default<int>(
|
||||
"material_index", ATTR_DOMAIN_FACE, 0);
|
||||
if (material_indices.is_single()) {
|
||||
return material_indices.get_internal_single() == index;
|
||||
@ -1718,11 +1711,11 @@ void BKE_mesh_mselect_validate(Mesh *me)
|
||||
(me->totselect), sizeof(MSelect), "Mesh selection history");
|
||||
|
||||
const AttributeAccessor attributes = me->attributes();
|
||||
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
|
||||
".select_vert", ATTR_DOMAIN_POINT, false);
|
||||
const VArray<bool> select_edge = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> select_edge = *attributes.lookup_or_default<bool>(
|
||||
".select_edge", ATTR_DOMAIN_EDGE, false);
|
||||
const VArray<bool> select_poly = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> select_poly = *attributes.lookup_or_default<bool>(
|
||||
".select_poly", ATTR_DOMAIN_FACE, false);
|
||||
|
||||
for (i_src = 0, i_dst = 0; i_src < me->totselect; i_src++) {
|
||||
@ -1830,7 +1823,7 @@ void BKE_mesh_count_selected_items(const Mesh *mesh, int r_count[3])
|
||||
void BKE_mesh_vert_coords_get(const Mesh *mesh, float (*vert_coords)[3])
|
||||
{
|
||||
blender::bke::AttributeAccessor attributes = mesh->attributes();
|
||||
VArray<float3> positions = attributes.lookup_or_default(
|
||||
VArray<float3> positions = *attributes.lookup_or_default(
|
||||
"position", ATTR_DOMAIN_POINT, float3(0));
|
||||
positions.materialize({(float3 *)vert_coords, mesh->totvert});
|
||||
}
|
||||
|
@ -411,7 +411,7 @@ static void copy_poly_attributes(Mesh *dest_mesh,
|
||||
}
|
||||
|
||||
/* Fix material indices after they have been transferred as a generic attribute. */
|
||||
const VArray<int> src_material_indices = orig_me->attributes().lookup_or_default<int>(
|
||||
const VArray<int> src_material_indices = *orig_me->attributes().lookup_or_default<int>(
|
||||
"material_index", ATTR_DOMAIN_FACE, 0);
|
||||
const int src_index = src_material_indices[index_in_orig_me];
|
||||
if (material_remap.index_range().contains(src_index)) {
|
||||
@ -700,7 +700,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
|
||||
}
|
||||
/* Will calculate edges later. */
|
||||
Mesh *result = BKE_mesh_new_nomain_from_template(
|
||||
mim.meshes[0], out_totvert, 0, out_totloop, out_totpoly);
|
||||
mim.meshes[0], out_totvert, 0, out_totpoly, out_totloop);
|
||||
|
||||
merge_vertex_loop_poly_customdata_layers(result, mim);
|
||||
/* Set the vertex coordinate values and other data. */
|
||||
|
@ -151,14 +151,13 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg
|
||||
});
|
||||
}
|
||||
|
||||
static void update_edge_indices_in_poly_loops(Mesh *mesh,
|
||||
Span<EdgeMap> edge_maps,
|
||||
uint32_t parallel_mask)
|
||||
static void update_edge_indices_in_poly_loops(const OffsetIndices<int> polys,
|
||||
const Span<int> corner_verts,
|
||||
const Span<EdgeMap> edge_maps,
|
||||
const uint32_t parallel_mask,
|
||||
MutableSpan<int> corner_edges)
|
||||
{
|
||||
const OffsetIndices polys = mesh->polys();
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
MutableSpan<int> corner_edges = mesh->corner_edges_for_write();
|
||||
threading::parallel_for(IndexRange(mesh->totpoly), 100, [&](IndexRange range) {
|
||||
threading::parallel_for(polys.index_range(), 100, [&](IndexRange range) {
|
||||
for (const int poly_index : range) {
|
||||
const IndexRange poly = polys[poly_index];
|
||||
int prev_corner = poly.last();
|
||||
@ -239,7 +238,11 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select
|
||||
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);
|
||||
calc_edges::update_edge_indices_in_poly_loops(mesh, edge_maps, parallel_mask);
|
||||
calc_edges::update_edge_indices_in_poly_loops(mesh->polys(),
|
||||
mesh->corner_verts(),
|
||||
edge_maps,
|
||||
parallel_mask,
|
||||
mesh->corner_edges_for_write());
|
||||
|
||||
/* Free old CustomData and assign new one. */
|
||||
CustomData_free(&mesh->edata, mesh->totedge);
|
||||
|
@ -62,98 +62,8 @@ using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::StringRefNull;
|
||||
|
||||
/* Define for cases when you want extra validation of mesh
|
||||
* after certain modifications.
|
||||
*/
|
||||
// #undef VALIDATE_MESH
|
||||
|
||||
#ifdef VALIDATE_MESH
|
||||
# define ASSERT_IS_VALID_MESH(mesh) \
|
||||
(BLI_assert((mesh == nullptr) || (BKE_mesh_is_valid(mesh) == true)))
|
||||
#else
|
||||
# define ASSERT_IS_VALID_MESH(mesh)
|
||||
#endif
|
||||
|
||||
static CLG_LogRef LOG = {"bke.mesh_convert"};
|
||||
|
||||
static void poly_edgehash_insert(EdgeHash *ehash, const Span<int> poly_verts)
|
||||
{
|
||||
int i = poly_verts.size();
|
||||
|
||||
int next = 0; /* first loop */
|
||||
int poly_corner = (i - 1); /* last loop */
|
||||
|
||||
while (i-- != 0) {
|
||||
BLI_edgehash_reinsert(ehash, poly_verts[poly_corner], poly_verts[next], nullptr);
|
||||
|
||||
poly_corner = next;
|
||||
next++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized function to use when we _know_ existing edges don't overlap with poly edges.
|
||||
*/
|
||||
static void make_edges_mdata_extend(Mesh &mesh)
|
||||
{
|
||||
int totedge = mesh.totedge;
|
||||
|
||||
const blender::OffsetIndices polys = mesh.polys();
|
||||
const Span<int> corner_verts = mesh.corner_verts();
|
||||
MutableSpan<int> corner_edges = mesh.corner_edges_for_write();
|
||||
|
||||
const int eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(mesh.totpoly));
|
||||
EdgeHash *eh = BLI_edgehash_new_ex(__func__, eh_reserve);
|
||||
|
||||
for (const int i : polys.index_range()) {
|
||||
poly_edgehash_insert(eh, corner_verts.slice(polys[i]));
|
||||
}
|
||||
|
||||
const int totedge_new = BLI_edgehash_len(eh);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* ensure that there's no overlap! */
|
||||
if (totedge_new) {
|
||||
for (const blender::int2 &edge : mesh.edges()) {
|
||||
BLI_assert(BLI_edgehash_haskey(eh, edge[0], edge[1]) == false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (totedge_new) {
|
||||
/* The only layer should be edges, so no other layers need to be initialized. */
|
||||
BLI_assert(mesh.edata.totlayer == 1);
|
||||
CustomData_realloc(&mesh.edata, totedge, totedge + totedge_new);
|
||||
mesh.totedge += totedge_new;
|
||||
MutableSpan<blender::int2> edges = mesh.edges_for_write();
|
||||
blender::int2 *edge = &edges[totedge];
|
||||
|
||||
EdgeHashIterator *ehi;
|
||||
uint e_index = totedge;
|
||||
for (ehi = BLI_edgehashIterator_new(eh); BLI_edgehashIterator_isDone(ehi) == false;
|
||||
BLI_edgehashIterator_step(ehi), ++edge, e_index++) {
|
||||
BLI_edgehashIterator_getKey(ehi, &(*edge)[0], &(*edge)[1]);
|
||||
BLI_edgehashIterator_setValue(ehi, POINTER_FROM_UINT(e_index));
|
||||
}
|
||||
BLI_edgehashIterator_free(ehi);
|
||||
|
||||
for (const int i : polys.index_range()) {
|
||||
const IndexRange poly = polys[i];
|
||||
int corner = poly.start();
|
||||
int corner_prev = poly.start() + (poly.size() - 1);
|
||||
int j;
|
||||
for (j = 0; j < poly.size(); j++, corner++) {
|
||||
/* lookup hashed edge index */
|
||||
corner_edges[corner_prev] = POINTER_AS_UINT(
|
||||
BLI_edgehash_lookup(eh, corner_verts[corner_prev], corner_verts[corner]));
|
||||
corner_prev = corner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLI_edgehash_free(eh, nullptr);
|
||||
}
|
||||
|
||||
static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispbase)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
@ -203,7 +113,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
||||
return BKE_mesh_new_nomain(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
Mesh *mesh = BKE_mesh_new_nomain(totvert, totedge, totloop, totpoly);
|
||||
Mesh *mesh = BKE_mesh_new_nomain(totvert, totedge, totpoly, totloop);
|
||||
MutableSpan<float3> positions = mesh->vert_positions_for_write();
|
||||
MutableSpan<blender::int2> edges = mesh->edges_for_write();
|
||||
MutableSpan<int> poly_offsets = mesh->poly_offsets_for_write();
|
||||
@ -393,7 +303,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
||||
}
|
||||
|
||||
if (totpoly) {
|
||||
make_edges_mdata_extend(*mesh);
|
||||
BKE_mesh_calc_edges(mesh, true, false);
|
||||
}
|
||||
|
||||
material_indices.finish();
|
||||
@ -783,7 +693,7 @@ static const Curves *get_evaluated_curves_from_object(const Object *object)
|
||||
static Mesh *mesh_new_from_evaluated_curve_type_object(const Object *evaluated_object)
|
||||
{
|
||||
if (const Mesh *mesh = BKE_object_get_evaluated_mesh(evaluated_object)) {
|
||||
return BKE_mesh_copy_for_eval(mesh, false);
|
||||
return BKE_mesh_copy_for_eval(mesh);
|
||||
}
|
||||
if (const Curves *curves = get_evaluated_curves_from_object(evaluated_object)) {
|
||||
const blender::bke::AnonymousAttributePropagationInfo propagation_info;
|
||||
@ -842,7 +752,7 @@ static Mesh *mesh_new_from_mball_object(Object *object)
|
||||
return (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
|
||||
}
|
||||
|
||||
return BKE_mesh_copy_for_eval(mesh_eval, false);
|
||||
return BKE_mesh_copy_for_eval(mesh_eval);
|
||||
}
|
||||
|
||||
static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
|
||||
@ -1087,7 +997,7 @@ static void move_shapekey_layers_to_keyblocks(const Mesh &mesh,
|
||||
if (kb->uid == actshape_uid) {
|
||||
kb->data = MEM_malloc_arrayN(kb->totelem, sizeof(float3), __func__);
|
||||
MutableSpan<float3> kb_coords(static_cast<float3 *>(kb->data), kb->totelem);
|
||||
mesh.attributes().lookup<float3>("position").materialize(kb_coords);
|
||||
mesh.attributes().lookup<float3>("position").varray.materialize(kb_coords);
|
||||
}
|
||||
else {
|
||||
kb->data = layer.data;
|
||||
|
@ -623,7 +623,7 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me)
|
||||
using namespace blender::bke;
|
||||
MutableAttributeAccessor attributes = me->attributes_for_write();
|
||||
|
||||
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
|
||||
".hide_vert", ATTR_DOMAIN_POINT, false);
|
||||
if (hide_vert.is_single() && !hide_vert.get_internal_single()) {
|
||||
attributes.remove(".hide_edge");
|
||||
@ -662,7 +662,7 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me)
|
||||
using namespace blender::bke;
|
||||
MutableAttributeAccessor attributes = me->attributes_for_write();
|
||||
|
||||
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
|
||||
".hide_poly", ATTR_DOMAIN_FACE, false);
|
||||
if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
|
||||
attributes.remove(".hide_vert");
|
||||
@ -705,7 +705,7 @@ void BKE_mesh_flush_select_from_polys(Mesh *me)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
MutableAttributeAccessor attributes = me->attributes_for_write();
|
||||
const VArray<bool> select_poly = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> select_poly = *attributes.lookup_or_default<bool>(
|
||||
".select_poly", ATTR_DOMAIN_FACE, false);
|
||||
if (select_poly.is_single() && !select_poly.get_internal_single()) {
|
||||
attributes.remove(".select_vert");
|
||||
@ -720,9 +720,9 @@ void BKE_mesh_flush_select_from_polys(Mesh *me)
|
||||
/* Use generic domain interpolation to read the polygon attribute on the other domains.
|
||||
* Assume selected faces are not hidden and none of their vertices/edges are hidden. */
|
||||
attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_POINT, false)
|
||||
.materialize(select_vert.span);
|
||||
.varray.materialize(select_vert.span);
|
||||
attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_EDGE, false)
|
||||
.materialize(select_edge.span);
|
||||
.varray.materialize(select_edge.span);
|
||||
|
||||
select_vert.finish();
|
||||
select_edge.finish();
|
||||
@ -759,7 +759,7 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
MutableAttributeAccessor attributes = me->attributes_for_write();
|
||||
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
|
||||
".select_vert", ATTR_DOMAIN_POINT, false);
|
||||
if (select_vert.is_single() && !select_vert.get_internal_single()) {
|
||||
attributes.remove(".select_edge");
|
||||
@ -774,8 +774,8 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
|
||||
me->edges(),
|
||||
me->polys(),
|
||||
me->corner_verts(),
|
||||
attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false),
|
||||
attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false),
|
||||
*attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false),
|
||||
*attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false),
|
||||
select_vert,
|
||||
select_edge.span,
|
||||
select_poly.span);
|
||||
|
@ -1552,7 +1552,7 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh,
|
||||
const AttributeAccessor attributes = mesh->attributes();
|
||||
|
||||
MutableSpan<MVert> verts(mesh->mvert, mesh->totvert);
|
||||
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
|
||||
".hide_vert", ATTR_DOMAIN_POINT, false);
|
||||
threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@ -1561,7 +1561,7 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh,
|
||||
});
|
||||
|
||||
MutableSpan<MEdge> edges(mesh->medge, mesh->totedge);
|
||||
const VArray<bool> hide_edge = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> hide_edge = *attributes.lookup_or_default<bool>(
|
||||
".hide_edge", ATTR_DOMAIN_EDGE, false);
|
||||
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@ -1569,7 +1569,7 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh,
|
||||
}
|
||||
});
|
||||
|
||||
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
|
||||
".hide_poly", ATTR_DOMAIN_FACE, false);
|
||||
threading::parallel_for(legacy_polys.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@ -1645,7 +1645,7 @@ void BKE_mesh_legacy_convert_material_indices_to_mpoly(Mesh *mesh,
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
const AttributeAccessor attributes = mesh->attributes();
|
||||
const VArray<int> material_indices = attributes.lookup_or_default<int>(
|
||||
const VArray<int> material_indices = *attributes.lookup_or_default<int>(
|
||||
"material_index", ATTR_DOMAIN_FACE, 0);
|
||||
threading::parallel_for(legacy_polys.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@ -1901,7 +1901,7 @@ void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh,
|
||||
const AttributeAccessor attributes = mesh->attributes();
|
||||
|
||||
MutableSpan<MVert> verts(mesh->mvert, mesh->totvert);
|
||||
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
|
||||
".select_vert", ATTR_DOMAIN_POINT, false);
|
||||
threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@ -1910,7 +1910,7 @@ void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh,
|
||||
});
|
||||
|
||||
MutableSpan<MEdge> edges(mesh->medge, mesh->totedge);
|
||||
const VArray<bool> select_edge = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> select_edge = *attributes.lookup_or_default<bool>(
|
||||
".select_edge", ATTR_DOMAIN_EDGE, false);
|
||||
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@ -1918,7 +1918,7 @@ void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh,
|
||||
}
|
||||
});
|
||||
|
||||
const VArray<bool> select_poly = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> select_poly = *attributes.lookup_or_default<bool>(
|
||||
".select_poly", ATTR_DOMAIN_FACE, false);
|
||||
threading::parallel_for(legacy_polys.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@ -2197,7 +2197,10 @@ void BKE_mesh_legacy_attribute_strings_to_flags(Mesh *mesh)
|
||||
|
||||
CustomData_clear_layer_flag(
|
||||
vdata, CD_PROP_BYTE_COLOR, CD_FLAG_COLOR_ACTIVE | CD_FLAG_COLOR_RENDER);
|
||||
CustomData_clear_layer_flag(
|
||||
ldata, CD_PROP_BYTE_COLOR, CD_FLAG_COLOR_ACTIVE | CD_FLAG_COLOR_RENDER);
|
||||
CustomData_clear_layer_flag(ldata, CD_PROP_COLOR, CD_FLAG_COLOR_ACTIVE | CD_FLAG_COLOR_RENDER);
|
||||
CustomData_clear_layer_flag(vdata, CD_PROP_COLOR, CD_FLAG_COLOR_ACTIVE | CD_FLAG_COLOR_RENDER);
|
||||
|
||||
if (const char *name = mesh->active_color_attribute) {
|
||||
int i;
|
||||
|
@ -191,7 +191,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
const int src_loops_num = mesh->totloop;
|
||||
|
||||
Mesh *result = BKE_mesh_new_nomain_from_template(
|
||||
mesh, src_verts_num * 2, src_edges_num * 2, src_loops_num * 2, src_polys.size() * 2);
|
||||
mesh, src_verts_num * 2, src_edges_num * 2, src_polys.size() * 2, src_loops_num * 2);
|
||||
|
||||
/* Copy custom-data to original geometry. */
|
||||
CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, src_verts_num);
|
||||
|
@ -117,7 +117,7 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
|
||||
}
|
||||
|
||||
/* Construct the new output mesh */
|
||||
Mesh *mesh = BKE_mesh_new_nomain(qrd.out_totverts, 0, qrd.out_totfaces * 4, qrd.out_totfaces);
|
||||
Mesh *mesh = BKE_mesh_new_nomain(qrd.out_totverts, 0, qrd.out_totfaces, qrd.out_totfaces * 4);
|
||||
BKE_mesh_copy_parameters(mesh, input_mesh);
|
||||
MutableSpan<int> poly_offsets = mesh->poly_offsets_for_write();
|
||||
MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
|
||||
@ -222,7 +222,7 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set
|
||||
*level_set_grid, vertices, tris, quads, isovalue, adaptivity, relax_disoriented_triangles);
|
||||
|
||||
Mesh *mesh = BKE_mesh_new_nomain(
|
||||
vertices.size(), 0, quads.size() * 4 + tris.size() * 3, quads.size() + tris.size());
|
||||
vertices.size(), 0, quads.size() + tris.size(), quads.size() * 4 + tris.size() * 3);
|
||||
MutableSpan<float3> vert_positions = mesh->vert_positions_for_write();
|
||||
MutableSpan<int> poly_offsets = mesh->poly_offsets_for_write();
|
||||
MutableSpan<int> mesh_corner_verts = mesh->corner_verts_for_write();
|
||||
@ -317,8 +317,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
|
||||
const OffsetIndices target_polys = target->polys();
|
||||
const Span<int> target_corner_verts = target->corner_verts();
|
||||
|
||||
const VArray<int> src_face_sets = src_attributes.lookup<int>(".sculpt_face_set",
|
||||
ATTR_DOMAIN_FACE);
|
||||
const VArray src_face_sets = *src_attributes.lookup<int>(".sculpt_face_set", ATTR_DOMAIN_FACE);
|
||||
if (!src_face_sets) {
|
||||
return;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
|
||||
}
|
||||
|
||||
const AttributeAccessor attributes = mesh->attributes();
|
||||
const VArraySpan<float2> uv_map = attributes.lookup<float2>(uvmap, ATTR_DOMAIN_CORNER);
|
||||
const VArraySpan uv_map = *attributes.lookup<float2>(uvmap, ATTR_DOMAIN_CORNER);
|
||||
if (uv_map.is_empty()) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
|
@ -241,7 +241,7 @@ Mesh *BKE_multires_create_mesh(struct Depsgraph *depsgraph,
|
||||
Mesh *result = mti->modifyMesh(&mmd->modifier, &modifier_ctx, deformed_mesh);
|
||||
|
||||
if (result == deformed_mesh) {
|
||||
result = BKE_mesh_copy_for_eval(deformed_mesh, true);
|
||||
result = BKE_mesh_copy_for_eval(deformed_mesh);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1833,7 +1833,7 @@ static bool find_geonode_attribute_rgba(const DupliObject *dupli,
|
||||
|
||||
/* Attempt to look up the attribute. */
|
||||
std::optional<bke::AttributeAccessor> attributes = component->attributes();
|
||||
const VArray data = attributes->lookup<ColorGeometry4f>(name);
|
||||
const VArray data = *attributes->lookup<ColorGeometry4f>(name);
|
||||
|
||||
/* If the attribute was found and converted to float RGBA successfully, output it. */
|
||||
if (data) {
|
||||
|
@ -2127,7 +2127,7 @@ void BKE_sculpt_sync_face_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)
|
||||
}
|
||||
|
||||
const AttributeAccessor attributes = mesh->attributes();
|
||||
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
|
||||
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
|
||||
".hide_poly", ATTR_DOMAIN_FACE, false);
|
||||
if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
|
||||
/* Nothing is hidden, so we can just remove all visibility bitmaps. */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user