Merge branch 'master' into blender2.8
This commit is contained in:
@@ -111,6 +111,16 @@ public:
|
|||||||
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
|
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Utility to push/pop CUDA context. */
|
||||||
|
class CUDAContextScope {
|
||||||
|
public:
|
||||||
|
CUDAContextScope(CUDADevice *device);
|
||||||
|
~CUDAContextScope();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CUDADevice *device;
|
||||||
|
};
|
||||||
|
|
||||||
class CUDADevice : public Device
|
class CUDADevice : public Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -206,16 +216,6 @@ public:
|
|||||||
cuda_error_documentation();
|
cuda_error_documentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cuda_push_context()
|
|
||||||
{
|
|
||||||
cuda_assert(cuCtxSetCurrent(cuContext));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cuda_pop_context()
|
|
||||||
{
|
|
||||||
cuda_assert(cuCtxSetCurrent(NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
CUDADevice(DeviceInfo& info, Stats &stats, bool background_)
|
CUDADevice(DeviceInfo& info, Stats &stats, bool background_)
|
||||||
: Device(info, stats, background_)
|
: Device(info, stats, background_)
|
||||||
{
|
{
|
||||||
@@ -263,7 +263,8 @@ public:
|
|||||||
cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
|
cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
|
||||||
cuDevArchitecture = major*100 + minor*10;
|
cuDevArchitecture = major*100 + minor*10;
|
||||||
|
|
||||||
cuda_pop_context();
|
/* Pop context set by cuCtxCreate. */
|
||||||
|
cuCtxPopCurrent(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CUDADevice()
|
~CUDADevice()
|
||||||
@@ -519,7 +520,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* open module */
|
/* open module */
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
string cubin_data;
|
string cubin_data;
|
||||||
CUresult result;
|
CUresult result;
|
||||||
@@ -540,8 +541,6 @@ public:
|
|||||||
if(cuda_error_(result, "cuModuleLoad"))
|
if(cuda_error_(result, "cuModuleLoad"))
|
||||||
cuda_error_message(string_printf("Failed loading CUDA kernel %s.", filter_cubin.c_str()));
|
cuda_error_message(string_printf("Failed loading CUDA kernel %s.", filter_cubin.c_str()));
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
|
|
||||||
return (result == CUDA_SUCCESS);
|
return (result == CUDA_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,36 +555,36 @@ public:
|
|||||||
|
|
||||||
void mem_alloc(const char *name, device_memory& mem, MemoryType /*type*/)
|
void mem_alloc(const char *name, device_memory& mem, MemoryType /*type*/)
|
||||||
{
|
{
|
||||||
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
if(name) {
|
if(name) {
|
||||||
VLOG(1) << "Buffer allocate: " << name << ", "
|
VLOG(1) << "Buffer allocate: " << name << ", "
|
||||||
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
|
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
|
||||||
<< string_human_readable_size(mem.memory_size()) << ")";
|
<< string_human_readable_size(mem.memory_size()) << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
CUdeviceptr device_pointer;
|
CUdeviceptr device_pointer;
|
||||||
size_t size = mem.memory_size();
|
size_t size = mem.memory_size();
|
||||||
cuda_assert(cuMemAlloc(&device_pointer, size));
|
cuda_assert(cuMemAlloc(&device_pointer, size));
|
||||||
mem.device_pointer = (device_ptr)device_pointer;
|
mem.device_pointer = (device_ptr)device_pointer;
|
||||||
mem.device_size = size;
|
mem.device_size = size;
|
||||||
stats.mem_alloc(size);
|
stats.mem_alloc(size);
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_copy_to(device_memory& mem)
|
void mem_copy_to(device_memory& mem)
|
||||||
{
|
{
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
if(mem.device_pointer)
|
if(mem.device_pointer)
|
||||||
cuda_assert(cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer), (void*)mem.data_pointer, mem.memory_size()));
|
cuda_assert(cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer), (void*)mem.data_pointer, mem.memory_size()));
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
|
void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
|
||||||
{
|
{
|
||||||
|
CUDAContextScope scope(this);
|
||||||
size_t offset = elem*y*w;
|
size_t offset = elem*y*w;
|
||||||
size_t size = elem*w*h;
|
size_t size = elem*w*h;
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
if(mem.device_pointer) {
|
if(mem.device_pointer) {
|
||||||
cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset,
|
cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset,
|
||||||
(CUdeviceptr)(mem.device_pointer + offset), size));
|
(CUdeviceptr)(mem.device_pointer + offset), size));
|
||||||
@@ -593,7 +592,6 @@ public:
|
|||||||
else {
|
else {
|
||||||
memset((char*)mem.data_pointer + offset, 0, size);
|
memset((char*)mem.data_pointer + offset, 0, size);
|
||||||
}
|
}
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_zero(device_memory& mem)
|
void mem_zero(device_memory& mem)
|
||||||
@@ -602,18 +600,17 @@ public:
|
|||||||
memset((void*)mem.data_pointer, 0, mem.memory_size());
|
memset((void*)mem.data_pointer, 0, mem.memory_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
cuda_push_context();
|
if(mem.device_pointer) {
|
||||||
if(mem.device_pointer)
|
CUDAContextScope scope(this);
|
||||||
cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()));
|
cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()));
|
||||||
cuda_pop_context();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_free(device_memory& mem)
|
void mem_free(device_memory& mem)
|
||||||
{
|
{
|
||||||
if(mem.device_pointer) {
|
if(mem.device_pointer) {
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
cuda_assert(cuMemFree(cuda_device_ptr(mem.device_pointer)));
|
cuda_assert(cuMemFree(cuda_device_ptr(mem.device_pointer)));
|
||||||
cuda_pop_context();
|
|
||||||
|
|
||||||
mem.device_pointer = 0;
|
mem.device_pointer = 0;
|
||||||
|
|
||||||
@@ -629,14 +626,13 @@ public:
|
|||||||
|
|
||||||
void const_copy_to(const char *name, void *host, size_t size)
|
void const_copy_to(const char *name, void *host, size_t size)
|
||||||
{
|
{
|
||||||
|
CUDAContextScope scope(this);
|
||||||
CUdeviceptr mem;
|
CUdeviceptr mem;
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
cuda_assert(cuModuleGetGlobal(&mem, &bytes, cuModule, name));
|
cuda_assert(cuModuleGetGlobal(&mem, &bytes, cuModule, name));
|
||||||
//assert(bytes == size);
|
//assert(bytes == size);
|
||||||
cuda_assert(cuMemcpyHtoD(mem, host, size));
|
cuda_assert(cuMemcpyHtoD(mem, host, size));
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tex_alloc(const char *name,
|
void tex_alloc(const char *name,
|
||||||
@@ -644,6 +640,8 @@ public:
|
|||||||
InterpolationType interpolation,
|
InterpolationType interpolation,
|
||||||
ExtensionType extension)
|
ExtensionType extension)
|
||||||
{
|
{
|
||||||
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
VLOG(1) << "Texture allocate: " << name << ", "
|
VLOG(1) << "Texture allocate: " << name << ", "
|
||||||
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
|
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
|
||||||
<< string_human_readable_size(mem.memory_size()) << ")";
|
<< string_human_readable_size(mem.memory_size()) << ")";
|
||||||
@@ -706,9 +704,7 @@ public:
|
|||||||
tokens[3].c_str());
|
tokens[3].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
cuda_assert(cuModuleGetTexRef(&texref, cuModule, bind_name.c_str()));
|
cuda_assert(cuModuleGetTexRef(&texref, cuModule, bind_name.c_str()));
|
||||||
cuda_pop_context();
|
|
||||||
|
|
||||||
if(!texref) {
|
if(!texref) {
|
||||||
return;
|
return;
|
||||||
@@ -721,8 +717,6 @@ public:
|
|||||||
mem_alloc(NULL, mem, MEM_READ_ONLY);
|
mem_alloc(NULL, mem, MEM_READ_ONLY);
|
||||||
mem_copy_to(mem);
|
mem_copy_to(mem);
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
|
|
||||||
CUdeviceptr cumem;
|
CUdeviceptr cumem;
|
||||||
size_t cubytes;
|
size_t cubytes;
|
||||||
|
|
||||||
@@ -738,28 +732,20 @@ public:
|
|||||||
uint32_t ptr = (uint32_t)mem.device_pointer;
|
uint32_t ptr = (uint32_t)mem.device_pointer;
|
||||||
cuda_assert(cuMemcpyHtoD(cumem, (void*)&ptr, cubytes));
|
cuda_assert(cuMemcpyHtoD(cumem, (void*)&ptr, cubytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mem_alloc(NULL, mem, MEM_READ_ONLY);
|
mem_alloc(NULL, mem, MEM_READ_ONLY);
|
||||||
mem_copy_to(mem);
|
mem_copy_to(mem);
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
|
|
||||||
cuda_assert(cuTexRefSetAddress(NULL, texref, cuda_device_ptr(mem.device_pointer), size));
|
cuda_assert(cuTexRefSetAddress(NULL, texref, cuda_device_ptr(mem.device_pointer), size));
|
||||||
cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_POINT));
|
cuda_assert(cuTexRefSetFilterMode(texref, CU_TR_FILTER_MODE_POINT));
|
||||||
cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_READ_AS_INTEGER));
|
cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_READ_AS_INTEGER));
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Texture Storage */
|
/* Texture Storage */
|
||||||
else {
|
else {
|
||||||
CUarray handle = NULL;
|
CUarray handle = NULL;
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
|
|
||||||
if(mem.data_depth > 1) {
|
if(mem.data_depth > 1) {
|
||||||
CUDA_ARRAY3D_DESCRIPTOR desc;
|
CUDA_ARRAY3D_DESCRIPTOR desc;
|
||||||
|
|
||||||
@@ -784,7 +770,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!handle) {
|
if(!handle) {
|
||||||
cuda_pop_context();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -877,14 +862,10 @@ public:
|
|||||||
cuda_assert(cuTexRefSetFilterMode(texref, filter_mode));
|
cuda_assert(cuTexRefSetFilterMode(texref, filter_mode));
|
||||||
cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_NORMALIZED_COORDINATES));
|
cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_NORMALIZED_COORDINATES));
|
||||||
}
|
}
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fermi, Data and Image Textures */
|
/* Fermi, Data and Image Textures */
|
||||||
if(!has_bindless_textures) {
|
if(!has_bindless_textures) {
|
||||||
cuda_push_context();
|
|
||||||
|
|
||||||
cuda_assert(cuTexRefSetAddressMode(texref, 0, address_mode));
|
cuda_assert(cuTexRefSetAddressMode(texref, 0, address_mode));
|
||||||
cuda_assert(cuTexRefSetAddressMode(texref, 1, address_mode));
|
cuda_assert(cuTexRefSetAddressMode(texref, 1, address_mode));
|
||||||
if(mem.data_depth > 1) {
|
if(mem.data_depth > 1) {
|
||||||
@@ -892,8 +873,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
cuda_assert(cuTexRefSetFormat(texref, format, mem.data_elements));
|
cuda_assert(cuTexRefSetFormat(texref, format, mem.data_elements));
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fermi and Kepler */
|
/* Fermi and Kepler */
|
||||||
@@ -904,9 +883,8 @@ public:
|
|||||||
{
|
{
|
||||||
if(mem.device_pointer) {
|
if(mem.device_pointer) {
|
||||||
if(tex_interp_map[mem.device_pointer]) {
|
if(tex_interp_map[mem.device_pointer]) {
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
cuArrayDestroy((CUarray)mem.device_pointer);
|
cuArrayDestroy((CUarray)mem.device_pointer);
|
||||||
cuda_pop_context();
|
|
||||||
|
|
||||||
/* Free CUtexObject (Bindless Textures) */
|
/* Free CUtexObject (Bindless Textures) */
|
||||||
if(info.has_bindless_textures && tex_bindless_map[mem.device_pointer]) {
|
if(info.has_bindless_textures && tex_bindless_map[mem.device_pointer]) {
|
||||||
@@ -960,7 +938,7 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
int4 rect = task->rect;
|
int4 rect = task->rect;
|
||||||
int w = align_up(rect.z-rect.x, 4);
|
int w = align_up(rect.z-rect.x, 4);
|
||||||
@@ -1017,7 +995,6 @@ public:
|
|||||||
CUDA_LAUNCH_KERNEL(cuNLMNormalize, normalize_args);
|
CUDA_LAUNCH_KERNEL(cuNLMNormalize, normalize_args);
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
return !have_error();
|
return !have_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1026,7 +1003,7 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
CUfunction cuFilterConstructTransform;
|
CUfunction cuFilterConstructTransform;
|
||||||
cuda_assert(cuModuleGetFunction(&cuFilterConstructTransform, cuFilterModule, "kernel_cuda_filter_construct_transform"));
|
cuda_assert(cuModuleGetFunction(&cuFilterConstructTransform, cuFilterModule, "kernel_cuda_filter_construct_transform"));
|
||||||
@@ -1046,7 +1023,6 @@ public:
|
|||||||
CUDA_LAUNCH_KERNEL(cuFilterConstructTransform, args);
|
CUDA_LAUNCH_KERNEL(cuFilterConstructTransform, args);
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
return !have_error();
|
return !have_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1058,11 +1034,11 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
mem_zero(task->storage.XtWX);
|
mem_zero(task->storage.XtWX);
|
||||||
mem_zero(task->storage.XtWY);
|
mem_zero(task->storage.XtWY);
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
|
|
||||||
CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMConstructGramian, cuFinalize;
|
CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMConstructGramian, cuFinalize;
|
||||||
cuda_assert(cuModuleGetFunction(&cuNLMCalcDifference, cuFilterModule, "kernel_cuda_filter_nlm_calc_difference"));
|
cuda_assert(cuModuleGetFunction(&cuNLMCalcDifference, cuFilterModule, "kernel_cuda_filter_nlm_calc_difference"));
|
||||||
cuda_assert(cuModuleGetFunction(&cuNLMBlur, cuFilterModule, "kernel_cuda_filter_nlm_blur"));
|
cuda_assert(cuModuleGetFunction(&cuNLMBlur, cuFilterModule, "kernel_cuda_filter_nlm_blur"));
|
||||||
@@ -1150,7 +1126,6 @@ public:
|
|||||||
CUDA_LAUNCH_KERNEL(cuFinalize, finalize_args);
|
CUDA_LAUNCH_KERNEL(cuFinalize, finalize_args);
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
return !have_error();
|
return !have_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1161,7 +1136,7 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
CUfunction cuFilterCombineHalves;
|
CUfunction cuFilterCombineHalves;
|
||||||
cuda_assert(cuModuleGetFunction(&cuFilterCombineHalves, cuFilterModule, "kernel_cuda_filter_combine_halves"));
|
cuda_assert(cuModuleGetFunction(&cuFilterCombineHalves, cuFilterModule, "kernel_cuda_filter_combine_halves"));
|
||||||
@@ -1179,7 +1154,6 @@ public:
|
|||||||
CUDA_LAUNCH_KERNEL(cuFilterCombineHalves, args);
|
CUDA_LAUNCH_KERNEL(cuFilterCombineHalves, args);
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
return !have_error();
|
return !have_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1190,7 +1164,7 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
CUfunction cuFilterDivideShadow;
|
CUfunction cuFilterDivideShadow;
|
||||||
cuda_assert(cuModuleGetFunction(&cuFilterDivideShadow, cuFilterModule, "kernel_cuda_filter_divide_shadow"));
|
cuda_assert(cuModuleGetFunction(&cuFilterDivideShadow, cuFilterModule, "kernel_cuda_filter_divide_shadow"));
|
||||||
@@ -1214,7 +1188,6 @@ public:
|
|||||||
CUDA_LAUNCH_KERNEL(cuFilterDivideShadow, args);
|
CUDA_LAUNCH_KERNEL(cuFilterDivideShadow, args);
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
return !have_error();
|
return !have_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1227,7 +1200,7 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
CUfunction cuFilterGetFeature;
|
CUfunction cuFilterGetFeature;
|
||||||
cuda_assert(cuModuleGetFunction(&cuFilterGetFeature, cuFilterModule, "kernel_cuda_filter_get_feature"));
|
cuda_assert(cuModuleGetFunction(&cuFilterGetFeature, cuFilterModule, "kernel_cuda_filter_get_feature"));
|
||||||
@@ -1250,7 +1223,6 @@ public:
|
|||||||
CUDA_LAUNCH_KERNEL(cuFilterGetFeature, args);
|
CUDA_LAUNCH_KERNEL(cuFilterGetFeature, args);
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
return !have_error();
|
return !have_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1263,7 +1235,7 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
CUfunction cuFilterDetectOutliers;
|
CUfunction cuFilterDetectOutliers;
|
||||||
cuda_assert(cuModuleGetFunction(&cuFilterDetectOutliers, cuFilterModule, "kernel_cuda_filter_detect_outliers"));
|
cuda_assert(cuModuleGetFunction(&cuFilterDetectOutliers, cuFilterModule, "kernel_cuda_filter_detect_outliers"));
|
||||||
@@ -1282,7 +1254,6 @@ public:
|
|||||||
CUDA_LAUNCH_KERNEL(cuFilterDetectOutliers, args);
|
CUDA_LAUNCH_KERNEL(cuFilterDetectOutliers, args);
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
return !have_error();
|
return !have_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1319,7 +1290,7 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
CUfunction cuPathTrace;
|
CUfunction cuPathTrace;
|
||||||
CUdeviceptr d_buffer = cuda_device_ptr(rtile.buffer);
|
CUdeviceptr d_buffer = cuda_device_ptr(rtile.buffer);
|
||||||
@@ -1333,8 +1304,9 @@ public:
|
|||||||
cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
|
cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(have_error())
|
if(have_error()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* pass in parameters */
|
/* pass in parameters */
|
||||||
void *args[] = {&d_buffer,
|
void *args[] = {&d_buffer,
|
||||||
@@ -1370,8 +1342,6 @@ public:
|
|||||||
0, 0, args, 0));
|
0, 0, args, 0));
|
||||||
|
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half)
|
void film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half)
|
||||||
@@ -1379,7 +1349,7 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
CUfunction cuFilmConvert;
|
CUfunction cuFilmConvert;
|
||||||
CUdeviceptr d_rgba = map_pixels((rgba_byte)? rgba_byte: rgba_half);
|
CUdeviceptr d_rgba = map_pixels((rgba_byte)? rgba_byte: rgba_half);
|
||||||
@@ -1424,8 +1394,6 @@ public:
|
|||||||
0, 0, args, 0));
|
0, 0, args, 0));
|
||||||
|
|
||||||
unmap_pixels((rgba_byte)? rgba_byte: rgba_half);
|
unmap_pixels((rgba_byte)? rgba_byte: rgba_half);
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader(DeviceTask& task)
|
void shader(DeviceTask& task)
|
||||||
@@ -1433,7 +1401,7 @@ public:
|
|||||||
if(have_error())
|
if(have_error())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
CUfunction cuShader;
|
CUfunction cuShader;
|
||||||
CUdeviceptr d_input = cuda_device_ptr(task.shader_input);
|
CUdeviceptr d_input = cuda_device_ptr(task.shader_input);
|
||||||
@@ -1498,8 +1466,6 @@ public:
|
|||||||
|
|
||||||
task.update_progress(NULL);
|
task.update_progress(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CUdeviceptr map_pixels(device_ptr mem)
|
CUdeviceptr map_pixels(device_ptr mem)
|
||||||
@@ -1535,7 +1501,7 @@ public:
|
|||||||
pmem.w = mem.data_width;
|
pmem.w = mem.data_width;
|
||||||
pmem.h = mem.data_height;
|
pmem.h = mem.data_height;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
glGenBuffers(1, &pmem.cuPBO);
|
glGenBuffers(1, &pmem.cuPBO);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
|
||||||
@@ -1559,8 +1525,6 @@ public:
|
|||||||
CUresult result = cuGraphicsGLRegisterBuffer(&pmem.cuPBOresource, pmem.cuPBO, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
|
CUresult result = cuGraphicsGLRegisterBuffer(&pmem.cuPBOresource, pmem.cuPBO, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
|
||||||
|
|
||||||
if(result == CUDA_SUCCESS) {
|
if(result == CUDA_SUCCESS) {
|
||||||
cuda_pop_context();
|
|
||||||
|
|
||||||
mem.device_pointer = pmem.cuTexId;
|
mem.device_pointer = pmem.cuTexId;
|
||||||
pixel_mem_map[mem.device_pointer] = pmem;
|
pixel_mem_map[mem.device_pointer] = pmem;
|
||||||
|
|
||||||
@@ -1574,8 +1538,6 @@ public:
|
|||||||
glDeleteBuffers(1, &pmem.cuPBO);
|
glDeleteBuffers(1, &pmem.cuPBO);
|
||||||
glDeleteTextures(1, &pmem.cuTexId);
|
glDeleteTextures(1, &pmem.cuTexId);
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
|
|
||||||
background = true;
|
background = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1588,7 +1550,7 @@ public:
|
|||||||
if(!background) {
|
if(!background) {
|
||||||
PixelMem pmem = pixel_mem_map[mem.device_pointer];
|
PixelMem pmem = pixel_mem_map[mem.device_pointer];
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
|
||||||
uchar *pixels = (uchar*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_ONLY);
|
uchar *pixels = (uchar*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_ONLY);
|
||||||
@@ -1597,8 +1559,6 @@ public:
|
|||||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1611,14 +1571,12 @@ public:
|
|||||||
if(!background) {
|
if(!background) {
|
||||||
PixelMem pmem = pixel_mem_map[mem.device_pointer];
|
PixelMem pmem = pixel_mem_map[mem.device_pointer];
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
cuda_assert(cuGraphicsUnregisterResource(pmem.cuPBOresource));
|
cuda_assert(cuGraphicsUnregisterResource(pmem.cuPBOresource));
|
||||||
glDeleteBuffers(1, &pmem.cuPBO);
|
glDeleteBuffers(1, &pmem.cuPBO);
|
||||||
glDeleteTextures(1, &pmem.cuTexId);
|
glDeleteTextures(1, &pmem.cuTexId);
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
|
|
||||||
pixel_mem_map.erase(pixel_mem_map.find(mem.device_pointer));
|
pixel_mem_map.erase(pixel_mem_map.find(mem.device_pointer));
|
||||||
mem.device_pointer = 0;
|
mem.device_pointer = 0;
|
||||||
|
|
||||||
@@ -1643,7 +1601,7 @@ public:
|
|||||||
PixelMem pmem = pixel_mem_map[mem.device_pointer];
|
PixelMem pmem = pixel_mem_map[mem.device_pointer];
|
||||||
float *vpointer;
|
float *vpointer;
|
||||||
|
|
||||||
cuda_push_context();
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
/* for multi devices, this assumes the inefficient method that we allocate
|
/* for multi devices, this assumes the inefficient method that we allocate
|
||||||
* all pixels on the device even though we only render to a subset */
|
* all pixels on the device even though we only render to a subset */
|
||||||
@@ -1749,8 +1707,6 @@ public:
|
|||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
cuda_pop_context();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1759,6 +1715,8 @@ public:
|
|||||||
|
|
||||||
void thread_run(DeviceTask *task)
|
void thread_run(DeviceTask *task)
|
||||||
{
|
{
|
||||||
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
if(task->type == DeviceTask::RENDER) {
|
if(task->type == DeviceTask::RENDER) {
|
||||||
RenderTile tile;
|
RenderTile tile;
|
||||||
|
|
||||||
@@ -1826,9 +1784,7 @@ public:
|
|||||||
|
|
||||||
shader(*task);
|
shader(*task);
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1849,12 +1805,11 @@ public:
|
|||||||
void task_add(DeviceTask& task)
|
void task_add(DeviceTask& task)
|
||||||
{
|
{
|
||||||
if(task.type == DeviceTask::FILM_CONVERT) {
|
if(task.type == DeviceTask::FILM_CONVERT) {
|
||||||
|
CUDAContextScope scope(this);
|
||||||
|
|
||||||
/* must be done in main thread due to opengl access */
|
/* must be done in main thread due to opengl access */
|
||||||
film_convert(task, task.buffer, task.rgba_byte, task.rgba_half);
|
film_convert(task, task.buffer, task.rgba_byte, task.rgba_half);
|
||||||
|
|
||||||
cuda_push_context();
|
|
||||||
cuda_assert(cuCtxSynchronize());
|
cuda_assert(cuCtxSynchronize());
|
||||||
cuda_pop_context();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
task_pool.push(new CUDADeviceTask(this, task));
|
task_pool.push(new CUDADeviceTask(this, task));
|
||||||
@@ -1873,6 +1828,7 @@ public:
|
|||||||
|
|
||||||
friend class CUDASplitKernelFunction;
|
friend class CUDASplitKernelFunction;
|
||||||
friend class CUDASplitKernel;
|
friend class CUDASplitKernel;
|
||||||
|
friend class CUDAContextScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* redefine the cuda_assert macro so it can be used outside of the CUDADevice class
|
/* redefine the cuda_assert macro so it can be used outside of the CUDADevice class
|
||||||
@@ -1893,6 +1849,20 @@ public:
|
|||||||
} \
|
} \
|
||||||
} (void)0
|
} (void)0
|
||||||
|
|
||||||
|
|
||||||
|
/* CUDA context scope. */
|
||||||
|
|
||||||
|
CUDAContextScope::CUDAContextScope(CUDADevice *device)
|
||||||
|
: device(device)
|
||||||
|
{
|
||||||
|
cuda_assert(cuCtxPushCurrent(device->cuContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
CUDAContextScope::~CUDAContextScope()
|
||||||
|
{
|
||||||
|
cuda_assert(cuCtxPopCurrent(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
/* split kernel */
|
/* split kernel */
|
||||||
|
|
||||||
class CUDASplitKernelFunction : public SplitKernelFunction{
|
class CUDASplitKernelFunction : public SplitKernelFunction{
|
||||||
@@ -1910,11 +1880,11 @@ public:
|
|||||||
/* enqueue the kernel, returns false if there is an error */
|
/* enqueue the kernel, returns false if there is an error */
|
||||||
bool enqueue(const KernelDimensions &dim, void *args[])
|
bool enqueue(const KernelDimensions &dim, void *args[])
|
||||||
{
|
{
|
||||||
device->cuda_push_context();
|
|
||||||
|
|
||||||
if(device->have_error())
|
if(device->have_error())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
CUDAContextScope scope(device);
|
||||||
|
|
||||||
/* we ignore dim.local_size for now, as this is faster */
|
/* we ignore dim.local_size for now, as this is faster */
|
||||||
int threads_per_block;
|
int threads_per_block;
|
||||||
cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func));
|
cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func));
|
||||||
@@ -1928,8 +1898,6 @@ public:
|
|||||||
threads_per_block, 1, 1, /* threads */
|
threads_per_block, 1, 1, /* threads */
|
||||||
0, 0, args, 0));
|
0, 0, args, 0));
|
||||||
|
|
||||||
device->cuda_pop_context();
|
|
||||||
|
|
||||||
return !device->have_error();
|
return !device->have_error();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1940,12 +1908,12 @@ CUDASplitKernel::CUDASplitKernel(CUDADevice *device) : DeviceSplitKernel(device)
|
|||||||
|
|
||||||
uint64_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory& /*data*/, size_t num_threads)
|
uint64_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory& /*data*/, size_t num_threads)
|
||||||
{
|
{
|
||||||
|
CUDAContextScope scope(device);
|
||||||
|
|
||||||
device_vector<uint64_t> size_buffer;
|
device_vector<uint64_t> size_buffer;
|
||||||
size_buffer.resize(1);
|
size_buffer.resize(1);
|
||||||
device->mem_alloc(NULL, size_buffer, MEM_READ_WRITE);
|
device->mem_alloc(NULL, size_buffer, MEM_READ_WRITE);
|
||||||
|
|
||||||
device->cuda_push_context();
|
|
||||||
|
|
||||||
uint threads = num_threads;
|
uint threads = num_threads;
|
||||||
CUdeviceptr d_size = device->cuda_device_ptr(size_buffer.device_pointer);
|
CUdeviceptr d_size = device->cuda_device_ptr(size_buffer.device_pointer);
|
||||||
|
|
||||||
@@ -1967,8 +1935,6 @@ uint64_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory
|
|||||||
1, 1, 1,
|
1, 1, 1,
|
||||||
0, 0, (void**)&args, 0));
|
0, 0, (void**)&args, 0));
|
||||||
|
|
||||||
device->cuda_pop_context();
|
|
||||||
|
|
||||||
device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint64_t));
|
device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint64_t));
|
||||||
device->mem_free(size_buffer);
|
device->mem_free(size_buffer);
|
||||||
|
|
||||||
@@ -1986,7 +1952,7 @@ bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim
|
|||||||
device_memory& use_queues_flag,
|
device_memory& use_queues_flag,
|
||||||
device_memory& work_pool_wgs)
|
device_memory& work_pool_wgs)
|
||||||
{
|
{
|
||||||
device->cuda_push_context();
|
CUDAContextScope scope(device);
|
||||||
|
|
||||||
CUdeviceptr d_split_data = device->cuda_device_ptr(split_data.device_pointer);
|
CUdeviceptr d_split_data = device->cuda_device_ptr(split_data.device_pointer);
|
||||||
CUdeviceptr d_ray_state = device->cuda_device_ptr(ray_state.device_pointer);
|
CUdeviceptr d_ray_state = device->cuda_device_ptr(ray_state.device_pointer);
|
||||||
@@ -2050,26 +2016,21 @@ bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim
|
|||||||
|
|
||||||
CUDASplitKernelFunction(device, data_init).enqueue(dim, (void**)&args);
|
CUDASplitKernelFunction(device, data_init).enqueue(dim, (void**)&args);
|
||||||
|
|
||||||
device->cuda_pop_context();
|
|
||||||
|
|
||||||
return !device->have_error();
|
return !device->have_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
SplitKernelFunction* CUDASplitKernel::get_split_kernel_function(const string& kernel_name,
|
SplitKernelFunction* CUDASplitKernel::get_split_kernel_function(const string& kernel_name,
|
||||||
const DeviceRequestedFeatures&)
|
const DeviceRequestedFeatures&)
|
||||||
{
|
{
|
||||||
|
CUDAContextScope scope(device);
|
||||||
CUfunction func;
|
CUfunction func;
|
||||||
|
|
||||||
device->cuda_push_context();
|
|
||||||
|
|
||||||
cuda_assert(cuModuleGetFunction(&func, device->cuModule, (string("kernel_cuda_") + kernel_name).data()));
|
cuda_assert(cuModuleGetFunction(&func, device->cuModule, (string("kernel_cuda_") + kernel_name).data()));
|
||||||
if(device->have_error()) {
|
if(device->have_error()) {
|
||||||
device->cuda_error_message(string_printf("kernel \"kernel_cuda_%s\" not found in module", kernel_name.data()));
|
device->cuda_error_message(string_printf("kernel \"kernel_cuda_%s\" not found in module", kernel_name.data()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
device->cuda_pop_context();
|
|
||||||
|
|
||||||
return new CUDASplitKernelFunction(device, func);
|
return new CUDASplitKernelFunction(device, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2080,12 +2041,11 @@ int2 CUDASplitKernel::split_kernel_local_size()
|
|||||||
|
|
||||||
int2 CUDASplitKernel::split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask * /*task*/)
|
int2 CUDASplitKernel::split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask * /*task*/)
|
||||||
{
|
{
|
||||||
|
CUDAContextScope scope(device);
|
||||||
size_t free;
|
size_t free;
|
||||||
size_t total;
|
size_t total;
|
||||||
|
|
||||||
device->cuda_push_context();
|
|
||||||
cuda_assert(cuMemGetInfo(&free, &total));
|
cuda_assert(cuMemGetInfo(&free, &total));
|
||||||
device->cuda_pop_context();
|
|
||||||
|
|
||||||
VLOG(1) << "Maximum device allocation size: "
|
VLOG(1) << "Maximum device allocation size: "
|
||||||
<< string_human_readable_number(free) << " bytes. ("
|
<< string_human_readable_number(free) << " bytes. ("
|
||||||
|
|||||||
@@ -51,6 +51,19 @@ def draw_keyframing_tools(context, layout):
|
|||||||
row.operator("anim.keyframe_delete_v3d", text="Remove")
|
row.operator("anim.keyframe_delete_v3d", text="Remove")
|
||||||
|
|
||||||
|
|
||||||
|
# Used by vertex & weight paint
|
||||||
|
def draw_vpaint_symmetry(layout, vpaint):
|
||||||
|
col = layout.column(align=True)
|
||||||
|
col.label(text="Mirror:")
|
||||||
|
row = col.row(align=True)
|
||||||
|
|
||||||
|
row.prop(vpaint, "use_symmetry_x", text="X", toggle=True)
|
||||||
|
row.prop(vpaint, "use_symmetry_y", text="Y", toggle=True)
|
||||||
|
row.prop(vpaint, "use_symmetry_z", text="Z", toggle=True)
|
||||||
|
|
||||||
|
col = layout.column()
|
||||||
|
col.prop(vpaint, "radial_symmetry", text="Radial")
|
||||||
|
|
||||||
# ********** default tools for object-mode ****************
|
# ********** default tools for object-mode ****************
|
||||||
|
|
||||||
|
|
||||||
@@ -1134,7 +1147,11 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
|
|||||||
self.prop_unified_color_picker(col, context, brush, "color", value_slider=True)
|
self.prop_unified_color_picker(col, context, brush, "color", value_slider=True)
|
||||||
if settings.palette:
|
if settings.palette:
|
||||||
col.template_palette(settings, "palette", color=True)
|
col.template_palette(settings, "palette", color=True)
|
||||||
self.prop_unified_color(col, context, brush, "color", text="")
|
row = col.row(align=True)
|
||||||
|
self.prop_unified_color(row, context, brush, "color", text="")
|
||||||
|
self.prop_unified_color(row, context, brush, "secondary_color", text="")
|
||||||
|
row.separator()
|
||||||
|
row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="")
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
row = col.row(align=True)
|
row = col.row(align=True)
|
||||||
@@ -1717,6 +1734,19 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
|
|||||||
props.data_type = 'VGROUP_WEIGHTS'
|
props.data_type = 'VGROUP_WEIGHTS'
|
||||||
|
|
||||||
|
|
||||||
|
class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel):
|
||||||
|
bl_category = "Tools"
|
||||||
|
bl_context = "weightpaint"
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
bl_label = "Symmetry"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
toolsettings = context.tool_settings
|
||||||
|
wpaint = toolsettings.weight_paint
|
||||||
|
draw_vpaint_symmetry(layout, wpaint)
|
||||||
|
|
||||||
|
|
||||||
class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
|
class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
|
||||||
bl_category = "Options"
|
bl_category = "Options"
|
||||||
bl_context = "weightpaint"
|
bl_context = "weightpaint"
|
||||||
@@ -1779,6 +1809,20 @@ class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
|
|||||||
#~ col.label(text="Multiply:")
|
#~ col.label(text="Multiply:")
|
||||||
#~ col.prop(vpaint, "mul", text="")
|
#~ col.prop(vpaint, "mul", text="")
|
||||||
|
|
||||||
|
|
||||||
|
class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel):
|
||||||
|
bl_category = "Tools"
|
||||||
|
bl_context = "vertexpaint"
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
bl_label = "Symmetry"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
toolsettings = context.tool_settings
|
||||||
|
vpaint = toolsettings.vertex_paint
|
||||||
|
draw_vpaint_symmetry(layout, vpaint)
|
||||||
|
|
||||||
|
|
||||||
# ********** default tools for texture-paint ****************
|
# ********** default tools for texture-paint ****************
|
||||||
|
|
||||||
|
|
||||||
@@ -2058,8 +2102,10 @@ classes = (
|
|||||||
VIEW3D_PT_sculpt_symmetry,
|
VIEW3D_PT_sculpt_symmetry,
|
||||||
VIEW3D_PT_tools_brush_appearance,
|
VIEW3D_PT_tools_brush_appearance,
|
||||||
VIEW3D_PT_tools_weightpaint,
|
VIEW3D_PT_tools_weightpaint,
|
||||||
|
VIEW3D_PT_tools_weightpaint_symmetry,
|
||||||
VIEW3D_PT_tools_weightpaint_options,
|
VIEW3D_PT_tools_weightpaint_options,
|
||||||
VIEW3D_PT_tools_vertexpaint,
|
VIEW3D_PT_tools_vertexpaint,
|
||||||
|
VIEW3D_PT_tools_vertexpaint_symmetry,
|
||||||
VIEW3D_PT_tools_imagepaint_external,
|
VIEW3D_PT_tools_imagepaint_external,
|
||||||
VIEW3D_PT_tools_imagepaint_symmetry,
|
VIEW3D_PT_tools_imagepaint_symmetry,
|
||||||
VIEW3D_PT_tools_projectpaint,
|
VIEW3D_PT_tools_projectpaint,
|
||||||
|
|||||||
@@ -162,6 +162,14 @@ void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups, struct B
|
|||||||
|
|
||||||
void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
|
void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
|
||||||
|
|
||||||
|
/* Used for both vertex color and weight paint */
|
||||||
|
struct SculptVertexPaintGeomMap {
|
||||||
|
int *vert_map_mem;
|
||||||
|
struct MeshElemMap *vert_to_loop;
|
||||||
|
int *poly_map_mem;
|
||||||
|
struct MeshElemMap *vert_to_poly;
|
||||||
|
};
|
||||||
|
|
||||||
/* Session data (mode-specific) */
|
/* Session data (mode-specific) */
|
||||||
|
|
||||||
typedef struct SculptSession {
|
typedef struct SculptSession {
|
||||||
@@ -207,10 +215,38 @@ typedef struct SculptSession {
|
|||||||
|
|
||||||
struct SculptStroke *stroke;
|
struct SculptStroke *stroke;
|
||||||
struct StrokeCache *cache;
|
struct StrokeCache *cache;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
struct SculptVertexPaintGeomMap gmap;
|
||||||
|
|
||||||
|
/* For non-airbrush painting to re-apply from the original (MLoop aligned). */
|
||||||
|
unsigned int *previous_color;
|
||||||
|
} vpaint;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct SculptVertexPaintGeomMap gmap;
|
||||||
|
|
||||||
|
/* Vertex aligned arrays of weights. */
|
||||||
|
/* For non-airbrush painting to re-apply from the original. */
|
||||||
|
float *previous_weight;
|
||||||
|
/* Keep track of how much each vertex has been painted (non-airbrush only). */
|
||||||
|
float *alpha_weight;
|
||||||
|
} wpaint;
|
||||||
|
|
||||||
|
//struct {
|
||||||
|
//ToDo: identify sculpt-only fields
|
||||||
|
//} sculpt;
|
||||||
|
} mode;
|
||||||
|
int mode_type;
|
||||||
|
|
||||||
|
/* This flag prevents PBVH from being freed when creating the vp_handle for texture paint. */
|
||||||
|
bool building_vp_handle;
|
||||||
} SculptSession;
|
} SculptSession;
|
||||||
|
|
||||||
void BKE_sculptsession_free(struct Object *ob);
|
void BKE_sculptsession_free(struct Object *ob);
|
||||||
void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
|
void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
|
||||||
|
void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
|
||||||
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
|
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
|
||||||
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
|
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
|
||||||
void BKE_sculpt_update_mesh_elements(
|
void BKE_sculpt_update_mesh_elements(
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
struct Gwn_Batch;
|
struct Gwn_Batch;
|
||||||
struct CCGElem;
|
struct CCGElem;
|
||||||
struct CCGKey;
|
struct CCGKey;
|
||||||
|
struct CCGDerivedMesh;
|
||||||
struct CustomData;
|
struct CustomData;
|
||||||
struct DMFlagMat;
|
struct DMFlagMat;
|
||||||
struct MPoly;
|
struct MPoly;
|
||||||
@@ -72,7 +73,7 @@ void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
|
|||||||
struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
|
struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
|
||||||
unsigned int **grid_hidden);
|
unsigned int **grid_hidden);
|
||||||
void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, bool smooth_shading, struct BMLog *log, const int cd_vert_node_offset, const int cd_face_node_offset);
|
void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, bool smooth_shading, struct BMLog *log, const int cd_vert_node_offset, const int cd_face_node_offset);
|
||||||
|
void BKE_pbvh_set_ccgdm(PBVH *bvh, struct CCGDerivedMesh *ccgdm);
|
||||||
void BKE_pbvh_free(PBVH *bvh);
|
void BKE_pbvh_free(PBVH *bvh);
|
||||||
void BKE_pbvh_free_layer_disp(PBVH *bvh);
|
void BKE_pbvh_free_layer_disp(PBVH *bvh);
|
||||||
|
|
||||||
@@ -119,6 +120,7 @@ void BKE_pbvh_raycast_project_ray_root(
|
|||||||
void BKE_pbvh_node_draw(PBVHNode *node, void *data);
|
void BKE_pbvh_node_draw(PBVHNode *node, void *data);
|
||||||
void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
|
void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
|
||||||
int (*setMaterial)(int matnr, void *attribs), bool wireframe, bool fast);
|
int (*setMaterial)(int matnr, void *attribs), bool wireframe, bool fast);
|
||||||
|
void BKE_pbvh_draw_BB(PBVH *bvh);
|
||||||
void BKE_pbvh_draw_cb(
|
void BKE_pbvh_draw_cb(
|
||||||
PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
|
PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
|
||||||
void (*draw_fn)(void *user_data, struct Gwn_Batch *batch), void *user_data);
|
void (*draw_fn)(void *user_data, struct Gwn_Batch *batch), void *user_data);
|
||||||
@@ -145,6 +147,7 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
|
|||||||
|
|
||||||
/* multires level, only valid for type == PBVH_GRIDS */
|
/* multires level, only valid for type == PBVH_GRIDS */
|
||||||
void BKE_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
|
void BKE_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
|
||||||
|
struct CCGDerivedMesh *BKE_pbvh_get_ccgdm(const PBVH *bvh);
|
||||||
|
|
||||||
/* Only valid for type == PBVH_BMESH */
|
/* Only valid for type == PBVH_BMESH */
|
||||||
struct BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
|
struct BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
|
||||||
|
|||||||
@@ -2666,7 +2666,7 @@ static void mesh_build_data(
|
|||||||
ob->lastDataMask = dataMask;
|
ob->lastDataMask = dataMask;
|
||||||
ob->lastNeedMapping = need_mapping;
|
ob->lastNeedMapping = need_mapping;
|
||||||
|
|
||||||
if ((ob->mode & OB_MODE_SCULPT) && ob->sculpt) {
|
if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) {
|
||||||
/* create PBVH immediately (would be created on the fly too,
|
/* create PBVH immediately (would be created on the fly too,
|
||||||
* but this avoids waiting on first stroke) */
|
* but this avoids waiting on first stroke) */
|
||||||
|
|
||||||
|
|||||||
@@ -551,6 +551,11 @@ static void cdDM_drawMappedFaces(
|
|||||||
|
|
||||||
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
|
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
|
||||||
|
|
||||||
|
if (cddm->pbvh) {
|
||||||
|
if (G.debug_value == 14)
|
||||||
|
BKE_pbvh_draw_BB(cddm->pbvh);
|
||||||
|
}
|
||||||
|
|
||||||
/* fist, setup common buffers */
|
/* fist, setup common buffers */
|
||||||
GPU_vertex_setup(dm);
|
GPU_vertex_setup(dm);
|
||||||
GPU_triangle_setup(dm);
|
GPU_triangle_setup(dm);
|
||||||
|
|||||||
@@ -2736,7 +2736,7 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
|
|||||||
{
|
{
|
||||||
SculptSession *ss = ob->sculpt;
|
SculptSession *ss = ob->sculpt;
|
||||||
|
|
||||||
if (ss) {
|
if (ss && ss->building_vp_handle == false) {
|
||||||
if (!ss->cache) {
|
if (!ss->cache) {
|
||||||
/* we free pbvh on changes, except during sculpt since it can't deal with
|
/* we free pbvh on changes, except during sculpt since it can't deal with
|
||||||
* changing PVBH node organization, we hope topology does not change in
|
* changing PVBH node organization, we hope topology does not change in
|
||||||
@@ -2747,6 +2747,9 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BKE_sculptsession_free_deformMats(ob->sculpt);
|
BKE_sculptsession_free_deformMats(ob->sculpt);
|
||||||
|
|
||||||
|
/* In vertex/weight paint, force maps to be rebuilt. */
|
||||||
|
BKE_sculptsession_free_vwpaint_data(ob->sculpt);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PBVHNode **nodes;
|
PBVHNode **nodes;
|
||||||
|
|||||||
@@ -676,6 +676,29 @@ void BKE_sculptsession_free_deformMats(SculptSession *ss)
|
|||||||
MEM_SAFE_FREE(ss->deform_imats);
|
MEM_SAFE_FREE(ss->deform_imats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss)
|
||||||
|
{
|
||||||
|
struct SculptVertexPaintGeomMap *gmap = NULL;
|
||||||
|
if (ss->mode_type == OB_MODE_VERTEX_PAINT) {
|
||||||
|
gmap = &ss->mode.vpaint.gmap;
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(ss->mode.vpaint.previous_color);
|
||||||
|
}
|
||||||
|
else if (ss->mode_type == OB_MODE_WEIGHT_PAINT) {
|
||||||
|
gmap = &ss->mode.wpaint.gmap;
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(ss->mode.wpaint.alpha_weight);
|
||||||
|
MEM_SAFE_FREE(ss->mode.wpaint.previous_weight);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MEM_SAFE_FREE(gmap->vert_to_loop);
|
||||||
|
MEM_SAFE_FREE(gmap->vert_map_mem);
|
||||||
|
MEM_SAFE_FREE(gmap->vert_to_poly);
|
||||||
|
MEM_SAFE_FREE(gmap->poly_map_mem);
|
||||||
|
}
|
||||||
|
|
||||||
/* Write out the sculpt dynamic-topology BMesh to the Mesh */
|
/* Write out the sculpt dynamic-topology BMesh to the Mesh */
|
||||||
static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
|
static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
|
||||||
{
|
{
|
||||||
@@ -717,10 +740,7 @@ void BKE_sculptsession_bm_to_me_for_render(Object *object)
|
|||||||
*/
|
*/
|
||||||
BKE_object_free_derived_caches(object);
|
BKE_object_free_derived_caches(object);
|
||||||
|
|
||||||
if (object->sculpt->pbvh) {
|
MEM_SAFE_FREE(object->sculpt->pbvh);
|
||||||
BKE_pbvh_free(object->sculpt->pbvh);
|
|
||||||
object->sculpt->pbvh = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sculptsession_bm_to_me_update_data_only(object, false);
|
sculptsession_bm_to_me_update_data_only(object, false);
|
||||||
|
|
||||||
@@ -767,6 +787,8 @@ void BKE_sculptsession_free(Object *ob)
|
|||||||
if (ss->deform_imats)
|
if (ss->deform_imats)
|
||||||
MEM_freeN(ss->deform_imats);
|
MEM_freeN(ss->deform_imats);
|
||||||
|
|
||||||
|
BKE_sculptsession_free_vwpaint_data(ob->sculpt);
|
||||||
|
|
||||||
MEM_freeN(ss);
|
MEM_freeN(ss);
|
||||||
|
|
||||||
ob->sculpt = NULL;
|
ob->sculpt = NULL;
|
||||||
@@ -852,6 +874,8 @@ void BKE_sculpt_update_mesh_elements(
|
|||||||
ss->modifiers_active = sculpt_modifiers_active(scene, sd, ob);
|
ss->modifiers_active = sculpt_modifiers_active(scene, sd, ob);
|
||||||
ss->show_diffuse_color = (sd->flags & SCULPT_SHOW_DIFFUSE) != 0;
|
ss->show_diffuse_color = (sd->flags & SCULPT_SHOW_DIFFUSE) != 0;
|
||||||
|
|
||||||
|
ss->building_vp_handle = false;
|
||||||
|
|
||||||
if (need_mask) {
|
if (need_mask) {
|
||||||
if (mmd == NULL) {
|
if (mmd == NULL) {
|
||||||
if (!CustomData_has_layer(&me->vdata, CD_PAINT_MASK)) {
|
if (!CustomData_has_layer(&me->vdata, CD_PAINT_MASK)) {
|
||||||
@@ -880,7 +904,8 @@ void BKE_sculpt_update_mesh_elements(
|
|||||||
|
|
||||||
dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH);
|
dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH);
|
||||||
|
|
||||||
if (mmd) {
|
/* VWPaint require mesh info for loop lookup, so require sculpt mode here */
|
||||||
|
if (mmd && ob->mode & OB_MODE_SCULPT) {
|
||||||
ss->multires = mmd;
|
ss->multires = mmd;
|
||||||
ss->totvert = dm->getNumVerts(dm);
|
ss->totvert = dm->getNumVerts(dm);
|
||||||
ss->totpoly = dm->getNumPolys(dm);
|
ss->totpoly = dm->getNumPolys(dm);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include "BKE_pbvh.h"
|
#include "BKE_pbvh.h"
|
||||||
#include "BKE_ccg.h"
|
#include "BKE_ccg.h"
|
||||||
|
#include "BKE_subsurf.h"
|
||||||
#include "BKE_DerivedMesh.h"
|
#include "BKE_DerivedMesh.h"
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
|
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
|
||||||
@@ -607,6 +608,10 @@ void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids,
|
|||||||
MEM_freeN(prim_bbc);
|
MEM_freeN(prim_bbc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BKE_pbvh_set_ccgdm(PBVH *bvh, CCGDerivedMesh *ccgdm) {
|
||||||
|
bvh->ccgdm = ccgdm;
|
||||||
|
}
|
||||||
|
|
||||||
PBVH *BKE_pbvh_new(void)
|
PBVH *BKE_pbvh_new(void)
|
||||||
{
|
{
|
||||||
PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
|
PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
|
||||||
@@ -1157,7 +1162,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pbvh_draw_BB(PBVH *bvh)
|
void BKE_pbvh_draw_BB(PBVH *bvh)
|
||||||
{
|
{
|
||||||
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
|
||||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||||
@@ -1331,6 +1336,11 @@ void BKE_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
|
|||||||
*key = bvh->gridkey;
|
*key = bvh->gridkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCGDerivedMesh *BKE_pbvh_get_ccgdm(const PBVH *bvh) {
|
||||||
|
return bvh->ccgdm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
|
BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
|
||||||
{
|
{
|
||||||
BLI_assert(bvh->type == PBVH_BMESH);
|
BLI_assert(bvh->type == PBVH_BMESH);
|
||||||
@@ -1844,7 +1854,7 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*fnors)[3],
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (G.debug_value == 14)
|
if (G.debug_value == 14)
|
||||||
pbvh_draw_BB(bvh);
|
BKE_pbvh_draw_BB(bvh);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PBVHNodeDrawCallbackData {
|
struct PBVHNodeDrawCallbackData {
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ struct PBVH {
|
|||||||
* objects in sculpt mode with different sizes at the same time, so now storing that common gpu buffer
|
* objects in sculpt mode with different sizes at the same time, so now storing that common gpu buffer
|
||||||
* in an opaque pointer per pbvh. See T47637. */
|
* in an opaque pointer per pbvh. See T47637. */
|
||||||
struct GridCommonGPUBuffer *grid_common_gpu_buffer;
|
struct GridCommonGPUBuffer *grid_common_gpu_buffer;
|
||||||
|
/* The ccgdm is required for CD_ORIGINDEX lookup in vertex paint + multires */
|
||||||
|
struct CCGDerivedMesh *ccgdm;
|
||||||
|
|
||||||
/* Only used during BVH build and update,
|
/* Only used during BVH build and update,
|
||||||
* don't need to remain valid after */
|
* don't need to remain valid after */
|
||||||
|
|||||||
@@ -346,16 +346,10 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
|
|||||||
ToolSettings *ts = sce_dst->toolsettings = MEM_dupallocN(sce_dst->toolsettings);
|
ToolSettings *ts = sce_dst->toolsettings = MEM_dupallocN(sce_dst->toolsettings);
|
||||||
if (ts->vpaint) {
|
if (ts->vpaint) {
|
||||||
ts->vpaint = MEM_dupallocN(ts->vpaint);
|
ts->vpaint = MEM_dupallocN(ts->vpaint);
|
||||||
ts->vpaint->paintcursor = NULL;
|
|
||||||
ts->vpaint->vpaint_prev = NULL;
|
|
||||||
ts->vpaint->wpaint_prev = NULL;
|
|
||||||
BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag_subdata);
|
BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag_subdata);
|
||||||
}
|
}
|
||||||
if (ts->wpaint) {
|
if (ts->wpaint) {
|
||||||
ts->wpaint = MEM_dupallocN(ts->wpaint);
|
ts->wpaint = MEM_dupallocN(ts->wpaint);
|
||||||
ts->wpaint->paintcursor = NULL;
|
|
||||||
ts->wpaint->vpaint_prev = NULL;
|
|
||||||
ts->wpaint->wpaint_prev = NULL;
|
|
||||||
BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag_subdata);
|
BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag_subdata);
|
||||||
}
|
}
|
||||||
if (ts->sculpt) {
|
if (ts->sculpt) {
|
||||||
@@ -464,16 +458,10 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
|
|||||||
if (ts) {
|
if (ts) {
|
||||||
if (ts->vpaint) {
|
if (ts->vpaint) {
|
||||||
ts->vpaint = MEM_dupallocN(ts->vpaint);
|
ts->vpaint = MEM_dupallocN(ts->vpaint);
|
||||||
ts->vpaint->paintcursor = NULL;
|
|
||||||
ts->vpaint->vpaint_prev = NULL;
|
|
||||||
ts->vpaint->wpaint_prev = NULL;
|
|
||||||
BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, 0);
|
BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, 0);
|
||||||
}
|
}
|
||||||
if (ts->wpaint) {
|
if (ts->wpaint) {
|
||||||
ts->wpaint = MEM_dupallocN(ts->wpaint);
|
ts->wpaint = MEM_dupallocN(ts->wpaint);
|
||||||
ts->wpaint->paintcursor = NULL;
|
|
||||||
ts->wpaint->vpaint_prev = NULL;
|
|
||||||
ts->wpaint->wpaint_prev = NULL;
|
|
||||||
BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, 0);
|
BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, 0);
|
||||||
}
|
}
|
||||||
if (ts->sculpt) {
|
if (ts->sculpt) {
|
||||||
|
|||||||
@@ -3429,6 +3429,11 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
|
|||||||
int gridFaces = gridSize - 1, totface;
|
int gridFaces = gridSize - 1, totface;
|
||||||
int prev_mat_nr = -1;
|
int prev_mat_nr = -1;
|
||||||
|
|
||||||
|
if (ccgdm->pbvh) {
|
||||||
|
if (G.debug_value == 14)
|
||||||
|
BKE_pbvh_draw_BB(ccgdm->pbvh);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WITH_OPENSUBDIV
|
#ifdef WITH_OPENSUBDIV
|
||||||
if (ccgdm->useGpuBackend) {
|
if (ccgdm->useGpuBackend) {
|
||||||
int new_matnr;
|
int new_matnr;
|
||||||
@@ -4162,7 +4167,8 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
|
|||||||
if (!ob->sculpt)
|
if (!ob->sculpt)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
|
/* In vwpaint, we always use a grid_pbvh for multires/subsurf */
|
||||||
|
grid_pbvh = (!(ob->mode & OB_MODE_SCULPT) || ccgDM_use_grid_pbvh(ccgdm));
|
||||||
|
|
||||||
if (ob->sculpt->pbvh) {
|
if (ob->sculpt->pbvh) {
|
||||||
if (grid_pbvh) {
|
if (grid_pbvh) {
|
||||||
@@ -4178,12 +4184,18 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
|
|||||||
ccgdm->pbvh = ob->sculpt->pbvh;
|
ccgdm->pbvh = ob->sculpt->pbvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ccgdm->pbvh)
|
if (ccgdm->pbvh) {
|
||||||
|
/* For vertex paint, keep track of ccgdm */
|
||||||
|
if (!(ob->mode & OB_MODE_SCULPT)) {
|
||||||
|
BKE_pbvh_set_ccgdm(ccgdm->pbvh, ccgdm);
|
||||||
|
}
|
||||||
return ccgdm->pbvh;
|
return ccgdm->pbvh;
|
||||||
|
}
|
||||||
|
|
||||||
/* no pbvh exists yet, we need to create one. only in case of multires
|
/* no pbvh exists yet, we need to create one. only in case of multires
|
||||||
* we build a pbvh over the modified mesh, in other cases the base mesh
|
* we build a pbvh over the modified mesh, in other cases the base mesh
|
||||||
* is being sculpted, so we build a pbvh from that. */
|
* is being sculpted, so we build a pbvh from that. */
|
||||||
|
/* Note: vwpaint always builds a pbvh over the modified mesh. */
|
||||||
if (grid_pbvh) {
|
if (grid_pbvh) {
|
||||||
ccgdm_create_grids(dm);
|
ccgdm_create_grids(dm);
|
||||||
|
|
||||||
@@ -4214,6 +4226,10 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
|
|||||||
if (ccgdm->pbvh)
|
if (ccgdm->pbvh)
|
||||||
pbvh_show_diffuse_color_set(ccgdm->pbvh, ob->sculpt->show_diffuse_color);
|
pbvh_show_diffuse_color_set(ccgdm->pbvh, ob->sculpt->show_diffuse_color);
|
||||||
|
|
||||||
|
/* For vertex paint, keep track of ccgdm */
|
||||||
|
if (!(ob->mode & OB_MODE_SCULPT) && ccgdm->pbvh) {
|
||||||
|
BKE_pbvh_set_ccgdm(ccgdm->pbvh, ccgdm);
|
||||||
|
}
|
||||||
return ccgdm->pbvh;
|
return ccgdm->pbvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6130,16 +6130,6 @@ static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain)
|
|||||||
sce->toolsettings->particle.scene_layer = NULL;
|
sce->toolsettings->particle.scene_layer = NULL;
|
||||||
sce->toolsettings->particle.object = NULL;
|
sce->toolsettings->particle.object = NULL;
|
||||||
sce->toolsettings->gp_sculpt.paintcursor = NULL;
|
sce->toolsettings->gp_sculpt.paintcursor = NULL;
|
||||||
|
|
||||||
/* in rare cases this is needed, see [#33806] */
|
|
||||||
if (sce->toolsettings->vpaint) {
|
|
||||||
sce->toolsettings->vpaint->vpaint_prev = NULL;
|
|
||||||
sce->toolsettings->vpaint->tot = 0;
|
|
||||||
}
|
|
||||||
if (sce->toolsettings->wpaint) {
|
|
||||||
sce->toolsettings->wpaint->wpaint_prev = NULL;
|
|
||||||
sce->toolsettings->wpaint->tot = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* relink grease pencil drawing brushes */
|
/* relink grease pencil drawing brushes */
|
||||||
link_list(fd, &sce->toolsettings->gp_brushes);
|
link_list(fd, &sce->toolsettings->gp_brushes);
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
#include "DNA_genfile.h"
|
#include "DNA_genfile.h"
|
||||||
|
|
||||||
#include "BKE_animsys.h"
|
#include "BKE_animsys.h"
|
||||||
|
#include "BKE_brush.h"
|
||||||
#include "BKE_colortools.h"
|
#include "BKE_colortools.h"
|
||||||
#include "BKE_library.h"
|
#include "BKE_library.h"
|
||||||
#include "BKE_main.h"
|
#include "BKE_main.h"
|
||||||
@@ -1702,6 +1703,24 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Brush *br;
|
||||||
|
br = (Brush *)BKE_libblock_find_name_ex(main, ID_BR, "Average");
|
||||||
|
if (!br) {
|
||||||
|
br = BKE_brush_add(main, "Average", OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT);
|
||||||
|
br->vertexpaint_tool = PAINT_BLEND_AVERAGE;
|
||||||
|
br->ob_mode = OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
br = (Brush *)BKE_libblock_find_name_ex(main, ID_BR, "Smear");
|
||||||
|
if (!br) {
|
||||||
|
br = BKE_brush_add(main, "Smear", OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT);
|
||||||
|
br->vertexpaint_tool = PAINT_BLEND_SMEAR;
|
||||||
|
br->ob_mode = OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,6 +140,16 @@ void BLO_update_defaults_startup_blend(Main *bmain)
|
|||||||
sculpt->detail_size = 12;
|
sculpt->detail_size = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ts->vpaint) {
|
||||||
|
VPaint *vp = ts->vpaint;
|
||||||
|
vp->radial_symm[0] = vp->radial_symm[1] = vp->radial_symm[2] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ts->wpaint) {
|
||||||
|
VPaint *wp = ts->wpaint;
|
||||||
|
wp->radial_symm[0] = wp->radial_symm[1] = wp->radial_symm[2] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ts->gp_sculpt.brush[0].size == 0) {
|
if (ts->gp_sculpt.brush[0].size == 0) {
|
||||||
GP_BrushEdit_Settings *gset = &ts->gp_sculpt;
|
GP_BrushEdit_Settings *gset = &ts->gp_sculpt;
|
||||||
GP_EditBrush_Data *brush;
|
GP_EditBrush_Data *brush;
|
||||||
|
|||||||
@@ -1470,7 +1470,20 @@ void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
|
|||||||
static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
|
static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
|
||||||
{
|
{
|
||||||
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
|
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
|
||||||
Brush *br = image_paint_brush(C);
|
|
||||||
|
Brush *br;
|
||||||
|
Object *ob = CTX_data_active_object(C);
|
||||||
|
if (!(ob && (ob->mode & OB_MODE_VERTEX_PAINT))) {
|
||||||
|
br = image_paint_brush(C);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* At the moment, wpaint does not support the color flipper.
|
||||||
|
* So for now we're only handling vpaint */
|
||||||
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||||
|
VPaint *vp = ts->vpaint;
|
||||||
|
br = BKE_paint_brush(&vp->paint);
|
||||||
|
}
|
||||||
|
|
||||||
if (ups->flag & UNIFIED_PAINT_COLOR) {
|
if (ups->flag & UNIFIED_PAINT_COLOR) {
|
||||||
swap_v3_v3(ups->rgb, ups->secondary_rgb);
|
swap_v3_v3(ups->rgb, ups->secondary_rgb);
|
||||||
}
|
}
|
||||||
@@ -1489,7 +1502,12 @@ static int brush_colors_flip_poll(bContext *C)
|
|||||||
if (br->imagepaint_tool == PAINT_TOOL_DRAW)
|
if (br->imagepaint_tool == PAINT_TOOL_DRAW)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
Object *ob = CTX_data_active_object(C);
|
||||||
|
if (ob && (ob->mode & OB_MODE_VERTEX_PAINT)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ int vertex_paint_poll(struct bContext *C);
|
|||||||
int vertex_paint_mode_poll(struct bContext *C);
|
int vertex_paint_mode_poll(struct bContext *C);
|
||||||
|
|
||||||
bool ED_vpaint_fill(struct Object *ob, unsigned int paintcol);
|
bool ED_vpaint_fill(struct Object *ob, unsigned int paintcol);
|
||||||
bool ED_wpaint_fill(struct VPaint *wp, struct Object *ob, float paintweight);
|
bool ED_wpaint_fill(struct Object *ob, float paintweight);
|
||||||
|
|
||||||
bool ED_vpaint_smooth(struct Object *ob);
|
bool ED_vpaint_smooth(struct Object *ob);
|
||||||
|
|
||||||
|
|||||||
@@ -1613,6 +1613,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
|
|||||||
keymap->poll = vertex_paint_mode_poll;
|
keymap->poll = vertex_paint_mode_poll;
|
||||||
|
|
||||||
WM_keymap_verify_item(keymap, "PAINT_OT_vertex_paint", LEFTMOUSE, KM_PRESS, 0, 0);
|
WM_keymap_verify_item(keymap, "PAINT_OT_vertex_paint", LEFTMOUSE, KM_PRESS, 0, 0);
|
||||||
|
WM_keymap_add_item(keymap, "PAINT_OT_brush_colors_flip", XKEY, KM_PRESS, 0, 0);
|
||||||
WM_keymap_add_item(keymap, "PAINT_OT_sample_color", SKEY, KM_PRESS, 0, 0);
|
WM_keymap_add_item(keymap, "PAINT_OT_sample_color", SKEY, KM_PRESS, 0, 0);
|
||||||
|
|
||||||
WM_keymap_add_item(keymap,
|
WM_keymap_add_item(keymap,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,6 @@
|
|||||||
#include "BLI_blenlib.h"
|
#include "BLI_blenlib.h"
|
||||||
#include "BLI_dial.h"
|
#include "BLI_dial.h"
|
||||||
#include "BLI_task.h"
|
#include "BLI_task.h"
|
||||||
#include "BLI_threads.h"
|
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
#include "BLI_ghash.h"
|
#include "BLI_ghash.h"
|
||||||
|
|
||||||
@@ -166,111 +165,12 @@ static bool sculpt_brush_needs_rake_rotation(const Brush *brush)
|
|||||||
return SCULPT_TOOL_HAS_RAKE(brush->sculpt_tool) && (brush->rake_factor != 0.0f);
|
return SCULPT_TOOL_HAS_RAKE(brush->sculpt_tool) && (brush->rake_factor != 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Factor of brush to have rake point following behind
|
|
||||||
* (could be configurable but this is reasonable default). */
|
|
||||||
#define SCULPT_RAKE_BRUSH_FACTOR 0.25f
|
|
||||||
|
|
||||||
struct SculptRakeData {
|
|
||||||
float follow_dist;
|
|
||||||
float follow_co[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum StrokeFlags {
|
typedef enum StrokeFlags {
|
||||||
CLIP_X = 1,
|
CLIP_X = 1,
|
||||||
CLIP_Y = 2,
|
CLIP_Y = 2,
|
||||||
CLIP_Z = 4
|
CLIP_Z = 4
|
||||||
} StrokeFlags;
|
} StrokeFlags;
|
||||||
|
|
||||||
/* Cache stroke properties. Used because
|
|
||||||
* RNA property lookup isn't particularly fast.
|
|
||||||
*
|
|
||||||
* For descriptions of these settings, check the operator properties.
|
|
||||||
*/
|
|
||||||
typedef struct StrokeCache {
|
|
||||||
/* Invariants */
|
|
||||||
float initial_radius;
|
|
||||||
float scale[3];
|
|
||||||
int flag;
|
|
||||||
float clip_tolerance[3];
|
|
||||||
float initial_mouse[2];
|
|
||||||
|
|
||||||
/* Variants */
|
|
||||||
float radius;
|
|
||||||
float radius_squared;
|
|
||||||
float true_location[3];
|
|
||||||
float location[3];
|
|
||||||
|
|
||||||
bool pen_flip;
|
|
||||||
bool invert;
|
|
||||||
float pressure;
|
|
||||||
float mouse[2];
|
|
||||||
float bstrength;
|
|
||||||
float normal_weight; /* from brush (with optional override) */
|
|
||||||
|
|
||||||
/* The rest is temporary storage that isn't saved as a property */
|
|
||||||
|
|
||||||
bool first_time; /* Beginning of stroke may do some things special */
|
|
||||||
|
|
||||||
/* from ED_view3d_ob_project_mat_get() */
|
|
||||||
float projection_mat[4][4];
|
|
||||||
|
|
||||||
/* Clean this up! */
|
|
||||||
ViewContext *vc;
|
|
||||||
Brush *brush;
|
|
||||||
|
|
||||||
float special_rotation;
|
|
||||||
float grab_delta[3], grab_delta_symmetry[3];
|
|
||||||
float old_grab_location[3], orig_grab_location[3];
|
|
||||||
|
|
||||||
/* screen-space rotation defined by mouse motion */
|
|
||||||
float rake_rotation[4], rake_rotation_symmetry[4];
|
|
||||||
bool is_rake_rotation_valid;
|
|
||||||
struct SculptRakeData rake_data;
|
|
||||||
|
|
||||||
int symmetry; /* Symmetry index between 0 and 7 bit combo 0 is Brush only;
|
|
||||||
* 1 is X mirror; 2 is Y mirror; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
|
|
||||||
int mirror_symmetry_pass; /* the symmetry pass we are currently on between 0 and 7*/
|
|
||||||
float true_view_normal[3];
|
|
||||||
float view_normal[3];
|
|
||||||
|
|
||||||
/* sculpt_normal gets calculated by calc_sculpt_normal(), then the
|
|
||||||
* sculpt_normal_symm gets updated quickly with the usual symmetry
|
|
||||||
* transforms */
|
|
||||||
float sculpt_normal[3];
|
|
||||||
float sculpt_normal_symm[3];
|
|
||||||
|
|
||||||
/* Used for area texture mode, local_mat gets calculated by
|
|
||||||
* calc_brush_local_mat() and used in tex_strength(). */
|
|
||||||
float brush_local_mat[4][4];
|
|
||||||
|
|
||||||
float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */
|
|
||||||
int tile_pass;
|
|
||||||
|
|
||||||
float last_center[3];
|
|
||||||
int radial_symmetry_pass;
|
|
||||||
float symm_rot_mat[4][4];
|
|
||||||
float symm_rot_mat_inv[4][4];
|
|
||||||
bool original;
|
|
||||||
float anchored_location[3];
|
|
||||||
|
|
||||||
float vertex_rotation; /* amount to rotate the vertices when using rotate brush */
|
|
||||||
Dial *dial;
|
|
||||||
|
|
||||||
char saved_active_brush_name[MAX_ID_NAME];
|
|
||||||
char saved_mask_brush_tool;
|
|
||||||
int saved_smooth_size; /* smooth tool copies the size of the current tool */
|
|
||||||
bool alt_smooth;
|
|
||||||
|
|
||||||
float plane_trim_squared;
|
|
||||||
|
|
||||||
bool supports_gravity;
|
|
||||||
float true_gravity_direction[3];
|
|
||||||
float gravity_direction[3];
|
|
||||||
|
|
||||||
rcti previous_r; /* previous redraw rectangle */
|
|
||||||
rcti current_r; /* current redraw rectangle */
|
|
||||||
} StrokeCache;
|
|
||||||
|
|
||||||
/************** Access to original unmodified vertex data *************/
|
/************** Access to original unmodified vertex data *************/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -477,41 +377,6 @@ static bool sculpt_stroke_is_dynamic_topology(
|
|||||||
|
|
||||||
/*** paint mesh ***/
|
/*** paint mesh ***/
|
||||||
|
|
||||||
/* Single struct used by all BLI_task threaded callbacks, let's avoid adding 10's of those... */
|
|
||||||
typedef struct SculptThreadedTaskData {
|
|
||||||
Sculpt *sd;
|
|
||||||
Object *ob;
|
|
||||||
Brush *brush;
|
|
||||||
PBVHNode **nodes;
|
|
||||||
int totnode;
|
|
||||||
|
|
||||||
/* Data specific to some callbacks. */
|
|
||||||
/* Note: even if only one or two of those are used at a time, keeping them separated, names help figuring out
|
|
||||||
* what it is, and memory overhead is ridiculous anyway... */
|
|
||||||
float flippedbstrength;
|
|
||||||
float angle;
|
|
||||||
float strength;
|
|
||||||
bool smooth_mask;
|
|
||||||
bool has_bm_orco;
|
|
||||||
|
|
||||||
SculptProjectVector *spvc;
|
|
||||||
float *offset;
|
|
||||||
float *grab_delta;
|
|
||||||
float *cono;
|
|
||||||
float *area_no;
|
|
||||||
float *area_no_sp;
|
|
||||||
float *area_co;
|
|
||||||
float (*mat)[4];
|
|
||||||
float (*vertCos)[3];
|
|
||||||
|
|
||||||
/* 0=towards view, 1=flipped */
|
|
||||||
float (*area_cos)[3];
|
|
||||||
float (*area_nos)[3];
|
|
||||||
int *count;
|
|
||||||
|
|
||||||
ThreadMutex mutex;
|
|
||||||
} SculptThreadedTaskData;
|
|
||||||
|
|
||||||
static void paint_mesh_restore_co_task_cb(void *userdata, const int n)
|
static void paint_mesh_restore_co_task_cb(void *userdata, const int n)
|
||||||
{
|
{
|
||||||
SculptThreadedTaskData *data = userdata;
|
SculptThreadedTaskData *data = userdata;
|
||||||
@@ -601,7 +466,7 @@ static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get a screen-space rectangle of the modified area */
|
/* Get a screen-space rectangle of the modified area */
|
||||||
static bool sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
|
bool sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
|
||||||
Object *ob, rcti *rect)
|
Object *ob, rcti *rect)
|
||||||
{
|
{
|
||||||
PBVH *pbvh = ob->sculpt->pbvh;
|
PBVH *pbvh = ob->sculpt->pbvh;
|
||||||
@@ -650,17 +515,7 @@ void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob)
|
|||||||
|
|
||||||
/************************ Brush Testing *******************/
|
/************************ Brush Testing *******************/
|
||||||
|
|
||||||
typedef struct SculptBrushTest {
|
void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
|
||||||
float radius_squared;
|
|
||||||
float location[3];
|
|
||||||
float dist;
|
|
||||||
int mirror_symmetry_pass;
|
|
||||||
|
|
||||||
/* View3d clipping - only set rv3d for clipping */
|
|
||||||
RegionView3D *clip_rv3d;
|
|
||||||
} SculptBrushTest;
|
|
||||||
|
|
||||||
static void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
|
|
||||||
{
|
{
|
||||||
RegionView3D *rv3d = ss->cache->vc->rv3d;
|
RegionView3D *rv3d = ss->cache->vc->rv3d;
|
||||||
|
|
||||||
@@ -689,7 +544,7 @@ BLI_INLINE bool sculpt_brush_test_clipping(const SculptBrushTest *test, const fl
|
|||||||
return ED_view3d_clipping_test(rv3d, symm_co, true);
|
return ED_view3d_clipping_test(rv3d, symm_co, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sculpt_brush_test(SculptBrushTest *test, const float co[3])
|
bool sculpt_brush_test(SculptBrushTest *test, const float co[3])
|
||||||
{
|
{
|
||||||
float distsq = len_squared_v3v3(co, test->location);
|
float distsq = len_squared_v3v3(co, test->location);
|
||||||
|
|
||||||
@@ -705,7 +560,7 @@ static bool sculpt_brush_test(SculptBrushTest *test, const float co[3])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sculpt_brush_test_sq(SculptBrushTest *test, const float co[3])
|
bool sculpt_brush_test_sq(SculptBrushTest *test, const float co[3])
|
||||||
{
|
{
|
||||||
float distsq = len_squared_v3v3(co, test->location);
|
float distsq = len_squared_v3v3(co, test->location);
|
||||||
|
|
||||||
@@ -721,7 +576,7 @@ static bool sculpt_brush_test_sq(SculptBrushTest *test, const float co[3])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sculpt_brush_test_fast(const SculptBrushTest *test, const float co[3])
|
bool sculpt_brush_test_fast(const SculptBrushTest *test, const float co[3])
|
||||||
{
|
{
|
||||||
if (sculpt_brush_test_clipping(test, co)) {
|
if (sculpt_brush_test_clipping(test, co)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -729,7 +584,7 @@ static bool sculpt_brush_test_fast(const SculptBrushTest *test, const float co[3
|
|||||||
return len_squared_v3v3(co, test->location) <= test->radius_squared;
|
return len_squared_v3v3(co, test->location) <= test->radius_squared;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float local[4][4])
|
bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float local[4][4])
|
||||||
{
|
{
|
||||||
float side = M_SQRT1_2;
|
float side = M_SQRT1_2;
|
||||||
float local_co[3];
|
float local_co[3];
|
||||||
@@ -1237,13 +1092,13 @@ static float brush_strength(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return a multiplier for brush strength on a particular vertex. */
|
/* Return a multiplier for brush strength on a particular vertex. */
|
||||||
static float tex_strength(SculptSession *ss, Brush *br,
|
float tex_strength(SculptSession *ss, Brush *br,
|
||||||
const float brush_point[3],
|
const float brush_point[3],
|
||||||
const float len,
|
const float len,
|
||||||
const short vno[3],
|
const short vno[3],
|
||||||
const float fno[3],
|
const float fno[3],
|
||||||
const float mask,
|
const float mask,
|
||||||
const int thread_id)
|
const int thread_id)
|
||||||
{
|
{
|
||||||
StrokeCache *cache = ss->cache;
|
StrokeCache *cache = ss->cache;
|
||||||
const Scene *scene = cache->vc->scene;
|
const Scene *scene = cache->vc->scene;
|
||||||
@@ -1316,15 +1171,8 @@ static float tex_strength(SculptSession *ss, Brush *br,
|
|||||||
return avg;
|
return avg;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Sculpt *sd;
|
|
||||||
SculptSession *ss;
|
|
||||||
float radius_squared;
|
|
||||||
bool original;
|
|
||||||
} SculptSearchSphereData;
|
|
||||||
|
|
||||||
/* Test AABB against sphere */
|
/* Test AABB against sphere */
|
||||||
static bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
|
bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
|
||||||
{
|
{
|
||||||
SculptSearchSphereData *data = data_v;
|
SculptSearchSphereData *data = data_v;
|
||||||
float *center = data->ss->cache->location, nearest[3];
|
float *center = data->ss->cache->location, nearest[3];
|
||||||
@@ -1632,6 +1480,22 @@ typedef struct SculptDoBrushSmoothGridDataChunk {
|
|||||||
size_t tmpgrid_size;
|
size_t tmpgrid_size;
|
||||||
} SculptDoBrushSmoothGridDataChunk;
|
} SculptDoBrushSmoothGridDataChunk;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SculptSession *ss;
|
||||||
|
const float *ray_start, *ray_normal;
|
||||||
|
bool hit;
|
||||||
|
float dist;
|
||||||
|
bool original;
|
||||||
|
PBVHNode* node;
|
||||||
|
} SculptRaycastData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const float *ray_start, *ray_normal;
|
||||||
|
bool hit;
|
||||||
|
float dist;
|
||||||
|
float detail;
|
||||||
|
} SculptDetailRaycastData;
|
||||||
|
|
||||||
static void do_smooth_brush_mesh_task_cb_ex(
|
static void do_smooth_brush_mesh_task_cb_ex(
|
||||||
void *userdata, void *UNUSED(userdata_chunk), const int n, const int thread_id)
|
void *userdata, void *UNUSED(userdata_chunk), const int n, const int thread_id)
|
||||||
{
|
{
|
||||||
@@ -3952,7 +3816,7 @@ static const char *sculpt_tool_name(Sculpt *sd)
|
|||||||
* Operator for applying a stroke (various attributes including mouse path)
|
* Operator for applying a stroke (various attributes including mouse path)
|
||||||
* using the current brush. */
|
* using the current brush. */
|
||||||
|
|
||||||
static void sculpt_cache_free(StrokeCache *cache)
|
void sculpt_cache_free(StrokeCache *cache)
|
||||||
{
|
{
|
||||||
if (cache->dial)
|
if (cache->dial)
|
||||||
MEM_freeN(cache->dial);
|
MEM_freeN(cache->dial);
|
||||||
@@ -4405,21 +4269,6 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SculptSession *ss;
|
|
||||||
const float *ray_start, *ray_normal;
|
|
||||||
bool hit;
|
|
||||||
float dist;
|
|
||||||
bool original;
|
|
||||||
} SculptRaycastData;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const float *ray_start, *ray_normal;
|
|
||||||
bool hit;
|
|
||||||
float dist;
|
|
||||||
float detail;
|
|
||||||
} SculptDetailRaycastData;
|
|
||||||
|
|
||||||
static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
|
static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
|
||||||
{
|
{
|
||||||
if (BKE_pbvh_node_get_tmin(node) < *tmin) {
|
if (BKE_pbvh_node_get_tmin(node) < *tmin) {
|
||||||
@@ -4444,6 +4293,9 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
|
|||||||
{
|
{
|
||||||
srd->hit = 1;
|
srd->hit = 1;
|
||||||
*tmin = srd->dist;
|
*tmin = srd->dist;
|
||||||
|
|
||||||
|
//for vwpaint testing
|
||||||
|
srd->node = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4528,12 +4380,17 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
|
|||||||
srd.dist = dist;
|
srd.dist = dist;
|
||||||
|
|
||||||
BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
|
BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
|
||||||
ray_start, ray_normal, srd.original);
|
ray_start, ray_normal, srd.original);
|
||||||
|
|
||||||
copy_v3_v3(out, ray_normal);
|
copy_v3_v3(out, ray_normal);
|
||||||
mul_v3_fl(out, srd.dist);
|
mul_v3_fl(out, srd.dist);
|
||||||
add_v3_v3(out, ray_start);
|
add_v3_v3(out, ray_start);
|
||||||
|
|
||||||
|
//used in vwpaint
|
||||||
|
if (cache && srd.hit){
|
||||||
|
copy_v3_v3(cache->true_location, out);
|
||||||
|
}
|
||||||
|
|
||||||
return srd.hit;
|
return srd.hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,12 +38,15 @@
|
|||||||
#include "DNA_key_types.h"
|
#include "DNA_key_types.h"
|
||||||
|
|
||||||
#include "BLI_bitmap.h"
|
#include "BLI_bitmap.h"
|
||||||
|
#include "BLI_threads.h"
|
||||||
|
|
||||||
#include "BKE_pbvh.h"
|
#include "BKE_pbvh.h"
|
||||||
|
|
||||||
struct bContext;
|
struct bContext;
|
||||||
struct KeyBlock;
|
struct KeyBlock;
|
||||||
struct Object;
|
struct Object;
|
||||||
struct SculptUndoNode;
|
struct SculptUndoNode;
|
||||||
|
struct SculptOrigVertData;
|
||||||
|
|
||||||
int sculpt_mode_poll(struct bContext *C);
|
int sculpt_mode_poll(struct bContext *C);
|
||||||
int sculpt_mode_poll_view3d(struct bContext *C);
|
int sculpt_mode_poll_view3d(struct bContext *C);
|
||||||
@@ -115,6 +118,194 @@ typedef struct SculptUndoNode {
|
|||||||
char shapeName[sizeof(((KeyBlock *)0))->name];
|
char shapeName[sizeof(((KeyBlock *)0))->name];
|
||||||
} SculptUndoNode;
|
} SculptUndoNode;
|
||||||
|
|
||||||
|
/* Factor of brush to have rake point following behind
|
||||||
|
* (could be configurable but this is reasonable default). */
|
||||||
|
#define SCULPT_RAKE_BRUSH_FACTOR 0.25f
|
||||||
|
|
||||||
|
struct SculptRakeData {
|
||||||
|
float follow_dist;
|
||||||
|
float follow_co[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Single struct used by all BLI_task threaded callbacks, let's avoid adding 10's of those... */
|
||||||
|
typedef struct SculptThreadedTaskData {
|
||||||
|
bContext *C;
|
||||||
|
struct Sculpt *sd;
|
||||||
|
struct Object *ob;
|
||||||
|
struct Brush *brush;
|
||||||
|
struct PBVHNode **nodes;
|
||||||
|
int totnode;
|
||||||
|
|
||||||
|
struct VPaint *vp;
|
||||||
|
struct VPaintData *vpd;
|
||||||
|
struct WPaintData *wpd;
|
||||||
|
struct WeightPaintInfo *wpi;
|
||||||
|
unsigned int *lcol;
|
||||||
|
struct Mesh *me;
|
||||||
|
/* For passing generic params. */
|
||||||
|
void *custom_data;
|
||||||
|
|
||||||
|
|
||||||
|
/* Data specific to some callbacks. */
|
||||||
|
/* Note: even if only one or two of those are used at a time, keeping them separated, names help figuring out
|
||||||
|
* what it is, and memory overhead is ridiculous anyway... */
|
||||||
|
float flippedbstrength;
|
||||||
|
float angle;
|
||||||
|
float strength;
|
||||||
|
bool smooth_mask;
|
||||||
|
bool has_bm_orco;
|
||||||
|
|
||||||
|
struct SculptProjectVector *spvc;
|
||||||
|
float *offset;
|
||||||
|
float *grab_delta;
|
||||||
|
float *cono;
|
||||||
|
float *area_no;
|
||||||
|
float *area_no_sp;
|
||||||
|
float *area_co;
|
||||||
|
float(*mat)[4];
|
||||||
|
float(*vertCos)[3];
|
||||||
|
|
||||||
|
/* 0=towards view, 1=flipped */
|
||||||
|
float(*area_cos)[3];
|
||||||
|
float(*area_nos)[3];
|
||||||
|
int *count;
|
||||||
|
|
||||||
|
ThreadMutex mutex;
|
||||||
|
|
||||||
|
} SculptThreadedTaskData;
|
||||||
|
|
||||||
|
/*************** Brush testing declarations ****************/
|
||||||
|
typedef struct SculptBrushTest {
|
||||||
|
float radius_squared;
|
||||||
|
float location[3];
|
||||||
|
float dist;
|
||||||
|
int mirror_symmetry_pass;
|
||||||
|
|
||||||
|
/* View3d clipping - only set rv3d for clipping */
|
||||||
|
struct RegionView3D *clip_rv3d;
|
||||||
|
} SculptBrushTest;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct Sculpt *sd;
|
||||||
|
struct SculptSession *ss;
|
||||||
|
float radius_squared;
|
||||||
|
bool original;
|
||||||
|
} SculptSearchSphereData;
|
||||||
|
|
||||||
|
void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test);
|
||||||
|
bool sculpt_brush_test(SculptBrushTest *test, const float co[3]);
|
||||||
|
bool sculpt_brush_test_sq(SculptBrushTest *test, const float co[3]);
|
||||||
|
bool sculpt_brush_test_fast(const SculptBrushTest *test, const float co[3]);
|
||||||
|
bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float local[4][4]);
|
||||||
|
bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v);
|
||||||
|
float tex_strength(
|
||||||
|
SculptSession *ss, struct Brush *br,
|
||||||
|
const float point[3],
|
||||||
|
const float len,
|
||||||
|
const short vno[3],
|
||||||
|
const float fno[3],
|
||||||
|
const float mask,
|
||||||
|
const int thread_id);
|
||||||
|
|
||||||
|
|
||||||
|
/* Cache stroke properties. Used because
|
||||||
|
* RNA property lookup isn't particularly fast.
|
||||||
|
*
|
||||||
|
* For descriptions of these settings, check the operator properties.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct StrokeCache {
|
||||||
|
/* Invariants */
|
||||||
|
float initial_radius;
|
||||||
|
float scale[3];
|
||||||
|
int flag;
|
||||||
|
float clip_tolerance[3];
|
||||||
|
float initial_mouse[2];
|
||||||
|
|
||||||
|
/* Variants */
|
||||||
|
float radius;
|
||||||
|
float radius_squared;
|
||||||
|
float true_location[3];
|
||||||
|
float true_last_location[3];
|
||||||
|
float location[3];
|
||||||
|
float last_location[3];
|
||||||
|
bool is_last_valid;
|
||||||
|
|
||||||
|
bool pen_flip;
|
||||||
|
bool invert;
|
||||||
|
float pressure;
|
||||||
|
float mouse[2];
|
||||||
|
float bstrength;
|
||||||
|
float normal_weight; /* from brush (with optional override) */
|
||||||
|
|
||||||
|
/* The rest is temporary storage that isn't saved as a property */
|
||||||
|
|
||||||
|
bool first_time; /* Beginning of stroke may do some things special */
|
||||||
|
|
||||||
|
/* from ED_view3d_ob_project_mat_get() */
|
||||||
|
float projection_mat[4][4];
|
||||||
|
|
||||||
|
/* Clean this up! */
|
||||||
|
struct ViewContext *vc;
|
||||||
|
struct Brush *brush;
|
||||||
|
|
||||||
|
float special_rotation;
|
||||||
|
float grab_delta[3], grab_delta_symmetry[3];
|
||||||
|
float old_grab_location[3], orig_grab_location[3];
|
||||||
|
|
||||||
|
/* screen-space rotation defined by mouse motion */
|
||||||
|
float rake_rotation[4], rake_rotation_symmetry[4];
|
||||||
|
bool is_rake_rotation_valid;
|
||||||
|
struct SculptRakeData rake_data;
|
||||||
|
|
||||||
|
/* Symmetry index between 0 and 7 bit combo 0 is Brush only;
|
||||||
|
* 1 is X mirror; 2 is Y mirror; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
|
||||||
|
int symmetry;
|
||||||
|
int mirror_symmetry_pass; /* the symmetry pass we are currently on between 0 and 7*/
|
||||||
|
float true_view_normal[3];
|
||||||
|
float view_normal[3];
|
||||||
|
|
||||||
|
/* sculpt_normal gets calculated by calc_sculpt_normal(), then the
|
||||||
|
* sculpt_normal_symm gets updated quickly with the usual symmetry
|
||||||
|
* transforms */
|
||||||
|
float sculpt_normal[3];
|
||||||
|
float sculpt_normal_symm[3];
|
||||||
|
|
||||||
|
/* Used for area texture mode, local_mat gets calculated by
|
||||||
|
* calc_brush_local_mat() and used in tex_strength(). */
|
||||||
|
float brush_local_mat[4][4];
|
||||||
|
|
||||||
|
float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */
|
||||||
|
int tile_pass;
|
||||||
|
|
||||||
|
float last_center[3];
|
||||||
|
int radial_symmetry_pass;
|
||||||
|
float symm_rot_mat[4][4];
|
||||||
|
float symm_rot_mat_inv[4][4];
|
||||||
|
bool original;
|
||||||
|
float anchored_location[3];
|
||||||
|
|
||||||
|
float vertex_rotation; /* amount to rotate the vertices when using rotate brush */
|
||||||
|
struct Dial *dial;
|
||||||
|
|
||||||
|
char saved_active_brush_name[MAX_ID_NAME];
|
||||||
|
char saved_mask_brush_tool;
|
||||||
|
int saved_smooth_size; /* smooth tool copies the size of the current tool */
|
||||||
|
bool alt_smooth;
|
||||||
|
|
||||||
|
float plane_trim_squared;
|
||||||
|
|
||||||
|
bool supports_gravity;
|
||||||
|
float true_gravity_direction[3];
|
||||||
|
float gravity_direction[3];
|
||||||
|
|
||||||
|
rcti previous_r; /* previous redraw rectangle */
|
||||||
|
rcti current_r; /* current redraw rectangle */
|
||||||
|
|
||||||
|
} StrokeCache;
|
||||||
|
|
||||||
|
void sculpt_cache_free(StrokeCache *cache);
|
||||||
|
|
||||||
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type);
|
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type);
|
||||||
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node);
|
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node);
|
||||||
void sculpt_undo_push_begin(const char *name);
|
void sculpt_undo_push_begin(const char *name);
|
||||||
@@ -124,6 +315,8 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]);
|
|||||||
|
|
||||||
void sculpt_update_object_bounding_box(struct Object *ob);
|
void sculpt_update_object_bounding_box(struct Object *ob);
|
||||||
|
|
||||||
|
bool sculpt_get_redraw_rect(struct ARegion *ar, struct RegionView3D *rv3d, Object *ob, rcti *rect);
|
||||||
|
|
||||||
#define SCULPT_THREADED_LIMIT 4
|
#define SCULPT_THREADED_LIMIT 4
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -315,7 +315,9 @@ enum {
|
|||||||
PAINT_BLEND_MUL = 3,
|
PAINT_BLEND_MUL = 3,
|
||||||
PAINT_BLEND_BLUR = 4,
|
PAINT_BLEND_BLUR = 4,
|
||||||
PAINT_BLEND_LIGHTEN = 5,
|
PAINT_BLEND_LIGHTEN = 5,
|
||||||
PAINT_BLEND_DARKEN = 6
|
PAINT_BLEND_DARKEN = 6,
|
||||||
|
PAINT_BLEND_AVERAGE = 7,
|
||||||
|
PAINT_BLEND_SMEAR = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -723,6 +723,9 @@ typedef enum ObjectMode {
|
|||||||
/* any mode where the brush system is used */
|
/* any mode where the brush system is used */
|
||||||
#define OB_MODE_ALL_PAINT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)
|
#define OB_MODE_ALL_PAINT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)
|
||||||
|
|
||||||
|
/* any mode that uses ob->sculpt */
|
||||||
|
#define OB_MODE_ALL_SCULPT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)
|
||||||
|
|
||||||
#define MAX_DUPLI_RECUR 8
|
#define MAX_DUPLI_RECUR 8
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -1121,13 +1121,8 @@ typedef struct UvSculpt {
|
|||||||
/* Vertex Paint */
|
/* Vertex Paint */
|
||||||
typedef struct VPaint {
|
typedef struct VPaint {
|
||||||
Paint paint;
|
Paint paint;
|
||||||
|
|
||||||
short flag, pad;
|
short flag, pad;
|
||||||
int tot; /* allocation size of prev buffers */
|
int radial_symm[3]; /* For mirrored painting */
|
||||||
unsigned int *vpaint_prev; /* previous mesh colors */
|
|
||||||
struct MDeformVert *wpaint_prev; /* previous vertex weights */
|
|
||||||
|
|
||||||
void *paintcursor; /* wm handle */
|
|
||||||
} VPaint;
|
} VPaint;
|
||||||
|
|
||||||
/* VPaint.flag */
|
/* VPaint.flag */
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ EnumPropertyItem rna_enum_brush_vertex_tool_items[] = {
|
|||||||
{PAINT_BLEND_BLUR, "BLUR", ICON_BRUSH_BLUR, "Blur", "Blur the color with surrounding values"},
|
{PAINT_BLEND_BLUR, "BLUR", ICON_BRUSH_BLUR, "Blur", "Blur the color with surrounding values"},
|
||||||
{PAINT_BLEND_LIGHTEN, "LIGHTEN", ICON_BRUSH_LIGHTEN, "Lighten", "Use lighten blending mode while painting"},
|
{PAINT_BLEND_LIGHTEN, "LIGHTEN", ICON_BRUSH_LIGHTEN, "Lighten", "Use lighten blending mode while painting"},
|
||||||
{PAINT_BLEND_DARKEN, "DARKEN", ICON_BRUSH_DARKEN, "Darken", "Use darken blending mode while painting"},
|
{PAINT_BLEND_DARKEN, "DARKEN", ICON_BRUSH_DARKEN, "Darken", "Use darken blending mode while painting"},
|
||||||
|
{PAINT_BLEND_AVERAGE, "AVERAGE", ICON_BRUSH_BLUR, "Average", "Use average blending mode while painting" },
|
||||||
|
{PAINT_BLEND_SMEAR, "SMEAR", ICON_BRUSH_BLUR, "Smear", "Use smear blending mode while painting" },
|
||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -706,6 +706,15 @@ static void rna_def_vertex_paint(BlenderRNA *brna)
|
|||||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", VP_ONLYVGROUP);
|
RNA_def_property_boolean_sdna(prop, NULL, "flag", VP_ONLYVGROUP);
|
||||||
RNA_def_property_ui_text(prop, "Restrict", "Restrict painting to vertices in the group");
|
RNA_def_property_ui_text(prop, "Restrict", "Restrict painting to vertices in the group");
|
||||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||||
|
|
||||||
|
/* Mirroring */
|
||||||
|
prop = RNA_def_property(srna, "radial_symmetry", PROP_INT, PROP_XYZ);
|
||||||
|
RNA_def_property_int_sdna(prop, NULL, "radial_symm");
|
||||||
|
RNA_def_property_int_default(prop, 1);
|
||||||
|
RNA_def_property_range(prop, 1, 64);
|
||||||
|
RNA_def_property_ui_range(prop, 1, 32, 1, 1);
|
||||||
|
RNA_def_property_ui_text(prop, "Radial Symmetry Count X Axis",
|
||||||
|
"Number of times to copy strokes across the surface");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_image_paint(BlenderRNA *brna)
|
static void rna_def_image_paint(BlenderRNA *brna)
|
||||||
|
|||||||
@@ -476,6 +476,34 @@ int BGL_typeSize(int type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int gl_buffer_type_from_py_format_char(char format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case 'b':
|
||||||
|
return GL_BYTE;
|
||||||
|
case 'h':
|
||||||
|
case 'i':
|
||||||
|
return GL_SHORT;
|
||||||
|
case 'l':
|
||||||
|
return GL_INT;
|
||||||
|
case 'f':
|
||||||
|
return GL_FLOAT;
|
||||||
|
case 'd':
|
||||||
|
return GL_DOUBLE;
|
||||||
|
}
|
||||||
|
return -1; /* UNKNOWN */
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool compare_dimensions(int ndim, int *dim1, Py_ssize_t *dim2)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ndim; i++) {
|
||||||
|
if (dim1[i] != dim2[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
|
||||||
@@ -634,6 +662,22 @@ PyTypeObject BGL_bufferType = {
|
|||||||
NULL /*tp_del*/
|
NULL /*tp_del*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static Buffer *BGL_MakeBuffer_FromData(PyObject *parent, int type, int ndimensions, int *dimensions, void *buf)
|
||||||
|
{
|
||||||
|
Buffer *buffer = (Buffer *)PyObject_NEW(Buffer, &BGL_bufferType);
|
||||||
|
|
||||||
|
Py_XINCREF(parent);
|
||||||
|
buffer->parent = parent;
|
||||||
|
buffer->ndimensions = ndimensions;
|
||||||
|
buffer->dimensions = MEM_mallocN(ndimensions * sizeof(int), "Buffer dimensions");
|
||||||
|
memcpy(buffer->dimensions, dimensions, ndimensions * sizeof(int));
|
||||||
|
buffer->type = type;
|
||||||
|
buffer->buf.asvoid = buf;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a buffer object
|
* Create a buffer object
|
||||||
*
|
*
|
||||||
@@ -645,30 +689,21 @@ Buffer *BGL_MakeBuffer(int type, int ndimensions, int *dimensions, void *initbuf
|
|||||||
{
|
{
|
||||||
Buffer *buffer;
|
Buffer *buffer;
|
||||||
void *buf = NULL;
|
void *buf = NULL;
|
||||||
int i, size, length;
|
int i, size = BGL_typeSize(type);
|
||||||
|
|
||||||
length = 1;
|
|
||||||
for (i = 0; i < ndimensions; i++) {
|
for (i = 0; i < ndimensions; i++) {
|
||||||
length *= dimensions[i];
|
size *= dimensions[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
size = BGL_typeSize(type);
|
buf = MEM_mallocN(size, "Buffer buffer");
|
||||||
|
|
||||||
buf = MEM_mallocN(length * size, "Buffer buffer");
|
buffer = BGL_MakeBuffer_FromData(NULL, type, ndimensions, dimensions, buf);
|
||||||
|
|
||||||
buffer = (Buffer *)PyObject_NEW(Buffer, &BGL_bufferType);
|
|
||||||
buffer->parent = NULL;
|
|
||||||
buffer->ndimensions = ndimensions;
|
|
||||||
buffer->dimensions = MEM_mallocN(ndimensions * sizeof(int), "Buffer dimensions");
|
|
||||||
memcpy(buffer->dimensions, dimensions, ndimensions * sizeof(int));
|
|
||||||
buffer->type = type;
|
|
||||||
buffer->buf.asvoid = buf;
|
|
||||||
|
|
||||||
if (initbuffer) {
|
if (initbuffer) {
|
||||||
memcpy(buffer->buf.asvoid, initbuffer, length * size);
|
memcpy(buffer->buf.asvoid, initbuffer, size);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memset(buffer->buf.asvoid, 0, length * size);
|
memset(buffer->buf.asvoid, 0, size);
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@@ -678,7 +713,7 @@ Buffer *BGL_MakeBuffer(int type, int ndimensions, int *dimensions, void *initbuf
|
|||||||
static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
|
static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
PyObject *length_ob = NULL, *init = NULL;
|
PyObject *length_ob = NULL, *init = NULL;
|
||||||
Buffer *buffer;
|
Buffer *buffer = NULL;
|
||||||
int dimensions[MAX_DIMENSIONS];
|
int dimensions[MAX_DIMENSIONS];
|
||||||
|
|
||||||
int type;
|
int type;
|
||||||
@@ -743,9 +778,32 @@ static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = BGL_MakeBuffer(type, ndimensions, dimensions, NULL);
|
if (init && PyObject_CheckBuffer(init)) {
|
||||||
if (init && ndimensions) {
|
Py_buffer pybuffer;
|
||||||
if (Buffer_ass_slice(buffer, 0, dimensions[0], init)) {
|
|
||||||
|
if (PyObject_GetBuffer(init, &pybuffer, PyBUF_ND | PyBUF_FORMAT) == -1) {
|
||||||
|
/* PyObject_GetBuffer raise a PyExc_BufferError */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != gl_buffer_type_from_py_format_char(*pybuffer.format)) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"`GL_TYPE` and `format` of object with buffer interface do not match");
|
||||||
|
}
|
||||||
|
else if (ndimensions != pybuffer.ndim ||
|
||||||
|
!compare_dimensions(ndimensions, dimensions, pybuffer.shape))
|
||||||
|
{
|
||||||
|
PyErr_Format(PyExc_TypeError, "array size does not match");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer = BGL_MakeBuffer_FromData(init, type, pybuffer.ndim, dimensions, pybuffer.buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyBuffer_Release(&pybuffer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer = BGL_MakeBuffer(type, ndimensions, dimensions, NULL);
|
||||||
|
if (init && Buffer_ass_slice(buffer, 0, dimensions[0], init)) {
|
||||||
Py_DECREF(buffer);
|
Py_DECREF(buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -778,27 +836,17 @@ static PyObject *Buffer_item(Buffer *self, int i)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Buffer *newbuf;
|
int j, offset = i * BGL_typeSize(self->type);
|
||||||
int j, length, size;
|
|
||||||
|
|
||||||
length = 1;
|
|
||||||
for (j = 1; j < self->ndimensions; j++) {
|
for (j = 1; j < self->ndimensions; j++) {
|
||||||
length *= self->dimensions[j];
|
offset *= self->dimensions[j];
|
||||||
}
|
}
|
||||||
size = BGL_typeSize(self->type);
|
|
||||||
|
|
||||||
newbuf = (Buffer *)PyObject_NEW(Buffer, &BGL_bufferType);
|
return (PyObject *)BGL_MakeBuffer_FromData(
|
||||||
|
(PyObject *)self, self->type,
|
||||||
Py_INCREF(self);
|
self->ndimensions - 1,
|
||||||
newbuf->parent = (PyObject *)self;
|
self->dimensions + 1,
|
||||||
|
self->buf.asbyte + offset);
|
||||||
newbuf->ndimensions = self->ndimensions - 1;
|
|
||||||
newbuf->type = self->type;
|
|
||||||
newbuf->buf.asvoid = self->buf.asbyte + i * length * size;
|
|
||||||
newbuf->dimensions = MEM_mallocN(newbuf->ndimensions * sizeof(int), "Buffer dimensions");
|
|
||||||
memcpy(newbuf->dimensions, self->dimensions + 1, newbuf->ndimensions * sizeof(int));
|
|
||||||
|
|
||||||
return (PyObject *)newbuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user