From a201b99c5aaa7945bd0702c42987a60e3d70ee46 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Mar 2017 14:48:37 +0100 Subject: [PATCH 01/73] Fix T50975: Cycles: Light sampling threshold inadvertently clamps negative lamps --- intern/cycles/kernel/kernel_emission.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index bc2d9604122..cf14a159e47 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -157,7 +157,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, return false; if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) { - float probability = max3(bsdf_eval_sum(eval)) * kernel_data.integrator.light_inv_rr_threshold; + float probability = max3(fabs(bsdf_eval_sum(eval))) * kernel_data.integrator.light_inv_rr_threshold; if(probability < 1.0f) { if(rand_terminate >= probability) { return false; From d544a61e8a366f05a6360d9e5baea84edcaa2ca0 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Thu, 19 Jan 2017 00:41:55 +0100 Subject: [PATCH 02/73] Cycles: Update remaining time once per second without waiting for a tile change Previously, the code would only update the status string if the main status changed. However, the main status did not include the remaining time, and therefore it wasn't updated until the amount of rendered tiles (which is part of the main status) changed. This commit therefore makes the BlenderSession remember the time of the last status update and forces a status update if the last one was more than a second ago. Reviewers: sergey Differential Revision: https://developer.blender.org/D2465 --- intern/cycles/blender/blender_session.cpp | 8 +++++++- intern/cycles/blender/blender_session.h | 1 + intern/cycles/render/session.cpp | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index c5f5ffe9928..d00b4b67a58 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -70,6 +70,7 @@ BlenderSession::BlenderSession(BL::RenderEngine& b_engine, background = true; last_redraw_time = 0.0; start_resize_time = 0.0; + last_status_time = 0.0; } BlenderSession::BlenderSession(BL::RenderEngine& b_engine, @@ -95,6 +96,7 @@ BlenderSession::BlenderSession(BL::RenderEngine& b_engine, background = false; last_redraw_time = 0.0; start_resize_time = 0.0; + last_status_time = 0.0; } BlenderSession::~BlenderSession() @@ -991,10 +993,14 @@ void BlenderSession::update_status_progress() if(substatus.size() > 0) status += " | " + substatus; - if(status != last_status) { + double current_time = time_dt(); + /* When rendering in a window, redraw the status at least once per second to keep the elapsed and remaining time up-to-date. + * For headless rendering, only report when something significant changes to keep the console output readable. */ + if(status != last_status || (!headless && (current_time - last_status_time) > 1.0)) { b_engine.update_stats("", (timestatus + scene + status).c_str()); b_engine.update_memory_stats(mem_used, mem_peak); last_status = status; + last_status_time = current_time; } if(progress != last_progress) { b_engine.update_progress(progress); diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 700b8acec1b..33b88b9ab5e 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -113,6 +113,7 @@ public: string last_status; string last_error; float last_progress; + double last_status_time; int width, height; double start_resize_time; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 0c7bd271371..e7050f9ef37 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -833,7 +833,7 @@ void Session::update_status_time(bool show_pause, bool show_done) int progressive_sample = tile_manager.state.sample; int num_samples = tile_manager.get_num_effective_samples(); - int tile = tile_manager.state.num_rendered_tiles; + int tile = progress.get_finished_tiles(); int num_tiles = tile_manager.state.num_tiles; /* update status */ @@ -841,7 +841,7 @@ void Session::update_status_time(bool show_pause, bool show_done) if(!params.progressive) { const bool is_cpu = params.device.type == DEVICE_CPU; - const bool is_last_tile = (progress.get_finished_tiles() + 1) == num_tiles; + const bool is_last_tile = (tile + 1) == num_tiles; substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles); From 3c4df13924a86355a16774e44b6c5e126001c979 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Mar 2017 15:37:05 +0100 Subject: [PATCH 03/73] Fix T50268: Cycles allows to select un supported GPUs for OpenCL --- intern/cycles/device/opencl/opencl_util.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp index a689c7eae26..52f8a77c09e 100644 --- a/intern/cycles/device/opencl/opencl_util.cpp +++ b/intern/cycles/device/opencl/opencl_util.cpp @@ -605,6 +605,19 @@ bool OpenCLInfo::device_supported(const string& platform_name, sizeof(cl_device_type), &device_type, NULL); + char device_name[1024] = "\0"; + clGetDeviceInfo(device_id, + CL_DEVICE_NAME, + sizeof(device_name), + &device_name, + NULL); + /* It is possible tyo have Iris GPU on AMD/Apple OpenCL framework + * (aka, it will not be on Intel framework). This isn't supported + * and needs an explicit blacklist. + */ + if(strstr(device_name, "Iris")) { + return false; + } if(platform_name == "AMD Accelerated Parallel Processing" && device_type == CL_DEVICE_TYPE_GPU) { From 13d8661503f07a16da15f75d9fc9597e43d78283 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Mon, 20 Mar 2017 18:51:32 -0300 Subject: [PATCH 04/73] Fix T51012: Surface modifier was not working with curves This prevented the Force Field Curve Shape of working --- source/blender/modifiers/intern/MOD_surface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index 68987a1d28e..e5b0f9c0001 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -172,6 +172,7 @@ ModifierTypeInfo modifierType_Surface = { /* structSize */ sizeof(SurfaceModifierData), /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_NoUserAdd, /* copyData */ NULL, From 8fff6cc2f56a088c4c9d3112bdb94b85bc9cb498 Mon Sep 17 00:00:00 2001 From: Mai Lavelle Date: Mon, 20 Mar 2017 22:51:36 -0400 Subject: [PATCH 05/73] Cycles: Fix building of OpenCL kernels Theres no overloading of functions in OpenCL so we can't make use of `safe_normalize` with `float2`. --- intern/cycles/kernel/closure/bsdf_microfacet_multi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index aa4b91eac40..1dd24078037 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -83,7 +83,7 @@ ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha const float3 wi_11 = normalize(make_float3(alpha.x*wi.x, alpha.y*wi.y, wi.z)); const float2 slope_11 = mf_sampleP22_11(wi_11.z, randU); - const float2 cossin_phi = safe_normalize(make_float2(wi_11.x, wi_11.y)); + const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f)); const float slope_x = alpha.x*(cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y); const float slope_y = alpha.y*(cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y); From eb1a57b12c6506cff2c4fb2e8078cc2834c8d6af Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Tue, 21 Mar 2017 04:30:08 +0100 Subject: [PATCH 06/73] Cycles: Fix wrong vector allocation in the mesh sync code --- intern/cycles/blender/blender_mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 78f73d8e062..f949b530f90 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -819,7 +819,7 @@ static void create_mesh(Scene *scene, int shader = clamp(p->material_index(), 0, used_shaders.size()-1); bool smooth = p->use_smooth() || use_loop_normals; - vi.reserve(n); + vi.resize(n); for(int i = 0; i < n; i++) { /* NOTE: Autosmooth is already taken care about. */ vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index(); From fceb1d07813885825f8e73fa41323d3a458a44da Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Mar 2017 17:57:37 +0100 Subject: [PATCH 07/73] Cycles: Cleanup, add some utility functions to shorten access to low level API Should be no functional changes. --- intern/cycles/device/opencl/opencl.h | 40 +++ intern/cycles/device/opencl/opencl_util.cpp | 335 ++++++++++++++++---- 2 files changed, 309 insertions(+), 66 deletions(-) diff --git a/intern/cycles/device/opencl/opencl.h b/intern/cycles/device/opencl/opencl.h index be7e9fa5e30..6b3bbf91f22 100644 --- a/intern/cycles/device/opencl/opencl.h +++ b/intern/cycles/device/opencl/opencl.h @@ -91,6 +91,46 @@ public: static void get_usable_devices(vector *usable_devices, bool force_all = false); static bool use_single_program(); + + /* ** Some handy shortcuts to low level cl*GetInfo() functions. ** */ + + /* Platform information. */ + static bool get_num_platforms(cl_uint *num_platforms, cl_int *error = NULL); + static cl_uint get_num_platforms(); + + static bool get_platforms(vector *platform_ids, + cl_int *error = NULL); + static vector get_platforms(); + + static bool get_platform_name(cl_platform_id platform_id, + string *platform_name); + static string get_platform_name(cl_platform_id platform_id); + + static bool get_num_platform_devices(cl_platform_id platform_id, + cl_device_type device_type, + cl_uint *num_devices, + cl_int *error = NULL); + static cl_uint get_num_platform_devices(cl_platform_id platform_id, + cl_device_type device_type); + + static bool get_platform_devices(cl_platform_id platform_id, + cl_device_type device_type, + vector *device_ids, + cl_int* error = NULL); + static vector get_platform_devices(cl_platform_id platform_id, + cl_device_type device_type); + + /* Device information. */ + static bool get_device_name(cl_device_id device_id, + string *device_name, + cl_int* error = NULL); + + static string get_device_name(cl_device_id device_id); + + static bool get_device_type(cl_device_id device_id, + cl_device_type *device_type, + cl_int* error = NULL); + static cl_device_type get_device_type(cl_device_id device_id); }; /* Thread safe cache for contexts and programs. diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp index 52f8a77c09e..6b0d4e14f27 100644 --- a/intern/cycles/device/opencl/opencl_util.cpp +++ b/intern/cycles/device/opencl/opencl_util.cpp @@ -600,22 +600,18 @@ bool OpenCLInfo::device_supported(const string& platform_name, const cl_device_id device_id) { cl_device_type device_type; - clGetDeviceInfo(device_id, - CL_DEVICE_TYPE, - sizeof(cl_device_type), - &device_type, - NULL); - char device_name[1024] = "\0"; - clGetDeviceInfo(device_id, - CL_DEVICE_NAME, - sizeof(device_name), - &device_name, - NULL); + if(!get_device_type(device_id, &device_type)) { + return false; + } + string device_name; + if(!get_device_name(device_id, &device_name)) { + return false; + } /* It is possible tyo have Iris GPU on AMD/Apple OpenCL framework * (aka, it will not be on Intel framework). This isn't supported * and needs an explicit blacklist. */ - if(strstr(device_name, "Iris")) { + if(strstr(device_name.c_str(), "Iris")) { return false; } if(platform_name == "AMD Accelerated Parallel Processing" && @@ -731,39 +727,30 @@ void OpenCLInfo::get_usable_devices(vector *usable_devices return; } + cl_int error; vector device_ids; - cl_uint num_devices = 0; vector platform_ids; - cl_uint num_platforms = 0; - /* Get devices. */ - if(clGetPlatformIDs(0, NULL, &num_platforms) != CL_SUCCESS || - num_platforms == 0) - { + /* Get platforms. */ + if(!get_platforms(&platform_ids, &error)) { + FIRST_VLOG(2) << "Error fetching platforms:" + << string(clewErrorString(error)); + first_time = false; + return; + } + if(platform_ids.size() == 0) { FIRST_VLOG(2) << "No OpenCL platforms were found."; first_time = false; return; } - platform_ids.resize(num_platforms); - if(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL) != CL_SUCCESS) { - FIRST_VLOG(2) << "Failed to fetch platform IDs from the driver.."; - first_time = false; - return; - } /* Devices are numbered consecutively across platforms. */ - for(int platform = 0; platform < num_platforms; platform++) { + for(int platform = 0; platform < platform_ids.size(); platform++) { cl_platform_id platform_id = platform_ids[platform]; - char pname[256]; - if(clGetPlatformInfo(platform_id, - CL_PLATFORM_NAME, - sizeof(pname), - &pname, - NULL) != CL_SUCCESS) - { + string platform_name; + if(!get_platform_name(platform_id, &platform_name)) { FIRST_VLOG(2) << "Failed to get platform name, ignoring."; continue; } - string platform_name = pname; FIRST_VLOG(2) << "Enumerating devices for platform " << platform_name << "."; if(!platform_version_check(platform_id)) { @@ -771,39 +758,28 @@ void OpenCLInfo::get_usable_devices(vector *usable_devices << " due to too old compiler version."; continue; } - num_devices = 0; - cl_int ciErr; - if((ciErr = clGetDeviceIDs(platform_id, - device_type, - 0, - NULL, - &num_devices)) != CL_SUCCESS || num_devices == 0) + if(!get_platform_devices(platform_id, + device_type, + &device_ids, + &error)) { FIRST_VLOG(2) << "Ignoring platform " << platform_name - << ", failed to fetch number of devices: " << string(clewErrorString(ciErr)); + << ", failed to fetch of devices: " + << string(clewErrorString(error)); continue; } - device_ids.resize(num_devices); - if(clGetDeviceIDs(platform_id, - device_type, - num_devices, - &device_ids[0], - NULL) != CL_SUCCESS) - { + if(device_ids.size() == 0) { FIRST_VLOG(2) << "Ignoring platform " << platform_name - << ", failed to fetch devices list."; + << ", it has no devices."; continue; } - for(int num = 0; num < num_devices; num++) { - cl_device_id device_id = device_ids[num]; - char device_name[1024] = "\0"; - if(clGetDeviceInfo(device_id, - CL_DEVICE_NAME, - sizeof(device_name), - &device_name, - NULL) != CL_SUCCESS) - { - FIRST_VLOG(2) << "Failed to fetch device name, ignoring."; + for(int num = 0; num < device_ids.size(); num++) { + const cl_device_id device_id = device_ids[num]; + string device_name; + if(!get_device_name(device_id, &device_name, &error)) { + FIRST_VLOG(2) << "Failed to fetch device name: " + << string(clewErrorString(error)) + << ", ignoring."; continue; } if(!device_version_check(device_id)) { @@ -815,14 +791,10 @@ void OpenCLInfo::get_usable_devices(vector *usable_devices device_supported(platform_name, device_id)) { cl_device_type device_type; - if(clGetDeviceInfo(device_id, - CL_DEVICE_TYPE, - sizeof(cl_device_type), - &device_type, - NULL) != CL_SUCCESS) - { + if(!get_device_type(device_id, &device_type, &error)) { FIRST_VLOG(2) << "Ignoring device " << device_name - << ", failed to fetch device type."; + << ", failed to fetch device type:" + << string(clewErrorString(error)); continue; } FIRST_VLOG(2) << "Adding new device " << device_name << "."; @@ -843,6 +815,237 @@ void OpenCLInfo::get_usable_devices(vector *usable_devices first_time = false; } +bool OpenCLInfo::get_platforms(vector *platform_ids, + cl_int *error) +{ + /* Reset from possible previous state. */ + platform_ids->resize(0); + cl_uint num_platforms; + if(!get_num_platforms(&num_platforms, error)) { + return false; + } + /* Get actual platforms. */ + cl_int err; + platform_ids->resize(num_platforms); + if((err = clGetPlatformIDs(num_platforms, + &platform_ids->at(0), + NULL)) != CL_SUCCESS) { + if(error != NULL) { + *error = err; + } + return false; + } + if(error != NULL) { + *error = CL_SUCCESS; + } + return true; +} + +vector OpenCLInfo::get_platforms() +{ + vector platform_ids; + get_platforms(&platform_ids); + return platform_ids; +} + +bool OpenCLInfo::get_num_platforms(cl_uint *num_platforms, cl_int *error) +{ + cl_int err; + if((err = clGetPlatformIDs(0, NULL, num_platforms)) != CL_SUCCESS) { + if(error != NULL) { + *error = err; + } + *num_platforms = 0; + return false; + } + if(error != NULL) { + *error = CL_SUCCESS; + } + return true; +} + +cl_uint OpenCLInfo::get_num_platforms() +{ + cl_uint num_platforms; + if(!get_num_platforms(&num_platforms)) { + return 0; + } + return num_platforms; +} + +bool OpenCLInfo::get_platform_name(cl_platform_id platform_id, + string *platform_name) +{ + char buffer[256]; + if(clGetPlatformInfo(platform_id, + CL_PLATFORM_NAME, + sizeof(buffer), + &buffer, + NULL) != CL_SUCCESS) + { + *platform_name = ""; + return false; + } + *platform_name = buffer; + return true; +} + +string OpenCLInfo::get_platform_name(cl_platform_id platform_id) +{ + string platform_name; + if (!get_platform_name(platform_id, &platform_name)) { + return ""; + } + return platform_name; +} + +bool OpenCLInfo::get_num_platform_devices(cl_platform_id platform_id, + cl_device_type device_type, + cl_uint *num_devices, + cl_int *error) +{ + cl_int err; + if((err = clGetDeviceIDs(platform_id, + device_type, + 0, + NULL, + num_devices)) != CL_SUCCESS) + { + if(error != NULL) { + *error = err; + } + *num_devices = 0; + return false; + } + if(error != NULL) { + *error = CL_SUCCESS; + } + return true; +} + +cl_uint OpenCLInfo::get_num_platform_devices(cl_platform_id platform_id, + cl_device_type device_type) +{ + cl_uint num_devices; + if(!get_num_platform_devices(platform_id, + device_type, + &num_devices)) + { + return 0; + } + return num_devices; +} + +bool OpenCLInfo::get_platform_devices(cl_platform_id platform_id, + cl_device_type device_type, + vector *device_ids, + cl_int* error) +{ + /* Reset from possible previous state. */ + device_ids->resize(0); + /* Get number of devices to pre-allocate memory. */ + cl_uint num_devices; + if(!get_num_platform_devices(platform_id, + device_type, + &num_devices, + error)) + { + return false; + } + /* Get actual device list. */ + device_ids->resize(num_devices); + cl_int err; + if((err = clGetDeviceIDs(platform_id, + device_type, + num_devices, + &device_ids->at(0), + NULL)) != CL_SUCCESS) + { + if(error != NULL) { + *error = err; + } + return false; + } + if(error != NULL) { + *error = CL_SUCCESS; + } + return true; +} + +vector OpenCLInfo::get_platform_devices(cl_platform_id platform_id, + cl_device_type device_type) +{ + vector devices; + get_platform_devices(platform_id, device_type, &devices); + return devices; +} + +bool OpenCLInfo::get_device_name(cl_device_id device_id, + string *device_name, + cl_int* error) +{ + char buffer[1024]; + cl_int err; + if((err = clGetDeviceInfo(device_id, + CL_DEVICE_NAME, + sizeof(buffer), + &buffer, + NULL)) != CL_SUCCESS) + { + if(error != NULL) { + *error = err; + } + *device_name = ""; + return false; + } + if(error != NULL) { + *error = CL_SUCCESS; + } + *device_name = buffer; + return true; +} + +string OpenCLInfo::get_device_name(cl_device_id device_id) +{ + string device_name; + if(!get_device_name(device_id, &device_name)) { + return ""; + } + return device_name; +} + +bool OpenCLInfo::get_device_type(cl_device_id device_id, + cl_device_type *device_type, + cl_int* error) +{ + cl_int err; + if((err = clGetDeviceInfo(device_id, + CL_DEVICE_TYPE, + sizeof(cl_device_type), + device_type, + NULL)) != CL_SUCCESS) + { + if(error != NULL) { + *error = err; + } + *device_type = 0; + return false; + } + if(error != NULL) { + *error = CL_SUCCESS; + } + return true; +} + +cl_device_type OpenCLInfo::get_device_type(cl_device_id device_id) +{ + cl_device_type device_type; + if(!get_device_type(device_id, &device_type)) { + return 0; + } + return device_type; +} + CCL_NAMESPACE_END #endif From a41240439b002fc26d2fa5dff51134cb960607f8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Mar 2017 17:59:25 +0100 Subject: [PATCH 08/73] Update CLEW to latest version Needed to get access to some AMD extensions. --- extern/clew/README.blender | 2 +- extern/clew/include/clew.h | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/extern/clew/README.blender b/extern/clew/README.blender index 8355a96db8e..972b46b754b 100644 --- a/extern/clew/README.blender +++ b/extern/clew/README.blender @@ -1,5 +1,5 @@ Project: OpenCL Wrangler URL: https://github.com/OpenCLWrangler/clew License: Apache 2.0 -Upstream version: 309a653 +Upstream version: 79a289e Local modifications: None diff --git a/extern/clew/include/clew.h b/extern/clew/include/clew.h index 2a583c81599..0bbb95b9839 100644 --- a/extern/clew/include/clew.h +++ b/extern/clew/include/clew.h @@ -369,7 +369,7 @@ typedef unsigned int cl_GLenum; #endif /* Define basic vector types */ -/* WOrkaround for ppc64el platform: conflicts with bool from C++. */ +/* Workaround for ppc64el platform: conflicts with bool from C++. */ #if defined( __VEC__ ) && !(defined(__PPC64__) && defined(__LITTLE_ENDIAN__)) #include /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */ typedef vector unsigned char __cl_uchar16; @@ -2765,11 +2765,40 @@ CLEW_FUN_EXPORT PFNCLGETGLCONTEXTINFOKHR __clewGetGLContextInfoKH #define CL_DEVICE_GPU_OVERLAP_NV 0x4004 #define CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 0x4005 #define CL_DEVICE_INTEGRATED_MEMORY_NV 0x4006 +#define CL_DEVICE_ATTRIBUTE_ASYNC_ENGINE_COUNT_NV 0x4007 +#define CL_DEVICE_PCI_BUS_ID_NV 0x4008 +#define CL_DEVICE_PCI_SLOT_ID_NV 0x4009 /********************************* * cl_amd_device_attribute_query * *********************************/ #define CL_DEVICE_PROFILING_TIMER_OFFSET_AMD 0x4036 +#define CL_DEVICE_TOPOLOGY_AMD 0x4037 +#define CL_DEVICE_BOARD_NAME_AMD 0x4038 +#define CL_DEVICE_GLOBAL_FREE_MEMORY_AMD 0x4039 +#define CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD 0x4040 +#define CL_DEVICE_SIMD_WIDTH_AMD 0x4041 +#define CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD 0x4042 +#define CL_DEVICE_WAVEFRONT_WIDTH_AMD 0x4043 +#define CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD 0x4044 +#define CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD 0x4045 +#define CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD 0x4046 +#define CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD 0x4047 +#define CL_DEVICE_LOCAL_MEM_BANKS_AMD 0x4048 +#define CL_DEVICE_THREAD_TRACE_SUPPORTED_AMD 0x4049 +#define CL_DEVICE_GFXIP_MAJOR_AMD 0x404A +#define CL_DEVICE_GFXIP_MINOR_AMD 0x404B +#define CL_DEVICE_AVAILABLE_ASYNC_QUEUES_AMD 0x404C + +#ifndef CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD +#define CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD 1 + +typedef union +{ + struct { cl_uint type; cl_uint data[5]; } raw; + struct { cl_uint type; cl_char unused[17]; cl_char bus; cl_char device; cl_char function; } pcie; +} cl_device_topology_amd; +#endif /********************************* * cl_arm_printf extension From 7780a108b3d561989b52c7a553969c31509a95ed Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Mar 2017 18:59:46 +0100 Subject: [PATCH 09/73] Cycles: Simplify some extra OpenCL query code --- intern/cycles/device/opencl/opencl_base.cpp | 6 ++---- intern/cycles/device/opencl/opencl_split.cpp | 10 ++-------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/intern/cycles/device/opencl/opencl_base.cpp b/intern/cycles/device/opencl/opencl_base.cpp index 51ff39f0ad3..0328dfed689 100644 --- a/intern/cycles/device/opencl/opencl_base.cpp +++ b/intern/cycles/device/opencl/opencl_base.cpp @@ -152,10 +152,8 @@ OpenCLDeviceBase::~OpenCLDeviceBase() void CL_CALLBACK OpenCLDeviceBase::context_notify_callback(const char *err_info, const void * /*private_info*/, size_t /*cb*/, void *user_data) { - char name[256]; - clGetDeviceInfo((cl_device_id)user_data, CL_DEVICE_NAME, sizeof(name), &name, NULL); - - fprintf(stderr, "OpenCL error (%s): %s\n", name, err_info); + string device_name = OpenCLInfo::get_device_name((cl_device_id)user_data); + fprintf(stderr, "OpenCL error (%s): %s\n", device_name.c_str(), err_info); } bool OpenCLDeviceBase::opencl_version_check() diff --git a/intern/cycles/device/opencl/opencl_split.cpp b/intern/cycles/device/opencl/opencl_split.cpp index 3faae4039e3..d50ae585062 100644 --- a/intern/cycles/device/opencl/opencl_split.cpp +++ b/intern/cycles/device/opencl/opencl_split.cpp @@ -41,11 +41,7 @@ static string get_build_options(OpenCLDeviceBase *device, const DeviceRequestedF /* Set compute device build option. */ cl_device_type device_type; - device->ciErr = clGetDeviceInfo(device->cdDevice, - CL_DEVICE_TYPE, - sizeof(cl_device_type), - &device_type, - NULL); + OpenCLInfo::get_device_type(device->cdDevice, &device_type, &device->ciErr); assert(device->ciErr == CL_SUCCESS); if(device_type == CL_DEVICE_TYPE_GPU) { build_options += " -D__COMPUTE_DEVICE_GPU__"; @@ -346,9 +342,7 @@ public: virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask */*task*/) { - cl_device_type type; - clGetDeviceInfo(device->cdDevice, CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL); - + cl_device_type type = OpenCLInfo::get_device_type(device->cdDevice); /* Use small global size on CPU devices as it seems to be much faster. */ if(type == CL_DEVICE_TYPE_CPU) { VLOG(1) << "Global size: (64, 64)."; From a0f16e12a03c686e05f9315634e4d081a0aa6a80 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Mar 2017 19:05:04 +0100 Subject: [PATCH 10/73] Cycles: Use more friendly GPU device name for AMD cards For example, for RX480 you'll no longer see "Ellesmere" but will see "AMD Radeon RX 480 Graphics" which makes more sense and allows to easily distinguish which exact card it is when having multiple different cards of Ellesmere codenames (i.e. RX480 and WX7100) in the same machine. --- intern/cycles/device/opencl/opencl.h | 7 ++++ intern/cycles/device/opencl/opencl_util.cpp | 37 +++++++++++++++++---- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/intern/cycles/device/opencl/opencl.h b/intern/cycles/device/opencl/opencl.h index 6b3bbf91f22..59e61aad25c 100644 --- a/intern/cycles/device/opencl/opencl.h +++ b/intern/cycles/device/opencl/opencl.h @@ -131,6 +131,13 @@ public: cl_device_type *device_type, cl_int* error = NULL); static cl_device_type get_device_type(cl_device_id device_id); + + /* Get somewhat more readable device name. + * Main difference is AMD OpenCL here which only gives code name + * for the regular device name. This will give more sane device + * name using some extensions. + */ + static string get_readable_device_name(cl_device_id device_id); }; /* Thread safe cache for contexts and programs. diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp index 6b0d4e14f27..1f5b9ee0896 100644 --- a/intern/cycles/device/opencl/opencl_util.cpp +++ b/intern/cycles/device/opencl/opencl_util.cpp @@ -797,14 +797,22 @@ void OpenCLInfo::get_usable_devices(vector *usable_devices << string(clewErrorString(error)); continue; } - FIRST_VLOG(2) << "Adding new device " << device_name << "."; + string readable_device_name = + get_readable_device_name(device_id); + if(readable_device_name != device_name) { + FIRST_VLOG(2) << "Using more readable device name: " + << readable_device_name; + } + FIRST_VLOG(2) << "Adding new device " + << readable_device_name << "."; string hardware_id = get_hardware_id(platform_name, device_id); - usable_devices->push_back(OpenCLPlatformDevice(platform_id, - platform_name, - device_id, - device_type, - device_name, - hardware_id)); + usable_devices->push_back(OpenCLPlatformDevice( + platform_id, + platform_name, + device_id, + device_type, + readable_device_name, + hardware_id)); } else { FIRST_VLOG(2) << "Ignoring device " << device_name @@ -1046,6 +1054,21 @@ cl_device_type OpenCLInfo::get_device_type(cl_device_id device_id) return device_type; } +string OpenCLInfo::get_readable_device_name(cl_device_id device_id) +{ + char board_name[1024]; + if(clGetDeviceInfo(device_id, + CL_DEVICE_BOARD_NAME_AMD, + sizeof(board_name), + &board_name, + NULL) == CL_SUCCESS) + { + return board_name; + } + /* Fallback to standard device name API. */ + return get_device_name(device_id); +} + CCL_NAMESPACE_END #endif From 253281f9d6cbfc6bc59238150c3928bffdf887eb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Mar 2017 13:47:27 +1100 Subject: [PATCH 11/73] Fix for splash not opening centered When the new window didn't end up using the size stored in the preferences the splash would not be centered (even outside the screen in some cases). Now centered popups listen for window resizing. --- .../editors/interface/interface_regions.c | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 466978272bc..7b6b41eeef3 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1692,6 +1692,28 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar) UI_block_draw(C, block); } +/** + * Use to refresh centered popups on screen resizing (for splash). + */ +static void ui_block_region_popup_window_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +{ + switch (wmn->category) { + case NC_WINDOW: + { + switch (wmn->action) { + case NA_EDITED: + { + /* window resize */ + ED_region_tag_refresh_ui(ar); + break; + } + } + break; + } + } +} + static void ui_popup_block_clip(wmWindow *window, uiBlock *block) { uiBut *bt; @@ -2003,6 +2025,11 @@ uiPopupBlockHandle *ui_popup_block_create( block = ui_popup_block_refresh(C, handle, butregion, but); handle = block->handle; + /* keep centered on window resizing */ + if ((block->bounds_type == UI_BLOCK_BOUNDS_POPUP_CENTER) && handle->can_refresh) { + type.listener = ui_block_region_popup_window_listener; + } + return handle; } From d0253b2ea4f3d196d76d3dd7ce6725abd2edc26b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Mar 2017 19:31:34 +1100 Subject: [PATCH 12/73] BLI_path_util: add BLI_path_name_at_index Utility to get a file/dir in the path by index, supporting negative indices to start from the end of the path. Without this it wasn't straightforward to get the a files parent directory name from a filepath. --- source/blender/blenlib/BLI_path_util.h | 3 + source/blender/blenlib/intern/path_util.c | 65 ++++++++++ tests/gtests/blenlib/BLI_path_util_test.cc | 133 +++++++++++++++++++++ 3 files changed, 201 insertions(+) diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index baa1f792018..7d971fbfc3d 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -61,6 +61,9 @@ void BLI_path_append(char *__restrict dst, const size_t maxlen, void BLI_join_dirfile(char *__restrict string, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL(); const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +bool BLI_path_name_at_index( + const char *__restrict path, const int index, + int *__restrict r_offset, int *__restrict r_len) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; #if 0 typedef enum bli_rebase_state { diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 6644e6605a1..83aa01d3d15 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1626,6 +1626,71 @@ const char *BLI_path_basename(const char *path) return filename ? filename + 1 : path; } +/** + * Get an element of the path at an index, eg: + * "/some/path/file.txt" where an index of... + * - 0 or -3: "some" + * - 1 or -2: "path" + * - 2 or -1: "file.txt" + * + * Ignores multiple slashes at any point in the path (including start/end). + */ +bool BLI_path_name_at_index(const char *path, const int index, int *r_offset, int *r_len) +{ + if (index >= 0) { + int index_step = 0; + int prev = -1; + int i = 0; + while (true) { + const char c = path[i]; + if (ELEM(c, SEP, ALTSEP, '\0')) { + if (prev + 1 != i) { + prev += 1; + if (index_step == index) { + *r_offset = prev; + *r_len = i - prev; + /* printf("!!! %d %d\n", start, end); */ + return true; + } + index_step += 1; + } + if (c == '\0') { + break; + } + prev = i; + } + i += 1; + } + return false; + } + else { + /* negative number, reverse where -1 is the last element */ + int index_step = -1; + int prev = strlen(path); + int i = prev - 1; + while (true) { + const char c = i >= 0 ? path[i] : '\0'; + if (ELEM(c, SEP, ALTSEP, '\0')) { + if (prev - 1 != i) { + i += 1; + if (index_step == index) { + *r_offset = i; + *r_len = prev - i; + return true; + } + index_step -= 1; + } + if (c == '\0') { + break; + } + prev = i; + } + i -= 1; + } + return false; + } +} + /* UNUSED */ #if 0 /** diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc index d017ab18b4d..ccfa59503c2 100644 --- a/tests/gtests/blenlib/BLI_path_util_test.cc +++ b/tests/gtests/blenlib/BLI_path_util_test.cc @@ -113,6 +113,139 @@ TEST(path_util, PathUtilClean) } #endif + +#define AT_INDEX(str_input, index_input, str_expect) \ + { \ + char path[] = str_input; \ + const char *expect = str_expect; \ + int index_output, len_output; \ + const bool ret = BLI_path_name_at_index(path, index_input, &index_output, &len_output); \ + if (expect == NULL) { \ + EXPECT_EQ(ret, false); \ + } \ + else { \ + EXPECT_EQ(ret, true); \ + EXPECT_EQ(strlen(expect), len_output); \ + path[index_output + len_output] = '\0'; \ + EXPECT_STREQ(expect, &path[index_output]); \ + } \ + }((void)0) + +/* BLI_path_name_at_index */ +TEST(path_util, NameAtIndex_Single) +{ + AT_INDEX("/a", 0, "a"); + AT_INDEX("/a/", 0, "a"); + AT_INDEX("a/", 0, "a"); + AT_INDEX("//a//", 0, "a"); + AT_INDEX("a/b", 0, "a"); + + AT_INDEX("/a", 1, NULL); + AT_INDEX("/a/", 1, NULL); + AT_INDEX("a/", 1, NULL); + AT_INDEX("//a//", 1, NULL); +} +TEST(path_util, NameAtIndex_SingleNeg) +{ + AT_INDEX("/a", -1, "a"); + AT_INDEX("/a/", -1, "a"); + AT_INDEX("a/", -1, "a"); + AT_INDEX("//a//", -1, "a"); + AT_INDEX("a/b", -1, "b"); + + AT_INDEX("/a", -2, NULL); + AT_INDEX("/a/", -2, NULL); + AT_INDEX("a/", -2, NULL); + AT_INDEX("//a//", -2, NULL); +} + +TEST(path_util, NameAtIndex_Double) +{ + AT_INDEX("/ab", 0, "ab"); + AT_INDEX("/ab/", 0, "ab"); + AT_INDEX("ab/", 0, "ab"); + AT_INDEX("//ab//", 0, "ab"); + AT_INDEX("ab/c", 0, "ab"); + + AT_INDEX("/ab", 1, NULL); + AT_INDEX("/ab/", 1, NULL); + AT_INDEX("ab/", 1, NULL); + AT_INDEX("//ab//", 1, NULL); +} + +TEST(path_util, NameAtIndex_DoublNeg) +{ + AT_INDEX("/ab", -1, "ab"); + AT_INDEX("/ab/", -1, "ab"); + AT_INDEX("ab/", -1, "ab"); + AT_INDEX("//ab//", -1, "ab"); + AT_INDEX("ab/c", -1, "c"); + + AT_INDEX("/ab", -2, NULL); + AT_INDEX("/ab/", -2, NULL); + AT_INDEX("ab/", -2, NULL); + AT_INDEX("//ab//", -2, NULL); +} + +TEST(path_util, NameAtIndex_Misc) +{ + AT_INDEX("/how/now/brown/cow", 0, "how"); + AT_INDEX("/how/now/brown/cow", 1, "now"); + AT_INDEX("/how/now/brown/cow", 2, "brown"); + AT_INDEX("/how/now/brown/cow", 3, "cow"); + AT_INDEX("/how/now/brown/cow", 4, NULL); + AT_INDEX("/how/now/brown/cow/", 4, NULL); +} + +TEST(path_util, NameAtIndex_MiscNeg) +{ + AT_INDEX("/how/now/brown/cow", 0, "how"); + AT_INDEX("/how/now/brown/cow", 1, "now"); + AT_INDEX("/how/now/brown/cow", 2, "brown"); + AT_INDEX("/how/now/brown/cow", 3, "cow"); + AT_INDEX("/how/now/brown/cow", 4, NULL); + AT_INDEX("/how/now/brown/cow/", 4, NULL); +} + +TEST(path_util, NameAtIndex_MiscComplex) +{ + AT_INDEX("how//now/brown/cow", 0, "how"); + AT_INDEX("//how///now\\/brown/cow", 1, "now"); + AT_INDEX("/how/now\\//brown\\/cow", 2, "brown"); + AT_INDEX("/how/now/brown/cow//\\", 3, "cow"); + AT_INDEX("/how/now/brown/\\cow", 4, NULL); + AT_INDEX("how/now/brown/\\cow\\", 4, NULL); +} + +TEST(path_util, NameAtIndex_MiscComplexNeg) +{ + AT_INDEX("how//now/brown/cow", -4, "how"); + AT_INDEX("//how///now\\/brown/cow", -3, "now"); + AT_INDEX("/how/now\\//brown\\/cow", -2, "brown"); + AT_INDEX("/how/now/brown/cow//\\", -1, "cow"); + AT_INDEX("/how/now/brown/\\cow", -5, NULL); + AT_INDEX("how/now/brown/\\cow\\", -5, NULL); +} + +TEST(path_util, NameAtIndex_NoneComplex) +{ + AT_INDEX("", 0, NULL); + AT_INDEX("/", 0, NULL); + AT_INDEX("//", 0, NULL); + AT_INDEX("///", 0, NULL); +} + +TEST(path_util, NameAtIndex_NoneComplexNeg) +{ + AT_INDEX("", -1, NULL); + AT_INDEX("/", -1, NULL); + AT_INDEX("//", -1, NULL); + AT_INDEX("///", -1, NULL); +} + +#undef AT_INDEX + + /* BLI_path_frame */ TEST(path_util, PathUtilFrame) { From 8563d3b254cdf647316167fcb9702f3a5093b698 Mon Sep 17 00:00:00 2001 From: Alexander Romanov Date: Wed, 22 Mar 2017 12:00:33 +0300 Subject: [PATCH 13/73] Create correct node after image file drag&drop for Blender Render --- source/blender/editors/space_node/node_add.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index d49df2afbd4..bcd0f6623e1 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -44,6 +44,8 @@ #include "BKE_main.h" #include "BKE_node.h" #include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_texture.h" #include "ED_node.h" /* own include */ #include "ED_screen.h" @@ -312,7 +314,10 @@ static int node_add_file_exec(bContext *C, wmOperator *op) switch (snode->nodetree->type) { case NTREE_SHADER: - type = SH_NODE_TEX_IMAGE; + if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C))) + type = SH_NODE_TEX_IMAGE; + else + type = SH_NODE_TEXTURE; break; case NTREE_TEXTURE: type = TEX_NODE_IMAGE; @@ -333,7 +338,14 @@ static int node_add_file_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - node->id = (ID *)ima; + if (type == SH_NODE_TEXTURE) { + Tex *tex = BKE_texture_add(CTX_data_main(C), DATA_(ima->id.name)); + tex->ima = ima; + node->id = (ID *)tex; + WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, node->id); + } + else + node->id = (ID *)ima; /* When adding new image file via drag-drop we need to load imbuf in order * to get proper image source. From 2b44db4cfca18d451298416c33544e8dd7615e1c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Mar 2017 11:37:23 +0100 Subject: [PATCH 14/73] Fix/workaround T50533: Transparency shader doesn't cast shadows with curve segments There seems to be a compiler bug of MSVC2013. The issue does not happen on Linux and does not happen on Windows when building with MSVC2015. Since it's reallly a pain to debug release builds with MSVC2013 the AVX2 optimization is disabled for curve sergemnts for this compiler. --- intern/cycles/kernel/geom/geom_curve.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h index 7cc840ce78d..4f84b80a5a8 100644 --- a/intern/cycles/kernel/geom/geom_curve.h +++ b/intern/cycles/kernel/geom/geom_curve.h @@ -264,7 +264,7 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte int ka = max(k0 - 1, v00.x); int kb = min(k1 + 1, v00.x + v00.y - 1); -#ifdef __KERNEL_AVX2__ +#if defined(__KERNEL_AVX2__) && (!defined(_MSC_VER) || _MSC_VER > 1800) avxf P_curve_0_1, P_curve_2_3; if(is_curve_primitive) { P_curve_0_1 = _mm256_loadu2_m128(&kg->__curve_keys.data[k0].x, &kg->__curve_keys.data[ka].x); @@ -299,7 +299,7 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte ssef htfm1 = shuffle<1, 0, 1, 3>(load1f_first(extract<0>(d_ss)), vdir0); ssef htfm2 = shuffle<1, 3, 2, 3>(mul_shuf, vdir0); -#ifdef __KERNEL_AVX2__ +#if defined(__KERNEL_AVX2__) && (!defined(_MSC_VER) || _MSC_VER > 1800) const avxf vPP = _mm256_broadcast_ps(&P.m128); const avxf htfm00 = avxf(htfm0.m128, htfm0.m128); const avxf htfm11 = avxf(htfm1.m128, htfm1.m128); From 797b1d505315351b48c3f231a476662482641024 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 22 Mar 2017 12:05:43 +0100 Subject: [PATCH 15/73] Fix T51024: Switch install_deps to set OSL_ROOT_DIR instead of CYCLES_OSL. Path by @alekulyn, thanks. Differential Revision: https://developer.blender.org/D2571 --- build_files/build_environment/install_deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index ee49f83b38d..ed1b9a3e62a 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -4252,7 +4252,7 @@ print_info() { PRINT " $_3" _buildargs="$_buildargs $_1 $_2 $_3" if [ -d $INST/osl ]; then - _1="-D CYCLES_OSL=$INST/osl" + _1="-D OSL_ROOT_DIR=$INST/osl" PRINT " $_1" _buildargs="$_buildargs $_1" fi From 412220c8d3b79204b768be3e3ed0f89e09216123 Mon Sep 17 00:00:00 2001 From: Stefan Werner Date: Wed, 22 Mar 2017 12:27:12 +0100 Subject: [PATCH 16/73] Cycles: fixed warnings --- intern/cycles/render/nodes.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index d159c801810..dfc44dbbf4a 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -324,7 +324,7 @@ private: class BsdfNode : public ShaderNode { public: explicit BsdfNode(const NodeType *node_type); - SHADER_NODE_BASE_CLASS(BsdfNode); + SHADER_NODE_BASE_CLASS(BsdfNode) bool has_spatial_varying() { return true; } void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL); @@ -641,7 +641,7 @@ public: class MixClosureWeightNode : public ShaderNode { public: - SHADER_NODE_CLASS(MixClosureWeightNode); + SHADER_NODE_CLASS(MixClosureWeightNode) float weight; float fac; @@ -887,7 +887,7 @@ public: class CurvesNode : public ShaderNode { public: explicit CurvesNode(const NodeType *node_type); - SHADER_NODE_BASE_CLASS(CurvesNode); + SHADER_NODE_BASE_CLASS(CurvesNode) virtual int get_group() { return NODE_GROUP_LEVEL_3; } From dc5007648c31a7819ade9d94fc5cd672ef56e8d7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Mar 2017 14:44:12 +0100 Subject: [PATCH 17/73] Depsgraph: Fix missing relations update tag when typing #frame New depsgraph requires relations to be updated after drivers changes. --- source/blender/editors/interface/interface_anim.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 5da294302e9..a04360b3395 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -39,6 +39,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_nla.h" @@ -210,6 +211,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str) /* updates */ driver->flag |= DRIVER_FLAG_RECOMPILE; + DAG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL); ok = true; } From 387ba87ad3b9eba8e0d117474b133a5a58ea44c6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Mar 2017 05:20:52 +1100 Subject: [PATCH 18/73] Cleanup: ignore open-blend as startup/prefs basis No reason startup/prefs would ever be blend-file relative. --- source/blender/windowmanager/intern/wm_files.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 60a361122c2..39c47599e30 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -675,15 +675,15 @@ int wm_homefile_read( BLI_strncpy(filepath_startup, filepath_startup_override, FILE_MAX); if (cfgdir) { - BLI_make_file_string(G.main->name, filepath_userdef, cfgdir, BLENDER_USERPREF_FILE); + BLI_make_file_string("/", filepath_userdef, cfgdir, BLENDER_USERPREF_FILE); } else { filepath_userdef[0] = '\0'; } } else if (cfgdir) { - BLI_make_file_string(G.main->name, filepath_startup, cfgdir, BLENDER_STARTUP_FILE); - BLI_make_file_string(G.main->name, filepath_userdef, cfgdir, BLENDER_USERPREF_FILE); + BLI_make_file_string("/", filepath_startup, cfgdir, BLENDER_STARTUP_FILE); + BLI_make_file_string("/", filepath_userdef, cfgdir, BLENDER_USERPREF_FILE); } else { filepath_startup[0] = '\0'; From 2ba1868c3fd2dc84d75b531c6c5457de86b1e551 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 22 Mar 2017 19:41:03 +0100 Subject: [PATCH 19/73] Cleanup/optimization: Simplify some usages of uiItemFullO/_ptr, avoid multiple search of same op. --- .../editors/interface/interface_handlers.c | 13 ++--- .../editors/interface/interface_layout.c | 7 ++- source/blender/editors/screen/screen_ops.c | 27 +++++------ source/blender/editors/space_node/drawnode.c | 24 +++------- .../blender/editors/space_node/node_buttons.c | 11 +++-- .../editors/space_outliner/outliner_edit.c | 48 +++++++------------ .../editors/space_view3d/view3d_buttons.c | 21 ++------ .../windowmanager/intern/wm_operators.c | 2 +- 8 files changed, 56 insertions(+), 97 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 6e3c3c3674a..4846272b17d 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -7005,20 +7005,17 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), ICON_URL, "WM_OT_doc_view_manual_ui_context"); - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); + ptr_props = uiItemFullO(layout, "WM_OT_doc_view", + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), + ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); /* XXX inactive option, not for public! */ #if 0 - WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit"); + ptr_props = uiItemFullO(layout, "WM_OT_doc_edit", + "Submit Description", ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr_props, "doc_id", buf); RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop)); - - uiItemFullO(layout, "WM_OT_doc_edit", - "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); #endif } } diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index c62fb4cadd6..76fa1720863 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -3556,14 +3556,13 @@ void uiLayoutOperatorButs( row = uiLayoutRow(layout, true); uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE); - WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); + wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); + op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMIN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&op_ptr, "operator", op->type->idname); - uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); - WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); + op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMOUT, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&op_ptr, "operator", op->type->idname); RNA_boolean_set(&op_ptr, "remove_active", true); - uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); } if (op->type->ui) { diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index d88c36a8e24..c2e094fc161 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2808,7 +2808,7 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent bScreen *sc = CTX_wm_screen(C); uiPopupMenu *pup; uiLayout *layout; - PointerRNA ptr1, ptr2; + PointerRNA ptr; ScrEdge *actedge; const int winsize_x = WM_window_pixels_x(win); const int winsize_y = WM_window_pixels_y(win); @@ -2820,22 +2820,17 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE); layout = UI_popup_menu_layout(pup); - WM_operator_properties_create(&ptr1, "SCREEN_OT_area_join"); - - /* mouse cursor on edge, '4' can fail on wide edges... */ - RNA_int_set(&ptr1, "min_x", event->x + 4); - RNA_int_set(&ptr1, "min_y", event->y + 4); - RNA_int_set(&ptr1, "max_x", event->x - 4); - RNA_int_set(&ptr1, "max_y", event->y - 4); - - WM_operator_properties_create(&ptr2, "SCREEN_OT_area_split"); - + ptr = uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); /* store initial mouse cursor position */ - RNA_int_set(&ptr2, "mouse_x", event->x); - RNA_int_set(&ptr2, "mouse_y", event->y); - - uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, ptr2.data, WM_OP_INVOKE_DEFAULT, 0); - uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, ptr1.data, WM_OP_INVOKE_DEFAULT, 0); + RNA_int_set(&ptr, "mouse_x", event->x); + RNA_int_set(&ptr, "mouse_y", event->y); + + ptr = uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + /* mouse cursor on edge, '4' can fail on wide edges... */ + RNA_int_set(&ptr, "min_x", event->x + 4); + RNA_int_set(&ptr, "min_y", event->y + 4); + RNA_int_set(&ptr, "max_x", event->x - 4); + RNA_int_set(&ptr, "max_y", event->y - 4); UI_popup_menu_end(C, pup); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index d31a475e45e..e4f5802a395 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1320,9 +1320,6 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point PropertyRNA *prop; const char *layer_name; char scene_name[MAX_ID_NAME - 2]; - wmOperatorType *ot = WM_operatortype_find("RENDER_OT_render", 1); - - BLI_assert(ot != 0); uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL); @@ -1339,11 +1336,9 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point scn_ptr = RNA_pointer_get(ptr, "scene"); RNA_string_get(&scn_ptr, "name", scene_name); - WM_operator_properties_create_ptr(&op_ptr, ot); + op_ptr = uiItemFullO(row, "RENDER_OT_render", "", ICON_RENDER_STILL, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&op_ptr, "layer", layer_name); RNA_string_set(&op_ptr, "scene", scene_name); - uiItemFullO_ptr(row, ot, "", ICON_RENDER_STILL, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); - } @@ -1792,6 +1787,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi Scene *scene = CTX_data_scene(C); PointerRNA imfptr = RNA_pointer_get(ptr, "format"); PointerRNA active_input_ptr, op_ptr; + wmOperatorType *ot; uiLayout *row, *col; int active_index; const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER; @@ -1830,11 +1826,10 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi active_input_ptr.id.data = ptr->id.data; col = uiLayoutColumn(row, true); - op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "", - ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + ot = WM_operatortype_find("NODE_OT_output_file_move_active_socket", false); + op_ptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&op_ptr, "direction", 1); - op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "", - ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + op_ptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&op_ptr, "direction", 2); if (active_input_ptr.data) { @@ -2166,14 +2161,7 @@ static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), Poi static void node_composit_buts_switch_view_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr)) { - PointerRNA op_ptr; - wmOperatorType *ot = WM_operatortype_find("NODE_OT_switch_view_update", 1); - - BLI_assert(ot != 0); - - WM_operator_properties_create_ptr(&op_ptr, ot); - - uiItemFullO_ptr(layout, ot, "Update Views", ICON_FILE_REFRESH, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + uiItemFullO(layout, "NODE_OT_switch_view_update", "Update Views", ICON_FILE_REFRESH, NULL, WM_OP_INVOKE_DEFAULT, 0); } static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index f0567924edd..925298451ce 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -133,6 +133,7 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa) int in_out; uiLayout *layout = pa->layout, *row, *split, *col; PointerRNA ptr, sockptr, opptr; + wmOperatorType *ot; if (!ntree) return; @@ -146,23 +147,25 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa) split = uiLayoutRow(row, true); col = uiLayoutColumn(split, true); + ot = WM_operatortype_find("NODE_OT_tree_socket_add", false); uiItemL(col, IFACE_("Inputs:"), ICON_NONE); uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input", NULL, 0, 0, 0, 0); - opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + opptr = uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "in_out", SOCK_IN); col = uiLayoutColumn(split, true); uiItemL(col, IFACE_("Outputs:"), ICON_NONE); uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output", NULL, 0, 0, 0, 0); - opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + opptr = uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "in_out", SOCK_OUT); + ot = WM_operatortype_find("NODE_OT_tree_socket_move", false); col = uiLayoutColumn(row, true); - opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + opptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "direction", 1); - opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + opptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "direction", 2); if (sock) { diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 8c3b9a55089..bf220784371 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -2071,74 +2071,62 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false); uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE); uiLayout *layout = UI_popup_menu_layout(pup); - PointerRNA ptr; - WM_operator_properties_create_ptr(&ptr, ot); + /* Cannot use uiItemEnumO()... have multiple properties to set. */ + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_OBJECT); - /* Cannot use uiItemEnumO()... have multiple properties to set. */ - uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - + /* par becomes parent, make the associated menus */ if (par->type == OB_ARMATURE) { - WM_operator_properties_create_ptr(&ptr, ot); + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_ARMATURE); - uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_ARMATURE_NAME); - uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_ARMATURE_ENVELOPE); - uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_ARMATURE_AUTO); - uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_BONE); - uiItemFullO_ptr(layout, ot, IFACE_("Bone"), - 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); } else if (par->type == OB_CURVE) { - WM_operator_properties_create_ptr(&ptr, ot); + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_CURVE); - uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_FOLLOW); - uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_PATH_CONST); - uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); } else if (par->type == OB_LATTICE) { - WM_operator_properties_create_ptr(&ptr, ot); + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_LATTICE); - uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); } UI_popup_menu_end(C, pup); diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 351c7ccec15..34e01405e7e 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -814,10 +814,6 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) if (dv && dv->totweight) { ToolSettings *ts = scene->toolsettings; - wmOperatorType *ot_weight_set_active = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true); - wmOperatorType *ot_weight_paste = WM_operatortype_find("OBJECT_OT_vertex_weight_paste", true); - wmOperatorType *ot_weight_delete = WM_operatortype_find("OBJECT_OT_vertex_weight_delete", true); - wmOperatorType *ot; PointerRNA op_ptr, tools_ptr; PointerRNA *but_ptr; @@ -856,7 +852,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) /* The Weight Group Name */ - ot = ot_weight_set_active; + ot = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true); but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, dg->name, xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, ""); but_ptr = UI_but_operator_ptr_get(but); @@ -882,23 +878,16 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) xco += x; /* The weight group paste function */ - - ot = ot_weight_paste; - WM_operator_properties_create_ptr(&op_ptr, ot); - RNA_int_set(&op_ptr, "weight_group", i); icon = (locked) ? ICON_BLANK1 : ICON_PASTEDOWN; - uiItemFullO_ptr(row, ot, "", icon, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + op_ptr = uiItemFullO(row, "OBJECT_OT_vertex_weight_paste", "", icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_int_set(&op_ptr, "weight_group", i); /* The weight entry delete function */ - - ot = ot_weight_delete; - WM_operator_properties_create_ptr(&op_ptr, ot); - RNA_int_set(&op_ptr, "weight_group", i); icon = (locked) ? ICON_LOCKED : ICON_X; - uiItemFullO_ptr(row, ot, "", icon, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + op_ptr = uiItemFullO(row, "OBJECT_OT_vertex_weight_delete", "", icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_int_set(&op_ptr, "weight_group", i); yco -= UI_UNIT_Y; - } } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 9d4c3986678..841b63d4ab8 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -900,7 +900,7 @@ void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot) void WM_operator_properties_create(PointerRNA *ptr, const char *opstring) { - wmOperatorType *ot = WM_operatortype_find(opstring, 0); + wmOperatorType *ot = WM_operatortype_find(opstring, false); if (ot) WM_operator_properties_create_ptr(ptr, ot); From c7a4f96f885c83a6c7feb99b1598f156db7a7294 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Wed, 22 Mar 2017 14:49:12 -0400 Subject: [PATCH 20/73] Pydoc: Change Wikipedia links and grammar in mathutils matrix code --- .../python/mathutils/mathutils_Matrix.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 4e980e4c0e6..bd44e77e7c6 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -1301,7 +1301,7 @@ PyDoc_STRVAR(Matrix_to_scale_doc, " :return: Return the scale of a matrix.\n" " :rtype: :class:`Vector`\n" "\n" -" .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n" +" .. note:: This method does not return a negative scale on any axis because it is not possible to obtain this data from the matrix alone.\n" ); static PyObject *Matrix_to_scale(MatrixObject *self) { @@ -1390,11 +1390,11 @@ PyDoc_STRVAR(Matrix_invert_doc, "\n" " Set the matrix to its inverse.\n" "\n" -" :arg fallback: Set the matrix to this value when the inverse can't be calculated\n" +" :arg fallback: Set the matrix to this value when the inverse cannot be calculated\n" " (instead of raising a :exc:`ValueError` exception).\n" " :type fallback: :class:`Matrix`\n" "\n" -" .. seealso:: \n" +" .. seealso:: `Inverse matrix ` on Wikipedia.\n" ); static PyObject *Matrix_invert(MatrixObject *self, PyObject *args) { @@ -1505,7 +1505,7 @@ PyDoc_STRVAR(Matrix_invert_safe_doc, " If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, to get an invertible one.\n" " If tweaked matrix is still degenerated, set to the identity matrix instead.\n" "\n" -" .. seealso:: \n" +" .. seealso:: `Inverse Matrix ` on Wikipedia.\n" ); static PyObject *Matrix_invert_safe(MatrixObject *self) { @@ -1554,9 +1554,9 @@ PyDoc_STRVAR(Matrix_adjugate_doc, "\n" " Set the matrix to its adjugate.\n" "\n" -" .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n" +" .. note:: When the matrix cannot be adjugated a :exc:`ValueError` exception is raised.\n" "\n" -" .. seealso:: \n" +" .. seealso:: `Adjugate matrix ` on Wikipedia.\n" ); static PyObject *Matrix_adjugate(MatrixObject *self) { @@ -1733,7 +1733,7 @@ PyDoc_STRVAR(Matrix_determinant_doc, " :return: Return the determinant of a matrix.\n" " :rtype: float\n" "\n" -" .. seealso:: \n" +" .. seealso:: `Determinant ` on Wikipedia.\n" ); static PyObject *Matrix_determinant(MatrixObject *self) { @@ -1755,7 +1755,7 @@ PyDoc_STRVAR(Matrix_transpose_doc, "\n" " Set the matrix to its transpose.\n" "\n" -" .. seealso:: \n" +" .. seealso:: `Transpose ` on Wikipedia.\n" ); static PyObject *Matrix_transpose(MatrixObject *self) { @@ -1887,10 +1887,10 @@ PyDoc_STRVAR(Matrix_identity_doc, "\n" " Set the matrix to the identity matrix.\n" "\n" -" .. note:: An object with zero location and rotation, a scale of one,\n" +" .. note:: An object with a location and rotation of zero, and a scale of one\n" " will have an identity matrix.\n" "\n" -" .. seealso:: \n" +" .. seealso:: `Identity matrix ` on Wikipedia.\n" ); static PyObject *Matrix_identity(MatrixObject *self) { From d8b34a17ac4375cf4618974626c6ba2643603590 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Mar 2017 06:32:16 +1100 Subject: [PATCH 21/73] Cleanup: remove BLI_getlastdir Replace with BLI_path_name_at_index --- source/blender/blenlib/BLI_path_util.h | 1 - source/blender/blenlib/intern/path_util.c | 24 ---------------------- source/blender/editors/space_file/fsmenu.c | 13 +++++++----- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 7d971fbfc3d..1c1725923a6 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -86,7 +86,6 @@ bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen); #endif bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *name); -void BLI_getlastdir(const char *dir, char *last, const size_t maxlen); bool BLI_testextensie(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; bool BLI_testextensie_n(const char *str, ...) ATTR_NONNULL(1) ATTR_SENTINEL(0); bool BLI_testextensie_array(const char *str, const char **ext_array) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 83aa01d3d15..955f603cdae 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1166,30 +1166,6 @@ bool BLI_path_program_search( return retval; } -/** - * Copies into *last the part of *dir following the second-last slash. - */ -void BLI_getlastdir(const char *dir, char *last, const size_t maxlen) -{ - const char *s = dir; - const char *lslash = NULL; - const char *prevslash = NULL; - while (*s) { - if ((*s == '\\') || (*s == '/')) { - prevslash = lslash; - lslash = s; - } - s++; - } - if (prevslash) { - BLI_strncpy(last, prevslash + 1, maxlen); - } - else { - BLI_strncpy(last, dir, maxlen); - } -} - - /** * Sets the specified environment variable to the specified value, * and clears it if val == NULL. diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index d7aa1040e0f..71d49e0dc2e 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -169,12 +169,15 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *path) static void fsmenu_entry_generate_name(struct FSMenuEntry *fsentry, char *name, size_t name_size) { - char temp[FILE_MAX]; + int offset = 0; + int len = name_size; - BLI_strncpy(temp, fsentry->path, FILE_MAX); - BLI_add_slash(temp); - BLI_getlastdir(temp, name, name_size); - BLI_del_slash(name); + if (BLI_path_name_at_index(fsentry->path, -1, &offset, &len)) { + /* use as size */ + len += 1; + } + + BLI_strncpy(name, &fsentry->path[offset], MIN2(len, name_size)); if (!name[0]) { name[0] = '/'; name[1] = '\0'; From 762319e911843e0014d8395b558203a8638d656a Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 22 Mar 2017 16:26:53 -0400 Subject: [PATCH 22/73] fix redundant assignment Thanks clang for the warning. --- source/blender/editors/space_outliner/outliner_draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 42d9e4356ee..121fe812016 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1052,8 +1052,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT; x += 2.0f * aspect; y += 2.0f * aspect; - arg.x = x = x; - arg.y = y = y; + arg.x = x; + arg.y = y; if (tselem->type) { switch (tselem->type) { From 12b62b58e102ed9dea683d1598d3f1b1811a2a95 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Mar 2017 10:32:16 +1100 Subject: [PATCH 23/73] Cleanup: minor wm_homefile_read simplification Logic in this function is a bit scattered, minor changes to avoid confusion. Also rename 'from_memory' to 'use_factory_settings'. --- source/blender/blenkernel/intern/blendfile.c | 6 +- .../blender/windowmanager/intern/wm_files.c | 71 +++++++++---------- source/blender/windowmanager/wm_files.h | 2 +- 3 files changed, 40 insertions(+), 39 deletions(-) diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 5725a12e3d4..6bcd3c8fb65 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -356,8 +356,10 @@ int BKE_blendfile_read( BlendFileData *bfd; int retval = BKE_BLENDFILE_READ_OK; - if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) /* don't print user-pref loading */ - printf("read blend: %s\n", filepath); + /* don't print user-pref loading */ + if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) { + printf("Read blend: %s\n", filepath); + } bfd = BLO_read_from_file(filepath, reports, skip_flags); if (bfd) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 39c47599e30..241bd90bdf3 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -316,7 +316,7 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist) } /* in case UserDef was read, we re-initialize all, and do versioning */ -static void wm_init_userdef(bContext *C, const bool from_memory) +static void wm_init_userdef(bContext *C, const bool use_factory_settings) { Main *bmain = CTX_data_main(C); @@ -336,7 +336,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory) } /* avoid re-saving for every small change to our prefs, allow overrides */ - if (from_memory) { + if (use_factory_settings) { BLO_update_defaults_userpref_blend(); } @@ -632,13 +632,13 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) * Called on startup, (context entirely filled with NULLs) * or called for 'New File' both startup.blend and userpref.blend are checked. * - * \param from_memory: Ignore on-disk startup file, use bundled ``datatoc_startup_blend`` instead. + * \param use_factory_settings: Ignore on-disk startup file, use bundled ``datatoc_startup_blend`` instead. * Used for "Restore Factory Settings". * \param filepath_startup_override: Optional path pointing to an alternative blend file (may be NULL). */ int wm_homefile_read( bContext *C, ReportList *reports, - bool from_memory, const char *filepath_startup_override) + bool use_factory_settings, const char *filepath_startup_override) { ListBase wmbase; char filepath_startup[FILE_MAX]; @@ -647,7 +647,7 @@ int wm_homefile_read( /* Indicates whether user preferences were really load from memory. * - * This is used for versioning code, and for this we can not rely on from_memory + * This is used for versioning code, and for this we can not rely on use_factory_settings * passed via argument. This is because there might be configuration folder * exists but it might not have userpref.blend and in this case we fallback to * reading home file from memory. @@ -658,7 +658,7 @@ int wm_homefile_read( eBLOReadSkip skip_flags = 0; /* options exclude eachother */ - BLI_assert((from_memory && filepath_startup_override) == 0); + BLI_assert((use_factory_settings && filepath_startup_override) == 0); if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) { BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC); @@ -669,34 +669,30 @@ int wm_homefile_read( UI_view2d_zoom_cache_reset(); G.relbase_valid = 0; - if (!from_memory) { - const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); - if (filepath_startup_override) { - BLI_strncpy(filepath_startup, filepath_startup_override, FILE_MAX); - if (cfgdir) { - BLI_make_file_string("/", filepath_userdef, cfgdir, BLENDER_USERPREF_FILE); - } - else { - filepath_userdef[0] = '\0'; - } - } - else if (cfgdir) { + /* put aside screens to match with persistent windows later */ + wm_window_match_init(C, &wmbase); + + filepath_startup[0] = '\0'; + filepath_userdef[0] = '\0'; + + if (!use_factory_settings) { + const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); + if (cfgdir) { BLI_make_file_string("/", filepath_startup, cfgdir, BLENDER_STARTUP_FILE); BLI_make_file_string("/", filepath_userdef, cfgdir, BLENDER_USERPREF_FILE); } else { - filepath_startup[0] = '\0'; - filepath_userdef[0] = '\0'; - from_memory = true; + use_factory_settings = true; + } + + if (filepath_startup_override) { + BLI_strncpy(filepath_startup, filepath_startup_override, FILE_MAX); } } - - /* put aside screens to match with persistent windows later */ - wm_window_match_init(C, &wmbase); - + /* load preferences before startup.blend */ - if (!from_memory && BLI_exists(filepath_userdef)) { + if (!use_factory_settings && BLI_exists(filepath_userdef)) { UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL); if (userdef != NULL) { BKE_blender_userdef_set_data(userdef); @@ -708,7 +704,7 @@ int wm_homefile_read( } } - if (!from_memory) { + if (!use_factory_settings) { if (BLI_access(filepath_startup, R_OK) == 0) { success = (BKE_blendfile_read(C, filepath_startup, NULL, skip_flags) != BKE_BLENDFILE_READ_FAIL); } @@ -754,11 +750,14 @@ int wm_homefile_read( G.main->name[0] = '\0'; /* When loading factory settings, the reset solid OpenGL lights need to be applied. */ - if (!G.background) GPU_default_lights(); - - /* XXX */ - G.save_over = 0; // start with save preference untitled.blend - G.fileflags &= ~G_FILE_AUTOPLAY; /* disable autoplay in startup.blend... */ + if (!G.background) { + GPU_default_lights(); + } + + /* start with save preference untitled.blend */ + G.save_over = 0; + /* disable auto-play in startup.blend... */ + G.fileflags &= ~G_FILE_AUTOPLAY; wm_file_read_post(C, true); @@ -1410,11 +1409,11 @@ void WM_OT_read_history(wmOperatorType *ot) static int wm_homefile_read_exec(bContext *C, wmOperator *op) { - const bool from_memory = (STREQ(op->type->idname, "WM_OT_read_factory_settings")); + const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings")); char filepath_buf[FILE_MAX]; const char *filepath = NULL; - if (!from_memory) { + if (!use_factory_settings) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath"); /* This can be used when loading of a start-up file should only change @@ -1436,9 +1435,9 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) G.fileflags &= ~G_FILE_NO_UI; } - if (wm_homefile_read(C, op->reports, from_memory, filepath)) { + if (wm_homefile_read(C, op->reports, use_factory_settings, filepath)) { /* Load a file but keep the splash open */ - if (!from_memory && RNA_boolean_get(op->ptr, "use_splash")) { + if (!use_factory_settings && RNA_boolean_get(op->ptr, "use_splash")) { WM_init_splash(C); } return OPERATOR_FINISHED; diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index 954d35722f3..048b5a997bb 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -37,7 +37,7 @@ struct wmOperatorType; void wm_history_file_read(void); int wm_homefile_read( struct bContext *C, struct ReportList *reports, - bool from_memory, const char *filepath_startup_override); + bool use_factory_settings, const char *filepath_startup_override); void wm_file_read_report(bContext *C); void WM_OT_save_homefile(struct wmOperatorType *ot); From a63ba2739e2a3956a2049be74dc67aa59f26c7fc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Mar 2017 15:05:42 +1100 Subject: [PATCH 24/73] Cleanup: remove redundant temp dir init This is already called by wm_init_userdef, in old code different initialization methods were used but now it's not needed. Confusing since prefs are loaded in this function that don't initialize temp. --- source/blender/windowmanager/intern/wm_files.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 241bd90bdf3..cff27dfc9e8 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -727,8 +727,6 @@ int wm_homefile_read( if (BLI_listbase_is_empty(&wmbase)) { wm_clear_default_size(C); } - BKE_tempdir_init(U.tempdir); - #ifdef WITH_PYTHON_SECURITY /* use alternative setting for security nuts * otherwise we'd need to patch the binary blob - startup.blend.c */ From 4d82d525f85af937bb59c08d584413e5419037ce Mon Sep 17 00:00:00 2001 From: Mai Lavelle Date: Thu, 23 Mar 2017 00:11:29 -0400 Subject: [PATCH 25/73] Cycles: Fix building for some compilers --- intern/cycles/device/device_cuda.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 58471ba67c2..08dfa181385 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -1500,7 +1500,7 @@ uint64_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory cuda_assert(cuLaunchKernel(state_buffer_size, 1, 1, 1, 1, 1, 1, - 0, 0, &args, 0)); + 0, 0, (void**)&args, 0)); device->cuda_pop_context(); From 4f4a484b9b208fe5719825aa750b72e0b67937c8 Mon Sep 17 00:00:00 2001 From: Luca Rood Date: Thu, 23 Mar 2017 03:52:31 -0300 Subject: [PATCH 26/73] Cloth refactor: Remove goal springs and some other cleanup This removes the goal springs, in favor of simply calculating the goal forces on the vertices directly. The vertices already store all the necessary data for the goal forces, thus the springs were redundant, and just defined both ends as being the same vertex. The main advantage of removing the goal springs, is an increase in flexibility, allowing us to much more nicely do some neat dynamic stuff with the goals/pins, such as animated vertex weights. But this also has the advantage of simpler code, and a slightly reduced memory footprint. This also removes the `f`, `dfdx` and `dfdv` fields from the `ClothSpring` struct, as that data is only used by the solver, and is re-computed on each step, and thus does not need to be stored throughout the simulation. Reviewers: sergey Reviewed By: sergey Tags: #physics Differential Revision: https://developer.blender.org/D2514 --- source/blender/blenkernel/BKE_cloth.h | 6 --- source/blender/blenkernel/intern/cloth.c | 37 -------------- .../physics/intern/BPH_mass_spring.cpp | 51 ++++++++----------- source/blender/physics/intern/implicit.h | 10 ++-- .../blender/physics/intern/implicit_blender.c | 34 ++----------- 5 files changed, 28 insertions(+), 110 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 36330242f18..6c517bd02df 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -136,9 +136,6 @@ typedef struct ClothSpring { float restlen; /* The original length of the spring. */ int type; /* types defined in BKE_cloth.h ("springType") */ int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ - float dfdx[3][3]; - float dfdv[3][3]; - float f[3]; float stiffness; /* stiffness factor from the vertex groups */ float editrestlen; @@ -240,9 +237,6 @@ void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving); // needed for button_object.c void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float framenr ); -// needed for cloth.c -int cloth_add_spring (struct ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type); - void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]); //////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 28ef3f6f248..ee0fde1ea61 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -869,12 +869,6 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d return 0; } - for ( i = 0; i < dm->getNumVerts(dm); i++) { - if ((!(cloth->verts[i].flags & CLOTH_VERT_FLAG_PINNED)) && (cloth->verts[i].goal > ALMOST_ZERO)) { - cloth_add_spring (clmd, i, i, 0.0, CLOTH_SPRING_TYPE_GOAL); - } - } - // init our solver BPH_cloth_solver_init(ob, clmd); @@ -944,37 +938,6 @@ BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1) } } -// be careful: implicit solver has to be resettet when using this one! -// --> only for implicit handling of this spring! -int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type) -{ - Cloth *cloth = clmd->clothObject; - ClothSpring *spring = NULL; - - if (cloth) { - // TODO: look if this spring is already there - - spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); - - if (!spring) - return 0; - - spring->ij = indexA; - spring->kl = indexB; - spring->restlen = restlength; - spring->type = spring_type; - spring->flags = 0; - spring->stiffness = 0; - - cloth->numsprings++; - - BLI_linklist_prepend ( &cloth->springs, spring ); - - return 1; - } - return 0; -} - static void cloth_free_edgelist(LinkNodePair *edgelist, unsigned int mvert_num) { if (edgelist) { diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index 359395b63c4..b694b6e994d 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -333,19 +333,14 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo return 1; } -BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float time) +BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s) { Cloth *cloth = clmd->clothObject; ClothSimSettings *parms = clmd->sim_parms; Implicit_Data *data = cloth->implicit; - ClothVertex *verts = cloth->verts; bool no_compress = parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; - zero_v3(s->f); - zero_m3(s->dfdx); - zero_m3(s->dfdv); - s->flags &= ~CLOTH_SPRING_FLAG_NEEDED; // calculate force of structural + shear springs @@ -361,29 +356,11 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, if (s->type & CLOTH_SPRING_TYPE_SEWING) { // TODO: verify, half verified (couldn't see error) // sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects - BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing, s->f, s->dfdx, s->dfdv); + BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing); } else { - BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f, s->f, s->dfdx, s->dfdv); + BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f); } -#endif - } - else if (s->type & CLOTH_SPRING_TYPE_GOAL) { -#ifdef CLOTH_FORCE_SPRING_GOAL - float goal_x[3], goal_v[3]; - float k, scaling; - - s->flags |= CLOTH_SPRING_FLAG_NEEDED; - - // current_position = xold + t * (newposition - xold) - /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */ - interp_v3_v3v3(goal_x, verts[s->ij].xold, verts[s->ij].xconst, time / parms->time_scale); - sub_v3_v3v3(goal_v, verts[s->ij].xconst, verts[s->ij].xold); // distance covered over dt==1 - - scaling = parms->goalspring + s->stiffness * fabsf(parms->max_struct - parms->goalspring); - k = verts[s->ij].goal * scaling / (parms->avg_spring_len + FLT_EPSILON); - - BPH_mass_spring_force_spring_goal(data, s->ij, goal_x, goal_v, k, parms->goalfrict * 0.01f, s->f, s->dfdx, s->dfdv); #endif } else if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */ @@ -398,7 +375,7 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, // Fix for [#45084] for cloth stiffness must have cb proportional to kb cb = kb * parms->bending_damping; - BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb, s->f, s->dfdx, s->dfdv); + BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb); #endif } else if (s->type & CLOTH_SPRING_TYPE_BENDING_ANG) { @@ -474,9 +451,24 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB /* scale gravity force */ mul_v3_v3fl(gravity, clmd->scene->physics_settings.gravity, 0.001f * clmd->sim_parms->effector_weights->global_gravity); } + vert = cloth->verts; for (i = 0; i < cloth->mvert_num; i++, vert++) { BPH_mass_spring_force_gravity(data, i, vert->mass, gravity); + + /* Vertex goal springs */ + if ((!(vert->flags & CLOTH_VERT_FLAG_PINNED)) && (vert->goal > FLT_EPSILON)) { + float goal_x[3], goal_v[3]; + float k; + + /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */ + interp_v3_v3v3(goal_x, vert->xold, vert->xconst, time / clmd->sim_parms->time_scale); + sub_v3_v3v3(goal_v, vert->xconst, vert->xold); /* distance covered over dt==1 */ + + k = vert->goal * clmd->sim_parms->goalspring / (clmd->sim_parms->avg_spring_len + FLT_EPSILON); + + BPH_mass_spring_force_spring_goal(data, i, goal_x, goal_v, k, clmd->sim_parms->goalfrict * 0.01f); + } } #endif @@ -544,8 +536,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB for (LinkNode *link = cloth->springs; link; link = link->next) { ClothSpring *spring = (ClothSpring *)link->link; // only handle active springs - if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) - cloth_calc_spring_force(clmd, spring, time); + if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) { + cloth_calc_spring_force(clmd, spring); + } } } diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h index d1a75ca5297..2f62ab98e12 100644 --- a/source/blender/physics/intern/implicit.h +++ b/source/blender/physics/intern/implicit.h @@ -114,19 +114,15 @@ void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2, void BPH_mass_spring_force_vertex_wind(struct Implicit_Data *data, int v, float radius, const float (*winvec)[3]); /* Linear spring force between two points */ bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen, - float stiffness, float damping, bool no_compress, float clamp_force, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]); + float stiffness, float damping, bool no_compress, float clamp_force); /* Bending force, forming a triangle at the base of two structural springs */ -bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen, - float kb, float cb, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]); +bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen, float kb, float cb); /* Angular bending force based on local target vectors */ bool BPH_mass_spring_force_spring_bending_angular(struct Implicit_Data *data, int i, int j, int k, const float target[3], float stiffness, float damping); /* Global goal spring */ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3], - float stiffness, float damping, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]); + float stiffness, float damping); /* ======== Hair Volumetric Forces ======== */ diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c index 2ad8ee0547f..16cd335dc0c 100644 --- a/source/blender/physics/intern/implicit_blender.c +++ b/source/blender/physics/intern/implicit_blender.c @@ -1579,8 +1579,7 @@ BLI_INLINE void apply_spring(Implicit_Data *data, int i, int j, const float f[3] } bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, float restlen, - float stiffness, float damping, bool no_compress, float clamp_force, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]) + float stiffness, float damping, bool no_compress, float clamp_force) { float extent[3], length, dir[3], vel[3]; @@ -1608,25 +1607,15 @@ bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, floa apply_spring(data, i, j, f, dfdx, dfdv); - if (r_f) copy_v3_v3(r_f, f); - if (r_dfdx) copy_m3_m3(r_dfdx, dfdx); - if (r_dfdv) copy_m3_m3(r_dfdv, dfdv); - return true; } else { - if (r_f) zero_v3(r_f); - if (r_dfdx) zero_m3(r_dfdx); - if (r_dfdv) zero_m3(r_dfdv); - return false; } } /* See "Stable but Responsive Cloth" (Choi, Ko 2005) */ -bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen, - float kb, float cb, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]) +bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen, float kb, float cb) { float extent[3], length, dir[3], vel[3]; @@ -1646,17 +1635,9 @@ bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, flo apply_spring(data, i, j, f, dfdx, dfdv); - if (r_f) copy_v3_v3(r_f, f); - if (r_dfdx) copy_m3_m3(r_dfdx, dfdx); - if (r_dfdv) copy_m3_m3(r_dfdv, dfdv); - return true; } else { - if (r_f) zero_v3(r_f); - if (r_dfdx) zero_m3(r_dfdx); - if (r_dfdv) zero_m3(r_dfdv); - return false; } } @@ -1945,8 +1926,7 @@ bool BPH_mass_spring_force_spring_bending_angular(Implicit_Data *data, int i, in } bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3], - float stiffness, float damping, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]) + float stiffness, float damping) { float root_goal_x[3], root_goal_v[3], extent[3], length, dir[3], vel[3]; float f[3], dfdx[3][3], dfdv[3][3]; @@ -1973,17 +1953,9 @@ bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float g add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, dfdx); add_m3_m3m3(data->dFdV[i].m, data->dFdV[i].m, dfdv); - if (r_f) copy_v3_v3(r_f, f); - if (r_dfdx) copy_m3_m3(r_dfdx, dfdx); - if (r_dfdv) copy_m3_m3(r_dfdv, dfdv); - return true; } else { - if (r_f) zero_v3(r_f); - if (r_dfdx) zero_m3(r_dfdx); - if (r_dfdv) zero_m3(r_dfdv); - return false; } } From 1600b93fb822ea39383ea6849f866aac767ceb12 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Mar 2017 20:42:44 +1100 Subject: [PATCH 27/73] UI: allow to extend camera as a menu Needed for T46853 --- release/scripts/modules/bpy_types.py | 4 ++++ release/scripts/startup/bl_ui/space_view3d.py | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 5eb8b946568..600b29a6b2b 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -682,6 +682,10 @@ class _GenericUI: return draw_funcs + @classmethod + def is_extended(cls): + return bool(getattr(cls.draw, "_draw_funcs", None)) + @classmethod def append(cls, draw_func): """ diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index b718228e7b2..e17d237b060 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1206,6 +1206,16 @@ class INFO_MT_lamp_add(Menu): layout.operator_enum("object.lamp_add", "type") +class INFO_MT_camera_add(Menu): + bl_idname = "INFO_MT_camera_add" + bl_label = "Camera" + + def draw(self, context): + layout = self.layout + layout.operator_context = 'EXEC_REGION_WIN' + layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA') + + class INFO_MT_add(Menu): bl_label = "Add" @@ -1237,7 +1247,11 @@ class INFO_MT_add(Menu): layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER') layout.separator() - layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA') + if INFO_MT_camera_add.is_extended(): + layout.menu("INFO_MT_camera_add", icon='OUTLINER_OB_CAMERA') + else: + INFO_MT_camera_add.draw(self, context) + layout.menu("INFO_MT_lamp_add", icon='OUTLINER_OB_LAMP') layout.separator() From 89631485ccf5fac5e61f77f29c4b9ca2e9779574 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Tue, 21 Mar 2017 17:10:19 +0100 Subject: [PATCH 28/73] collada: use vector copy function instead of direct assigning --- source/blender/collada/ArmatureImporter.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index f4ce3992771..5b3340a938f 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -322,10 +322,7 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH) { - pebone->tail[0] = cebone->head[0]; - pebone->tail[1] = cebone->head[1]; - pebone->tail[2] = cebone->head[2]; - + copy_v3_v3(pebone->tail, cebone->head); if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) { cebone->flag |= BONE_CONNECTED; printf("Connecting chain: parent %s --> %s (child)\n", pebone->name, cebone->name); From 1978ac65c43533d4539c1b06621ef999c8d0a5c2 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Tue, 21 Mar 2017 17:13:31 +0100 Subject: [PATCH 29/73] collada: use local variable to avoid repeated call of bone chain_length_calculator --- source/blender/collada/ArmatureImporter.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 5b3340a938f..d5c1af9347d 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -290,12 +290,13 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone for (; child; child = child->next) { BoneExtended *be = extended_bones[child->name]; if (be != NULL) { - if (be->get_chain_length() <= clip) { - if (be->get_chain_length() > maxlen) { + int chain_len = be->get_chain_length(); + if (chain_len <= clip) { + if (chain_len > maxlen) { dominant_child = be; - maxlen = be->get_chain_length(); + maxlen = chain_len; } - else if (be->get_chain_length() == maxlen) { + else if (chain_len == maxlen) { dominant_child = NULL; } } From ec3989441f8ad514a7110587e77611573c65a409 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Tue, 21 Mar 2017 17:24:39 +0100 Subject: [PATCH 30/73] fix: collada - Connected bones get their tails set to wrong location when fix leaf nodes option is enabled --- source/blender/collada/ArmatureImporter.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index d5c1af9347d..a365b5ca350 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -324,10 +324,15 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH) { copy_v3_v3(pebone->tail, cebone->head); + pbe->set_tail(pebone->tail); /* to make fix_leafbone happy ...*/ if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) { + + BoneExtended *cbe = extended_bones[cebone->name]; + cbe->set_use_connect(true); + cebone->flag |= BONE_CONNECTED; - printf("Connecting chain: parent %s --> %s (child)\n", pebone->name, cebone->name); pbe->set_leaf_bone(false); + printf("Connect Bone chain: parent (%s --> %s) child)\n", pebone->name, cebone->name); } } } From 33e32c341aa0139f8ac03006d9b14c7df6277d65 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Tue, 21 Mar 2017 17:42:34 +0100 Subject: [PATCH 31/73] collada: add extern 'C' for c header includes --- source/blender/collada/ArmatureImporter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index a365b5ca350..6a8fe2e13f0 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -32,6 +32,7 @@ #include "COLLADAFWUniqueId.h" +extern "C" { #include "BKE_action.h" #include "BKE_depsgraph.h" #include "BKE_object.h" @@ -39,6 +40,7 @@ #include "BLI_string.h" #include "BLI_listbase.h" #include "ED_armature.h" +} #include "ArmatureImporter.h" From 1729dd99981ad2d35582ebb67d32542a0e0b24bd Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Tue, 21 Mar 2017 17:49:21 +0100 Subject: [PATCH 32/73] collada: Make sure that bone use_conncet is set to false when connect type is not defined in Import --- source/blender/collada/ArmatureImporter.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 6a8fe2e13f0..13196c4a150 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -159,10 +159,11 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon int use_connect = be.get_use_connect(); switch (use_connect) { - case 1: bone->flag |= BONE_CONNECTED; - break; - case 0: bone->flag &= ~BONE_CONNECTED; - case -1: break; // not defined + case 1: bone->flag |= BONE_CONNECTED; + break; + case -1:/* Connect type not specified */ + case 0: bone->flag &= ~BONE_CONNECTED; + break; } if (be.has_roll()) { From 339d0170d1843e6a67217cfc4085af8725708eca Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Tue, 21 Mar 2017 18:05:10 +0100 Subject: [PATCH 33/73] collada: Simplify reading Node Matrix --- source/blender/collada/ArmatureImporter.cpp | 13 +----------- source/blender/collada/TransformReader.cpp | 23 ++++++++++++++++++++- source/blender/collada/TransformReader.h | 3 ++- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 13196c4a150..398c4a2c106 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -132,18 +132,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon // create a bone even if there's no joint data for it (i.e. it has no influence) if (!bone_is_skinned) { - float obmat[4][4]; - // bone-space - get_node_mat(obmat, node, NULL, NULL); - - // get world-space - if (parent) { - mul_m4_m4m4(mat, parent_mat, obmat); - } - else { - copy_m4_m4(mat, obmat); - } - + get_node_mat(mat, node, NULL, NULL, parent_mat); } if (parent) bone->parent = parent; diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp index f8f31304d28..7f742be7e30 100644 --- a/source/blender/collada/TransformReader.cpp +++ b/source/blender/collada/TransformReader.cpp @@ -34,7 +34,21 @@ TransformReader::TransformReader(UnitConverter *conv) : unit_converter(conv) /* pass */ } -void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map *animation_map, Object *ob) +void TransformReader::get_node_mat( + float mat[4][4], + COLLADAFW::Node *node, + std::map *animation_map, + Object *ob) +{ + get_node_mat(mat, node, animation_map, ob, NULL); +} + +void TransformReader::get_node_mat( + float mat[4][4], + COLLADAFW::Node *node, + std::map *animation_map, + Object *ob, + float parent_mat[4][4]) { float cur[4][4]; float copy[4][4]; @@ -52,6 +66,9 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std:: // then this is considered as redundant information. // So if we find a Matrix we use that and return. dae_matrix_to_mat4(tm, mat); + if (parent_mat) { + mul_m4_m4m4(mat, parent_mat, mat); + } return; case COLLADAFW::Transformation::TRANSLATE: dae_translate_to_mat4(tm, cur); @@ -80,6 +97,10 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std:: (*animation_map)[anim_list_id] = anim; } } + + if (parent_mat) { + mul_m4_m4m4(mat, parent_mat, mat); + } } void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]) diff --git a/source/blender/collada/TransformReader.h b/source/blender/collada/TransformReader.h index ab974b9ba85..c598c466c9b 100644 --- a/source/blender/collada/TransformReader.h +++ b/source/blender/collada/TransformReader.h @@ -59,7 +59,8 @@ public: TransformReader(UnitConverter *conv); void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map *animation_map, Object *ob); - + void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map *animation_map, Object *ob, float parent_mat[4][4]); + void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); From 092d67368955d93392528eddd4bbc452adf04893 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 23 Mar 2017 00:07:05 +0100 Subject: [PATCH 34/73] Added new option for storing bindpose matrix, see T50412 --- source/blender/collada/ArmatureImporter.cpp | 13 +++-- source/blender/collada/ExportSettings.h | 2 + source/blender/collada/ImportSettings.h | 1 + source/blender/collada/collada.cpp | 9 +++- source/blender/collada/collada.h | 8 ++-- source/blender/editors/io/io_collada.c | 36 ++++++++++++-- .../blender/makesrna/intern/rna_scene_api.c | 48 ++++++++++--------- 7 files changed, 84 insertions(+), 33 deletions(-) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 398c4a2c106..2e4a7dfebc7 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -93,6 +93,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon { float mat[4][4]; float joint_inv_bind_mat[4][4]; + float joint_bind_mat[4][4]; int chain_length = 0; //Checking if bone is already made. @@ -116,7 +117,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon // get original world-space matrix invert_m4_m4(mat, joint_inv_bind_mat); - + copy_m4_m4(joint_bind_mat, mat); // And make local to armature Object *ob_arm = skin->BKE_armature_from_object(); if (ob_arm) { @@ -165,6 +166,14 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon bone->roll = angle; } copy_v3_v3(bone->head, mat[3]); + + if (bone_is_skinned) + { + float rest_mat[4][4]; + get_node_mat(rest_mat, node, NULL, NULL, NULL); + bc_create_bindpose_properties(this->import_settings, bone, joint_bind_mat, rest_mat); + } + add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero /* find smallest bone length in armature (used later for leaf bone length) */ @@ -266,7 +275,6 @@ void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone) } - void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip) { BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); @@ -302,7 +310,6 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone EditBone *pebone = bc_get_edit_bone(armature, parentbone->name); EditBone *cebone = bc_get_edit_bone(armature, dominant_child->get_name()); if (pebone && !(cebone->flag & BONE_CONNECTED)) { - float vec[3]; sub_v3_v3v3(vec, cebone->head, pebone->head); diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index 9451cac9dae..03e380dc198 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -51,7 +51,9 @@ public: bool use_blender_profile; bool sort_by_name; BC_export_transformation_type export_transformation_type; + bool open_sim; + bool keep_bind_info; char *filepath; LinkNode *export_set; diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h index 2c52d73e756..4a2d4e8046a 100644 --- a/source/blender/collada/ImportSettings.h +++ b/source/blender/collada/ImportSettings.h @@ -37,6 +37,7 @@ public: bool fix_orientation; int min_chain_length; char *filepath; + bool keep_bind_info; }; #endif diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index fe8b1d2320a..c0784ca8eb5 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -48,7 +48,8 @@ int collada_import(bContext *C, int find_chains, int auto_connect, int fix_orientation, - int min_chain_length) + int min_chain_length, + int keep_bind_info) { ImportSettings import_settings; @@ -58,6 +59,7 @@ int collada_import(bContext *C, import_settings.find_chains = find_chains != 0; import_settings.fix_orientation = fix_orientation != 0; import_settings.min_chain_length = min_chain_length; + import_settings.keep_bind_info = keep_bind_info; DocumentImporter imp(C, &import_settings); if (imp.import()) return 1; @@ -87,7 +89,9 @@ int collada_export(Scene *sce, int use_blender_profile, int sort_by_name, BC_export_transformation_type export_transformation_type, - int open_sim) + int open_sim, + + int keep_bind_info) { ExportSettings export_settings; @@ -113,6 +117,7 @@ int collada_export(Scene *sce, export_settings.export_transformation_type = export_transformation_type; export_settings.open_sim = open_sim != 0; + export_settings.keep_bind_info = keep_bind_info; int includeFilter = OB_REL_NONE; if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index a4416608584..09acc4a064b 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -58,7 +58,9 @@ int collada_import(struct bContext *C, int find_chains, int auto_connect, int fix_orientation, - int min_chain_length); + int min_chain_length, + + int keep_bind_info); int collada_export(struct Scene *sce, const char *filepath, @@ -81,9 +83,9 @@ int collada_export(struct Scene *sce, int use_blender_profile, int sort_by_name, BC_export_transformation_type export_transformation_type, - int open_sim); - + int open_sim, + int keep_bind_info); #ifdef __cplusplus } diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 0e185cd93a7..9b12aa6d475 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -97,7 +97,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int use_blender_profile; int sort_by_name; int export_transformation_type; + int open_sim; + int keep_bind_info; int export_count; @@ -148,6 +150,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection"); open_sim = RNA_boolean_get(op->ptr, "open_sim"); + keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info"); + /* get editmode results */ ED_object_editmode_load(CTX_data_edit_object(C)); @@ -172,7 +176,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) use_blender_profile, sort_by_name, export_transformation_type, - open_sim); + + open_sim, + keep_bind_info + ); if (export_count == 0) { BKE_report(op->reports, RPT_WARNING, "No objects selected -- Created empty export file"); @@ -269,6 +276,8 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE); + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE); } @@ -386,6 +395,10 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds"); + + RNA_def_boolean(func, "keep_bind_info", 0, + "Keep Bind Info", "Store Bindpose information in custom bone properties for later use during Collada export"); + } @@ -397,7 +410,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) int find_chains; int auto_connect; int fix_orientation; - int min_chain_length; + int min_chain_length; + + int keep_bind_info; if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); @@ -409,6 +424,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) find_chains = RNA_boolean_get(op->ptr, "find_chains"); auto_connect = RNA_boolean_get(op->ptr, "auto_connect"); fix_orientation = RNA_boolean_get(op->ptr, "fix_orientation"); + + keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info"); + min_chain_length = RNA_int_get(op->ptr, "min_chain_length"); RNA_string_get(op->ptr, "filepath", filename); @@ -418,7 +436,8 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) find_chains, auto_connect, fix_orientation, - min_chain_length)) + min_chain_length, + keep_bind_info) ) { return OPERATOR_FINISHED; } @@ -455,6 +474,13 @@ static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE); + + box = uiLayoutBox(layout); + row = uiLayoutRow(box, false); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE); + } static void wm_collada_import_draw(bContext *UNUSED(C), wmOperator *op) @@ -510,5 +536,9 @@ void WM_OT_collada_import(wmOperatorType *ot) 0, INT_MAX); + RNA_def_boolean(ot->srna, + "keep_bind_info", 0, "Keep Bind Info", + "Store Bindpose information in custom bone properties for later use during Collada export"); + } #endif diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index d4d8e23fdf5..d1ecd912773 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -284,32 +284,34 @@ static void rna_Scene_collada_export( int use_blender_profile, int sort_by_name, int export_transformation_type, - int open_sim) + int open_sim, + int keep_bind_info) { - collada_export(scene, - filepath, + collada_export(scene, + filepath, - apply_modifiers, - export_mesh_type, + apply_modifiers, + export_mesh_type, - selected, - include_children, - include_armatures, - include_shapekeys, - deform_bones_only, + selected, + include_children, + include_armatures, + include_shapekeys, + deform_bones_only, - active_uv_only, - include_uv_textures, - include_material_textures, - use_texture_copies, + active_uv_only, + include_uv_textures, + include_material_textures, + use_texture_copies, - triangulate, - use_object_instantiation, - use_blender_profile, - sort_by_name, + triangulate, + use_object_instantiation, + use_blender_profile, + sort_by_name, - export_transformation_type, - open_sim); + export_transformation_type, + open_sim, + keep_bind_info); } #endif @@ -396,7 +398,6 @@ void RNA_api_scene(StructRNA *srna) RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures"); - RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map", "Export only the selected UV Map"); @@ -409,7 +410,6 @@ void RNA_api_scene(StructRNA *srna) RNA_def_boolean(func, "use_texture_copies", 1, "Copy", "Copy textures to same folder where the .dae file is exported"); - RNA_def_boolean(func, "triangulate", 1, "Triangulate", "Export Polygons (Quads & NGons) as Triangles"); @@ -427,6 +427,10 @@ void RNA_api_scene(StructRNA *srna) RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds"); + + RNA_def_boolean(func, "keep_bind_info", 0, + "Keep Bind Info", "Store Bindpose information in custom bone properties for later use during Collada export"); + #endif #ifdef WITH_ALEMBIC From 7c094f6079aca16b02571c96ee4a4ed30b4d610f Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 23 Mar 2017 12:38:41 +0100 Subject: [PATCH 35/73] Collada - Added some helper functions into collada_utils, for common usage in the collada module --- source/blender/collada/collada_utils.cpp | 232 +++++++++++++++++++++++ source/blender/collada/collada_utils.h | 16 ++ 2 files changed, 248 insertions(+) diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 2efa8b21d81..407f0799014 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -33,6 +33,7 @@ #include "COLLADAFWMeshVertexData.h" #include "collada_utils.h" +#include "ExportSettings.h" extern "C" { #include "DNA_modifier_types.h" @@ -352,6 +353,28 @@ void bc_match_scale(std::vector *objects_done, } } +/* + Convenience function to get only the needed components of a matrix +*/ +void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size) +{ + if (size) { + mat4_to_size(size, mat); + } + + if (eul) { + mat4_to_eul(eul, mat); + } + + if (quat) { + mat4_to_quat(quat, mat); + } + + if (loc) { + copy_v3_v3(loc, mat[3]); + } +} + void bc_triangulate_mesh(Mesh *me) { bool use_beauty = false; @@ -612,3 +635,212 @@ int BoneExtended::get_use_connect() { return this->use_connect; } + +/** +* Stores a 4*4 matrix as a custom bone property array of size 16 +*/ +void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]) +{ + IDProperty *idgroup = (IDProperty *)ebone->prop; + if (idgroup == NULL) + { + IDPropertyTemplate val = { 0 }; + idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); + ebone->prop = idgroup; + } + + IDPropertyTemplate val = { 0 }; + val.array.len = 16; + val.array.type = IDP_FLOAT; + + IDProperty *data = IDP_New(IDP_ARRAY, &val, key); + float *array = (float *)IDP_Array(data); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + array[4 * i + j] = mat[i][j]; + + IDP_AddToGroup(idgroup, data); +} + +#if 0 +/** +* Stores a Float value as a custom bone property +* +* Note: This function is currently not needed. Keep for future usage +*/ +static void bc_set_IDProperty(EditBone *ebone, const char *key, float value) +{ + if (ebone->prop == NULL) + { + IDPropertyTemplate val = { 0 }; + ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); + } + + IDProperty *pgroup = (IDProperty *)ebone->prop; + IDPropertyTemplate val = { 0 }; + IDProperty *prop = IDP_New(IDP_FLOAT, &val, key); + IDP_Float(prop) = value; + IDP_AddToGroup(pgroup, prop); + +} +#endif + +/* +* Get a custom property when it exists. +* This function is also used to check if a property exists. +*/ +IDProperty *bc_get_IDProperty(Bone *bone, std::string key) +{ + return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str()); +} + +/** +* Read a custom bone property and convert to float +* Return def if the property does not exist. +*/ +float bc_get_property(Bone *bone, std::string key, float def) +{ + float result = def; + IDProperty *property = bc_get_IDProperty(bone, key); + if (property) { + switch (property->type) { + case IDP_INT: + result = (float)(IDP_Int(property)); + break; + case IDP_FLOAT: + result = (float)(IDP_Float(property)); + break; + case IDP_DOUBLE: + result = (float)(IDP_Double(property)); + break; + default: + result = def; + } + } + return result; +} + +/** +* Read a custom bone property and convert to matrix +* Return true if conversion was succesfull +* +* Return false if: +* - the property does not exist +* - is not an array of size 16 +*/ +bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]) +{ + IDProperty *property = bc_get_IDProperty(bone, key); + if (property && property->type == IDP_ARRAY && property->len == 16) { + float *array = (float *)IDP_Array(property); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + mat[i][j] = array[4 * i + j]; + return true; + } + return false; +} + +/** +* get a vector that is stored in 3 custom properties (used in Blender <= 2.78) +*/ +void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]) +{ + val[0] = bc_get_property(bone, key + "_x", def[0]); + val[1] = bc_get_property(bone, key + "_y", def[1]); + val[2] = bc_get_property(bone, key + "_z", def[2]); +} + +/** +* Check if vector exist stored in 3 custom properties (used in Blender <= 2.78) +*/ +static bool has_custom_props(Bone *bone, bool enabled, std::string key) +{ + if (!enabled) + return false; + + return (bc_get_IDProperty(bone, key + "_x") + || bc_get_IDProperty(bone, key + "_y") + || bc_get_IDProperty(bone, key + "_z")); + +} + +/** +* Check if custom information about bind matrix exists and modify the from_mat +* accordingly. +* +* Note: This is old style for Blender <= 2.78 only kept for compatibility +*/ +void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space) +{ + float loc[3]; + float rot[3]; + float scale[3]; + static const float V0[3] = { 0, 0, 0 }; + + if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") && + !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") && + !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale")) + { + /* No need */ + copy_m4_m4(to_mat, from_mat); + return; + } + + bc_decompose(from_mat, loc, rot, NULL, scale); + loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); + + if (export_settings->keep_bind_info) { + bc_get_property_vector(bone, "restpose_loc", loc, loc); + + if (use_local_space && bone->parent) { + Bone *b = bone; + while (b->parent) { + b = b->parent; + float ploc[3]; + bc_get_property_vector(b, "restpose_loc", ploc, V0); + loc[0] += ploc[0]; + loc[1] += ploc[1]; + loc[2] += ploc[2]; + } + } + } + + if (export_settings->keep_bind_info) { + if (bc_get_IDProperty(bone, "restpose_rot_x")) + rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0)); + if (bc_get_IDProperty(bone, "restpose_rot_y")) + rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0)); + if (bc_get_IDProperty(bone, "restpose_rot_z")) + rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0)); + } + + if (export_settings->keep_bind_info) { + bc_get_property_vector(bone, "restpose_scale", scale, scale); + } + + loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); + +} + +/* + To get rid of those lengthy float values which make the numbers unreadable. +*/ +float bc_sanitize_float(float value, float precision) +{ + float result = floor((value * pow(10, precision) + 0.5)) / pow(10, precision); + if (abs(result) < 1 / pow(10, precision)) { + result = 0; + } + return result; +} + +/* + Make 4*4 matrices better readable +*/ +void bc_sanitize_mat(float mat[4][4], float precision) +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + mat[i][j] = bc_sanitize_float(mat[i][j], precision); +} \ No newline at end of file diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 7fdbef3b6cb..b98f8bfb188 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -53,8 +53,10 @@ extern "C" { #include "BKE_object.h" #include "BKE_DerivedMesh.h" #include "BKE_scene.h" +#include "BKE_idprop.h" } +#include "ImportSettings.h" #include "ExportSettings.h" #include "collada_internal.h" @@ -88,11 +90,25 @@ extern std::string bc_url_encode(std::string data); extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene); extern void bc_match_scale(std::vector *objects_done, UnitConverter &unit_converter, bool scale_to_scene); +extern void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size); + extern void bc_triangulate_mesh(Mesh *me); extern bool bc_is_leaf_bone(Bone *bone); extern EditBone *bc_get_edit_bone(bArmature * armature, char *name); extern int bc_set_layer(int bitfield, int layer, bool enable); extern int bc_set_layer(int bitfield, int layer); +extern float bc_sanitize_float(float value, float precision); +extern void bc_sanitize_mat(float mat[4][4], float precision); + +extern IDProperty *bc_get_IDProperty(Bone *bone, std::string key); +extern void bc_set_IDProperty(EditBone *ebone, const char *key, float value); +extern void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]); + +extern float bc_get_property(Bone *bone, std::string key, float def); +extern void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]); +extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]); + +extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space); class BCPolygonNormalsIndices { From 6cfa9629861b44b6f5438047502a9a72ded66938 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 23 Mar 2017 12:45:40 +0100 Subject: [PATCH 36/73] Collada - removed TransformBase baseclass (not needed for anything) --- source/blender/collada/AnimationImporter.cpp | 2 +- source/blender/collada/TransformReader.h | 2 +- source/blender/collada/TransformWriter.cpp | 7 +++---- source/blender/collada/TransformWriter.h | 3 ++- source/blender/collada/collada_internal.cpp | 12 ------------ source/blender/collada/collada_internal.h | 6 ------ 6 files changed, 7 insertions(+), 25 deletions(-) diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 3801c9300df..bd47ee0214d 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -1934,7 +1934,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No mul_m4_m4m4(mat, ipar, temp); } - TransformBase::decompose(mat, job->loc, NULL, job->quat, job->size); + bc_decompose(mat, job->loc, NULL, job->quat, job->size); if (par_job) { job->parent = par_job; diff --git a/source/blender/collada/TransformReader.h b/source/blender/collada/TransformReader.h index c598c466c9b..08bb17ccac1 100644 --- a/source/blender/collada/TransformReader.h +++ b/source/blender/collada/TransformReader.h @@ -43,7 +43,7 @@ //struct Object; -class TransformReader : public TransformBase +class TransformReader { protected: diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index 908111ebae6..b7eeff3b074 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -27,11 +27,10 @@ #include "BKE_object.h" +#include "BLI_math.h" #include "TransformWriter.h" -#include "BLI_math.h" - void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]) { float loc[3], rot[3], scale[3]; @@ -51,7 +50,7 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], converter->mat4_to_dae_double(dmat, local); delete converter; - TransformBase::decompose(local, loc, rot, NULL, scale); + bc_decompose(local, loc, rot, NULL, scale); if (node.getType() == COLLADASW::Node::JOINT) { // XXX Why are joints handled differently ? @@ -116,7 +115,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B case BC_TRANSFORMATION_TYPE_TRANSROTLOC: { float loc[3], rot[3], scale[3]; - TransformBase::decompose(f_obmat, loc, rot, NULL, scale); + bc_decompose(f_obmat, loc, rot, NULL, scale); add_transform(node, loc, rot, scale); break; } diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h index 7f69a4b9c95..5bb13d4aac9 100644 --- a/source/blender/collada/TransformWriter.h +++ b/source/blender/collada/TransformWriter.h @@ -33,9 +33,10 @@ #include "DNA_object_types.h" #include "collada_internal.h" +#include "collada_utils.h" #include "collada.h" -class TransformWriter : protected TransformBase +class TransformWriter { protected: void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]); diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp index 70b44ebc222..6ebde6bd773 100644 --- a/source/blender/collada/collada_internal.cpp +++ b/source/blender/collada/collada_internal.cpp @@ -162,18 +162,6 @@ void UnitConverter::calculate_scale(Scene &sce) size_to_mat4(scale_mat4, rescale); } -void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size) -{ - mat4_to_size(size, mat); - if (eul) { - mat4_to_eul(eul, mat); - } - if (quat) { - mat4_to_quat(quat, mat); - } - copy_v3_v3(loc, mat[3]); -} - /** * Translation map. * Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h index 482dbf9ab31..1c7aa160f57 100644 --- a/source/blender/collada/collada_internal.h +++ b/source/blender/collada/collada_internal.h @@ -85,12 +85,6 @@ public: }; -class TransformBase -{ -public: - void decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size); -}; - extern void clear_global_id_map(); /** Look at documentation of translate_map */ extern std::string translate_id(const std::string &id); From 51d4743033a39a90e60cdad3dd30ffa834d999de Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 23 Mar 2017 12:53:56 +0100 Subject: [PATCH 37/73] Collada - Added support for custom bind matrix (using new bind_mat custom property) --- source/blender/collada/ControllerExporter.cpp | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index a868adc1e66..62a474b5181 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -580,30 +580,35 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas float world[4][4]; float inv_bind_mat[4][4]; + float bind_mat[4][4]; /* derived from bone->arm_mat */ + + bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat); - // SL/OPEN_SIM COMPATIBILITY - if (export_settings->open_sim) { - // Only translations, no rotation vs armature - float temp[4][4]; - unit_m4(temp); - copy_v3_v3(temp[3], pchan->bone->arm_mat[3]); - mul_m4_m4m4(world, ob_arm->obmat, temp); + if (!has_bindmat) { - // Add Maya restpose matrix (if defined as properties) - float restpose_mat[4][4]; - create_restpose_mat(pchan->bone, restpose_mat); - mul_m4_m4m4(world, world, restpose_mat); + /* Have no bind matrix stored, try old style <= Blender 2.78 */ - } - else { - // make world-space matrix, arm_mat is armature-space - mul_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat); + bc_create_restpose_mat(this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true); + + // SL/OPEN_SIM COMPATIBILITY + if (export_settings->open_sim) { + + float loc[3]; + float rot[3] = { 0, 0, 0 }; + float scale[3]; + bc_decompose(bind_mat, loc, NULL, NULL, scale); + + // Only translations, no rotation vs armature + loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6); + } } + // make world-space matrix (bind_mat is armature-space) + mul_m4_m4m4(world, ob_arm->obmat, bind_mat); invert_m4_m4(mat, world); converter.mat4_to_dae(inv_bind_mat, mat); - + bc_sanitize_mat(inv_bind_mat, 6); // XXX: Make this optional ? source.appendValues(inv_bind_mat); } } From 476f5c473ac752d58922e1fefbcbb5e8078d178d Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 23 Mar 2017 14:09:00 +0100 Subject: [PATCH 38/73] Collada - remove no longer used functions (moved to collada_utils) --- source/blender/collada/ControllerExporter.cpp | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 62a474b5181..5444c9dfa6b 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -463,81 +463,6 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defb return source_id; } -static float get_property(Bone *bone, const char *key, float def) -{ - float result = def; - if (bone->prop) { - IDProperty *property = IDP_GetPropertyFromGroup(bone->prop, key); - if (property) { - switch (property->type) { - case IDP_INT: - result = (float)(IDP_Int(property)); - break; - case IDP_FLOAT: - result = (float)(IDP_Float(property)); - break; - case IDP_DOUBLE: - result = (float)(IDP_Double(property)); - break; - default: - result = def; - } - } - } - return result; -} - -/** - * This function creates an arbitrary rest pose matrix from - * data provided as custom properties. This is a workaround - * for support of maya's restpose matrix which can be arbitrary - * in opposition to Blender where the Rest pose Matrix is always - * the Identity matrix. - * - * The custom properties are: - * - * restpose_scale_x - * restpose_scale_y - * restpose_scale_z - * - * restpose_rot_x - * restpose_rot_y - * restpose_rot_z - * - * restpose_loc_x - * restpose_loc_y - * restpose_loc_z - * - * The matrix is only setup if the scale AND the rot properties are defined. - * The presence of the loc properties is optional. - * - * This feature has been implemented to support Second Life "Fitted Mesh" - * TODO: Check if an arbitrary rest pose matrix makes sense within Blender. - * Eventually leverage the custom property data into an "official" - * Edit_bone Property - */ -static void create_restpose_mat(Bone *bone, float mat[4][4]) -{ - float loc[3] = { - get_property(bone, "restpose_loc_x", 0.0), - get_property(bone, "restpose_loc_y", 0.0), - get_property(bone, "restpose_loc_z", 0.0) - }; - - float rot[3] = { - DEG2RADF(get_property(bone, "restpose_rot_x", 0.0)), - DEG2RADF(get_property(bone, "restpose_rot_y", 0.0)), - DEG2RADF(get_property(bone, "restpose_rot_z", 0.0)) - }; - - float scale[3] = { - get_property(bone, "restpose_scale_x", 1.0), - get_property(bone, "restpose_scale_y", 1.0), - get_property(bone, "restpose_scale_z", 1.0) - }; - - loc_eulO_size_to_mat4(mat, loc, rot, scale, 6); -} std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) { From b48ba0909a2a609fadc91e9f6e1c031b99e6464e Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 23 Mar 2017 14:10:57 +0100 Subject: [PATCH 39/73] Collada - Import: now add bind_mat and rest_mat as custom properties (when the use_bind_info option is enabled) --- source/blender/collada/ArmatureImporter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 2e4a7dfebc7..0ea8324ed7c 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -42,6 +42,7 @@ extern "C" { #include "ED_armature.h" } +#include "collada_utils.h" #include "ArmatureImporter.h" // use node name, or fall back to original id if not present (name is optional) @@ -171,7 +172,8 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon { float rest_mat[4][4]; get_node_mat(rest_mat, node, NULL, NULL, NULL); - bc_create_bindpose_properties(this->import_settings, bone, joint_bind_mat, rest_mat); + bc_set_IDPropertyMatrix(bone, "bind_mat", joint_bind_mat); + bc_set_IDPropertyMatrix(bone, "rest_mat", rest_mat); } add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero From 2c78b0c71fc0a31016d081ee6a5a8fafc27c48cd Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 23 Mar 2017 14:11:55 +0100 Subject: [PATCH 40/73] Collada - Export: now use bind_mat and rest_mat custom properties (when the use_bind_info option is enabled and the properties exist) --- source/blender/collada/ArmatureExporter.cpp | 74 ++++++++++++--------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 40065956ecb..49722873a91 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -256,47 +256,57 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW: //bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); float mat[4][4]; + float bone_rest_mat[4][4]; /* derived from bone->arm_mat */ + float parent_rest_mat[4][4]; /* derived from bone->parent->arm_mat */ - if (bone->parent) { - // get bone-space matrix from parent pose - /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); - float invpar[4][4]; - invert_m4_m4(invpar, parchan->pose_mat); - mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/ + bool has_restmat = bc_get_property_matrix(bone, "rest_mat", mat); + + if (!has_restmat) { + + /* Have no restpose matrix stored, try old style <= Blender 2.78 */ - float invpar[4][4]; - invert_m4_m4(invpar, bone->parent->arm_mat); - mul_m4_m4m4(mat, invpar, bone->arm_mat); - - } - else { - - //copy_m4_m4(mat, pchan->pose_mat); - //pose mat is object space - //New change: export bone->arm_mat - copy_m4_m4(mat, bone->arm_mat); - } - - // OPEN_SIM_COMPATIBILITY - if (export_settings->open_sim) { - // Remove rotations vs armature from transform - // parent_rest_rot * mat * irest_rot - float temp[4][4]; - copy_m4_m4(temp, bone->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - invert_m4(temp); - - mul_m4_m4m4(mat, mat, temp); + bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true); if (bone->parent) { - copy_m4_m4(temp, bone->parent->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + // get bone-space matrix from parent pose + /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); + float invpar[4][4]; + invert_m4_m4(invpar, parchan->pose_mat); + mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/ + float invpar[4][4]; + bc_create_restpose_mat(this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true); - mul_m4_m4m4(mat, temp, mat); + invert_m4_m4(invpar, parent_rest_mat); + mul_m4_m4m4(mat, invpar, bone_rest_mat); + + } + else { + copy_m4_m4(mat, bone_rest_mat); + } + + // OPEN_SIM_COMPATIBILITY + if (export_settings->open_sim) { + // Remove rotations vs armature from transform + // parent_rest_rot * mat * irest_rot + float temp[4][4]; + copy_m4_m4(temp, bone_rest_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + invert_m4(temp); + + mul_m4_m4m4(mat, mat, temp); + + if (bone->parent) { + copy_m4_m4(temp, parent_rest_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + + mul_m4_m4m4(mat, temp, mat); + } } } + bc_sanitize_mat(mat, 6); // XXX: Make this optional ? TransformWriter::add_node_transform(node, mat, NULL); + } std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob) From e04970b392cdce4cf7b2d89b6cb3e7b623629103 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Thu, 23 Mar 2017 15:47:23 +0100 Subject: [PATCH 41/73] Fix player stubs (tm) --- source/blenderplayer/bad_level_call_stubs/stubs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 3b07d0acf5a..d659f5c1a8a 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -737,7 +737,8 @@ int collada_export(struct Scene *sce, int use_blender_profile, int sort_by_name, BC_export_transformation_type export_transformation_type, - int open_sim) RET_ZERO + int open_sim, + int keep_bind_info) RET_ZERO void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly) RET_NONE From 5c06ff8bb96d014dda33874d357ecb4652558998 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 12:04:49 +0100 Subject: [PATCH 42/73] Cycles: Cleanup, remove unused function --- intern/cycles/util/util_math.h | 43 ---------------------------------- 1 file changed, 43 deletions(-) diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 27d4ae510c7..da18ae907a0 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1514,49 +1514,6 @@ ccl_device bool ray_aligned_disk_intersect( return true; } -ccl_device bool ray_triangle_intersect( - float3 ray_P, float3 ray_D, float ray_t, - float3 v0, float3 v1, float3 v2, - float3 *isect_P, float *isect_t) -{ - /* Calculate intersection */ - float3 e1 = v1 - v0; - float3 e2 = v2 - v0; - float3 s1 = cross(ray_D, e2); - - const float divisor = dot(s1, e1); - if(UNLIKELY(divisor == 0.0f)) - return false; - - const float invdivisor = 1.0f/divisor; - - /* compute first barycentric coordinate */ - const float3 d = ray_P - v0; - const float u = dot(d, s1)*invdivisor; - if(u < 0.0f) - return false; - - /* Compute second barycentric coordinate */ - const float3 s2 = cross(d, e1); - const float v = dot(ray_D, s2)*invdivisor; - if(v < 0.0f) - return false; - - const float b0 = 1.0f - u - v; - if(b0 < 0.0f) - return false; - - /* compute t to intersection point */ - const float t = dot(e2, s2)*invdivisor; - if(t < 0.0f || t > ray_t) - return false; - - *isect_t = t; - *isect_P = ray_P + ray_D*t; - - return true; -} - ccl_device_inline bool ray_triangle_intersect_uv( float3 ray_P, float3 ray_D, float ray_t, float3 v0, float3 v1, float3 v2, From e8ff06186ee031e67e554467ced7cd16ac34af94 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 12:41:33 +0100 Subject: [PATCH 43/73] Cycles: Cleanup, inline AVX register construction from kernel global data Currently should be no functional changes, preparing for some upcoming refactor. --- intern/cycles/kernel/geom/geom_triangle_intersect.h | 5 +++-- intern/cycles/kernel/kernel_compat_cpu.h | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 4d234dd62bd..4f4ee93c077 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -123,8 +123,9 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, #if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) const avxf avxf_P(P.m128, P.m128); - const avxf tri_ab = kernel_tex_fetch_avxf(__prim_tri_verts, tri_vindex + 0); - const avxf tri_bc = kernel_tex_fetch_avxf(__prim_tri_verts, tri_vindex + 1); + const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex]; + const avxf tri_ab = _mm256_loadu_ps((float *)(ssef_verts)); + const avxf tri_bc = _mm256_loadu_ps((float *)(ssef_verts + 1)); const avxf AB = tri_ab - avxf_P; const avxf BC = tri_bc - avxf_P; diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index e347a1eca18..96276f313f8 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -87,9 +87,9 @@ template struct texture { ccl_always_inline avxf fetch_avxf(const int index) { kernel_assert(index >= 0 && (index+1) < width); - ssef *ssefData = (ssef*)data; - ssef *ssefNodeData = &ssefData[index]; - return _mm256_loadu_ps((float *)ssefNodeData); + ssef *ssef_data = (ssef*)data; + ssef *ssef_node_data = &ssef_data[index]; + return _mm256_loadu_ps((float *)ssef_node_data); } #endif From 1c5cceb7afef2666e937cc880bd206efebd0f044 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 12:47:27 +0100 Subject: [PATCH 44/73] Cycles: Move intersection math to own header file There are following benefits: - Modifying intersection algorithm will not cause so much re-compilation. - It works around header dependency hell and allows us to use vectorization types much easier in there. --- intern/cycles/kernel/CMakeLists.txt | 1 + intern/cycles/kernel/kernel_math.h | 1 + intern/cycles/util/CMakeLists.txt | 1 + intern/cycles/util/util_math.h | 135 ------------------- intern/cycles/util/util_math_intersect.h | 158 +++++++++++++++++++++++ 5 files changed, 161 insertions(+), 135 deletions(-) create mode 100644 intern/cycles/util/util_math_intersect.h diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 53c872e829d..8a8c3968c02 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -196,6 +196,7 @@ set(SRC_UTIL_HEADERS ../util/util_hash.h ../util/util_math.h ../util/util_math_fast.h + ../util/util_math_intersect.h ../util/util_static_assert.h ../util/util_transform.h ../util/util_texture.h diff --git a/intern/cycles/kernel/kernel_math.h b/intern/cycles/kernel/kernel_math.h index 9bee5603474..7653fa53247 100644 --- a/intern/cycles/kernel/kernel_math.h +++ b/intern/cycles/kernel/kernel_math.h @@ -20,6 +20,7 @@ #include "util_color.h" #include "util_math.h" #include "util_math_fast.h" +#include "util_math_intersect.h" #include "util_texture.h" #include "util_transform.h" diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index d8abf671bd6..6bd47120482 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -52,6 +52,7 @@ set(SRC_HEADERS util_math.h util_math_cdf.h util_math_fast.h + util_math_intersect.h util_md5.h util_opengl.h util_optimization.h diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index da18ae907a0..329b7f645c5 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1451,140 +1451,6 @@ ccl_device_inline float beta(float x, float y) #endif } -/* Ray Intersection */ - -ccl_device bool ray_sphere_intersect( - float3 ray_P, float3 ray_D, float ray_t, - float3 sphere_P, float sphere_radius, - float3 *isect_P, float *isect_t) -{ - float3 d = sphere_P - ray_P; - float radiussq = sphere_radius*sphere_radius; - float tsq = dot(d, d); - - if(tsq > radiussq) { /* ray origin outside sphere */ - float tp = dot(d, ray_D); - - if(tp < 0.0f) /* dir points away from sphere */ - return false; - - float dsq = tsq - tp*tp; /* pythagoras */ - - if(dsq > radiussq) /* closest point on ray outside sphere */ - return false; - - float t = tp - sqrtf(radiussq - dsq); /* pythagoras */ - - if(t < ray_t) { - *isect_t = t; - *isect_P = ray_P + ray_D*t; - return true; - } - } - - return false; -} - -ccl_device bool ray_aligned_disk_intersect( - float3 ray_P, float3 ray_D, float ray_t, - float3 disk_P, float disk_radius, - float3 *isect_P, float *isect_t) -{ - /* aligned disk normal */ - float disk_t; - float3 disk_N = normalize_len(ray_P - disk_P, &disk_t); - float div = dot(ray_D, disk_N); - - if(UNLIKELY(div == 0.0f)) - return false; - - /* compute t to intersection point */ - float t = -disk_t/div; - if(t < 0.0f || t > ray_t) - return false; - - /* test if within radius */ - float3 P = ray_P + ray_D*t; - if(len_squared(P - disk_P) > disk_radius*disk_radius) - return false; - - *isect_P = P; - *isect_t = t; - - return true; -} - -ccl_device_inline bool ray_triangle_intersect_uv( - float3 ray_P, float3 ray_D, float ray_t, - float3 v0, float3 v1, float3 v2, - float *isect_u, float *isect_v, float *isect_t) -{ - /* Calculate intersection */ - float3 e1 = v1 - v0; - float3 e2 = v2 - v0; - float3 s1 = cross(ray_D, e2); - - const float divisor = dot(s1, e1); - if(UNLIKELY(divisor == 0.0f)) - return false; - - const float invdivisor = 1.0f/divisor; - - /* compute first barycentric coordinate */ - const float3 d = ray_P - v0; - const float u = dot(d, s1)*invdivisor; - if(u < 0.0f) - return false; - - /* Compute second barycentric coordinate */ - const float3 s2 = cross(d, e1); - const float v = dot(ray_D, s2)*invdivisor; - if(v < 0.0f) - return false; - - const float b0 = 1.0f - u - v; - if(b0 < 0.0f) - return false; - - /* compute t to intersection point */ - const float t = dot(e2, s2)*invdivisor; - if(t < 0.0f || t > ray_t) - return false; - - *isect_u = u; - *isect_v = v; - *isect_t = t; - - return true; -} - -ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_mint, float ray_maxt, - float3 quad_P, float3 quad_u, float3 quad_v, float3 quad_n, - float3 *isect_P, float *isect_t, float *isect_u, float *isect_v) -{ - float t = -(dot(ray_P, quad_n) - dot(quad_P, quad_n)) / dot(ray_D, quad_n); - if(t < ray_mint || t > ray_maxt) - return false; - - float3 hit = ray_P + t*ray_D; - float3 inplane = hit - quad_P; - - float u = dot(inplane, quad_u) / dot(quad_u, quad_u) + 0.5f; - if(u < 0.0f || u > 1.0f) - return false; - - float v = dot(inplane, quad_v) / dot(quad_v, quad_v) + 0.5f; - if(v < 0.0f || v > 1.0f) - return false; - - if(isect_P) *isect_P = hit; - if(isect_t) *isect_t = t; - if(isect_u) *isect_u = u; - if(isect_v) *isect_v = v; - - return true; -} - /* projections */ ccl_device_inline float2 map_to_tube(const float3 co) { @@ -1647,4 +1513,3 @@ ccl_device_inline int util_max_axis(float3 vec) CCL_NAMESPACE_END #endif /* __UTIL_MATH_H__ */ - diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h new file mode 100644 index 00000000000..0cf3cbcff97 --- /dev/null +++ b/intern/cycles/util/util_math_intersect.h @@ -0,0 +1,158 @@ +/* + * Copyright 2011-2017 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __UTIL_MATH_INTERSECT_H__ +#define __UTIL_MATH_INTERSECT_H__ + +CCL_NAMESPACE_BEGIN + +/* Ray Intersection */ + +ccl_device bool ray_sphere_intersect( + float3 ray_P, float3 ray_D, float ray_t, + float3 sphere_P, float sphere_radius, + float3 *isect_P, float *isect_t) +{ + float3 d = sphere_P - ray_P; + float radiussq = sphere_radius*sphere_radius; + float tsq = dot(d, d); + + if(tsq > radiussq) { /* ray origin outside sphere */ + float tp = dot(d, ray_D); + + if(tp < 0.0f) /* dir points away from sphere */ + return false; + + float dsq = tsq - tp*tp; /* pythagoras */ + + if(dsq > radiussq) /* closest point on ray outside sphere */ + return false; + + float t = tp - sqrtf(radiussq - dsq); /* pythagoras */ + + if(t < ray_t) { + *isect_t = t; + *isect_P = ray_P + ray_D*t; + return true; + } + } + + return false; +} + +ccl_device bool ray_aligned_disk_intersect( + float3 ray_P, float3 ray_D, float ray_t, + float3 disk_P, float disk_radius, + float3 *isect_P, float *isect_t) +{ + /* aligned disk normal */ + float disk_t; + float3 disk_N = normalize_len(ray_P - disk_P, &disk_t); + float div = dot(ray_D, disk_N); + + if(UNLIKELY(div == 0.0f)) + return false; + + /* compute t to intersection point */ + float t = -disk_t/div; + if(t < 0.0f || t > ray_t) + return false; + + /* test if within radius */ + float3 P = ray_P + ray_D*t; + if(len_squared(P - disk_P) > disk_radius*disk_radius) + return false; + + *isect_P = P; + *isect_t = t; + + return true; +} + +ccl_device_inline bool ray_triangle_intersect_uv( + float3 ray_P, float3 ray_D, float ray_t, + float3 v0, float3 v1, float3 v2, + float *isect_u, float *isect_v, float *isect_t) +{ + /* Calculate intersection */ + float3 e1 = v1 - v0; + float3 e2 = v2 - v0; + float3 s1 = cross(ray_D, e2); + + const float divisor = dot(s1, e1); + if(UNLIKELY(divisor == 0.0f)) + return false; + + const float invdivisor = 1.0f/divisor; + + /* compute first barycentric coordinate */ + const float3 d = ray_P - v0; + const float u = dot(d, s1)*invdivisor; + if(u < 0.0f) + return false; + + /* Compute second barycentric coordinate */ + const float3 s2 = cross(d, e1); + const float v = dot(ray_D, s2)*invdivisor; + if(v < 0.0f) + return false; + + const float b0 = 1.0f - u - v; + if(b0 < 0.0f) + return false; + + /* compute t to intersection point */ + const float t = dot(e2, s2)*invdivisor; + if(t < 0.0f || t > ray_t) + return false; + + *isect_u = u; + *isect_v = v; + *isect_t = t; + + return true; +} + +ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_mint, float ray_maxt, + float3 quad_P, float3 quad_u, float3 quad_v, float3 quad_n, + float3 *isect_P, float *isect_t, float *isect_u, float *isect_v) +{ + float t = -(dot(ray_P, quad_n) - dot(quad_P, quad_n)) / dot(ray_D, quad_n); + if(t < ray_mint || t > ray_maxt) + return false; + + float3 hit = ray_P + t*ray_D; + float3 inplane = hit - quad_P; + + float u = dot(inplane, quad_u) / dot(quad_u, quad_u) + 0.5f; + if(u < 0.0f || u > 1.0f) + return false; + + float v = dot(inplane, quad_v) / dot(quad_v, quad_v) + 0.5f; + if(v < 0.0f || v > 1.0f) + return false; + + if(isect_P) *isect_P = hit; + if(isect_t) *isect_t = t; + if(isect_u) *isect_u = u; + if(isect_v) *isect_v = v; + + return true; +} + +CCL_NAMESPACE_END + +#endif /* __UTIL_MATH_INTERSECT_H__ */ From aa0602130bef65a11d068db7f3641a6f51fd3427 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 12:53:45 +0100 Subject: [PATCH 45/73] Cycles: Cleanup, code style and comments --- intern/cycles/util/util_math_intersect.h | 152 +++++++++++------------ 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h index 0cf3cbcff97..870f33cee0c 100644 --- a/intern/cycles/util/util_math_intersect.h +++ b/intern/cycles/util/util_math_intersect.h @@ -22,63 +22,60 @@ CCL_NAMESPACE_BEGIN /* Ray Intersection */ ccl_device bool ray_sphere_intersect( - float3 ray_P, float3 ray_D, float ray_t, - float3 sphere_P, float sphere_radius, - float3 *isect_P, float *isect_t) + float3 ray_P, float3 ray_D, float ray_t, + float3 sphere_P, float sphere_radius, + float3 *isect_P, float *isect_t) { - float3 d = sphere_P - ray_P; - float radiussq = sphere_radius*sphere_radius; - float tsq = dot(d, d); + const float3 d = sphere_P - ray_P; + const float radiussq = sphere_radius*sphere_radius; + const float tsq = dot(d, d); - if(tsq > radiussq) { /* ray origin outside sphere */ - float tp = dot(d, ray_D); - - if(tp < 0.0f) /* dir points away from sphere */ + if(tsq > radiussq) { + /* Ray origin outside sphere. */ + const float tp = dot(d, ray_D); + if(tp < 0.0f) { + /* Ray points away from sphere. */ return false; - - float dsq = tsq - tp*tp; /* pythagoras */ - - if(dsq > radiussq) /* closest point on ray outside sphere */ + } + const float dsq = tsq - tp*tp; /* pythagoras */ + if(dsq > radiussq) { + /* Closest point on ray outside sphere. */ return false; - - float t = tp - sqrtf(radiussq - dsq); /* pythagoras */ - + } + const float t = tp - sqrtf(radiussq - dsq); /* pythagoras */ if(t < ray_t) { *isect_t = t; *isect_P = ray_P + ray_D*t; return true; } } - return false; } ccl_device bool ray_aligned_disk_intersect( - float3 ray_P, float3 ray_D, float ray_t, - float3 disk_P, float disk_radius, - float3 *isect_P, float *isect_t) + float3 ray_P, float3 ray_D, float ray_t, + float3 disk_P, float disk_radius, + float3 *isect_P, float *isect_t) { - /* aligned disk normal */ + /* Aligned disk normal. */ float disk_t; - float3 disk_N = normalize_len(ray_P - disk_P, &disk_t); - float div = dot(ray_D, disk_N); - - if(UNLIKELY(div == 0.0f)) + const float3 disk_N = normalize_len(ray_P - disk_P, &disk_t); + const float div = dot(ray_D, disk_N); + if(UNLIKELY(div == 0.0f)) { return false; - - /* compute t to intersection point */ - float t = -disk_t/div; - if(t < 0.0f || t > ray_t) + } + /* Compute t to intersection point. */ + const float t = -disk_t/div; + if(t < 0.0f || t > ray_t) { return false; - - /* test if within radius */ + } + /* Test if within radius. */ float3 P = ray_P + ray_D*t; - if(len_squared(P - disk_P) > disk_radius*disk_radius) + if(len_squared(P - disk_P) > disk_radius*disk_radius) { return false; - + } *isect_P = P; *isect_t = t; - return true; } @@ -87,69 +84,72 @@ ccl_device_inline bool ray_triangle_intersect_uv( float3 v0, float3 v1, float3 v2, float *isect_u, float *isect_v, float *isect_t) { - /* Calculate intersection */ - float3 e1 = v1 - v0; - float3 e2 = v2 - v0; - float3 s1 = cross(ray_D, e2); + /* Calculate intersection. */ + const float3 e1 = v1 - v0; + const float3 e2 = v2 - v0; + const float3 s1 = cross(ray_D, e2); const float divisor = dot(s1, e1); - if(UNLIKELY(divisor == 0.0f)) + if(UNLIKELY(divisor == 0.0f)) { return false; + } + const float inv_divisor = 1.0f/divisor; - const float invdivisor = 1.0f/divisor; - - /* compute first barycentric coordinate */ + /* Compute first barycentric coordinate. */ const float3 d = ray_P - v0; - const float u = dot(d, s1)*invdivisor; - if(u < 0.0f) + const float u = dot(d, s1)*inv_divisor; + if(u < 0.0f) { return false; - - /* Compute second barycentric coordinate */ + } + /* Compute second barycentric coordinate. */ const float3 s2 = cross(d, e1); - const float v = dot(ray_D, s2)*invdivisor; - if(v < 0.0f) + const float v = dot(ray_D, s2)*inv_divisor; + if(v < 0.0f) { return false; - + } const float b0 = 1.0f - u - v; - if(b0 < 0.0f) + if(b0 < 0.0f) { return false; - - /* compute t to intersection point */ - const float t = dot(e2, s2)*invdivisor; - if(t < 0.0f || t > ray_t) + } + /* Compute distance to intersection point. */ + const float t = dot(e2, s2)*inv_divisor; + if(t < 0.0f || t > ray_t) { return false; - + } *isect_u = u; *isect_v = v; *isect_t = t; - return true; } -ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_mint, float ray_maxt, - float3 quad_P, float3 quad_u, float3 quad_v, float3 quad_n, - float3 *isect_P, float *isect_t, float *isect_u, float *isect_v) +ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, + float ray_mint, float ray_maxt, + float3 quad_P, + float3 quad_u, float3 quad_v, float3 quad_n, + float3 *isect_P, float *isect_t, + float *isect_u, float *isect_v) { + /* Perform intersection test. */ float t = -(dot(ray_P, quad_n) - dot(quad_P, quad_n)) / dot(ray_D, quad_n); - if(t < ray_mint || t > ray_maxt) + if(t < ray_mint || t > ray_maxt) { return false; - - float3 hit = ray_P + t*ray_D; - float3 inplane = hit - quad_P; - - float u = dot(inplane, quad_u) / dot(quad_u, quad_u) + 0.5f; - if(u < 0.0f || u > 1.0f) + } + const float3 hit = ray_P + t*ray_D; + const float3 inplane = hit - quad_P; + const float u = dot(inplane, quad_u) / dot(quad_u, quad_u) + 0.5f; + if(u < 0.0f || u > 1.0f) { return false; - - float v = dot(inplane, quad_v) / dot(quad_v, quad_v) + 0.5f; - if(v < 0.0f || v > 1.0f) + } + const float v = dot(inplane, quad_v) / dot(quad_v, quad_v) + 0.5f; + if(v < 0.0f || v > 1.0f) { return false; - - if(isect_P) *isect_P = hit; - if(isect_t) *isect_t = t; - if(isect_u) *isect_u = u; - if(isect_v) *isect_v = v; - + } + /* Store the result. */ + /* TODO(sergey): Check whether we can avoid some checks here. */ + if(isect_P != NULL) *isect_P = hit; + if(isect_t != NULL) *isect_t = t; + if(isect_u != NULL) *isect_u = u; + if(isect_v != NULL) *isect_v = v; return true; } From b797a5ff7849b6c32c7aefeccbf52445c9ccc597 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 12:55:51 +0100 Subject: [PATCH 46/73] Cycles: Cleanup, move utility function to utility file Was an old TODO, this function is handy for some math utilities as well. --- intern/cycles/kernel/geom/geom_triangle_intersect.h | 6 ------ intern/cycles/util/util_math.h | 5 +++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 4f4ee93c077..ca6e54c6b33 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -96,12 +96,6 @@ void triangle_intersect_precalc(float3 dir, isect_precalc->kz = kz; } -/* TODO(sergey): Make it general utility function. */ -ccl_device_inline float xor_signmask(float x, int y) -{ - return __int_as_float(__float_as_int(x) ^ y); -} - ccl_device_inline bool triangle_intersect(KernelGlobals *kg, const IsectPrecalc *isect_precalc, Intersection *isect, diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 329b7f645c5..a41beab6285 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1451,6 +1451,11 @@ ccl_device_inline float beta(float x, float y) #endif } +ccl_device_inline float xor_signmask(float x, int y) +{ + return __int_as_float(__float_as_int(x) ^ y); +} + /* projections */ ccl_device_inline float2 map_to_tube(const float3 co) { From f8a999c965435ed6cf3ed83aa4f1121c79f2a403 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 13:01:42 +0100 Subject: [PATCH 47/73] Cycles: Move triangle intersection precalc to an util file This is a preparation work for the followup commit which wil l move remaining parts of Woop intersection logic to an utility file. Doing it as a separate commit to keep changes more atomic and easier to bisect when/if needed. --- intern/cycles/kernel/bvh/bvh_shadow_all.h | 10 +-- intern/cycles/kernel/bvh/bvh_subsurface.h | 4 +- intern/cycles/kernel/bvh/bvh_traversal.h | 8 +- intern/cycles/kernel/bvh/bvh_volume.h | 8 +- intern/cycles/kernel/bvh/bvh_volume_all.h | 10 +-- intern/cycles/kernel/bvh/qbvh_shadow_all.h | 8 +- intern/cycles/kernel/bvh/qbvh_subsurface.h | 4 +- intern/cycles/kernel/bvh/qbvh_traversal.h | 8 +- intern/cycles/kernel/bvh/qbvh_volume.h | 8 +- intern/cycles/kernel/bvh/qbvh_volume_all.h | 8 +- .../kernel/geom/geom_triangle_intersect.h | 60 +-------------- intern/cycles/util/util_math_intersect.h | 76 +++++++++++++++++++ 12 files changed, 116 insertions(+), 96 deletions(-) diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h index b4f65bc8efd..a6e23d9f381 100644 --- a/intern/cycles/kernel/bvh/bvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h @@ -100,8 +100,8 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif /* __KERNEL_SSE2__ */ - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { @@ -314,7 +314,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); num_hits_in_instance = 0; isect_array->t = isect_t; @@ -354,7 +354,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); /* scale isect->t to adjust for instancing */ for(int i = 0; i < num_hits_in_instance; i++) { @@ -367,7 +367,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); } isect_t = tmax; diff --git a/intern/cycles/kernel/bvh/bvh_subsurface.h b/intern/cycles/kernel/bvh/bvh_subsurface.h index 583f7f7c469..11ea1f89c8b 100644 --- a/intern/cycles/kernel/bvh/bvh_subsurface.h +++ b/intern/cycles/kernel/bvh/bvh_subsurface.h @@ -109,8 +109,8 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { diff --git a/intern/cycles/kernel/bvh/bvh_traversal.h b/intern/cycles/kernel/bvh/bvh_traversal.h index 0eca0c8e38b..7c4671e074f 100644 --- a/intern/cycles/kernel/bvh/bvh_traversal.h +++ b/intern/cycles/kernel/bvh/bvh_traversal.h @@ -104,8 +104,8 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { @@ -358,7 +358,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); # if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); @@ -395,7 +395,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); # if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); diff --git a/intern/cycles/kernel/bvh/bvh_volume.h b/intern/cycles/kernel/bvh/bvh_volume.h index 136034aa484..45b5a3c687b 100644 --- a/intern/cycles/kernel/bvh/bvh_volume.h +++ b/intern/cycles/kernel/bvh/bvh_volume.h @@ -97,8 +97,8 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { @@ -243,7 +243,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); # if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); @@ -286,7 +286,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); # if defined(__KERNEL_SSE2__) Psplat[0] = ssef(P.x); diff --git a/intern/cycles/kernel/bvh/bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h index 6f3346e7634..62018e06e97 100644 --- a/intern/cycles/kernel/bvh/bvh_volume_all.h +++ b/intern/cycles/kernel/bvh/bvh_volume_all.h @@ -101,8 +101,8 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); #endif /* __KERNEL_SSE2__ */ - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* traversal loop */ do { @@ -294,7 +294,7 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); num_hits_in_instance = 0; isect_array->t = isect_t; @@ -340,7 +340,7 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Scale isect->t to adjust for instancing. */ for(int i = 0; i < num_hits_in_instance; i++) { (isect_array-i-1)->t *= t_fac; @@ -352,7 +352,7 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # else bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); } isect_t = tmax; diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h index 2a4da3eea82..5a8ec4768d6 100644 --- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h @@ -96,8 +96,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { @@ -414,7 +414,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); ++stack_ptr; kernel_assert(stack_ptr < BVH_QSTACK_SIZE); @@ -471,7 +471,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); object = OBJECT_NONE; node_addr = traversal_stack[stack_ptr].addr; diff --git a/intern/cycles/kernel/bvh/qbvh_subsurface.h b/intern/cycles/kernel/bvh/qbvh_subsurface.h index a6431a94e6e..d466fe73d24 100644 --- a/intern/cycles/kernel/bvh/qbvh_subsurface.h +++ b/intern/cycles/kernel/bvh/qbvh_subsurface.h @@ -105,8 +105,8 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { diff --git a/intern/cycles/kernel/bvh/qbvh_traversal.h b/intern/cycles/kernel/bvh/qbvh_traversal.h index c20a8f3703f..bf69bfade1b 100644 --- a/intern/cycles/kernel/bvh/qbvh_traversal.h +++ b/intern/cycles/kernel/bvh/qbvh_traversal.h @@ -106,8 +106,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { @@ -447,7 +447,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); ++stack_ptr; kernel_assert(stack_ptr < BVH_QSTACK_SIZE); @@ -489,7 +489,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); object = OBJECT_NONE; node_addr = traversal_stack[stack_ptr].addr; diff --git a/intern/cycles/kernel/bvh/qbvh_volume.h b/intern/cycles/kernel/bvh/qbvh_volume.h index 859c5da808b..d34ddb6ea2b 100644 --- a/intern/cycles/kernel/bvh/qbvh_volume.h +++ b/intern/cycles/kernel/bvh/qbvh_volume.h @@ -91,8 +91,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { @@ -316,7 +316,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); ++stack_ptr; kernel_assert(stack_ptr < BVH_QSTACK_SIZE); @@ -362,7 +362,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); object = OBJECT_NONE; node_addr = traversal_stack[stack_ptr].addr; diff --git a/intern/cycles/kernel/bvh/qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h index bbe588c878f..4e1ee04916b 100644 --- a/intern/cycles/kernel/bvh/qbvh_volume_all.h +++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h @@ -95,8 +95,8 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z); - IsectPrecalc isect_precalc; - triangle_intersect_precalc(dir, &isect_precalc); + TriangleIsectPrecalc isect_precalc; + ray_triangle_intersect_precalc(dir, &isect_precalc); /* Traversal loop. */ do { @@ -367,7 +367,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); num_hits_in_instance = 0; isect_array->t = isect_t; @@ -432,7 +432,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z)); # endif - triangle_intersect_precalc(dir, &isect_precalc); + ray_triangle_intersect_precalc(dir, &isect_precalc); object = OBJECT_NONE; node_addr = traversal_stack[stack_ptr].addr; diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index ca6e54c6b33..12700c7a246 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -40,64 +40,8 @@ CCL_NAMESPACE_BEGIN * http://jcgt.org/published/0002/01/05/paper.pdf */ -/* Precalculated data for the ray->tri intersection. */ -typedef struct IsectPrecalc { - /* Maximal dimension kz, and orthogonal dimensions. */ - int kx, ky, kz; - - /* Shear constants. */ - float Sx, Sy, Sz; -} IsectPrecalc; - -#if (defined(__KERNEL_OPENCL_APPLE__)) || \ - (defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86))) -ccl_device_noinline -#else -ccl_device_inline -#endif -void triangle_intersect_precalc(float3 dir, - IsectPrecalc *isect_precalc) -{ - /* Calculate dimension where the ray direction is maximal. */ -#ifndef __KERNEL_SSE__ - int kz = util_max_axis(make_float3(fabsf(dir.x), - fabsf(dir.y), - fabsf(dir.z))); - int kx = kz + 1; if(kx == 3) kx = 0; - int ky = kx + 1; if(ky == 3) ky = 0; -#else - int kx, ky, kz; - /* Avoiding mispredicted branch on direction. */ - kz = util_max_axis(fabs(dir)); - static const char inc_xaxis[] = {1, 2, 0, 55}; - static const char inc_yaxis[] = {2, 0, 1, 55}; - kx = inc_xaxis[kz]; - ky = inc_yaxis[kz]; -#endif - - float dir_kz = IDX(dir, kz); - - /* Swap kx and ky dimensions to preserve winding direction of triangles. */ - if(dir_kz < 0.0f) { - int tmp = kx; - kx = ky; - ky = tmp; - } - - /* Calculate the shear constants. */ - float inv_dir_z = 1.0f / dir_kz; - isect_precalc->Sx = IDX(dir, kx) * inv_dir_z; - isect_precalc->Sy = IDX(dir, ky) * inv_dir_z; - isect_precalc->Sz = inv_dir_z; - - /* Store the dimensions. */ - isect_precalc->kx = kx; - isect_precalc->ky = ky; - isect_precalc->kz = kz; -} - ccl_device_inline bool triangle_intersect(KernelGlobals *kg, - const IsectPrecalc *isect_precalc, + const TriangleIsectPrecalc *isect_precalc, Intersection *isect, float3 P, uint visibility, @@ -255,7 +199,7 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, #ifdef __SUBSURFACE__ ccl_device_inline void triangle_intersect_subsurface( KernelGlobals *kg, - const IsectPrecalc *isect_precalc, + const TriangleIsectPrecalc *isect_precalc, SubsurfaceIntersection *ss_isect, float3 P, int object, diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h index 870f33cee0c..7e02c04d939 100644 --- a/intern/cycles/util/util_math_intersect.h +++ b/intern/cycles/util/util_math_intersect.h @@ -79,6 +79,82 @@ ccl_device bool ray_aligned_disk_intersect( return true; } +/* Optimized watertight ray-triangle intersection. + * + * Sven Woop + * Watertight Ray/Triangle Intersection + * + * http://jcgt.org/published/0002/01/05/paper.pdf + */ + +/* Precalculated data for the ray->tri intersection. */ +typedef struct TriangleIsectPrecalc { + /* Maximal dimension kz, and orthogonal dimensions. */ + int kx, ky, kz; + + /* Shear constants. */ + float Sx, Sy, Sz; +} TriangleIsectPrecalc; + +/* Workaround stupidness of CUDA/OpenCL which doesn't allow to access indexed + * component of float3 value. + */ +#ifdef __KERNEL_GPU__ +# define IDX(vec, idx) \ + ((idx == 0) ? ((vec).x) : ( (idx == 1) ? ((vec).y) : ((vec).z) )) +#else +# define IDX(vec, idx) ((vec)[idx]) +#endif + +#if (defined(__KERNEL_OPENCL_APPLE__)) || \ + (defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86))) +ccl_device_noinline +#else +ccl_device_inline +#endif +void ray_triangle_intersect_precalc(float3 dir, + TriangleIsectPrecalc *isect_precalc) +{ + /* Calculate dimension where the ray direction is maximal. */ +#ifndef __KERNEL_SSE__ + int kz = util_max_axis(make_float3(fabsf(dir.x), + fabsf(dir.y), + fabsf(dir.z))); + int kx = kz + 1; if(kx == 3) kx = 0; + int ky = kx + 1; if(ky == 3) ky = 0; +#else + int kx, ky, kz; + /* Avoiding mispredicted branch on direction. */ + kz = util_max_axis(fabs(dir)); + static const char inc_xaxis[] = {1, 2, 0, 55}; + static const char inc_yaxis[] = {2, 0, 1, 55}; + kx = inc_xaxis[kz]; + ky = inc_yaxis[kz]; +#endif + + float dir_kz = IDX(dir, kz); + + /* Swap kx and ky dimensions to preserve winding direction of triangles. */ + if(dir_kz < 0.0f) { + int tmp = kx; + kx = ky; + ky = tmp; + } + + /* Calculate the shear constants. */ + float inv_dir_z = 1.0f / dir_kz; + isect_precalc->Sx = IDX(dir, kx) * inv_dir_z; + isect_precalc->Sy = IDX(dir, ky) * inv_dir_z; + isect_precalc->Sz = inv_dir_z; + + /* Store the dimensions. */ + isect_precalc->kx = kx; + isect_precalc->ky = ky; + isect_precalc->kz = kz; +} + +#undef IDX + ccl_device_inline bool ray_triangle_intersect_uv( float3 ray_P, float3 ray_D, float ray_t, float3 v0, float3 v1, float3 v2, From a5b6742ed277533f32fefa27f9763e101fa0545d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 13:30:18 +0100 Subject: [PATCH 48/73] Cycles: Move watertight triangle intersection to an utility file This way the code can be reused more easily. --- .../kernel/geom/geom_triangle_intersect.h | 148 +++--------------- intern/cycles/util/util_math_intersect.h | 135 ++++++++++++++++ 2 files changed, 156 insertions(+), 127 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 12700c7a246..ea2ee5c3536 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -48,145 +48,39 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, int object, int prim_addr) { - const int kx = isect_precalc->kx; - const int ky = isect_precalc->ky; - const int kz = isect_precalc->kz; - const float Sx = isect_precalc->Sx; - const float Sy = isect_precalc->Sy; - const float Sz = isect_precalc->Sz; - - /* Calculate vertices relative to ray origin. */ const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr); #if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) - const avxf avxf_P(P.m128, P.m128); - - const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex]; - const avxf tri_ab = _mm256_loadu_ps((float *)(ssef_verts)); - const avxf tri_bc = _mm256_loadu_ps((float *)(ssef_verts + 1)); - - const avxf AB = tri_ab - avxf_P; - const avxf BC = tri_bc - avxf_P; - - const __m256i permute_mask = _mm256_set_epi32(0x3, kz, ky, kx, 0x3, kz, ky, kx); - - const avxf AB_k = shuffle(AB, permute_mask); - const avxf BC_k = shuffle(BC, permute_mask); - - /* Akz, Akz, Bkz, Bkz, Bkz, Bkz, Ckz, Ckz */ - const avxf ABBC_kz = shuffle<2>(AB_k, BC_k); - - /* Akx, Aky, Bkx, Bky, Bkx,Bky, Ckx, Cky */ - const avxf ABBC_kxy = shuffle<0,1,0,1>(AB_k, BC_k); - - const avxf Sxy(Sy, Sx, Sy, Sx); - - /* Ax, Ay, Bx, By, Bx, By, Cx, Cy */ - const avxf ABBC_xy = nmadd(ABBC_kz, Sxy, ABBC_kxy); - - float ABBC_kz_array[8]; - _mm256_storeu_ps((float*)&ABBC_kz_array, ABBC_kz); - - const float A_kz = ABBC_kz_array[0]; - const float B_kz = ABBC_kz_array[2]; - const float C_kz = ABBC_kz_array[6]; - - /* By, Bx, Cy, Cx, By, Bx, Ay, Ax */ - const avxf BCBA_yx = permute<3,2,7,6,3,2,1,0>(ABBC_xy); - - const avxf neg_mask(0,0,0,0,0x80000000, 0x80000000, 0x80000000, 0x80000000); - - /* W U V - * (AxBy-AyBx) (BxCy-ByCx) XX XX (BxBy-ByBx) (CxAy-CyAx) XX XX - */ - const avxf WUxxxxVxx_neg = _mm256_hsub_ps(ABBC_xy * BCBA_yx, neg_mask /* Dont care */); - - const avxf WUVWnegWUVW = permute<0,1,5,0,0,1,5,0>(WUxxxxVxx_neg) ^ neg_mask; - - /* Calculate scaled barycentric coordinates. */ - float WUVW_array[4]; - _mm_storeu_ps((float*)&WUVW_array, _mm256_castps256_ps128 (WUVWnegWUVW)); - - const float W = WUVW_array[0]; - const float U = WUVW_array[1]; - const float V = WUVW_array[2]; - - const int WUVW_mask = 0x7 & _mm256_movemask_ps(WUVWnegWUVW); - const int WUVW_zero = 0x7 & _mm256_movemask_ps(_mm256_cmp_ps(WUVWnegWUVW, - _mm256_setzero_ps(), 0)); - - if(!((WUVW_mask == 7) || (WUVW_mask == 0)) && ((WUVW_mask | WUVW_zero) != 7)) { - return false; - } + const ssef *verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex]; #else const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0), tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1), tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2); - const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z); - const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z); - const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z); - - const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz); - const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz); - const float C_kx = IDX(C, kx), C_ky = IDX(C, ky), C_kz = IDX(C, kz); - - /* Perform shear and scale of vertices. */ - const float Ax = A_kx - Sx * A_kz; - const float Ay = A_ky - Sy * A_kz; - const float Bx = B_kx - Sx * B_kz; - const float By = B_ky - Sy * B_kz; - const float Cx = C_kx - Sx * C_kz; - const float Cy = C_ky - Sy * C_kz; - - /* Calculate scaled barycentric coordinates. */ - float U = Cx * By - Cy * Bx; - float V = Ax * Cy - Ay * Cx; - float W = Bx * Ay - By * Ax; - if((U < 0.0f || V < 0.0f || W < 0.0f) && - (U > 0.0f || V > 0.0f || W > 0.0f)) - { - return false; - } + const float3 verts[3] = {float4_to_float3(tri_a), + float4_to_float3(tri_b), + float4_to_float3(tri_c)}; #endif - - /* Calculate determinant. */ - float det = U + V + W; - if(UNLIKELY(det == 0.0f)) { - return false; - } - - /* Calculate scaled z-coordinates of vertices and use them to calculate - * the hit distance. - */ - const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz; - const int sign_det = (__float_as_int(det) & 0x80000000); - const float sign_T = xor_signmask(T, sign_det); - if((sign_T < 0.0f) || - (sign_T > isect->t * xor_signmask(det, sign_det))) + float t, u, v; + if(ray_triangle_intersect(isect_precalc, + P, isect->t, + verts, + &u, &v, &t)) { - return false; - } - #ifdef __VISIBILITY_FLAG__ - /* visibility flag test. we do it here under the assumption - * that most triangles are culled by node flags */ - if(kernel_tex_fetch(__prim_visibility, prim_addr) & visibility) + /* Visibility flag test. we do it here under the assumption + * that most triangles are culled by node flags. + */ + if(kernel_tex_fetch(__prim_visibility, prim_addr) & visibility) #endif - { -#ifdef __KERNEL_CUDA__ - if(A == B && B == C) { - return false; + { + isect->prim = prim_addr; + isect->object = object; + isect->type = PRIMITIVE_TRIANGLE; + isect->u = u; + isect->v = v; + isect->t = t; + return true; } -#endif - /* Normalize U, V, W, and T. */ - const float inv_det = 1.0f / det; - isect->prim = prim_addr; - isect->object = object; - isect->type = PRIMITIVE_TRIANGLE; - isect->u = U * inv_det; - isect->v = V * inv_det; - isect->t = T * inv_det; - return true; } return false; } diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h index 7e02c04d939..4a052b8b9c6 100644 --- a/intern/cycles/util/util_math_intersect.h +++ b/intern/cycles/util/util_math_intersect.h @@ -153,6 +153,141 @@ void ray_triangle_intersect_precalc(float3 dir, isect_precalc->kz = kz; } +ccl_device_inline bool ray_triangle_intersect( + const TriangleIsectPrecalc *isect_precalc, + float3 ray_P, float ray_t, +#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) + const ssef *ssef_verts, +#else + const float3 *verts, +#endif + float *isect_u, float *isect_v, float *isect_t) +{ + const int kx = isect_precalc->kx; + const int ky = isect_precalc->ky; + const int kz = isect_precalc->kz; + const float Sx = isect_precalc->Sx; + const float Sy = isect_precalc->Sy; + const float Sz = isect_precalc->Sz; + +#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) + const avxf avxf_P(ray_P.m128, ray_P.m128); + const avxf tri_ab(_mm256_loadu_ps((float *)(ssef_verts))); + const avxf tri_bc(_mm256_loadu_ps((float *)(ssef_verts + 1))); + + const avxf AB = tri_ab - avxf_P; + const avxf BC = tri_bc - avxf_P; + + const __m256i permute_mask = _mm256_set_epi32(0x3, kz, ky, kx, 0x3, kz, ky, kx); + + const avxf AB_k = shuffle(AB, permute_mask); + const avxf BC_k = shuffle(BC, permute_mask); + + /* Akz, Akz, Bkz, Bkz, Bkz, Bkz, Ckz, Ckz */ + const avxf ABBC_kz = shuffle<2>(AB_k, BC_k); + + /* Akx, Aky, Bkx, Bky, Bkx,Bky, Ckx, Cky */ + const avxf ABBC_kxy = shuffle<0,1,0,1>(AB_k, BC_k); + + const avxf Sxy(Sy, Sx, Sy, Sx); + + /* Ax, Ay, Bx, By, Bx, By, Cx, Cy */ + const avxf ABBC_xy = nmadd(ABBC_kz, Sxy, ABBC_kxy); + + float ABBC_kz_array[8]; + _mm256_storeu_ps((float*)&ABBC_kz_array, ABBC_kz); + + const float A_kz = ABBC_kz_array[0]; + const float B_kz = ABBC_kz_array[2]; + const float C_kz = ABBC_kz_array[6]; + + /* By, Bx, Cy, Cx, By, Bx, Ay, Ax */ + const avxf BCBA_yx = permute<3,2,7,6,3,2,1,0>(ABBC_xy); + + const avxf neg_mask(0,0,0,0,0x80000000, 0x80000000, 0x80000000, 0x80000000); + + /* W U V + * (AxBy-AyBx) (BxCy-ByCx) XX XX (BxBy-ByBx) (CxAy-CyAx) XX XX + */ + const avxf WUxxxxVxx_neg = _mm256_hsub_ps(ABBC_xy * BCBA_yx, neg_mask /* Dont care */); + + const avxf WUVWnegWUVW = permute<0,1,5,0,0,1,5,0>(WUxxxxVxx_neg) ^ neg_mask; + + /* Calculate scaled barycentric coordinates. */ + float WUVW_array[4]; + _mm_storeu_ps((float*)&WUVW_array, _mm256_castps256_ps128 (WUVWnegWUVW)); + + const float W = WUVW_array[0]; + const float U = WUVW_array[1]; + const float V = WUVW_array[2]; + + const int WUVW_mask = 0x7 & _mm256_movemask_ps(WUVWnegWUVW); + const int WUVW_zero = 0x7 & _mm256_movemask_ps(_mm256_cmp_ps(WUVWnegWUVW, + _mm256_setzero_ps(), 0)); + + if(!((WUVW_mask == 7) || (WUVW_mask == 0)) && ((WUVW_mask | WUVW_zero) != 7)) { + return false; + } +#else + /* Calculate vertices relative to ray origin. */ + const float3 A = verts[0] - ray_P; + const float3 B = verts[1] - ray_P; + const float3 C = verts[2] - ray_P; + + const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz); + const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz); + const float C_kx = IDX(C, kx), C_ky = IDX(C, ky), C_kz = IDX(C, kz); + + /* Perform shear and scale of vertices. */ + const float Ax = A_kx - Sx * A_kz; + const float Ay = A_ky - Sy * A_kz; + const float Bx = B_kx - Sx * B_kz; + const float By = B_ky - Sy * B_kz; + const float Cx = C_kx - Sx * C_kz; + const float Cy = C_ky - Sy * C_kz; + + /* Calculate scaled barycentric coordinates. */ + float U = Cx * By - Cy * Bx; + float V = Ax * Cy - Ay * Cx; + float W = Bx * Ay - By * Ax; + if((U < 0.0f || V < 0.0f || W < 0.0f) && + (U > 0.0f || V > 0.0f || W > 0.0f)) + { + return false; + } +#endif + + /* Calculate determinant. */ + float det = U + V + W; + if(UNLIKELY(det == 0.0f)) { + return false; + } + + /* Calculate scaled z-coordinates of vertices and use them to calculate + * the hit distance. + */ + const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz; + const int sign_det = (__float_as_int(det) & 0x80000000); + const float sign_T = xor_signmask(T, sign_det); + if((sign_T < 0.0f) || + (sign_T > ray_t * xor_signmask(det, sign_det))) + { + return false; + } + + /* Workaround precision error on CUDA. */ +#ifdef __KERNEL_CUDA__ + if(A == B && B == C) { + return false; + } +#endif + const float inv_det = 1.0f / det; + *isect_u = U * inv_det; + *isect_v = V * inv_det; + *isect_t = T * inv_det; + return true; +} + #undef IDX ccl_device_inline bool ray_triangle_intersect_uv( From 2a5d7b5b1e0345ce8ebf40c78ecd31eaeaa88f6d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 15:17:26 +0100 Subject: [PATCH 49/73] Cycles: Use utility function for SSS triangle intersection This effectively de-duplicates triangle intersection logic implemented for both regular triangle and SSS triangle. --- .../kernel/geom/geom_triangle_intersect.h | 136 +++--------------- 1 file changed, 20 insertions(+), 116 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index ea2ee5c3536..973b3566378 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -102,129 +102,27 @@ ccl_device_inline void triangle_intersect_subsurface( uint *lcg_state, int max_hits) { - const int kx = isect_precalc->kx; - const int ky = isect_precalc->ky; - const int kz = isect_precalc->kz; - const float Sx = isect_precalc->Sx; - const float Sy = isect_precalc->Sy; - const float Sz = isect_precalc->Sz; - - /* Calculate vertices relative to ray origin. */ const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr); + +#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) + const ssef *verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex]; +#else const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0), tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1), tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2); - -#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) - const avxf avxf_P(P.m128, P.m128); - - const avxf tri_ab = kernel_tex_fetch_avxf(__prim_tri_verts, tri_vindex + 0); - const avxf tri_bc = kernel_tex_fetch_avxf(__prim_tri_verts, tri_vindex + 1); - - const avxf AB = tri_ab - avxf_P; - const avxf BC = tri_bc - avxf_P; - - const __m256i permuteMask = _mm256_set_epi32(0x3, kz, ky, kx, 0x3, kz, ky, kx); - - const avxf AB_k = shuffle(AB, permuteMask); - const avxf BC_k = shuffle(BC, permuteMask); - - /* Akz, Akz, Bkz, Bkz, Bkz, Bkz, Ckz, Ckz */ - const avxf ABBC_kz = shuffle<2>(AB_k, BC_k); - - /* Akx, Aky, Bkx, Bky, Bkx,Bky, Ckx, Cky */ - const avxf ABBC_kxy = shuffle<0,1,0,1>(AB_k, BC_k); - - const avxf Sxy(Sy, Sx, Sy, Sx); - - /* Ax, Ay, Bx, By, Bx, By, Cx, Cy */ - const avxf ABBC_xy = nmadd(ABBC_kz, Sxy, ABBC_kxy); - - float ABBC_kz_array[8]; - _mm256_storeu_ps((float*)&ABBC_kz_array, ABBC_kz); - - const float A_kz = ABBC_kz_array[0]; - const float B_kz = ABBC_kz_array[2]; - const float C_kz = ABBC_kz_array[6]; - - /* By, Bx, Cy, Cx, By, Bx, Ay, Ax */ - const avxf BCBA_yx = permute<3,2,7,6,3,2,1,0>(ABBC_xy); - - const avxf negMask(0,0,0,0,0x80000000, 0x80000000, 0x80000000, 0x80000000); - - /* W U V - * (AxBy-AyBx) (BxCy-ByCx) XX XX (BxBy-ByBx) (CxAy-CyAx) XX XX - */ - const avxf WUxxxxVxx_neg = _mm256_hsub_ps(ABBC_xy * BCBA_yx, negMask /* Dont care */); - - const avxf WUVWnegWUVW = permute<0,1,5,0,0,1,5,0>(WUxxxxVxx_neg) ^ negMask; - - /* Calculate scaled barycentric coordinates. */ - float WUVW_array[4]; - _mm_storeu_ps((float*)&WUVW_array, _mm256_castps256_ps128 (WUVWnegWUVW)); - - const float W = WUVW_array[0]; - const float U = WUVW_array[1]; - const float V = WUVW_array[2]; - - const int WUVW_mask = 0x7 & _mm256_movemask_ps(WUVWnegWUVW); - const int WUVW_zero = 0x7 & _mm256_movemask_ps(_mm256_cmp_ps(WUVWnegWUVW, - _mm256_setzero_ps(), 0)); - - if(!((WUVW_mask == 7) || (WUVW_mask == 0)) && ((WUVW_mask | WUVW_zero) != 7)) { - return; - } -#else - const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z); - const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z); - const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z); - - const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz); - const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz); - const float C_kx = IDX(C, kx), C_ky = IDX(C, ky), C_kz = IDX(C, kz); - - /* Perform shear and scale of vertices. */ - const float Ax = A_kx - Sx * A_kz; - const float Ay = A_ky - Sy * A_kz; - const float Bx = B_kx - Sx * B_kz; - const float By = B_ky - Sy * B_kz; - const float Cx = C_kx - Sx * C_kz; - const float Cy = C_ky - Sy * C_kz; - - /* Calculate scaled barycentric coordinates. */ - float U = Cx * By - Cy * Bx; - float V = Ax * Cy - Ay * Cx; - float W = Bx * Ay - By * Ax; - - if((U < 0.0f || V < 0.0f || W < 0.0f) && - (U > 0.0f || V > 0.0f || W > 0.0f)) - { - return; - } + const float3 verts[3] = {float4_to_float3(tri_a), + float4_to_float3(tri_b), + float4_to_float3(tri_c)}; #endif - - /* Calculate determinant. */ - float det = U + V + W; - if(UNLIKELY(det == 0.0f)) { - return; - } - - /* Calculate scaled z−coordinates of vertices and use them to calculate - * the hit distance. - */ - const int sign_det = (__float_as_int(det) & 0x80000000); - const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz; - const float sign_T = xor_signmask(T, sign_det); - if((sign_T < 0.0f) || - (sign_T > tmax * xor_signmask(det, sign_det))) + float t, u, v; + if(!ray_triangle_intersect(isect_precalc, + P, tmax, + verts, + &u, &v, &t)) { return; } - /* Normalize U, V, W, and T. */ - const float inv_det = 1.0f / det; - - const float t = T * inv_det; for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) { if(ss_isect->hits[i].t == t) { return; @@ -251,11 +149,17 @@ ccl_device_inline void triangle_intersect_subsurface( isect->prim = prim_addr; isect->object = object; isect->type = PRIMITIVE_TRIANGLE; - isect->u = U * inv_det; - isect->v = V * inv_det; + isect->u = u; + isect->v = v; isect->t = t; /* Record geometric normal. */ + /* TODO(sergey): Check whether it's faster to re-use ssef verts. */ +#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) + const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0), + tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1), + tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2); +#endif /* TODO(sergey): Use float4_to_float3() on just an edges. */ const float3 v0 = float4_to_float3(tri_a); const float3 v1 = float4_to_float3(tri_b); From a1348dde2ed27d0a8a1d62f9e17602857b1f19f1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 17:15:54 +0100 Subject: [PATCH 50/73] Cycles: Fix speed regression on GPU Avoid construction of temporary array and make utility function force-inlined. Additionally avoid calling float4_to_float3 twice. This brings render times to the same values as before current patch series. --- .../kernel/geom/geom_triangle_intersect.h | 44 ++++++++++--------- intern/cycles/util/util_math_intersect.h | 10 ++--- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 973b3566378..313121104f9 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -51,19 +51,22 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr); #if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) - const ssef *verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex]; + const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex]; #else const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0), tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1), tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2); - const float3 verts[3] = {float4_to_float3(tri_a), - float4_to_float3(tri_b), - float4_to_float3(tri_c)}; #endif float t, u, v; if(ray_triangle_intersect(isect_precalc, P, isect->t, - verts, +#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) + ssef_verts, +#else + float4_to_float3(tri_a), + float4_to_float3(tri_b), + float4_to_float3(tri_c), +#endif &u, &v, &t)) { #ifdef __VISIBILITY_FLAG__ @@ -105,19 +108,22 @@ ccl_device_inline void triangle_intersect_subsurface( const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr); #if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) - const ssef *verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex]; + const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex]; #else - const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0), - tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1), - tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2); - const float3 verts[3] = {float4_to_float3(tri_a), - float4_to_float3(tri_b), - float4_to_float3(tri_c)}; + const float3 tri_a = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+0)), + tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+1)), + tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2)); #endif float t, u, v; if(!ray_triangle_intersect(isect_precalc, P, tmax, - verts, +#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) + ssef_verts, +#else + tri_a, + tri_b, + tri_c, +#endif &u, &v, &t)) { return; @@ -156,15 +162,11 @@ ccl_device_inline void triangle_intersect_subsurface( /* Record geometric normal. */ /* TODO(sergey): Check whether it's faster to re-use ssef verts. */ #if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) - const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0), - tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1), - tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2); + const float3 tri_a = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+0)), + tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+1)), + tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2)); #endif - /* TODO(sergey): Use float4_to_float3() on just an edges. */ - const float3 v0 = float4_to_float3(tri_a); - const float3 v1 = float4_to_float3(tri_b); - const float3 v2 = float4_to_float3(tri_c); - ss_isect->Ng[hit] = normalize(cross(v1 - v0, v2 - v0)); + ss_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a)); } #endif diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h index 4a052b8b9c6..5bd3a52dcea 100644 --- a/intern/cycles/util/util_math_intersect.h +++ b/intern/cycles/util/util_math_intersect.h @@ -153,13 +153,13 @@ void ray_triangle_intersect_precalc(float3 dir, isect_precalc->kz = kz; } -ccl_device_inline bool ray_triangle_intersect( +ccl_device_forceinline bool ray_triangle_intersect( const TriangleIsectPrecalc *isect_precalc, float3 ray_P, float ray_t, #if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) const ssef *ssef_verts, #else - const float3 *verts, + const float3 tri_a, const float3 tri_b, const float3 tri_c, #endif float *isect_u, float *isect_v, float *isect_t) { @@ -230,9 +230,9 @@ ccl_device_inline bool ray_triangle_intersect( } #else /* Calculate vertices relative to ray origin. */ - const float3 A = verts[0] - ray_P; - const float3 B = verts[1] - ray_P; - const float3 C = verts[2] - ray_P; + const float3 A = make_float3(tri_a.x - ray_P.x, tri_a.y - ray_P.y, tri_a.z - ray_P.z); + const float3 B = make_float3(tri_b.x - ray_P.x, tri_b.y - ray_P.y, tri_b.z - ray_P.z); + const float3 C = make_float3(tri_c.x - ray_P.x, tri_c.y - ray_P.y, tri_c.z - ray_P.z); const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz); const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz); From ba8c7d2ba120f5ba7fdbaef67fe2e301ec3e5dcb Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 16:16:05 +0100 Subject: [PATCH 51/73] Cycles: Use SSE-optimized version of triangle intersection for motion triangles The title says it all actually. Gives up to 10% speedup on test scenes here on i7-6800K. Render times on GPU are unreliable here, but there might be some slowdown caused by watertight nature of intersections. --- intern/cycles/kernel/bvh/bvh_shadow_all.h | 2 +- intern/cycles/kernel/bvh/bvh_subsurface.h | 2 +- intern/cycles/kernel/bvh/bvh_traversal.h | 2 +- intern/cycles/kernel/bvh/bvh_volume.h | 2 +- intern/cycles/kernel/bvh/bvh_volume_all.h | 2 +- intern/cycles/kernel/bvh/qbvh_shadow_all.h | 2 +- intern/cycles/kernel/bvh/qbvh_subsurface.h | 2 +- intern/cycles/kernel/bvh/qbvh_traversal.h | 2 +- intern/cycles/kernel/bvh/qbvh_volume.h | 2 +- intern/cycles/kernel/bvh/qbvh_volume_all.h | 2 +- .../geom/geom_motion_triangle_intersect.h | 47 +++++++++++-------- 11 files changed, 38 insertions(+), 29 deletions(-) diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h index a6e23d9f381..8f7c005e961 100644 --- a/intern/cycles/kernel/bvh/bvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h @@ -209,9 +209,9 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, #if BVH_FEATURE(BVH_MOTION) case PRIMITIVE_MOTION_TRIANGLE: { hit = motion_triangle_intersect(kg, + &isect_precalc, isect_array, P, - dir, ray->time, PATH_RAY_SHADOW, object, diff --git a/intern/cycles/kernel/bvh/bvh_subsurface.h b/intern/cycles/kernel/bvh/bvh_subsurface.h index 11ea1f89c8b..cb7a4e3bc31 100644 --- a/intern/cycles/kernel/bvh/bvh_subsurface.h +++ b/intern/cycles/kernel/bvh/bvh_subsurface.h @@ -214,9 +214,9 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, for(; prim_addr < prim_addr2; prim_addr++) { kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); motion_triangle_intersect_subsurface(kg, + &isect_precalc, ss_isect, P, - dir, ray->time, object, prim_addr, diff --git a/intern/cycles/kernel/bvh/bvh_traversal.h b/intern/cycles/kernel/bvh/bvh_traversal.h index 7c4671e074f..eac98a3165a 100644 --- a/intern/cycles/kernel/bvh/bvh_traversal.h +++ b/intern/cycles/kernel/bvh/bvh_traversal.h @@ -267,9 +267,9 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, BVH_DEBUG_NEXT_INTERSECTION(); kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); if(motion_triangle_intersect(kg, + &isect_precalc, isect, P, - dir, ray->time, visibility, object, diff --git a/intern/cycles/kernel/bvh/bvh_volume.h b/intern/cycles/kernel/bvh/bvh_volume.h index 45b5a3c687b..da97dae0b99 100644 --- a/intern/cycles/kernel/bvh/bvh_volume.h +++ b/intern/cycles/kernel/bvh/bvh_volume.h @@ -215,9 +215,9 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, continue; } motion_triangle_intersect(kg, + &isect_precalc, isect, P, - dir, ray->time, visibility, object, diff --git a/intern/cycles/kernel/bvh/bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h index 62018e06e97..6efb7e265d0 100644 --- a/intern/cycles/kernel/bvh/bvh_volume_all.h +++ b/intern/cycles/kernel/bvh/bvh_volume_all.h @@ -243,9 +243,9 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, continue; } hit = motion_triangle_intersect(kg, + &isect_precalc, isect_array, P, - dir, ray->time, visibility, object, diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h index 5a8ec4768d6..5d960787134 100644 --- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h @@ -290,9 +290,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, #if BVH_FEATURE(BVH_MOTION) case PRIMITIVE_MOTION_TRIANGLE: { hit = motion_triangle_intersect(kg, + &isect_precalc, isect_array, P, - dir, ray->time, PATH_RAY_SHADOW, object, diff --git a/intern/cycles/kernel/bvh/qbvh_subsurface.h b/intern/cycles/kernel/bvh/qbvh_subsurface.h index d466fe73d24..d67a7826589 100644 --- a/intern/cycles/kernel/bvh/qbvh_subsurface.h +++ b/intern/cycles/kernel/bvh/qbvh_subsurface.h @@ -270,9 +270,9 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, for(; prim_addr < prim_addr2; prim_addr++) { kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); motion_triangle_intersect_subsurface(kg, + &isect_precalc, ss_isect, P, - dir, ray->time, object, prim_addr, diff --git a/intern/cycles/kernel/bvh/qbvh_traversal.h b/intern/cycles/kernel/bvh/qbvh_traversal.h index bf69bfade1b..d88e0e07203 100644 --- a/intern/cycles/kernel/bvh/qbvh_traversal.h +++ b/intern/cycles/kernel/bvh/qbvh_traversal.h @@ -354,9 +354,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, BVH_DEBUG_NEXT_INTERSECTION(); kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); if(motion_triangle_intersect(kg, + &isect_precalc, isect, P, - dir, ray->time, visibility, object, diff --git a/intern/cycles/kernel/bvh/qbvh_volume.h b/intern/cycles/kernel/bvh/qbvh_volume.h index d34ddb6ea2b..7cfb2cf8c18 100644 --- a/intern/cycles/kernel/bvh/qbvh_volume.h +++ b/intern/cycles/kernel/bvh/qbvh_volume.h @@ -281,7 +281,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, continue; } /* Intersect ray against primitive. */ - motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, prim_addr); + motion_triangle_intersect(kg, &isect_precalc, isect, P, ray->time, visibility, object, prim_addr); } break; } diff --git a/intern/cycles/kernel/bvh/qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h index 4e1ee04916b..3dbac8446d7 100644 --- a/intern/cycles/kernel/bvh/qbvh_volume_all.h +++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h @@ -309,7 +309,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, continue; } /* Intersect ray against primitive. */ - hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, visibility, object, prim_addr); + hit = motion_triangle_intersect(kg, &isect_precalc, isect_array, P, ray->time, visibility, object, prim_addr); if(hit) { /* Move on to next entry in intersections array. */ isect_array++; diff --git a/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h b/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h index 2500228281e..971a34308f1 100644 --- a/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h @@ -166,14 +166,15 @@ float3 motion_triangle_refine_subsurface(KernelGlobals *kg, * time and do a ray intersection with the resulting triangle. */ -ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg, - Intersection *isect, - float3 P, - float3 dir, - float time, - uint visibility, - int object, - int prim_addr) +ccl_device_inline bool motion_triangle_intersect( + KernelGlobals *kg, + const TriangleIsectPrecalc *isect_precalc, + Intersection *isect, + float3 P, + float time, + uint visibility, + int object, + int prim_addr) { /* Primitive index for vertex location lookup. */ int prim = kernel_tex_fetch(__prim_index, prim_addr); @@ -185,11 +186,15 @@ ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg, motion_triangle_vertices(kg, fobject, prim, time, verts); /* Ray-triangle intersection, unoptimized. */ float t, u, v; - if(ray_triangle_intersect_uv(P, - dir, - isect->t, - verts[2], verts[0], verts[1], - &u, &v, &t)) + if(ray_triangle_intersect(isect_precalc, + P, + isect->t, +#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) + (ssef*)verts, +#else + verts[0], verts[1], verts[2], +#endif + &u, &v, &t)) { #ifdef __VISIBILITY_FLAG__ /* Visibility flag test. we do it here under the assumption @@ -217,9 +222,9 @@ ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg, #ifdef __SUBSURFACE__ ccl_device_inline void motion_triangle_intersect_subsurface( KernelGlobals *kg, + const TriangleIsectPrecalc *isect_precalc, SubsurfaceIntersection *ss_isect, float3 P, - float3 dir, float time, int object, int prim_addr, @@ -237,11 +242,15 @@ ccl_device_inline void motion_triangle_intersect_subsurface( motion_triangle_vertices(kg, fobject, prim, time, verts); /* Ray-triangle intersection, unoptimized. */ float t, u, v; - if(ray_triangle_intersect_uv(P, - dir, - tmax, - verts[2], verts[0], verts[1], - &u, &v, &t)) + if(ray_triangle_intersect(isect_precalc, + P, + tmax, +#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) + (ssef*)verts, +#else + verts[0], verts[1], verts[2], +#endif + &u, &v, &t)) { for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) { if(ss_isect->hits[i].t == t) { From 27248c8636ab8a6fa1e082ce9bc9bbdb09174358 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 17:59:02 +0100 Subject: [PATCH 52/73] Cycles: Remove unused macro --- intern/cycles/kernel/geom/geom_triangle_intersect.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 313121104f9..584d0b3508f 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -22,16 +22,6 @@ CCL_NAMESPACE_BEGIN -/* Workaround stupidness of CUDA/OpenCL which doesn't allow to access indexed - * component of float3 value. - */ -#ifndef __KERNEL_CPU__ -# define IDX(vec, idx) \ - ((idx == 0) ? ((vec).x) : ( (idx == 1) ? ((vec).y) : ((vec).z) )) -#else -# define IDX(vec, idx) ((vec)[idx]) -#endif - /* Ray-Triangle intersection for BVH traversal * * Sven Woop @@ -309,6 +299,4 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, return P; } -#undef IDX - CCL_NAMESPACE_END From a96110e7102d7a54127994b81c8c049f6e5fdeea Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 23 Mar 2017 17:59:34 +0100 Subject: [PATCH 53/73] Cycles: Remove old non-optimized triangle intersection function It is unused now and if we want similar function we should use Pluecker intersection which is same performance with SSE optimization but which is more watertight. --- intern/cycles/util/util_math_intersect.h | 43 ------------------------ 1 file changed, 43 deletions(-) diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h index 5bd3a52dcea..9e0587e1afb 100644 --- a/intern/cycles/util/util_math_intersect.h +++ b/intern/cycles/util/util_math_intersect.h @@ -290,49 +290,6 @@ ccl_device_forceinline bool ray_triangle_intersect( #undef IDX -ccl_device_inline bool ray_triangle_intersect_uv( - float3 ray_P, float3 ray_D, float ray_t, - float3 v0, float3 v1, float3 v2, - float *isect_u, float *isect_v, float *isect_t) -{ - /* Calculate intersection. */ - const float3 e1 = v1 - v0; - const float3 e2 = v2 - v0; - const float3 s1 = cross(ray_D, e2); - - const float divisor = dot(s1, e1); - if(UNLIKELY(divisor == 0.0f)) { - return false; - } - const float inv_divisor = 1.0f/divisor; - - /* Compute first barycentric coordinate. */ - const float3 d = ray_P - v0; - const float u = dot(d, s1)*inv_divisor; - if(u < 0.0f) { - return false; - } - /* Compute second barycentric coordinate. */ - const float3 s2 = cross(d, e1); - const float v = dot(ray_D, s2)*inv_divisor; - if(v < 0.0f) { - return false; - } - const float b0 = 1.0f - u - v; - if(b0 < 0.0f) { - return false; - } - /* Compute distance to intersection point. */ - const float t = dot(e2, s2)*inv_divisor; - if(t < 0.0f || t > ray_t) { - return false; - } - *isect_u = u; - *isect_v = v; - *isect_t = t; - return true; -} - ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_mint, float ray_maxt, float3 quad_P, From 9af6f40e4dcf0dc6e95a809ed0998bbdb8189a86 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Mar 2017 05:20:26 +1100 Subject: [PATCH 54/73] addon_utils: add disable_all function --- release/scripts/modules/addon_utils.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 886f078f046..51e3e65b78c 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -24,6 +24,7 @@ __all__ = ( "check", "enable", "disable", + "disable_all", "reset_all", "module_bl_info", ) @@ -444,6 +445,13 @@ def reset_all(*, reload_scripts=False): disable(mod_name) +def disable_all(): + import sys + for mod_name, mod in sys.modules.items(): + if getattr(mod, "__addon_enabled__", False): + disable(mod_name) + + def module_bl_info(mod, info_basis=None): if info_basis is None: info_basis = { From 05b7591c6240a3af1b71420ac3386787f1f384da Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Mar 2017 05:23:03 +1100 Subject: [PATCH 55/73] BLI_path_util: Add string versions of SEP, ALTSEP This allows for adding separators in string literals. --- source/blender/blenlib/BLI_path_util.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 1c1725923a6..a4f5c3c7a01 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -39,14 +39,6 @@ extern "C" { struct ListBase; -#ifdef WIN32 -#define SEP '\\' -#define ALTSEP '/' -#else -#define SEP '/' -#define ALTSEP '\\' -#endif - void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1); void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1); @@ -145,6 +137,18 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char # define FILE_MAX 1024 #endif +#ifdef WIN32 +# define SEP '\\' +# define ALTSEP '/' +# define SEP_STR "\\" +# define ALTSEP_STR "/" +#else +# define SEP '/' +# define ALTSEP '\\' +# define SEP_STR "/" +# define ALTSEP_STR "\\" +#endif + /* Parent and current dir helpers. */ #define FILENAME_PARENT ".." #define FILENAME_CURRENT "." From 096602d3a86b013771fcbc0268ef2c554a694636 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Mar 2017 06:48:24 +1100 Subject: [PATCH 56/73] bpy.path.display_name: strip spaces Useful for Python module paths that can't start with numbers. --- release/scripts/modules/bpy/path.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py index a864a86eba7..e17d710068c 100644 --- a/release/scripts/modules/bpy/path.py +++ b/release/scripts/modules/bpy/path.py @@ -204,7 +204,9 @@ def display_name(name): name = name.replace("_colon_", ":") name = name.replace("_plus_", "+") - name = name.replace("_", " ") + # strip to allow underscore prefix + # (when paths can't start with numbers for eg). + name = name.replace("_", " ").lstrip(" ") if name.islower(): name = name.lower().title() From 6a6566a7fcbdba4f0711293cce73dbd93b75a7df Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Mar 2017 10:11:01 +1100 Subject: [PATCH 57/73] Cleanup: line-length --- source/blender/blenkernel/intern/appdir.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index f2f0a92d8b3..347ae2d5d87 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -201,7 +201,8 @@ static bool get_path_local(char *targetpath, const char *folder_name, const char /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */ #ifdef __APPLE__ - static char osx_resourses[FILE_MAX]; /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */ + /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */ + static char osx_resourses[FILE_MAX]; sprintf(osx_resourses, "%s../Resources", bprogdir); return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder); #else @@ -233,7 +234,9 @@ static bool is_portable_install(void) * \param ver Blender version, used to construct a subdirectory name * \return true if it was able to construct such a path. */ -static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) +static bool get_path_user( + char *targetpath, const char *folder_name, const char *subfolder_name, + const char *envvar, const int ver) { char user_path[FILE_MAX]; const char *user_base_path; @@ -283,7 +286,9 @@ static bool get_path_user(char *targetpath, const char *folder_name, const char * \param ver Blender version, used to construct a subdirectory name * \return true if it was able to construct such a path. */ -static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) +static bool get_path_system( + char *targetpath, const char *folder_name, const char *subfolder_name, + const char *envvar, const int ver) { char system_path[FILE_MAX]; const char *system_base_path; @@ -713,7 +718,8 @@ static void where_is_temp(char *fullname, char *basename, const size_t maxlen, c BLI_add_slash(fullname); #ifdef WIN32 if (userdir && userdir != fullname) { - BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */ + /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */ + BLI_strncpy(userdir, fullname, maxlen); } #endif } From 0453c807e0b3e18c7df4b61affba8069bb8858ac Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Mar 2017 10:35:58 +1100 Subject: [PATCH 58/73] Add: BKE_appdir_folder_id_ex Allows getting the path without using a static string. --- source/blender/blenkernel/BKE_appdir.h | 1 + source/blender/blenkernel/intern/appdir.c | 121 +++++++++++++--------- 2 files changed, 73 insertions(+), 49 deletions(-) diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index 077fe2a629c..c6587b94666 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -27,6 +27,7 @@ /* note on naming: typical _get() suffix is omitted here, * since its the main purpose of the API. */ const char *BKE_appdir_folder_default(void); +const char *BKE_appdir_folder_id_ex(const int folder_id, const char *subfolder, char *path, size_t path_len); const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder); const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder); const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder); diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 347ae2d5d87..3fb8a147960 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -114,18 +114,26 @@ static char *blender_version_decimal(const int ver) * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath, * returning true if result points to a directory. */ -static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name) +static bool test_path( + char *targetpath, size_t targetpath_len, + const char *path_base, const char *path_sep, const char *folder_name) { char tmppath[FILE_MAX]; - if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); - else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); + if (path_sep) { + BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); + } + else { + BLI_strncpy(tmppath, path_base, sizeof(tmppath)); + } /* rare cases folder_name is omitted (when looking for ~/.config/blender/2.xx dir only) */ - if (folder_name) - BLI_make_file_string("/", targetpath, tmppath, folder_name); - else - BLI_strncpy(targetpath, tmppath, sizeof(tmppath)); + if (folder_name) { + BLI_join_dirfile(targetpath, targetpath_len, tmppath, folder_name); + } + else { + BLI_strncpy(targetpath, tmppath, targetpath_len); + } /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile) * if folder_name is specified but not otherwise? */ @@ -179,7 +187,9 @@ static bool test_env_path(char *path, const char *envvar) * \param ver To construct name of version-specific directory within bprogdir * \return true if such a directory exists. */ -static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver) +static bool get_path_local( + char *targetpath, size_t targetpath_len, + const char *folder_name, const char *subfolder_name, const int ver) { char relfolder[FILE_MAX]; @@ -204,9 +214,9 @@ static bool get_path_local(char *targetpath, const char *folder_name, const char /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */ static char osx_resourses[FILE_MAX]; sprintf(osx_resourses, "%s../Resources", bprogdir); - return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder); + return test_path(targetpath, targetpath_len, osx_resourses, blender_version_decimal(ver), relfolder); #else - return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder); + return test_path(targetpath, targetpath_len, bprogdir, blender_version_decimal(ver), relfolder); #endif } @@ -220,7 +230,7 @@ static bool is_portable_install(void) const int ver = BLENDER_VERSION; char path[FILE_MAX]; - return get_path_local(path, "config", NULL, ver); + return get_path_local(path, sizeof(path), "config", NULL, ver); } /** @@ -235,21 +245,21 @@ static bool is_portable_install(void) * \return true if it was able to construct such a path. */ static bool get_path_user( - char *targetpath, const char *folder_name, const char *subfolder_name, + char *targetpath, size_t targetpath_len, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) { char user_path[FILE_MAX]; const char *user_base_path; /* for portable install, user path is always local */ - if (is_portable_install()) - return get_path_local(targetpath, folder_name, subfolder_name, ver); - + if (is_portable_install()) { + return get_path_local(targetpath, targetpath_len, folder_name, subfolder_name, ver); + } user_path[0] = '\0'; if (test_env_path(user_path, envvar)) { if (subfolder_name) { - return test_path(targetpath, user_path, NULL, subfolder_name); + return test_path(targetpath, targetpath_len, user_path, NULL, subfolder_name); } else { BLI_strncpy(targetpath, user_path, FILE_MAX); @@ -269,10 +279,10 @@ static bool get_path_user( #endif if (subfolder_name) { - return test_path(targetpath, user_path, folder_name, subfolder_name); + return test_path(targetpath, targetpath_len, user_path, folder_name, subfolder_name); } else { - return test_path(targetpath, user_path, NULL, folder_name); + return test_path(targetpath, targetpath_len, user_path, NULL, folder_name); } } @@ -287,7 +297,7 @@ static bool get_path_user( * \return true if it was able to construct such a path. */ static bool get_path_system( - char *targetpath, const char *folder_name, const char *subfolder_name, + char *targetpath, size_t targetpath_len, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) { char system_path[FILE_MAX]; @@ -312,13 +322,13 @@ static bool get_path_system( /* try CWD/release/folder_name */ if (BLI_current_working_dir(cwd, sizeof(cwd))) { - if (test_path(targetpath, cwd, "release", relfolder)) { + if (test_path(targetpath, targetpath_len, cwd, "release", relfolder)) { return true; } } /* try EXECUTABLE_DIR/release/folder_name */ - if (test_path(targetpath, bprogdir, "release", relfolder)) + if (test_path(targetpath, targetpath_len, bprogdir, "release", relfolder)) return true; /* end developer overrides */ @@ -329,7 +339,7 @@ static bool get_path_system( if (test_env_path(system_path, envvar)) { if (subfolder_name) { - return test_path(targetpath, system_path, NULL, subfolder_name); + return test_path(targetpath, targetpath_len, system_path, NULL, subfolder_name); } else { BLI_strncpy(targetpath, system_path, FILE_MAX); @@ -350,57 +360,63 @@ static bool get_path_system( if (subfolder_name) { /* try $BLENDERPATH/folder_name/subfolder_name */ - return test_path(targetpath, system_path, folder_name, subfolder_name); + return test_path(targetpath, targetpath_len, system_path, folder_name, subfolder_name); } else { /* try $BLENDERPATH/folder_name */ - return test_path(targetpath, system_path, NULL, folder_name); + return test_path(targetpath, targetpath_len, system_path, NULL, folder_name); } } -/* get a folder out of the 'folder_id' presets for paths */ -/* returns the path if found, NULL string if not */ -const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder) +/** + * Get a folder out of the 'folder_id' presets for paths. + * returns the path if found, NULL string if not + * + * \param subfolder: The name of a directory to check for, + * this may contain path separators but must resolve to a directory, checked with #BLI_is_dir. + */ +const char *BKE_appdir_folder_id_ex( + const int folder_id, const char *subfolder, + char *path, size_t path_len) { const int ver = BLENDER_VERSION; - static char path[FILE_MAX] = ""; - + switch (folder_id) { case BLENDER_DATAFILES: /* general case */ - if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; - if (get_path_local(path, "datafiles", subfolder, ver)) break; - if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; + if (get_path_user(path, path_len, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; + if (get_path_local(path, path_len, "datafiles", subfolder, ver)) break; + if (get_path_system(path, path_len, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; return NULL; case BLENDER_USER_DATAFILES: - if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; + if (get_path_user(path, path_len, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; return NULL; case BLENDER_SYSTEM_DATAFILES: - if (get_path_local(path, "datafiles", subfolder, ver)) break; - if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; + if (get_path_local(path, path_len, "datafiles", subfolder, ver)) break; + if (get_path_system(path, path_len, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; return NULL; case BLENDER_USER_AUTOSAVE: - if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break; + if (get_path_user(path, path_len, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break; return NULL; case BLENDER_USER_CONFIG: - if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break; + if (get_path_user(path, path_len, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break; return NULL; case BLENDER_USER_SCRIPTS: - if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break; + if (get_path_user(path, path_len, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break; return NULL; case BLENDER_SYSTEM_SCRIPTS: - if (get_path_local(path, "scripts", subfolder, ver)) break; - if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break; + if (get_path_local(path, path_len, "scripts", subfolder, ver)) break; + if (get_path_system(path, path_len, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break; return NULL; case BLENDER_SYSTEM_PYTHON: - if (get_path_local(path, "python", subfolder, ver)) break; - if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break; + if (get_path_local(path, path_len, "python", subfolder, ver)) break; + if (get_path_system(path, path_len, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break; return NULL; default: @@ -411,6 +427,13 @@ const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder) return path; } +const char *BKE_appdir_folder_id( + const int folder_id, const char *subfolder) +{ + static char path[FILE_MAX] = ""; + return BKE_appdir_folder_id_ex(folder_id, subfolder, path, sizeof(path)); +} + /** * Returns the path to a folder in the user area without checking that it actually exists first. */ @@ -421,16 +444,16 @@ const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *su switch (folder_id) { case BLENDER_USER_DATAFILES: - get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver); + get_path_user(path, sizeof(path), "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver); break; case BLENDER_USER_CONFIG: - get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver); + get_path_user(path, sizeof(path), "config", subfolder, "BLENDER_USER_CONFIG", ver); break; case BLENDER_USER_AUTOSAVE: - get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver); + get_path_user(path, sizeof(path), "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver); break; case BLENDER_USER_SCRIPTS: - get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver); + get_path_user(path, sizeof(path), "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver); break; default: BLI_assert(0); @@ -474,13 +497,13 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con bool ok; switch (folder_id) { case BLENDER_RESOURCE_PATH_USER: - ok = get_path_user(path, NULL, NULL, NULL, ver); + ok = get_path_user(path, sizeof(path), NULL, NULL, NULL, ver); break; case BLENDER_RESOURCE_PATH_LOCAL: - ok = get_path_local(path, NULL, NULL, ver); + ok = get_path_local(path, sizeof(path), NULL, NULL, ver); break; case BLENDER_RESOURCE_PATH_SYSTEM: - ok = get_path_system(path, NULL, NULL, NULL, ver); + ok = get_path_system(path, sizeof(path), NULL, NULL, NULL, ver); break; default: path[0] = '\0'; /* in case do_check is false */ From 50f9fc7a53b53a53b9fc90bcb20396426631d20f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Mar 2017 17:29:48 +1100 Subject: [PATCH 59/73] BLI_path_util: Add BLI_path_join There weren't any convenient ways to join multiple paths in C that accounted for corner cases. --- source/blender/blenlib/BLI_path_util.h | 3 + source/blender/blenlib/intern/path_util.c | 84 +++++++++++++++++++ tests/gtests/blenlib/BLI_path_util_test.cc | 98 ++++++++++++++++++++++ 3 files changed, 185 insertions(+) diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index a4f5c3c7a01..b6a55d34d14 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -52,6 +52,9 @@ void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file) ATTR_NONNULL(); void BLI_join_dirfile(char *__restrict string, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL(); +size_t BLI_path_join( + char *__restrict dst, const size_t dst_len, + const char *path_first, ...) ATTR_NONNULL(1, 3) ATTR_SENTINEL(0); const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; bool BLI_path_name_at_index( const char *__restrict path, const int index, diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 955f603cdae..7b765cfa939 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1590,6 +1590,90 @@ void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__r BLI_strncpy(dst + dirlen, file, maxlen - dirlen); } +/** + * Join multiple strings into a path, ensuring only a single path separator between each, + * and trailing slash is kept. + * + * \note If you want a trailing slash, add ``SEP_STR`` as the last path argument, + * duplicate slashes will be cleaned up. + */ +size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path, ...) +{ + if (UNLIKELY(dst_len == 0)) { + return 0; + } + const size_t dst_last = dst_len - 1; + size_t ofs = BLI_strncpy_rlen(dst, path, dst_len); + + if (ofs == dst_last) { + return ofs; + } + + /* remove trailing slashes, unless there are _only_ trailing slashes + * (allow "//" as the first argument). */ + bool has_trailing_slash = false; + if (ofs != 0) { + size_t len = ofs; + while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { + len -= 1; + } + if (len != 0) { + ofs = len; + } + has_trailing_slash = (path[len] != '\0'); + } + + va_list args; + va_start(args, path); + while ((path = (const char *) va_arg(args, const char *))) { + has_trailing_slash = false; + const char *path_init = path; + while (ELEM(path[0], SEP, ALTSEP)) { + path++; + } + size_t len = strlen(path); + if (len != 0) { + while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { + len -= 1; + } + + if (len != 0) { + /* the very first path may have a slash at the end */ + if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) { + dst[ofs++] = SEP; + if (ofs == dst_last) { + break; + } + } + has_trailing_slash = (path[len] != '\0'); + if (ofs + len >= dst_last) { + len = dst_last - ofs; + } + memcpy(&dst[ofs], path, len); + ofs += len; + if (ofs == dst_last) { + break; + } + } + } + else { + has_trailing_slash = (path_init != path); + } + } + va_end(args); + + if (has_trailing_slash) { + if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) { + dst[ofs++] = SEP; + } + } + + BLI_assert(ofs <= dst_last); + dst[ofs] = '\0'; + + return ofs; +} + /** * like pythons os.path.basename() * diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc index ccfa59503c2..4c45bfd6758 100644 --- a/tests/gtests/blenlib/BLI_path_util_test.cc +++ b/tests/gtests/blenlib/BLI_path_util_test.cc @@ -5,6 +5,7 @@ extern "C" { #include "BLI_fileops.h" #include "BLI_path_util.h" +#include "BLI_string.h" #include "../../../source/blender/imbuf/IMB_imbuf.h" #ifdef _WIN32 @@ -245,6 +246,103 @@ TEST(path_util, NameAtIndex_NoneComplexNeg) #undef AT_INDEX +#define JOIN(str_expect, out_size, ...) \ + { \ + const char *expect = str_expect; \ + char result[(out_size) + 1024]; \ + /* check we don't write past the last byte */ \ + result[out_size] = '\0'; \ + BLI_path_join(result, out_size, __VA_ARGS__, NULL); \ + /* simplify expected string */ \ + BLI_str_replace_char(result, '\\', '/'); \ + EXPECT_STREQ(result, expect); \ + EXPECT_EQ(result[out_size], '\0'); \ + } ((void)0) + +/* BLI_path_join */ +TEST(path_util, JoinNop) +{ + JOIN("", 100, ""); + JOIN("", 100, "", ""); + JOIN("", 100, "", "", ""); + JOIN("/", 100, "/", "", ""); + JOIN("/", 100, "/", "/"); + JOIN("/", 100, "/", "", "/"); + JOIN("/", 100, "/", "", "/", ""); +} + +TEST(path_util, JoinSingle) +{ + JOIN("test", 100, "test"); + JOIN("", 100, ""); + JOIN("a", 100, "a"); + JOIN("/a", 100, "/a"); + JOIN("a/", 100, "a/"); + JOIN("/a/", 100, "/a/"); + JOIN("/a/", 100, "/a//"); + JOIN("//a/", 100, "//a//"); +} + +TEST(path_util, JoinTriple) +{ + JOIN("/a/b/c", 100, "/a", "b", "c"); + JOIN("/a/b/c", 100, "/a/", "/b/", "/c"); + JOIN("/a/b/c", 100, "/a/b/", "/c"); + JOIN("/a/b/c", 100, "/a/b/c"); + JOIN("/a/b/c", 100, "/", "a/b/c"); + + JOIN("/a/b/c/", 100, "/a/", "/b/", "/c/"); + JOIN("/a/b/c/", 100, "/a/b/c/"); + JOIN("/a/b/c/", 100, "/a/b/", "/c/"); + JOIN("/a/b/c/", 100, "/a/b/c", "/"); + JOIN("/a/b/c/", 100, "/", "a/b/c", "/"); +} + +TEST(path_util, JoinTruncateShort) +{ + JOIN("", 1, "/"); + JOIN("/", 2, "/"); + JOIN("a", 2, "", "aa"); + JOIN("a", 2, "", "a/"); + JOIN("a/b", 4, "a", "bc"); + JOIN("ab/", 4, "ab", "c"); + JOIN("/a/", 4, "/a", "b"); + JOIN("/a/", 4, "/a/", "b/"); + JOIN("/a/", 4, "/a", "/b/"); + JOIN("/a/", 4, "/", "a/b/"); + JOIN("//a", 4, "//", "a/b/"); + + JOIN("/a/b", 5, "/a", "b", "c"); +} + +TEST(path_util, JoinTruncateLong) +{ + JOIN("", 1, "//", "//longer", "path"); + JOIN("/", 2, "//", "//longer", "path"); + JOIN("//", 3, "//", "//longer", "path"); + JOIN("//l", 4, "//", "//longer", "path"); + /* snip */ + JOIN("//longe", 8, "//", "//longer", "path"); + JOIN("//longer", 9, "//", "//longer", "path"); + JOIN("//longer/", 10, "//", "//longer", "path"); + JOIN("//longer/p", 11, "//", "//longer", "path"); + JOIN("//longer/pa", 12, "//", "//longer", "path"); + JOIN("//longer/pat", 13, "//", "//longer", "path"); + JOIN("//longer/path", 14, "//", "//longer", "path"); // not truncated + JOIN("//longer/path", 14, "//", "//longer", "path/"); + JOIN("//longer/path/", 15, "//", "//longer", "path/"); // not truncated + JOIN("//longer/path/", 15, "//", "//longer", "path/", "trunc"); + JOIN("//longer/path/t", 16, "//", "//longer", "path/", "trunc"); +} + +TEST(path_util, JoinComplex) +{ + JOIN("/a/b/c/d/e/f/g/", 100, "/", "\\a/b", "//////c/d", "", "e\\\\", "f", "g//"); + JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "\\aa/bb", "//////cc/dd", "", "ee\\\\", "ff", "gg//"); + JOIN("1/2/3/", 100, "1", "////////", "", "2", "3\\"); +} + +#undef JOIN /* BLI_path_frame */ TEST(path_util, PathUtilFrame) From bc0b5d611c8bac1923f06dbcf9945e97c223b7c2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 24 Mar 2017 17:48:22 +1100 Subject: [PATCH 60/73] Cleanup: minor edits to path test No need for redundant ID's and correct arg order --- tests/gtests/blenlib/BLI_path_util_test.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc index 4c45bfd6758..ef469da50b2 100644 --- a/tests/gtests/blenlib/BLI_path_util_test.cc +++ b/tests/gtests/blenlib/BLI_path_util_test.cc @@ -58,7 +58,7 @@ char *zLhm65070058860608_br_find_exe(const char *default_exe) /* BLI_cleanup_path */ #ifndef _WIN32 -TEST(path_util, PathUtilClean) +TEST(path_util, Clean) { /* "/./" -> "/" */ { @@ -128,7 +128,7 @@ TEST(path_util, PathUtilClean) EXPECT_EQ(ret, true); \ EXPECT_EQ(strlen(expect), len_output); \ path[index_output + len_output] = '\0'; \ - EXPECT_STREQ(expect, &path[index_output]); \ + EXPECT_STREQ(&path[index_output], expect); \ } \ }((void)0) @@ -345,7 +345,7 @@ TEST(path_util, JoinComplex) #undef JOIN /* BLI_path_frame */ -TEST(path_util, PathUtilFrame) +TEST(path_util, Frame) { bool ret; @@ -408,7 +408,7 @@ TEST(path_util, PathUtilFrame) } /* BLI_split_dirfile */ -TEST(path_util, PathUtilSplitDirfile) +TEST(path_util, SplitDirfile) { { const char *path = ""; From d23459f5164092fb59cd952da6ddd8c0d23170d4 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 24 Mar 2017 04:06:30 -0300 Subject: [PATCH 61/73] Fix T51038: `layerInterp_mloopcol` was casting instead of rounding the interpolated RGBA channels Casting to int truncates a floating-point number, that is, it loose the fractional part. --- source/blender/blenkernel/intern/customdata.c | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index c9f0b8ec9ca..aca332f4bf5 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -805,18 +805,15 @@ static void layerInterp_mloopcol( const float *sub_weights, int count, void *dest) { MLoopCol *mc = dest; - int i; - const float *sub_weight; struct { float a; float r; float g; float b; - } col; - col.a = col.r = col.g = col.b = 0; + } col = {0}; - sub_weight = sub_weights; - for (i = 0; i < count; ++i) { + const float *sub_weight = sub_weights; + for (int i = 0; i < count; ++i) { float weight = weights ? weights[i] : 1; const MLoopCol *src = sources[i]; if (sub_weights) { @@ -833,19 +830,19 @@ static void layerInterp_mloopcol( col.a += src->a * weight; } } - + + /* delay writing to the destination incase dest is in sources */ + mc->r = iroundf(col.r); + mc->g = iroundf(col.g); + mc->b = iroundf(col.b); + mc->a = iroundf(col.a); + /* Subdivide smooth or fractal can cause problems without clamping * although weights should also not cause this situation */ CLAMP(col.a, 0.0f, 255.0f); CLAMP(col.r, 0.0f, 255.0f); CLAMP(col.g, 0.0f, 255.0f); CLAMP(col.b, 0.0f, 255.0f); - - /* delay writing to the destination incase dest is in sources */ - mc->r = (int)col.r; - mc->g = (int)col.g; - mc->b = (int)col.b; - mc->a = (int)col.a; } static int layerMaxNum_mloopcol(void) From 178708f1426dbde1d1fda33da47a76fab18e0bc8 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 24 Mar 2017 04:13:16 -0300 Subject: [PATCH 62/73] Fix of last commit. Clamp values that will be used! --- source/blender/blenkernel/intern/customdata.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index aca332f4bf5..debc7491fb8 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -839,10 +839,10 @@ static void layerInterp_mloopcol( /* Subdivide smooth or fractal can cause problems without clamping * although weights should also not cause this situation */ - CLAMP(col.a, 0.0f, 255.0f); - CLAMP(col.r, 0.0f, 255.0f); - CLAMP(col.g, 0.0f, 255.0f); - CLAMP(col.b, 0.0f, 255.0f); + CLAMP(mc->a, 0, 255); + CLAMP(mc->r, 0, 255); + CLAMP(mc->g, 0, 255); + CLAMP(mc->b, 0, 255); } static int layerMaxNum_mloopcol(void) From d52191616b5fecbdf4012909dae9a5446987ee54 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 24 Mar 2017 04:35:17 -0300 Subject: [PATCH 63/73] Fix for last fix of fix: (unsigned)char is limited to 255 setting char as value outside its range will wrap --- source/blender/blenkernel/intern/customdata.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index debc7491fb8..ea2c4f05423 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -831,18 +831,15 @@ static void layerInterp_mloopcol( } } - /* delay writing to the destination incase dest is in sources */ - mc->r = iroundf(col.r); - mc->g = iroundf(col.g); - mc->b = iroundf(col.b); - mc->a = iroundf(col.a); /* Subdivide smooth or fractal can cause problems without clamping * although weights should also not cause this situation */ - CLAMP(mc->a, 0, 255); - CLAMP(mc->r, 0, 255); - CLAMP(mc->g, 0, 255); - CLAMP(mc->b, 0, 255); + + /* also delay writing to the destination incase dest is in sources */ + mc->r = CLAMPIS(iroundf(col.r), 0, 255); + mc->g = CLAMPIS(iroundf(col.g), 0, 255); + mc->b = CLAMPIS(iroundf(col.b), 0, 255); + mc->a = CLAMPIS(iroundf(col.a), 0, 255); } static int layerMaxNum_mloopcol(void) From a14fb77feec1d3882fb2f4963498b82e18fc735c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Mar 2017 09:42:50 +0100 Subject: [PATCH 64/73] Update CLERW to the latest version --- extern/clew/README.blender | 2 +- extern/clew/src/clew.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extern/clew/README.blender b/extern/clew/README.blender index 972b46b754b..127b6bdac63 100644 --- a/extern/clew/README.blender +++ b/extern/clew/README.blender @@ -1,5 +1,5 @@ Project: OpenCL Wrangler URL: https://github.com/OpenCLWrangler/clew License: Apache 2.0 -Upstream version: 79a289e +Upstream version: 27a6867 Local modifications: None diff --git a/extern/clew/src/clew.c b/extern/clew/src/clew.c index 3717c74f1a0..dbdddfc0332 100644 --- a/extern/clew/src/clew.c +++ b/extern/clew/src/clew.c @@ -15,7 +15,7 @@ typedef HMODULE CLEW_DYNLIB_HANDLE; - #define CLEW_DYNLIB_OPEN LoadLibrary + #define CLEW_DYNLIB_OPEN LoadLibraryA #define CLEW_DYNLIB_CLOSE FreeLibrary #define CLEW_DYNLIB_IMPORT GetProcAddress #else @@ -223,7 +223,7 @@ int clewInit() __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLEW_DYNLIB_IMPORT(module, "clSetCommandQueueProperty"); #endif __clewCreateBuffer = (PFNCLCREATEBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer"); - __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer"); + __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateSubBuffer"); __clewCreateImage = (PFNCLCREATEIMAGE )CLEW_DYNLIB_IMPORT(module, "clCreateImage"); __clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clRetainMemObject"); __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clReleaseMemObject"); From 85a5fbf2ce72213c0c908ab37d0ef5cf770e1e89 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Mar 2017 10:08:18 +0100 Subject: [PATCH 65/73] Cycles: Workaround incorrect SSS with CUDA toolkit 8.0.61 --- intern/cycles/kernel/bvh/bvh.h | 7 ++++--- intern/cycles/kernel/kernel_subsurface.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h index 321983c1abc..598e138dbea 100644 --- a/intern/cycles/kernel/bvh/bvh.h +++ b/intern/cycles/kernel/bvh/bvh.h @@ -202,8 +202,9 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg, } #ifdef __SUBSURFACE__ +/* Note: ray is passed by value to work around a possible CUDA compiler bug. */ ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg, - const Ray *ray, + const Ray ray, SubsurfaceIntersection *ss_isect, int subsurface_object, uint *lcg_state, @@ -212,7 +213,7 @@ ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg, #ifdef __OBJECT_MOTION__ if(kernel_data.bvh.have_motion) { return bvh_intersect_subsurface_motion(kg, - ray, + &ray, ss_isect, subsurface_object, lcg_state, @@ -220,7 +221,7 @@ ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg, } #endif /* __OBJECT_MOTION__ */ return bvh_intersect_subsurface(kg, - ray, + &ray, ss_isect, subsurface_object, lcg_state, diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index fe88ba4ff05..64d240d779d 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -293,7 +293,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect( /* intersect with the same object. if multiple intersections are found it * will use at most BSSRDF_MAX_HITS hits, a random subset of all hits */ scene_intersect_subsurface(kg, - ray, + *ray, ss_isect, sd->object, lcg_state, @@ -448,7 +448,7 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathS /* intersect with the same object. if multiple intersections are * found it will randomly pick one of them */ SubsurfaceIntersection ss_isect; - scene_intersect_subsurface(kg, &ray, &ss_isect, sd->object, lcg_state, 1); + scene_intersect_subsurface(kg, ray, &ss_isect, sd->object, lcg_state, 1); /* evaluate bssrdf */ if(ss_isect.num_hits > 0) { From e32710d2d749b7060befb2d31fd70f127f90dc48 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Mar 2017 10:27:41 +0100 Subject: [PATCH 66/73] Buildbot: Use proper NVCC path In fact, we could probably remove this option all together. --- build_files/buildbot/slave_compile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 860dd1174cf..1d42f04f151 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -111,7 +111,7 @@ if 'cmake' in builder: cuda_chroot_name = 'buildbot_' + deb_name + '_x86_64' targets = ['player', 'blender', 'cuda'] - cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-8.0/bin/nvcc') + cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda/bin/nvcc') cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file)) From 467d824f805ab88bad63a6cef3e57113ba5a3b2b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Mar 2017 12:24:14 +0100 Subject: [PATCH 67/73] Fix T50238: Cycles: difference in texture position between OpenGL and Cycles render --- source/blender/gpu/intern/gpu_codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 211394e7932..c3896fbd659 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -360,7 +360,7 @@ static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data) BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]); for (i = 0; i < type; i++) { - BLI_dynstr_appendf(ds, "%f", data[i]); + BLI_dynstr_appendf(ds, "%.12f", data[i]); if (i == type - 1) BLI_dynstr_append(ds, ")"); else From 6aa972ebd466fea581c62c8981c020861becd714 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Mar 2017 14:36:00 +0100 Subject: [PATCH 68/73] Fix/workaround T51007: Material viewport mode crash on node with more than 64 outputs Ideally we need to find a way to remove such a static limit here, but it's not so trivial to implement for texture nodes. Requires some bigger system redesign there. Just raising limit for now, which is fine for modern systems. --- source/blender/blenkernel/BKE_node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 546f0d97c2b..193f1154c54 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -49,7 +49,7 @@ #include "RNA_types.h" /* not very important, but the stack solver likes to know a maximum */ -#define MAX_SOCKET 64 +#define MAX_SOCKET 512 struct bContext; struct bNode; From 5b45715f8a98c8577bc1f0dcbe95d58124475d2c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Mar 2017 15:22:27 +0100 Subject: [PATCH 69/73] Cycles: Correct isfinite check used in integrator Use fast-math friendly version of this function. We should probably avoid unsafe fast math, but this is to be done with real care with all the benchmarks properly done. For now comitting much safer fix. --- intern/cycles/kernel/kernel_accumulate.h | 4 ++-- intern/cycles/util/util_math.h | 27 ++++++++++++------------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 6c3ee6b8098..c589c112cc2 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -399,7 +399,7 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z); /* Reject invalid value */ - if(!isfinite(sum)) { + if(!isfinite_safe(sum)) { kernel_assert(!"Non-finite sum in path_radiance_clamp_and_sum!"); L_sum = make_float3(0.0f, 0.0f, 0.0f); @@ -468,7 +468,7 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi /* Reject invalid value */ float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z); - if(!isfinite(sum)) { + if(!isfinite_safe(sum)) { kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!"); L_sum = make_float3(0.0f, 0.0f, 0.0f); } diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index a41beab6285..2af0e56325f 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1241,19 +1241,6 @@ ccl_device_inline float __uint_as_float(uint i) return u.f; } -/* Versions of functions which are safe for fast math. */ -ccl_device_inline bool isnan_safe(float f) -{ - unsigned int x = __float_as_uint(f); - return (x << 1) > 0xff000000u; -} - -ccl_device_inline bool isfinite_safe(float f) -{ - /* By IEEE 754 rule, 2*Inf equals Inf */ - unsigned int x = __float_as_uint(f); - return (f == f) && (x == 0 || (f != 2.0f*f)); -} /* Interpolation */ @@ -1271,6 +1258,20 @@ ccl_device_inline float triangle_area(const float3& v1, const float3& v2, const #endif +/* Versions of functions which are safe for fast math. */ +ccl_device_inline bool isnan_safe(float f) +{ + unsigned int x = __float_as_uint(f); + return (x << 1) > 0xff000000u; +} + +ccl_device_inline bool isfinite_safe(float f) +{ + /* By IEEE 754 rule, 2*Inf equals Inf */ + unsigned int x = __float_as_uint(f); + return (f == f) && (x == 0 || (f != 2.0f*f)) && !((x << 1) > 0xff000000u); +} + /* Orthonormal vectors */ ccl_device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b) From 8e58e197fdb4935373eea353e0abd45973ead2da Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Mar 2017 16:33:26 +0100 Subject: [PATCH 70/73] =?UTF-8?q?=D0=90=D1=88=D1=87=20T50995:=20Wrong=20fr?= =?UTF-8?q?eestyle=20render=20with=20new=20depgraph?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The iossue was caused by 0371ef1/ --- source/blender/depsgraph/intern/builder/deg_builder.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index cb2f057a090..3ce3ec7a27a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -154,7 +154,7 @@ void deg_graph_build_finalize(Depsgraph *graph) } GHASH_FOREACH_END(); - if ((id_node->layers & graph->layers) != 0) { + if ((id_node->layers & graph->layers) != 0 || graph->layers == 0) { ID *id = id_node->id; if ((id->tag & LIB_TAG_ID_RECALC_ALL) && (id->tag & LIB_TAG_DOIT)) From e9770adf6370252993936d6a89c4a2fd7ce17498 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Fri, 24 Mar 2017 19:43:39 +0100 Subject: [PATCH 71/73] Cycles: Remove obsolete variable from the TileManager --- intern/cycles/render/tile.cpp | 2 -- intern/cycles/render/tile.h | 1 - 2 files changed, 3 deletions(-) diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index a493c3fa1cd..76d0b9a57c2 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -131,7 +131,6 @@ void TileManager::reset(BufferParams& params_, int num_samples_) state.buffer = BufferParams(); state.sample = range_start_sample - 1; state.num_tiles = 0; - state.num_rendered_tiles = 0; state.num_samples = 0; state.resolution_divider = get_divider(params.width, params.height, start_resolution); state.tiles.clear(); @@ -343,7 +342,6 @@ bool TileManager::next_tile(Tile& tile, int device) tile = Tile(state.tiles[logical_device].front()); state.tiles[logical_device].pop_front(); - state.num_rendered_tiles++; return true; } diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index 5d92ebac355..85fc89bc397 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -63,7 +63,6 @@ public: int num_samples; int resolution_divider; int num_tiles; - int num_rendered_tiles; /* Total samples over all pixels: Generally num_samples*num_pixels, * but can be higher due to the initial resolution division for previews. */ From dab3865c0bc8427a64a6a69a48cc3b727fbcf97e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 24 Mar 2017 19:59:14 +0100 Subject: [PATCH 72/73] Fix UI message issue, and style cleanup (!) --- .../blender/makesrna/intern/rna_scene_api.c | 64 +++++++++---------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index d1ecd912773..f3146c9e6a8 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -376,60 +376,54 @@ void RNA_api_scene(StructRNA *srna) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */ - RNA_def_boolean(func, - "apply_modifiers", 0, "Apply Modifiers", - "Apply modifiers to exported mesh (non destructive))"); + RNA_def_boolean(func, "apply_modifiers", false, + "Apply Modifiers", "Apply modifiers to exported mesh (non destructive))"); RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX, - "Resolution", "Modifier resolution for export", INT_MIN, INT_MAX); + "Resolution", "Modifier resolution for export", INT_MIN, INT_MAX); - RNA_def_boolean(func, "selected", 0, "Selection Only", - "Export only selected elements"); + RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements"); - RNA_def_boolean(func, "include_children", 0, "Include Children", - "Export all children of selected objects (even if not selected)"); + RNA_def_boolean(func, "include_children", false, + "Include Children", "Export all children of selected objects (even if not selected)"); - RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", - "Export related armatures (even if not selected)"); + RNA_def_boolean(func, "include_armatures", false, + "Include Armatures", "Export related armatures (even if not selected)"); - RNA_def_boolean(func, "include_shapekeys", 1, "Include Shape Keys", - "Export all Shape Keys from Mesh Objects"); + RNA_def_boolean(func, "include_shapekeys", true, "Include Shape Keys", "Export all Shape Keys from Mesh Objects"); - RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", - "Only export deforming bones with armatures"); + RNA_def_boolean(func, "deform_bones_only", false, + "Deform Bones only", "Only export deforming bones with armatures"); - RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map", - "Export only the selected UV Map"); + RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map"); - RNA_def_boolean(func, "include_uv_textures", 0, "Include UV Textures", - "Export textures assigned to the object UV Maps"); + RNA_def_boolean(func, "include_uv_textures", false, + "Include UV Textures", "Export textures assigned to the object UV Maps"); - RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures", - "Export textures assigned to the object Materials"); + RNA_def_boolean(func, "include_material_textures", false, + "Include Material Textures", "Export textures assigned to the object Materials"); - RNA_def_boolean(func, "use_texture_copies", 1, "Copy", - "Copy textures to same folder where the .dae file is exported"); + RNA_def_boolean(func, "use_texture_copies", true, + "Copy", "Copy textures to same folder where the .dae file is exported"); - RNA_def_boolean(func, "triangulate", 1, "Triangulate", - "Export Polygons (Quads & NGons) as Triangles"); + RNA_def_boolean(func, "triangulate", true, "Triangulate", "Export Polygons (Quads & NGons) as Triangles"); - RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", - "Instantiate multiple Objects from same Data"); + RNA_def_boolean(func, "use_object_instantiation", true, + "Use Object Instances", "Instantiate multiple Objects from same Data"); - RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile", - "Export additional Blender specific information (for material, shaders, bones, etc.)"); + RNA_def_boolean(func, "use_blender_profile", true, "Use Blender Profile", + "Export additional Blender specific information (for material, shaders, bones, etc.)"); - RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", - "Sort exported data by Object name"); + RNA_def_boolean(func, "sort_by_name", false, "Sort by Object name", "Sort exported data by Object name"); RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX, - "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); + "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); - RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim", - "Compatibility mode for SL, OpenSim and other compatible online worlds"); + RNA_def_boolean(func, "open_sim", false, + "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds"); - RNA_def_boolean(func, "keep_bind_info", 0, - "Keep Bind Info", "Store Bindpose information in custom bone properties for later use during Collada export"); + RNA_def_boolean(func, "keep_bind_info", false, "Keep Bind Info", + "Store bind pose information in custom bone properties for later use during Collada export"); #endif From a7f16c17c260f311e136758497e5490b226ebc03 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 24 Mar 2017 20:01:32 +0100 Subject: [PATCH 73/73] Fix various i18n ambiguous issues reported in T43295. --- source/blender/editors/space_outliner/outliner_edit.c | 3 ++- source/blender/editors/space_sequencer/sequencer_add.c | 3 +++ source/blender/makesrna/intern/rna_action.c | 3 +++ source/blender/makesrna/intern/rna_animation.c | 3 +++ source/blender/makesrna/intern/rna_fcurve.c | 3 +++ source/blender/makesrna/intern/rna_nodetree.c | 1 + 6 files changed, 15 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index bf220784371..335eb95da0e 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -519,7 +519,8 @@ void OUTLINER_OT_id_remap(wmOperatorType *ot) ot->flag = 0; - RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", ""); + prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", ""); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", "Old ID to replace"); RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, outliner_id_itemf); diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index ede6b7ce469..46f212e3679 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -38,6 +38,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "DNA_scene_types.h" #include "DNA_mask_types.h" @@ -445,6 +447,7 @@ void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot) sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", ""); RNA_def_enum_funcs(prop, RNA_movieclip_itemf); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP); RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); ot->prop = prop; } diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 0c4c7ddac81..d398ce95a52 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -34,6 +34,8 @@ #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "BKE_action.h" #include "RNA_access.h" @@ -731,6 +733,7 @@ static void rna_def_action(BlenderRNA *brna) RNA_def_property_ui_text(prop, "ID Root Type", "Type of ID block that action can be used on - " "DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); /* API calls */ RNA_api_action(srna); diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 9adbf5f6b2e..f271bccd326 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -32,6 +32,8 @@ #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "MEM_guardedalloc.h" #include "RNA_access.h" @@ -742,6 +744,7 @@ static void rna_def_keyingset_path(BlenderRNA *brna) RNA_def_property_enum_default(prop, ID_OB); RNA_def_property_enum_funcs(prop, NULL, "rna_ksPath_id_type_set", NULL); RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */ /* Group */ diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 4acdee490b8..bccc47aa95d 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -35,6 +35,8 @@ #include "BLI_math.h" +#include "BLT_translation.h" + #include "BKE_action.h" #include "RNA_access.h" @@ -1448,6 +1450,7 @@ static void rna_def_drivertarget(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, NULL, "rna_DriverTarget_id_type_set", NULL); RNA_def_property_editable_func(prop, "rna_DriverTarget_id_type_editable"); RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); /* Target Properties - Property to Drive */ diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 784004182dd..8d42d746e1c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3327,6 +3327,7 @@ static void def_frame(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); RNA_def_struct_sdna_from(srna, "NodeFrame", "storage"); + RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_ID_NODETREE); prop = RNA_def_property(srna, "shrink", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_FRAME_SHRINK);