diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-08-21 08:41:03 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-08-21 08:41:03 +0300 |
commit | 3e555d3d785b17bf9398d7666d5131c994da8c6b (patch) | |
tree | d15aaa353e31ed2acbd105d2b48ac4b1c99ea1e5 | |
parent | d007828ae78d66cdcc005d9ba3ad57e987f0190a (diff) | |
parent | 0033f0e161d984b38d3a36d18448f16baef121aa (diff) |
Merge branch 'master' into blender2.8
33 files changed, 394 insertions, 243 deletions
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py index dd4e8e60a42..17efb00abdb 100644 --- a/intern/cycles/blender/addon/presets.py +++ b/intern/cycles/blender/addon/presets.py @@ -67,6 +67,7 @@ class AddPresetSampling(AddPresetBase, Operator): "cycles.mesh_light_samples", "cycles.subsurface_samples", "cycles.volume_samples", + "cycles.use_square_samples", "cycles.progressive", "cycles.seed", "cycles.sample_clamp_direct", diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index cd71183acb6..a50da3634f3 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -172,6 +172,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default='PATH', ) + cls.use_square_samples = BoolProperty( + name="Square Samples", + description="Square sampling values for easier artist control", + default=False, + ) + cls.samples = IntProperty( name="Samples", description="Number of samples to render for each pixel", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 5ae9466b40c..459d0d7d05e 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -101,6 +101,8 @@ def draw_samples_info(layout, context): # Calculate sample values if integrator == 'PATH': aa = cscene.samples + if cscene.use_square_samples: + aa = aa * aa else: aa = cscene.aa_samples d = cscene.diffuse_samples @@ -111,9 +113,19 @@ def draw_samples_info(layout, context): sss = cscene.subsurface_samples vol = cscene.volume_samples + if cscene.use_square_samples: + aa = aa * aa + d = d * d + g = g * g + t = t * t + ao = ao * ao + ml = ml * ml + sss = sss * sss + vol = vol * vol + # Draw interface # Do not draw for progressive, when Square Samples are disabled - if use_branched_path(context): + if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'): col = layout.column(align=True) col.scale_y = 0.6 col.label("Total Samples:") @@ -146,7 +158,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): row = layout.row() sub = row.row() sub.prop(cscene, "progressive", text="") - sub.label() + row.prop(cscene, "use_square_samples") split = layout.split() diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py index a37ac38c101..efd794461d6 100644 --- a/intern/cycles/blender/addon/version_update.py +++ b/intern/cycles/blender/addon/version_update.py @@ -315,23 +315,3 @@ def do_versions(self): cscene.blur_glossy = 0.0 if not cscene.is_property_set("sample_clamp_indirect"): cscene.sample_clamp_indirect = 0.0 - - # Remove and apply square samples - use_square_samples = cscene.get("use_square_samples", False) - if use_square_samples: - del cscene["use_square_samples"] - - cscene.samples *= cscene.samples - cscene.preview_samples *= cscene.preview_samples - cscene.aa_samples *= cscene.aa_samples - cscene.preview_aa_samples *= cscene.preview_aa_samples - cscene.diffuse_samples *= cscene.diffuse_samples - cscene.glossy_samples *= cscene.glossy_samples - cscene.transmission_samples *= cscene.transmission_samples - cscene.ao_samples *= cscene.ao_samples - cscene.mesh_light_samples *= cscene.mesh_light_samples - cscene.subsurface_samples *= cscene.subsurface_samples - cscene.volume_samples *= cscene.volume_samples - - for layer in scene.render.layers: - layer.samples *= layer.samples diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 6b46402730e..991b834dcfa 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -163,11 +163,16 @@ void BlenderSync::sync_light(BL::Object& b_parent, light->shader = used_shaders[0]; /* shadow */ + PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles"); light->cast_shadow = get_boolean(clamp, "cast_shadow"); light->use_mis = get_boolean(clamp, "use_multiple_importance_sampling"); - light->samples = get_int(clamp, "samples"); + int samples = get_int(clamp, "samples"); + if(get_boolean(cscene, "use_square_samples")) + light->samples = samples * samples; + else + light->samples = samples; light->max_bounces = get_int(clamp, "max_bounces"); @@ -195,6 +200,7 @@ void BlenderSync::sync_background_light(bool use_portal) BL::World b_world = b_scene.world(); if(b_world) { + PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); bool sample_as_light = get_boolean(cworld, "sample_as_light"); @@ -213,7 +219,11 @@ void BlenderSync::sync_background_light(bool use_portal) light->use_mis = sample_as_light; light->max_bounces = get_int(cworld, "max_bounces"); - light->samples = get_int(cworld, "samples"); + int samples = get_int(cworld, "samples"); + if(get_boolean(cscene, "use_square_samples")) + light->samples = samples * samples; + else + light->samples = samples; light->tag_update(scene); light_map.set_recalc(b_world); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 423f781dc17..19d8044cd4a 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -294,13 +294,32 @@ void BlenderSync::sync_integrator() integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect"); integrator->light_sampling_threshold = get_float(cscene, "light_sampling_threshold"); - integrator->diffuse_samples = get_int(cscene, "diffuse_samples"); - integrator->glossy_samples = get_int(cscene, "glossy_samples"); - integrator->transmission_samples = get_int(cscene, "transmission_samples"); - integrator->ao_samples = get_int(cscene, "ao_samples"); - integrator->mesh_light_samples = get_int(cscene, "mesh_light_samples"); - integrator->subsurface_samples = get_int(cscene, "subsurface_samples"); - integrator->volume_samples = get_int(cscene, "volume_samples"); + int diffuse_samples = get_int(cscene, "diffuse_samples"); + int glossy_samples = get_int(cscene, "glossy_samples"); + int transmission_samples = get_int(cscene, "transmission_samples"); + int ao_samples = get_int(cscene, "ao_samples"); + int mesh_light_samples = get_int(cscene, "mesh_light_samples"); + int subsurface_samples = get_int(cscene, "subsurface_samples"); + int volume_samples = get_int(cscene, "volume_samples"); + + if(get_boolean(cscene, "use_square_samples")) { + integrator->diffuse_samples = diffuse_samples * diffuse_samples; + integrator->glossy_samples = glossy_samples * glossy_samples; + integrator->transmission_samples = transmission_samples * transmission_samples; + integrator->ao_samples = ao_samples * ao_samples; + integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples; + integrator->subsurface_samples = subsurface_samples * subsurface_samples; + integrator->volume_samples = volume_samples * volume_samples; + } + else { + integrator->diffuse_samples = diffuse_samples; + integrator->glossy_samples = glossy_samples; + integrator->transmission_samples = transmission_samples; + integrator->ao_samples = ao_samples; + integrator->mesh_light_samples = mesh_light_samples; + integrator->subsurface_samples = subsurface_samples; + integrator->volume_samples = volume_samples; + } if(b_scene.render().use_simplify()) { if(preview) { @@ -400,7 +419,11 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer) render_layer.bound_samples = (use_layer_samples == 1); if(use_layer_samples != 2) { - render_layer.samples = b_rlay->samples(); + int samples = b_rlay->samples(); + if(get_boolean(cscene, "use_square_samples")) + render_layer.samples = samples * samples; + else + render_layer.samples = samples; } } @@ -715,6 +738,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, int preview_samples = get_int(cscene, "preview_samples"); int preview_aa_samples = get_int(cscene, "preview_aa_samples"); + if(get_boolean(cscene, "use_square_samples")) { + aa_samples = aa_samples * aa_samples; + preview_aa_samples = preview_aa_samples * preview_aa_samples; + + samples = samples * samples; + preview_samples = preview_samples * preview_samples; + } + if(get_enum(cscene, "progressive") == 0) { if(background) { params.samples = aa_samples; diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index c68eba7bef6..f295f7e227c 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -2144,18 +2144,34 @@ Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background) return new CUDADevice(info, stats, background); } -void device_cuda_info(vector<DeviceInfo>& devices) +static CUresult device_cuda_safe_init() { - CUresult result; - int count = 0; +#ifdef _WIN32 + __try { + return cuInit(0); + } + __except(EXCEPTION_EXECUTE_HANDLER) { + /* Ignore crashes inside the CUDA driver and hope we can + * survive even with corrupted CUDA installs. */ + fprintf(stderr, "Cycles CUDA: driver crashed, continuing without CUDA.\n"); + } + + return CUDA_ERROR_NO_DEVICE; +#else + return cuInit(0); +#endif +} - result = cuInit(0); +void device_cuda_info(vector<DeviceInfo>& devices) +{ + CUresult result = device_cuda_safe_init(); if(result != CUDA_SUCCESS) { if(result != CUDA_ERROR_NO_DEVICE) fprintf(stderr, "CUDA cuInit: %s\n", cuewErrorString(result)); return; } + int count = 0; result = cuDeviceGetCount(&count); if(result != CUDA_SUCCESS) { fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", cuewErrorString(result)); @@ -2212,7 +2228,7 @@ void device_cuda_info(vector<DeviceInfo>& devices) string device_cuda_capabilities(void) { - CUresult result = cuInit(0); + CUresult result = device_cuda_safe_init(); if(result != CUDA_SUCCESS) { if(result != CUDA_ERROR_NO_DEVICE) { return string("Error initializing CUDA: ") + cuewErrorString(result); diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index aa380ec4b94..9d89decaaaf 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -73,8 +73,34 @@ bool device_opencl_init(void) return result; } + +static cl_int device_opencl_get_num_platforms_safe(cl_uint *num_platforms) +{ +#ifdef _WIN32 + __try { + return clGetPlatformIDs(0, NULL, num_platforms); + } + __except(EXCEPTION_EXECUTE_HANDLER) { + /* Ignore crashes inside the OpenCL driver and hope we can + * survive even with corrupted OpenCL installs. */ + fprintf(stderr, "Cycles OpenCL: driver crashed, continuing without OpenCL.\n"); + } + + *num_platforms = 0; + return CL_DEVICE_NOT_FOUND; +#else + return clGetPlatformIDs(0, NULL, num_platforms); +#endif +} + void device_opencl_info(vector<DeviceInfo>& devices) { + cl_uint num_platforms = 0; + device_opencl_get_num_platforms_safe(&num_platforms); + if(num_platforms == 0) { + return; + } + vector<OpenCLPlatformDevice> usable_devices; OpenCLInfo::get_usable_devices(&usable_devices); /* Devices are numbered consecutively across platforms. */ @@ -113,7 +139,7 @@ string device_opencl_capabilities(void) * it could also be nicely reported to the console. */ cl_uint num_platforms = 0; - opencl_assert(clGetPlatformIDs(0, NULL, &num_platforms)); + opencl_assert(device_opencl_get_num_platforms_safe(&num_platforms)); if(num_platforms == 0) { return "No OpenCL platforms found\n"; } diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index ea30ee9c139..d9b803cf692 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -342,8 +342,8 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN); } - /* compression: normal = (2 * color) - 1 */ - out = sd.N * 0.5f + make_float3(0.5f, 0.5f, 0.5f); + /* encoding: normal = (2 * color) - 1 */ + out = shader_bsdf_average_normal(kg, &sd) * 0.5f + make_float3(0.5f, 0.5f, 0.5f); break; } case SHADER_EVAL_UV: diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index de65e8ef27b..d454cce6e30 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -260,7 +260,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl } if(flag & PASS_NORMAL) { - float3 normal = sd->N; + float3 normal = shader_bsdf_average_normal(kg, sd); kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal); } if(flag & PASS_UV) { diff --git a/intern/cycles/kernel/kernel_path_subsurface.h b/intern/cycles/kernel/kernel_path_subsurface.h index 5fce5ed59d2..9bccc9201e0 100644 --- a/intern/cycles/kernel/kernel_path_subsurface.h +++ b/intern/cycles/kernel/kernel_path_subsurface.h @@ -46,7 +46,7 @@ bool kernel_path_subsurface_scatter( */ kernel_assert(!ss_indirect->tracing); - uint lcg_state = lcg_state_init(state, 0x68bc21eb); + uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb); SubsurfaceIntersection ss_isect; float bssrdf_u, bssrdf_v; diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index 459333f9807..221d92f5de1 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -307,12 +307,19 @@ ccl_device_inline void path_state_branch(ccl_addr_space PathState *state, state->num_samples = state->num_samples*num_branches; } -ccl_device_inline uint lcg_state_init(ccl_addr_space PathState *state, +ccl_device_inline uint lcg_state_init(PathState *state, uint scramble) { return lcg_init(state->rng_hash + state->rng_offset + state->sample*scramble); } +ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space PathState *state, + uint scramble) +{ + return lcg_init(state->rng_hash + state->rng_offset + state->sample*scramble); +} + + ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng) { /* Implicit mod 2^32 */ diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 01ba6d86f0b..a47766565a8 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -764,6 +764,19 @@ ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd) return eval; } +ccl_device float3 shader_bsdf_average_normal(KernelGlobals *kg, ShaderData *sd) +{ + float3 N = make_float3(0.0f, 0.0f, 0.0f); + + for(int i = 0; i < sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) + N += sc->N*average(sc->weight); + } + + return (is_zero(N))? sd->N : normalize(N); +} + ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N_) { float3 eval = make_float3(0.0f, 0.0f, 0.0f); @@ -783,12 +796,7 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac } } - if(is_zero(N)) - N = sd->N; - else - N = normalize(N); - - *N_ = N; + *N_ = (is_zero(N))? sd->N : normalize(N); return eval; } @@ -888,7 +896,7 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, } if(sd->flag & SD_BSDF_NEEDS_LCG) { - sd->lcg_state = lcg_state_init(state, 0xb4bc3953); + sd->lcg_state = lcg_state_init_addrspace(state, 0xb4bc3953); } } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 58371c56267..ce52ed4191c 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -878,7 +878,7 @@ enum ShaderDataFlag { SD_VOLUME_MIS = (1 << 23), /* Use cubic interpolation for voxels. */ SD_VOLUME_CUBIC = (1 << 24), - /* Has data connected to the displacement input. */ + /* Has data connected to the displacement input or uses bump map. */ SD_HAS_BUMP = (1 << 25), /* Has true displacement. */ SD_HAS_DISPLACEMENT = (1 << 26), diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h index 76d198abc8a..a487e53df5c 100644 --- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h +++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h @@ -51,8 +51,8 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it if(branched_state->ss_next_sample == 0 && branched_state->next_hit == 0 && branched_state->next_closure == 0 && branched_state->next_sample == 0) { - branched_state->lcg_state = lcg_state_init(&branched_state->path_state, - 0x68bc21eb); + branched_state->lcg_state = lcg_state_init_addrspace(&branched_state->path_state, + 0x68bc21eb); } int num_samples = kernel_data.integrator.subsurface_samples; float num_samples_inv = 1.0f/num_samples; @@ -258,7 +258,7 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg) /* do bssrdf scatter step if we picked a bssrdf closure */ if(sc) { - uint lcg_state = lcg_state_init(state, 0x68bc21eb); + uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb); float bssrdf_u, bssrdf_v; path_state_rng_2D(kg, state, diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 2d810ff664f..41e7e0205b0 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -221,28 +221,6 @@ OutputNode *ShaderGraph::output() return (OutputNode*)nodes.front(); } -ShaderGraph *ShaderGraph::copy() -{ - ShaderGraph *newgraph = new ShaderGraph(); - - /* copy nodes */ - ShaderNodeSet nodes_all; - foreach(ShaderNode *node, nodes) - nodes_all.insert(node); - - ShaderNodeMap nodes_copy; - copy_nodes(nodes_all, nodes_copy); - - /* add nodes (in same order, so output is still first) */ - newgraph->clear_nodes(); - foreach(ShaderNode *node, nodes) - newgraph->add(nodes_copy[node]); - - newgraph->simplified = simplified; - - return newgraph; -} - void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) { assert(!finalized); diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 72e391991a7..f0fd789c6bd 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -151,6 +151,7 @@ public: virtual bool has_surface_emission() { return false; } virtual bool has_surface_transparent() { return false; } virtual bool has_surface_bssrdf() { return false; } + virtual bool has_bump() { return false; } virtual bool has_bssrdf_bump() { return false; } virtual bool has_spatial_varying() { return false; } virtual bool has_object_dependency() { return false; } @@ -245,8 +246,6 @@ public: ShaderGraph(); ~ShaderGraph(); - ShaderGraph *copy(); - ShaderNode *add(ShaderNode *node); OutputNode *output(); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 90a68a06cb5..2b682756c6a 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1801,6 +1801,14 @@ BsdfBaseNode::BsdfBaseNode(const NodeType *node_type) special_type = SHADER_SPECIAL_TYPE_CLOSURE; } +bool BsdfBaseNode::has_bump() +{ + /* detect if anything is plugged into the normal input besides the default */ + ShaderInput *normal_in = input("Normal"); + return (normal_in && normal_in->link && + normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY); +} + /* BSDF Closure */ BsdfNode::BsdfNode(const NodeType *node_type) @@ -2439,9 +2447,7 @@ void PrincipledBsdfNode::compile(OSLCompiler& compiler) bool PrincipledBsdfNode::has_bssrdf_bump() { - /* detect if anything is plugged into the normal input besides the default */ - ShaderInput *normal_in = input("Normal"); - return (normal_in->link && normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY); + return has_surface_bssrdf() && has_bump(); } /* Translucent BSDF Closure */ diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index c0271a3c8eb..ec4c7c7c50d 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -326,6 +326,16 @@ class BsdfBaseNode : public ShaderNode { public: BsdfBaseNode(const NodeType *node_type); + bool has_spatial_varying() { return true; } + virtual ClosureType get_closure_type() { return closure; } + virtual bool has_bump(); + + virtual bool equals(const ShaderNode& /*other*/) + { + /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */ + return false; + } + ClosureType closure; }; @@ -334,19 +344,11 @@ public: explicit BsdfNode(const NodeType *node_type); SHADER_NODE_BASE_CLASS(BsdfNode) - bool has_spatial_varying() { return true; } void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL); - virtual ClosureType get_closure_type() { return closure; } float3 color; float3 normal; float surface_mix_weight; - - virtual bool equals(const ShaderNode& /*other*/) - { - /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */ - return false; - } }; class AnisotropicBsdfNode : public BsdfNode { @@ -373,7 +375,6 @@ class PrincipledBsdfNode : public BsdfBaseNode { public: SHADER_NODE_CLASS(PrincipledBsdfNode) - bool has_spatial_varying() { return true; } bool has_surface_bssrdf(); bool has_bssrdf_bump(); void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *subsurface_radius, @@ -390,13 +391,6 @@ public: float surface_mix_weight; ClosureType distribution, distribution_orig; - virtual bool equals(const ShaderNode * /*other*/) - { - /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */ - return false; - } - - ClosureType get_closure_type() { return closure; } bool has_integrator_dependency(); void attributes(Shader *shader, AttributeRequestSet *attributes); }; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index c337079b09f..5c5ac6e2be9 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -721,6 +721,7 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) current_shader->has_surface_bssrdf = true; current_shader->has_bssrdf_bump = true; /* can't detect yet */ } + current_shader->has_bump = true; /* can't detect yet */ } if(node->has_spatial_varying()) { @@ -1029,6 +1030,9 @@ void OSLCompiler::generate_nodes(const ShaderNodeSet& nodes) if(node->has_bssrdf_bump()) current_shader->has_bssrdf_bump = true; } + if(node->has_bump()) { + current_shader->has_bump = true; + } } else if(current_type == SHADER_TYPE_VOLUME) { if(node->has_spatial_varying()) @@ -1091,21 +1095,14 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader) ShaderGraph *graph = shader->graph; ShaderNode *output = (graph)? graph->output(): NULL; - /* copy graph for shader with bump mapping */ - if(output->input("Surface")->link && output->input("Displacement")->link) - if(!shader->graph_bump) - shader->graph_bump = shader->graph->copy(); + bool has_bump = (shader->displacement_method != DISPLACE_TRUE) && + output->input("Surface")->link && output->input("Displacement")->link; /* finalize */ shader->graph->finalize(scene, - false, - shader->has_integrator_dependency); - if(shader->graph_bump) { - shader->graph_bump->finalize(scene, - true, - shader->has_integrator_dependency, - shader->displacement_method == DISPLACE_BOTH); - } + has_bump, + shader->has_integrator_dependency, + shader->displacement_method == DISPLACE_BOTH); current_shader = shader; @@ -1113,7 +1110,8 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader) shader->has_surface_emission = false; shader->has_surface_transparent = false; shader->has_surface_bssrdf = false; - shader->has_bssrdf_bump = false; + shader->has_bump = has_bump; + shader->has_bssrdf_bump = has_bump; shader->has_volume = false; shader->has_displacement = false; shader->has_surface_spatial_varying = false; @@ -1125,8 +1123,8 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader) if(shader->used && graph && output->input("Surface")->link) { shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); - if(shader->graph_bump && shader->displacement_method != DISPLACE_TRUE) - shader->osl_surface_bump_ref = compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP); + if(has_bump) + shader->osl_surface_bump_ref = compile_type(shader, shader->graph, SHADER_TYPE_BUMP); else shader->osl_surface_bump_ref = OSL::ShaderGroupRef(); diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 493e01de363..86378dfb495 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -177,7 +177,6 @@ Shader::Shader() pass_id = 0; graph = NULL; - graph_bump = NULL; has_surface = false; has_surface_transparent = false; @@ -185,6 +184,7 @@ Shader::Shader() has_surface_bssrdf = false; has_volume = false; has_displacement = false; + has_bump = false; has_bssrdf_bump = false; has_surface_spatial_varying = false; has_volume_spatial_varying = false; @@ -204,7 +204,6 @@ Shader::Shader() Shader::~Shader() { delete graph; - delete graph_bump; } bool Shader::is_constant_emission(float3 *emission) @@ -239,9 +238,7 @@ void Shader::set_graph(ShaderGraph *graph_) /* assign graph */ delete graph; - delete graph_bump; graph = graph_; - graph_bump = NULL; /* Store info here before graph optimization to make sure that * nodes that get optimized away still count. */ @@ -458,15 +455,11 @@ void ShaderManager::device_update_common(Device *device, flag |= SD_VOLUME_MIS; if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) flag |= SD_VOLUME_CUBIC; - if(shader->graph_bump) + if(shader->has_bump) flag |= SD_HAS_BUMP; if(shader->displacement_method != DISPLACE_BUMP) flag |= SD_HAS_DISPLACEMENT; - /* shader with bump mapping */ - if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump) - flag |= SD_HAS_BSSRDF_BUMP; - /* constant emission check */ float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f); if(shader->is_constant_emission(&constant_emission)) @@ -608,11 +601,6 @@ void ShaderManager::get_requested_features(Scene *scene, Shader *shader = scene->shaders[i]; /* Gather requested features from all the nodes from the graph nodes. */ get_requested_graph_features(shader->graph, requested_features); - /* Gather requested features from the graph itself. */ - if(shader->graph_bump) { - get_requested_graph_features(shader->graph_bump, - requested_features); - } ShaderNode *output_node = shader->graph->output(); if(output_node->input("Displacement")->link != NULL) { requested_features->nodes_features |= NODE_FEATURE_BUMP; diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index b6714b13247..79a67d6756a 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -89,11 +89,6 @@ public: /* shader graph */ ShaderGraph *graph; - /* shader graph with auto bump mapping included, we compile two shaders, - * with and without bump, because the displacement method is a mesh - * level setting, so we need to handle both */ - ShaderGraph *graph_bump; - /* sampling */ bool use_mis; bool use_transparent_shadow; @@ -121,6 +116,7 @@ public: bool has_volume; bool has_displacement; bool has_surface_bssrdf; + bool has_bump; bool has_bssrdf_bump; bool has_surface_spatial_varying; bool has_volume_spatial_varying; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 48287d872d4..32f89897970 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -521,6 +521,9 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, if(node->has_bssrdf_bump()) current_shader->has_bssrdf_bump = true; } + if(node->has_bump()) { + current_shader->has_bump = true; + } } } @@ -799,29 +802,21 @@ void SVMCompiler::compile(Scene *scene, Summary *summary) { /* copy graph for shader with bump mapping */ - ShaderNode *node = shader->graph->output(); + ShaderNode *output = shader->graph->output(); int start_num_svm_nodes = svm_nodes.size(); const double time_start = time_dt(); - if(node->input("Surface")->link && node->input("Displacement")->link) - if(!shader->graph_bump) - shader->graph_bump = shader->graph->copy(); + bool has_bump = (shader->displacement_method != DISPLACE_TRUE) && + output->input("Surface")->link && output->input("Displacement")->link; /* finalize */ { scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL); shader->graph->finalize(scene, - false, - shader->has_integrator_dependency); - } - - if(shader->graph_bump) { - scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL); - shader->graph_bump->finalize(scene, - true, - shader->has_integrator_dependency, - shader->displacement_method == DISPLACE_BOTH); + has_bump, + shader->has_integrator_dependency, + shader->displacement_method == DISPLACE_BOTH); } current_shader = shader; @@ -830,7 +825,8 @@ void SVMCompiler::compile(Scene *scene, shader->has_surface_emission = false; shader->has_surface_transparent = false; shader->has_surface_bssrdf = false; - shader->has_bssrdf_bump = false; + shader->has_bump = has_bump; + shader->has_bssrdf_bump = has_bump; shader->has_volume = false; shader->has_displacement = false; shader->has_surface_spatial_varying = false; @@ -839,9 +835,9 @@ void SVMCompiler::compile(Scene *scene, shader->has_integrator_dependency = false; /* generate bump shader */ - if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump) { + if(has_bump) { scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL); - compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP); + compile_type(shader, shader->graph, SHADER_TYPE_BUMP); svm_nodes[index].y = svm_nodes.size(); svm_nodes.insert(svm_nodes.end(), current_svm_nodes.begin(), @@ -853,7 +849,7 @@ void SVMCompiler::compile(Scene *scene, scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL); compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); /* only set jump offset if there's no bump shader, as the bump shader will fall thru to this one if it exists */ - if(shader->displacement_method == DISPLACE_TRUE || !shader->graph_bump) { + if(!has_bump) { svm_nodes[index].y = svm_nodes.size(); } svm_nodes.insert(svm_nodes.end(), @@ -895,7 +891,6 @@ SVMCompiler::Summary::Summary() : num_svm_nodes(0), peak_stack_usage(0), time_finalize(0.0), - time_finalize_bump(0.0), time_generate_surface(0.0), time_generate_bump(0.0), time_generate_volume(0.0), @@ -911,10 +906,7 @@ string SVMCompiler::Summary::full_report() const report += string_printf("Peak stack usage: %d\n", peak_stack_usage); report += string_printf("Time (in seconds):\n"); - report += string_printf(" Finalize: %f\n", time_finalize); - report += string_printf(" Bump finalize: %f\n", time_finalize_bump); - report += string_printf("Finalize: %f\n", time_finalize + - time_finalize_bump); + report += string_printf("Finalize: %f\n", time_finalize); report += string_printf(" Surface: %f\n", time_generate_surface); report += string_printf(" Bump: %f\n", time_generate_bump); report += string_printf(" Volume: %f\n", time_generate_volume); diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index abbd9e50610..98ef5fa05d8 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -74,9 +74,6 @@ public: /* Time spent on surface graph finalization. */ double time_finalize; - /* Time spent on bump graph finalization. */ - double time_finalize_bump; - /* Time spent on generating SVM nodes for surface shader. */ double time_generate_surface; @@ -71,28 +71,28 @@ if NOT "%1" == "" ( -C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake" ) else if "%1" == "release" ( set TARGET=Release - ) else if "%1" == "x86" ( + ) else if "%1" == "x86" ( set BUILD_ARCH=x86 - ) else if "%1" == "x64" ( + ) else if "%1" == "x64" ( set BUILD_ARCH=x64 - ) else if "%1" == "2017" ( + ) else if "%1" == "2017" ( set BUILD_VS_VER=15 set BUILD_VS_YEAR=2017 set BUILD_VS_LIBDIRPOST=vc14 - ) else if "%1" == "2015" ( + ) else if "%1" == "2015" ( set BUILD_VS_VER=14 set BUILD_VS_YEAR=2015 set BUILD_VS_LIBDIRPOST=vc14 - ) else if "%1" == "2013" ( + ) else if "%1" == "2013" ( set BUILD_VS_VER=12 set BUILD_VS_YEAR=2013 set BUILD_VS_LIBDIRPOST=vc12 - ) else if "%1" == "packagename" ( + ) else if "%1" == "packagename" ( set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2" shift /1 - ) else if "%1" == "nobuild" ( + ) else if "%1" == "nobuild" ( set NOBUILD=1 - ) else if "%1" == "showhash" ( + ) else if "%1" == "showhash" ( for /f "delims=" %%i in ('git rev-parse HEAD') do echo Branch_hash=%%i cd release/datafiles/locale for /f "delims=" %%i in ('git rev-parse HEAD') do echo Locale_hash=%%i @@ -129,10 +129,10 @@ if "%BUILD_ARCH%"=="" ( set BUILD_ARCH=x86 ) ) else if "%BUILD_ARCH%"=="x64" ( - set WINDOWS_ARCH= Win64 - ) else if "%BUILD_ARCH%"=="x86" ( - set WINDOWS_ARCH= - ) + set WINDOWS_ARCH= Win64 +) else if "%BUILD_ARCH%"=="x86" ( + set WINDOWS_ARCH= +) if "%BUILD_VS_VER%"=="" ( set BUILD_VS_VER=12 @@ -142,19 +142,19 @@ if "%BUILD_VS_VER%"=="" ( if "%BUILD_ARCH%"=="x64" ( set MSBUILD_PLATFORM=x64 - ) else if "%BUILD_ARCH%"=="x86" ( - set MSBUILD_PLATFORM=win32 +) else if "%BUILD_ARCH%"=="x86" ( + set MSBUILD_PLATFORM=win32 ) if "%target%"=="Release" ( - rem for vc12 check for both cuda 7.5 and 8 - if "%CUDA_PATH%"=="" ( - echo Cuda Not found, aborting! - goto EOF - ) - set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^ - -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake" + rem for vc12 check for both cuda 7.5 and 8 + if "%CUDA_PATH%"=="" ( + echo Cuda Not found, aborting! + goto EOF + ) + set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^ + -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake" ) :DetectMSVC @@ -193,7 +193,7 @@ if %ERRORLEVEL% NEQ 0 ( set BUILD_VS_YEAR=2015 set BUILD_VS_LIBDIRPOST=vc14 goto DetectMSVC - ) else ( + ) else ( echo Error: "MSBuild" command not in the PATH. echo You must have MSVC installed and run this from the "Developer Command Prompt" echo ^(available from Visual Studio's Start menu entry^), aborting! @@ -216,8 +216,8 @@ if %ERRORLEVEL% NEQ 0 ( if "%BUILD_ARCH%"=="x64" ( set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST% - ) else if "%BUILD_ARCH%"=="x86" ( - set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST% +) else if "%BUILD_ARCH%"=="x86" ( + set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST% ) set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%" @@ -238,9 +238,9 @@ if NOT EXIST %BUILD_VS_LIBDIR% ( ) if NOT EXIST %BUILD_VS_LIBDIR% ( - echo Error: Path to libraries not found "%BUILD_VS_LIBDIR%" - echo This is needed for building, aborting! - goto EOF + echo Error: Path to libraries not found "%BUILD_VS_LIBDIR%" + echo This is needed for building, aborting! + goto EOF ) if "%TARGET%"=="" ( @@ -331,31 +331,31 @@ echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%\blender echo. goto EOF :HELP - echo. - echo Convenience targets - echo - release ^(identical to the official blender.org builds^) - echo - full ^(same as release minus the cuda kernels^) - echo - lite - echo - headless - echo - cycles - echo - bpy - echo. - echo Utilities ^(not associated with building^) - echo - clean ^(Target must be set^) - echo - update - echo - nobuild ^(only generate project files^) - echo - showhash ^(Show git hashes of source tree^) - echo. - echo Configuration options - echo - with_tests ^(enable building unit tests^) - echo - noge ^(disable building game enginge and player^) - echo - debug ^(Build an unoptimized debuggable build^) - echo - packagename [newname] ^(override default cpack package name^) - echo - buildir [newdir] ^(override default build folder^) - echo - x86 ^(override host auto-detect and build 32 bit code^) - echo - x64 ^(override host auto-detect and build 64 bit code^) - echo - 2013 ^(build with visual studio 2013^) - echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL] - echo. + echo. + echo Convenience targets + echo - release ^(identical to the official blender.org builds^) + echo - full ^(same as release minus the cuda kernels^) + echo - lite + echo - headless + echo - cycles + echo - bpy + echo. + echo Utilities ^(not associated with building^) + echo - clean ^(Target must be set^) + echo - update + echo - nobuild ^(only generate project files^) + echo - showhash ^(Show git hashes of source tree^) + echo. + echo Configuration options + echo - with_tests ^(enable building unit tests^) + echo - noge ^(disable building game enginge and player^) + echo - debug ^(Build an unoptimized debuggable build^) + echo - packagename [newname] ^(override default cpack package name^) + echo - buildir [newdir] ^(override default build folder^) + echo - x86 ^(override host auto-detect and build 32 bit code^) + echo - x64 ^(override host auto-detect and build 64 bit code^) + echo - 2013 ^(build with visual studio 2013^) + echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL] + echo. :EOF diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 761e6294ffa..ed14c3d24ee 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -294,7 +294,8 @@ class VIEW3D_MT_transform_object(VIEW3D_MT_transform_base): layout.operator("object.origin_set", text="Geometry to Origin").type = 'GEOMETRY_ORIGIN' layout.operator("object.origin_set", text="Origin to Geometry").type = 'ORIGIN_GEOMETRY' layout.operator("object.origin_set", text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR' - layout.operator("object.origin_set", text="Origin to Center of Mass").type = 'ORIGIN_CENTER_OF_MASS' + layout.operator("object.origin_set", text="Origin to Center of Mass (Surface)").type = 'ORIGIN_CENTER_OF_MASS' + layout.operator("object.origin_set", text="Origin to Center of Mass (Volume)").type = 'ORIGIN_CENTER_OF_VOLUME' layout.separator() layout.operator("object.randomize_transform") diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index d68712202c9..9463ea81bfc 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -278,7 +278,8 @@ void BKE_mesh_poly_edgebitmap_insert( bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]); bool BKE_mesh_center_bounds(const struct Mesh *me, float r_cent[3]); -bool BKE_mesh_center_centroid(const struct Mesh *me, float r_cent[3]); +bool BKE_mesh_center_of_surface(const struct Mesh *me, float r_cent[3]); +bool BKE_mesh_center_of_volume(const struct Mesh *me, float r_cent[3]); void BKE_mesh_calc_volume( const struct MVert *mverts, const int mverts_num, diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index ca8b58ffae3..654a25cbb3d 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -1856,11 +1856,14 @@ float BKE_mesh_calc_poly_area( * - http://forums.cgsociety.org/archive/index.php?t-756235.html * - http://www.globalspec.com/reference/52702/203279/4-8-the-centroid-of-a-tetrahedron * - * \note volume is 6x actual volume, and centroid is 4x actual volume-weighted centroid - * (so division can be done once at the end) - * \note results will have bias if polygon is non-planar. + * \note + * - Volume is 6x actual volume, and centroid is 4x actual volume-weighted centroid + * (so division can be done once at the end). + * - Results will have bias if polygon is non-planar. + * - The resulting volume will only be correct if the mesh is manifold and has consistent face winding + * (non-contiguous face normals or holes in the mesh surface). */ -static float mesh_calc_poly_volume_and_weighted_centroid( +static float mesh_calc_poly_volume_centroid( const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray, float r_cent[3]) { @@ -1897,6 +1900,43 @@ static float mesh_calc_poly_volume_and_weighted_centroid( return total_volume; } +/** + * \note + * - Results won't be correct if polygon is non-planar. + * - This has the advantage over #mesh_calc_poly_volume_centroid + * that it doesn't depend on solid geometry, instead it weights the surface by volume. + */ +static float mesh_calc_poly_area_centroid( + const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray, + float r_cent[3]) +{ + int i; + float tri_area; + float total_area = 0.0f; + float v1[3], v2[3], v3[3], normal[3], tri_cent[3]; + + BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, normal); + copy_v3_v3(v1, mvarray[loopstart[0].v].co); + copy_v3_v3(v2, mvarray[loopstart[1].v].co); + zero_v3(r_cent); + + for (i = 2; i < mpoly->totloop; i++) { + copy_v3_v3(v3, mvarray[loopstart[i].v].co); + + tri_area = area_tri_signed_v3(v1, v2, v3, normal); + total_area += tri_area; + + mid_v3_v3v3v3(tri_cent, v1, v2, v3); + madd_v3_v3fl(r_cent, tri_cent, tri_area); + + copy_v3_v3(v2, v3); + } + + mul_v3_fl(r_cent, 1.0f / total_area); + + return total_area; +} + #if 0 /* slow version of the function below */ void BKE_mesh_calc_poly_angles(MPoly *mpoly, MLoop *loopstart, MVert *mvarray, float angles[]) @@ -2011,7 +2051,40 @@ bool BKE_mesh_center_bounds(const Mesh *me, float r_cent[3]) return false; } -bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3]) +bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3]) +{ + int i = me->totpoly; + MPoly *mpoly; + float poly_area; + float total_area = 0.0f; + float poly_cent[3]; + + zero_v3(r_cent); + + /* calculate a weighted average of polygon centroids */ + for (mpoly = me->mpoly; i--; mpoly++) { + poly_area = mesh_calc_poly_area_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent); + + madd_v3_v3fl(r_cent, poly_cent, poly_area); + total_area += poly_area; + } + /* otherwise we get NAN for 0 polys */ + if (me->totpoly) { + mul_v3_fl(r_cent, 1.0f / total_area); + } + + /* zero area faces cause this, fallback to median */ + if (UNLIKELY(!is_finite_v3(r_cent))) { + return BKE_mesh_center_median(me, r_cent); + } + + return (me->totpoly != 0); +} + +/** + * \note Mesh must be manifold with consistent face-winding, see #mesh_calc_poly_volume_centroid for details. + */ +bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3]) { int i = me->totpoly; MPoly *mpoly; @@ -2023,7 +2096,7 @@ bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3]) /* calculate a weighted average of polyhedron centroids */ for (mpoly = me->mpoly; i--; mpoly++) { - poly_volume = mesh_calc_poly_volume_and_weighted_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent); + poly_volume = mesh_calc_poly_volume_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent); /* poly_cent is already volume-weighted, so no need to multiply by the volume */ add_v3_v3(r_cent, poly_cent); @@ -2043,6 +2116,7 @@ bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3]) return (me->totpoly != 0); } + /** \} */ diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 4f758bde7f9..ac9c60e8999 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -429,7 +429,6 @@ static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, i ParticleThreadContext *ctx= thread->ctx; MFace *mface; - DM_ensure_tessface(ctx->dm); mface = ctx->dm->getTessFaceDataArray(ctx->dm, CD_MFACE); int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ @@ -899,10 +898,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti else dm= CDDM_from_mesh((Mesh*)ob->data); - /* BMESH ONLY, for verts we don't care about tessfaces */ - if (from != PART_FROM_VERT) { - DM_ensure_tessface(dm); - } + DM_ensure_tessface(dm); /* we need orco for consistent distributions */ if (!CustomData_has_layer(&dm->vertData, CD_ORCO)) diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 1baa1926bd2..32c342f9f02 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -734,7 +734,8 @@ enum { GEOMETRY_TO_ORIGIN = 0, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR, - ORIGIN_TO_CENTER_OF_MASS + ORIGIN_TO_CENTER_OF_MASS_SURFACE, + ORIGIN_TO_CENTER_OF_MASS_VOLUME, }; static int object_origin_set_exec(bContext *C, wmOperator *op) @@ -891,10 +892,21 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (obedit == NULL && ob->type == OB_MESH) { Mesh *me = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ } - else if (centermode == ORIGIN_TO_CENTER_OF_MASS) { BKE_mesh_center_centroid(me, cent); } - else if (around == V3D_AROUND_CENTER_MEAN) { BKE_mesh_center_median(me, cent); } - else { BKE_mesh_center_bounds(me, cent); } + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ + } + else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) { + BKE_mesh_center_of_surface(me, cent); + } + else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) { + BKE_mesh_center_of_volume(me, cent); + } + else if (around == V3D_AROUND_CENTER_MEAN) { + BKE_mesh_center_median(me, cent); + } + else { + BKE_mesh_center_bounds(me, cent); + } negate_v3_v3(cent_neg, cent); BKE_mesh_translate(me, cent_neg, 1); @@ -1105,11 +1117,14 @@ void OBJECT_OT_origin_set(wmOperatorType *ot) static EnumPropertyItem prop_set_center_types[] = { {GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"}, {ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry", - "Move object origin to center of object geometry"}, + "Calculate the center of geometry based on the current pivot point (median, otherwise bounding-box)"}, {ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor", - "Move object origin to position of the 3D cursor"}, - {ORIGIN_TO_CENTER_OF_MASS, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass", - "Move object origin to the object center of mass (assuming uniform density)"}, + "Move object origin to position of the 3D cursor"}, + /* Intentional naming mismatch since some scripts refer to this. */ + {ORIGIN_TO_CENTER_OF_MASS_SURFACE, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass (Surface)", + "Calculate the center of mass from the surface area"}, + {ORIGIN_TO_CENTER_OF_MASS_VOLUME, "ORIGIN_CENTER_OF_VOLUME", 0, "Origin to Center of Mass (Volume)", + "Calculate the center of mass from the volume (must be manifold geometry with consistent normals)"}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c index e78bb2b0b24..b285f1a8a3e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c +++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c @@ -51,14 +51,23 @@ static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *node, bNodeExecData return GPU_stack_link(mat, node, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION)); } -static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) +static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { ShadeInput *shi = ((ShaderCallData *)data)->shi; - float eta = max_ff(in[0]->vec[0], 0.00001); + + /* Compute IOR. */ + float eta; + nodestack_get_vec(&eta, SOCK_FLOAT, in[0]); + eta = max_ff(eta, 0.00001); + eta = shi->flippednor ? 1 / eta : eta; + + /* Get normal from socket, but only if linked. */ + bNodeSocket *sock_normal = node->inputs.first; + sock_normal = sock_normal->next; float n[3]; - if (in[1]->hasinput) { - copy_v3_v3(n, in[1]->vec); + if (sock_normal->link) { + nodestack_get_vec(n, SOCK_VECTOR, in[1]); } else { copy_v3_v3(n, shi->vn); @@ -68,7 +77,7 @@ static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *UNUS mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n); } - out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? 1 / eta : eta); + out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, eta); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c index e84d8e7241c..3ab73fdde18 100644 --- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c +++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c @@ -52,24 +52,33 @@ static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *node, bNodeExec return GPU_stack_link(mat, node, "node_layer_weight", in, out, GPU_builtin(GPU_VIEW_POSITION)); } -static void node_shader_exec_layer_weight(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) +static void node_shader_exec_layer_weight(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { ShadeInput *shi = ((ShaderCallData *)data)->shi; - float blend = in[0]->vec[0]; + + /* Compute IOR. */ + float blend; + nodestack_get_vec(&blend, SOCK_FLOAT, in[0]); float eta = max_ff(1 - blend, 0.00001); + eta = shi->flippednor ? eta : 1 / eta; + + /* Get normal from socket, but only if linked. */ + bNodeSocket *sock_normal = node->inputs.first; + sock_normal = sock_normal->next; float n[3]; - if (in[1]->hasinput) { - copy_v3_v3(n, in[1]->vec); + if (sock_normal->link) { + nodestack_get_vec(n, SOCK_VECTOR, in[1]); } else { copy_v3_v3(n, shi->vn); } + if (shi->use_world_space_shading) mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n); - out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? eta : 1 / eta); + out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, eta); float facing = fabs(dot_v3v3(shi->view, n)); if (blend != 0.5) { diff --git a/source/gameengine/Expressions/EXP_PyObjectPlus.h b/source/gameengine/Expressions/EXP_PyObjectPlus.h index 32dc79cf6eb..504d79f7cbb 100644 --- a/source/gameengine/Expressions/EXP_PyObjectPlus.h +++ b/source/gameengine/Expressions/EXP_PyObjectPlus.h @@ -44,7 +44,8 @@ #include "STR_String.h" #include "MT_Vector3.h" #include "SG_QList.h" -#include <stddef.h> +#include <cstddef> +#include <cstdint> #ifdef WITH_PYTHON #ifdef USE_MATHUTILS |