diff options
Diffstat (limited to 'intern/cycles/blender')
23 files changed, 633 insertions, 265 deletions
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index b57502b3b14..ae4977aaed0 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -1,12 +1,6 @@ set(INC - ../graph - ../render - ../device - ../kernel - ../kernel/svm - ../util - ../subd + .. ../../glew-mx ../../guardedalloc ../../mikktspace diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 235d19e91e8..eb792af7264 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -107,7 +107,13 @@ def engine_exit(): engine.exit() +classes = ( + CyclesRender, +) + + def register(): + from bpy.utils import register_class from . import ui from . import properties from . import presets @@ -122,12 +128,15 @@ def register(): properties.register() ui.register() presets.register() - bpy.utils.register_module(__name__) + + for cls in classes: + register_class(cls) bpy.app.handlers.version_update.append(version_update.do_versions) def unregister(): + from bpy.utils import unregister_class from . import ui from . import properties from . import presets @@ -138,4 +147,6 @@ def unregister(): ui.unregister() properties.unregister() presets.unregister() - bpy.utils.unregister_module(__name__) + + for cls in classes: + unregister_class(cls) diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index c8c9ef58c52..ab57dd44bdb 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -50,6 +50,24 @@ def _workaround_buggy_drivers(): _cycles.opencl_disable() +def _configure_argument_parser(): + import argparse + parser = argparse.ArgumentParser(description="Cycles Addon argument parser") + parser.add_argument("--cycles-resumable-num-chunks", + help="Number of chunks to split sample range into", + default=None) + parser.add_argument("--cycles-resumable-current-chunk", + help="Current chunk of samples range to render", + default=None) + parser.add_argument("--cycles-resumable-start-chunk", + help="Start chunk to render", + default=None) + parser.add_argument("--cycles-resumable-end-chunk", + help="End chunk to render", + default=None) + return parser + + def _parse_command_line(): import sys @@ -57,25 +75,22 @@ def _parse_command_line(): if "--" not in argv: return - argv = argv[argv.index("--") + 1:] - - num_resumable_chunks = None - current_resumable_chunk = None - - # TODO(sergey): Add some nice error prints if argument is not used properly. - idx = 0 - while idx < len(argv) - 1: - arg = argv[idx] - if arg == '--cycles-resumable-num-chunks': - num_resumable_chunks = int(argv[idx + 1]) - elif arg == '--cycles-resumable-current-chunk': - current_resumable_chunk = int(argv[idx + 1]) - idx += 1 + parser = _configure_argument_parser() + args, unknown = parser.parse_known_args(argv[argv.index("--") + 1:]) - if num_resumable_chunks is not None and current_resumable_chunk is not None: - import _cycles - _cycles.set_resumable_chunks(num_resumable_chunks, - current_resumable_chunk) + if args.cycles_resumable_num_chunks is not None: + if args.cycles_resumable_current_chunk is not None: + import _cycles + _cycles.set_resumable_chunk( + int(args.cycles_resumable_num_chunks), + int(args.cycles_resumable_current_chunk)) + elif args.cycles_resumable_start_chunk is not None and \ + args.cycles_resumable_end_chunk: + import _cycles + _cycles.set_resumable_chunk_range( + int(args.cycles_resumable_num_chunks), + int(args.cycles_resumable_start_chunk), + int(args.cycles_resumable_end_chunk)) def init(): diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py index f97b51b629d..82c4ffc6e50 100644 --- a/intern/cycles/blender/addon/presets.py +++ b/intern/cycles/blender/addon/presets.py @@ -82,12 +82,23 @@ class AddPresetSampling(AddPresetBase, Operator): preset_subdir = "cycles/sampling" +classes = ( + AddPresetIntegrator, + AddPresetSampling, +) + + def register(): - pass + from bpy.utils import register_class + for cls in classes: + register_class(cls) def unregister(): - pass + from bpy.utils import unregister_class + for cls in classes: + unregister_class(cls) + if __name__ == "__main__": register() diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 5c51f9afc28..cbf469b3a89 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -665,8 +665,10 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): cls.debug_use_cpu_sse3 = BoolProperty(name="SSE3", default=True) cls.debug_use_cpu_sse2 = BoolProperty(name="SSE2", default=True) cls.debug_use_qbvh = BoolProperty(name="QBVH", default=True) + cls.debug_use_cpu_split_kernel = BoolProperty(name="Split Kernel", default=False) cls.debug_use_cuda_adaptive_compile = BoolProperty(name="Adaptive Compile", default=False) + cls.debug_use_cuda_split_kernel = BoolProperty(name="Split Kernel", default=False) cls.debug_opencl_kernel_type = EnumProperty( name="OpenCL Kernel Type", @@ -693,6 +695,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): update=devices_update_callback ) + cls.debug_opencl_kernel_single_program = BoolProperty(name="Single Program", default=False, update=devices_update_callback); + cls.debug_use_opencl_debug = BoolProperty(name="Debug OpenCL", default=False) @classmethod @@ -1092,6 +1096,12 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): default=1.0, ) + cls.is_shadow_catcher = BoolProperty( + name="Shadow Catcher", + description="Only render shadows on this object, for compositing renders into real footage", + default=False, + ) + @classmethod def unregister(cls): del bpy.types.Object.cycles diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 44af5f7efed..2b50d272be8 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -86,12 +86,10 @@ def use_sample_all_lights(context): return cscene.sample_all_lights_direct or cscene.sample_all_lights_indirect -def show_device_selection(context): - type = get_device_type(context) - if type == 'NETWORK': +def show_device_active(context): + cscene = context.scene.cycles + if cscene.device != 'GPU': return True - if not type in {'CUDA', 'OPENCL'}: - return False return context.user_preferences.addons[__package__].preferences.has_active_device() @@ -186,9 +184,6 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): sub.label(text="AA Samples:") sub.prop(cscene, "aa_samples", text="Render") sub.prop(cscene, "preview_aa_samples", text="Preview") - sub.separator() - sub.prop(cscene, "sample_all_lights_direct") - sub.prop(cscene, "sample_all_lights_indirect") col = split.column() sub = col.column(align=True) @@ -205,6 +200,10 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): sub.prop(cscene, "subsurface_samples", text="Subsurface") sub.prop(cscene, "volume_samples", text="Volume") + col = layout.column(align=True) + col.prop(cscene, "sample_all_lights_direct") + col.prop(cscene, "sample_all_lights_indirect") + if not (use_opencl(context) and cscene.feature_set != 'EXPERIMENTAL'): layout.row().prop(cscene, "sampling_pattern", text="Pattern") @@ -270,7 +269,7 @@ class CyclesRender_PT_geometry(CyclesButtonsPanel, Panel): row = col.row() row.prop(ccscene, "minimum_width", text="Min Pixels") - row.prop(ccscene, "maximum_width", text="Max Ext.") + row.prop(ccscene, "maximum_width", text="Max Extension") class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel): @@ -788,6 +787,8 @@ class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel): if ob.type != 'LAMP': flow.prop(visibility, "shadow") + layout.prop(cob, "is_shadow_catcher") + col = layout.column() col.label(text="Performance:") row = col.row() @@ -1518,15 +1519,18 @@ class CyclesRender_PT_debug(CyclesButtonsPanel, Panel): row.prop(cscene, "debug_use_cpu_avx", toggle=True) row.prop(cscene, "debug_use_cpu_avx2", toggle=True) col.prop(cscene, "debug_use_qbvh") + col.prop(cscene, "debug_use_cpu_split_kernel") col = layout.column() col.label('CUDA Flags:') col.prop(cscene, "debug_use_cuda_adaptive_compile") + col.prop(cscene, "debug_use_cuda_split_kernel") col = layout.column() col.label('OpenCL Flags:') col.prop(cscene, "debug_opencl_kernel_type", text="Kernel") col.prop(cscene, "debug_opencl_device_type", text="Device") + col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program") col.prop(cscene, "debug_use_opencl_debug", text="Debug") @@ -1633,7 +1637,7 @@ def draw_device(self, context): split = layout.split(percentage=1/3) split.label("Device:") row = split.row() - row.active = show_device_selection(context) + row.active = show_device_active(context) row.prop(cscene, "device", text="") if engine.with_osl() and use_cpu(context): @@ -1712,17 +1716,75 @@ def get_panels(): return panels + +classes = ( + CYCLES_MT_sampling_presets, + CYCLES_MT_integrator_presets, + CyclesRender_PT_sampling, + CyclesRender_PT_geometry, + CyclesRender_PT_light_paths, + CyclesRender_PT_motion_blur, + CyclesRender_PT_film, + CyclesRender_PT_performance, + CyclesRender_PT_layer_options, + CyclesRender_PT_layer_passes, + CyclesRender_PT_views, + Cycles_PT_post_processing, + CyclesCamera_PT_dof, + Cycles_PT_context_material, + CyclesObject_PT_motion_blur, + CyclesObject_PT_cycles_settings, + CYCLES_OT_use_shading_nodes, + CyclesLamp_PT_preview, + CyclesLamp_PT_lamp, + CyclesLamp_PT_nodes, + CyclesLamp_PT_spot, + CyclesWorld_PT_preview, + CyclesWorld_PT_surface, + CyclesWorld_PT_volume, + CyclesWorld_PT_ambient_occlusion, + CyclesWorld_PT_mist, + CyclesWorld_PT_ray_visibility, + CyclesWorld_PT_settings, + CyclesMaterial_PT_preview, + CyclesMaterial_PT_surface, + CyclesMaterial_PT_volume, + CyclesMaterial_PT_displacement, + CyclesMaterial_PT_settings, + CyclesTexture_PT_context, + CyclesTexture_PT_node, + CyclesTexture_PT_mapping, + CyclesTexture_PT_colors, + CyclesParticle_PT_textures, + CyclesRender_PT_bake, + CyclesRender_PT_debug, + CyclesParticle_PT_CurveSettings, + CyclesScene_PT_simplify, +) + + def register(): + from bpy.utils import register_class + bpy.types.RENDER_PT_render.append(draw_device) bpy.types.VIEW3D_HT_header.append(draw_pause) for panel in get_panels(): panel.COMPAT_ENGINES.add('CYCLES') + for cls in classes: + register_class(cls) + + def unregister(): + from bpy.utils import unregister_class + bpy.types.RENDER_PT_render.remove(draw_device) bpy.types.VIEW3D_HT_header.remove(draw_pause) for panel in get_panels(): if 'CYCLES' in panel.COMPAT_ENGINES: panel.COMPAT_ENGINES.remove('CYCLES') + + for cls in classes: + unregister_class(cls) diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index f02fc553908..40d6b25f2b7 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -14,13 +14,13 @@ * limitations under the License. */ -#include "camera.h" -#include "scene.h" +#include "render/camera.h" +#include "render/scene.h" -#include "blender_sync.h" -#include "blender_util.h" +#include "blender/blender_sync.h" +#include "blender/blender_util.h" -#include "util_logging.h" +#include "util/util_logging.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index e42ff5d72a6..6fa038e8bf0 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -14,18 +14,18 @@ * limitations under the License. */ -#include "attribute.h" -#include "camera.h" -#include "curves.h" -#include "mesh.h" -#include "object.h" -#include "scene.h" +#include "render/attribute.h" +#include "render/camera.h" +#include "render/curves.h" +#include "render/mesh.h" +#include "render/object.h" +#include "render/scene.h" -#include "blender_sync.h" -#include "blender_util.h" +#include "blender/blender_sync.h" +#include "blender/blender_util.h" -#include "util_foreach.h" -#include "util_logging.h" +#include "util/util_foreach.h" +#include "util/util_logging.h" CCL_NAMESPACE_BEGIN @@ -411,6 +411,7 @@ static void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, } } + mesh->resize_mesh(mesh->verts.size(), mesh->triangles.size()); mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL); mesh->attributes.remove(ATTR_STD_FACE_NORMAL); mesh->add_face_normals(); @@ -434,8 +435,8 @@ static void ExportCurveTriangleGeometry(Mesh *mesh, if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f) continue; - numverts += (CData->curve_keynum[curve] - 2)*2*resolution + resolution; - numtris += (CData->curve_keynum[curve] - 2)*resolution; + numverts += (CData->curve_keynum[curve] - 1)*resolution + resolution; + numtris += (CData->curve_keynum[curve] - 1)*2*resolution; } } @@ -545,6 +546,7 @@ static void ExportCurveTriangleGeometry(Mesh *mesh, } } + mesh->resize_mesh(mesh->verts.size(), mesh->triangles.size()); mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL); mesh->attributes.remove(ATTR_STD_FACE_NORMAL); mesh->add_face_normals(); @@ -890,7 +892,7 @@ void BlenderSync::sync_curves(Mesh *mesh, } /* obtain general settings */ - bool use_curves = scene->curve_system_manager->use_curves; + const bool use_curves = scene->curve_system_manager->use_curves; if(!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT)) { if(!motion) @@ -898,11 +900,11 @@ void BlenderSync::sync_curves(Mesh *mesh, return; } - int primitive = scene->curve_system_manager->primitive; - int triangle_method = scene->curve_system_manager->triangle_method; - int resolution = scene->curve_system_manager->resolution; - size_t vert_num = mesh->verts.size(); - size_t tri_num = mesh->num_triangles(); + const int primitive = scene->curve_system_manager->primitive; + const int triangle_method = scene->curve_system_manager->triangle_method; + const int resolution = scene->curve_system_manager->resolution; + const size_t vert_num = mesh->verts.size(); + const size_t tri_num = mesh->num_triangles(); int used_res = 1; /* extract particle hair data - should be combined with connecting to mesh later*/ diff --git a/intern/cycles/blender/blender_logging.cpp b/intern/cycles/blender/blender_logging.cpp index f4f86929168..d0f82e37662 100644 --- a/intern/cycles/blender/blender_logging.cpp +++ b/intern/cycles/blender/blender_logging.cpp @@ -14,8 +14,8 @@ * limitations under the License. */ -#include "CCL_api.h" -#include "util_logging.h" +#include "blender/CCL_api.h" +#include "util/util_logging.h" void CCL_init_logging(const char *argv0) { diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 85117cfff7b..e0e89cec65c 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -15,21 +15,22 @@ */ -#include "mesh.h" -#include "object.h" -#include "scene.h" -#include "camera.h" +#include "render/mesh.h" +#include "render/object.h" +#include "render/scene.h" +#include "render/camera.h" -#include "blender_sync.h" -#include "blender_session.h" -#include "blender_util.h" +#include "blender/blender_sync.h" +#include "blender/blender_session.h" +#include "blender/blender_util.h" -#include "subd_patch.h" -#include "subd_split.h" +#include "subd/subd_patch.h" +#include "subd/subd_split.h" -#include "util_foreach.h" -#include "util_logging.h" -#include "util_math.h" +#include "util/util_algorithm.h" +#include "util/util_foreach.h" +#include "util/util_logging.h" +#include "util/util_math.h" #include "mikktspace.h" @@ -525,69 +526,177 @@ static void attr_create_uv_map(Scene *scene, } /* Create vertex pointiness attributes. */ + +/* Compare vertices by sum of their coordinates. */ +class VertexAverageComparator { +public: + VertexAverageComparator(const array<float3>& verts) + : verts_(verts) { + } + + bool operator()(const int& vert_idx_a, const int& vert_idx_b) + { + const float3 &vert_a = verts_[vert_idx_a]; + const float3 &vert_b = verts_[vert_idx_b]; + if(vert_a == vert_b) { + /* Special case for doubles, so we ensure ordering. */ + return vert_idx_a > vert_idx_b; + } + const float x1 = vert_a.x + vert_a.y + vert_a.z; + const float x2 = vert_b.x + vert_b.y + vert_b.z; + return x1 < x2; + } + +protected: + const array<float3>& verts_; +}; + static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh& b_mesh, bool subdivision) { - if(mesh->need_attribute(scene, ATTR_STD_POINTINESS)) { - const int numverts = b_mesh.vertices.length(); - AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes; - Attribute *attr = attributes.add(ATTR_STD_POINTINESS); - float *data = attr->data_float(); - int *counter = new int[numverts]; - float *raw_data = new float[numverts]; - float3 *edge_accum = new float3[numverts]; - - /* Calculate pointiness using single ring neighborhood. */ - memset(counter, 0, sizeof(int) * numverts); - memset(raw_data, 0, sizeof(float) * numverts); - memset(edge_accum, 0, sizeof(float3) * numverts); - BL::Mesh::edges_iterator e; - int i = 0; - for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) { - int v0 = b_mesh.edges[i].vertices()[0], - v1 = b_mesh.edges[i].vertices()[1]; - float3 co0 = get_float3(b_mesh.vertices[v0].co()), - co1 = get_float3(b_mesh.vertices[v1].co()); - float3 edge = normalize(co1 - co0); - edge_accum[v0] += edge; - edge_accum[v1] += -edge; - ++counter[v0]; - ++counter[v1]; - } - i = 0; - BL::Mesh::vertices_iterator v; - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i) { - if(counter[i] > 0) { - float3 normal = get_float3(b_mesh.vertices[i].normal()); - float angle = safe_acosf(dot(normal, edge_accum[i] / counter[i])); - raw_data[i] = angle * M_1_PI_F; + if(!mesh->need_attribute(scene, ATTR_STD_POINTINESS)) { + return; + } + const int num_verts = b_mesh.vertices.length(); + /* STEP 1: Find out duplicated vertices and point duplicates to a single + * original vertex. + */ + vector<int> sorted_vert_indeices(num_verts); + for(int vert_index = 0; vert_index < num_verts; ++vert_index) { + sorted_vert_indeices[vert_index] = vert_index; + } + VertexAverageComparator compare(mesh->verts); + sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare); + /* This array stores index of the original vertex for the given vertex + * index. + */ + vector<int> vert_orig_index(num_verts); + for(int sorted_vert_index = 0; + sorted_vert_index < num_verts; + ++sorted_vert_index) + { + const int vert_index = sorted_vert_indeices[sorted_vert_index]; + const float3 &vert_co = mesh->verts[vert_index]; + bool found = false; + for(int other_sorted_vert_index = sorted_vert_index + 1; + other_sorted_vert_index < num_verts; + ++other_sorted_vert_index) + { + const int other_vert_index = + sorted_vert_indeices[other_sorted_vert_index]; + const float3 &other_vert_co = mesh->verts[other_vert_index]; + /* We are too far away now, we wouldn't have duplicate. */ + if((other_vert_co.x + other_vert_co.y + other_vert_co.z) - + (vert_co.x + vert_co.y + vert_co.z) > 3 * FLT_EPSILON) + { + break; } - else { - raw_data[i] = 0.0f; + /* Found duplicate. */ + if(len_squared(other_vert_co - vert_co) < FLT_EPSILON) { + found = true; + vert_orig_index[vert_index] = other_vert_index; + break; } } - - /* Blur vertices to approximate 2 ring neighborhood. */ - memset(counter, 0, sizeof(int) * numverts); - memcpy(data, raw_data, sizeof(float) * numverts); - i = 0; - for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) { - int v0 = b_mesh.edges[i].vertices()[0], - v1 = b_mesh.edges[i].vertices()[1]; - data[v0] += raw_data[v1]; - data[v1] += raw_data[v0]; - ++counter[v0]; - ++counter[v1]; + if(!found) { + vert_orig_index[vert_index] = vert_index; + } + } + /* Make sure we always points to the very first orig vertex. */ + for(int vert_index = 0; vert_index < num_verts; ++vert_index) { + int orig_index = vert_orig_index[vert_index]; + while(orig_index != vert_orig_index[orig_index]) { + orig_index = vert_orig_index[orig_index]; } - for(i = 0; i < numverts; ++i) { - data[i] /= counter[i] + 1; + vert_orig_index[vert_index] = orig_index; + } + sorted_vert_indeices.free_memory(); + /* STEP 2: Calculate vertex normals taking into account their possible + * duplicates which gets "welded" together. + */ + vector<float3> vert_normal(num_verts, make_float3(0.0f, 0.0f, 0.0f)); + /* First we accumulate all vertex normals in the original index. */ + for(int vert_index = 0; vert_index < num_verts; ++vert_index) { + const float3 normal = get_float3(b_mesh.vertices[vert_index].normal()); + const int orig_index = vert_orig_index[vert_index]; + vert_normal[orig_index] += normal; + } + /* Then we normalize the accumulated result and flush it to all duplicates + * as well. + */ + for(int vert_index = 0; vert_index < num_verts; ++vert_index) { + const int orig_index = vert_orig_index[vert_index]; + vert_normal[vert_index] = normalize(vert_normal[orig_index]); + } + /* STEP 3: Calculate pointiness using single ring neighborhood. */ + vector<int> counter(num_verts, 0); + vector<float> raw_data(num_verts, 0.0f); + vector<float3> edge_accum(num_verts, make_float3(0.0f, 0.0f, 0.0f)); + BL::Mesh::edges_iterator e; + EdgeMap visited_edges; + int edge_index = 0; + memset(&counter[0], 0, sizeof(int) * counter.size()); + for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) { + const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]], + v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]]; + if(visited_edges.exists(v0, v1)) { + continue; + } + visited_edges.insert(v0, v1); + float3 co0 = get_float3(b_mesh.vertices[v0].co()), + co1 = get_float3(b_mesh.vertices[v1].co()); + float3 edge = normalize(co1 - co0); + edge_accum[v0] += edge; + edge_accum[v1] += -edge; + ++counter[v0]; + ++counter[v1]; + } + for(int vert_index = 0; vert_index < num_verts; ++vert_index) { + const int orig_index = vert_orig_index[vert_index]; + if(orig_index != vert_index) { + /* Skip duplicates, they'll be overwritten later on. */ + continue; + } + if(counter[vert_index] > 0) { + const float3 normal = vert_normal[vert_index]; + const float angle = + safe_acosf(dot(normal, + edge_accum[vert_index] / counter[vert_index])); + raw_data[vert_index] = angle * M_1_PI_F; + } + else { + raw_data[vert_index] = 0.0f; } - - delete [] counter; - delete [] raw_data; - delete [] edge_accum; + } + /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */ + AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes; + Attribute *attr = attributes.add(ATTR_STD_POINTINESS); + float *data = attr->data_float(); + memcpy(data, &raw_data[0], sizeof(float) * raw_data.size()); + memset(&counter[0], 0, sizeof(int) * counter.size()); + edge_index = 0; + visited_edges.clear(); + for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) { + const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]], + v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]]; + if(visited_edges.exists(v0, v1)) { + continue; + } + visited_edges.insert(v0, v1); + data[v0] += raw_data[v1]; + data[v1] += raw_data[v0]; + ++counter[v0]; + ++counter[v1]; + } + for(int vert_index = 0; vert_index < num_verts; ++vert_index) { + data[vert_index] /= counter[vert_index] + 1; + } + /* STEP 4: Copy attribute to the duplicated vertices. */ + for(int vert_index = 0; vert_index < num_verts; ++vert_index) { + const int orig_index = vert_orig_index[vert_index]; + data[vert_index] = data[orig_index]; } } @@ -656,9 +765,6 @@ static void create_mesh(Scene *scene, generated[i++] = get_float3(v->undeformed_co())*size - loc; } - /* Create needed vertex attributes. */ - attr_create_pointiness(scene, mesh, b_mesh, subdivision); - /* create faces */ vector<int> nverts(numfaces); vector<int> face_flags(numfaces, FACE_FLAG_NONE); @@ -671,6 +777,15 @@ static void create_mesh(Scene *scene, int shader = clamp(f->material_index(), 0, used_shaders.size()-1); bool smooth = f->use_smooth() || use_loop_normals; + if(use_loop_normals) { + BL::Array<float, 12> loop_normals = f->split_normals(); + for(int i = 0; i < n; i++) { + N[vi[i]] = make_float3(loop_normals[i * 3], + loop_normals[i * 3 + 1], + loop_normals[i * 3 + 2]); + } + } + /* Create triangles. * * NOTE: Autosmooth is already taken care about. @@ -704,7 +819,7 @@ static void create_mesh(Scene *scene, int shader = clamp(p->material_index(), 0, used_shaders.size()-1); bool smooth = p->use_smooth() || use_loop_normals; - vi.reserve(n); + vi.resize(n); for(int i = 0; i < n; i++) { /* NOTE: Autosmooth is already taken care about. */ vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index(); @@ -718,6 +833,7 @@ static void create_mesh(Scene *scene, /* Create all needed attributes. * The calculate functions will check whether they're needed or not. */ + attr_create_pointiness(scene, mesh, b_mesh, subdivision); attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision); attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags, subdivision, subdivide_uvs); @@ -1178,4 +1294,3 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob, } CCL_NAMESPACE_END - diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 637cf7abda8..d05699236cc 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -14,24 +14,24 @@ * limitations under the License. */ -#include "camera.h" -#include "integrator.h" -#include "graph.h" -#include "light.h" -#include "mesh.h" -#include "object.h" -#include "scene.h" -#include "nodes.h" -#include "particles.h" -#include "shader.h" - -#include "blender_object_cull.h" -#include "blender_sync.h" -#include "blender_util.h" - -#include "util_foreach.h" -#include "util_hash.h" -#include "util_logging.h" +#include "render/camera.h" +#include "render/integrator.h" +#include "render/graph.h" +#include "render/light.h" +#include "render/mesh.h" +#include "render/object.h" +#include "render/scene.h" +#include "render/nodes.h" +#include "render/particles.h" +#include "render/shader.h" + +#include "blender/blender_object_cull.h" +#include "blender/blender_sync.h" +#include "blender/blender_util.h" + +#include "util/util_foreach.h" +#include "util/util_hash.h" +#include "util/util_logging.h" CCL_NAMESPACE_BEGIN @@ -343,6 +343,13 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, object_updated = true; } + PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); + bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher"); + if(is_shadow_catcher != object->is_shadow_catcher) { + object->is_shadow_catcher = is_shadow_catcher; + object_updated = true; + } + /* object sync * transform comparison should not be needed, but duplis don't work perfect * in the depsgraph and may not signal changes, so this is a workaround */ diff --git a/intern/cycles/blender/blender_object_cull.cpp b/intern/cycles/blender/blender_object_cull.cpp index 08918dd1a49..0333c027f70 100644 --- a/intern/cycles/blender/blender_object_cull.cpp +++ b/intern/cycles/blender/blender_object_cull.cpp @@ -16,9 +16,9 @@ #include <cstdlib> -#include "camera.h" +#include "render/camera.h" -#include "blender_object_cull.h" +#include "blender/blender_object_cull.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/blender/blender_object_cull.h b/intern/cycles/blender/blender_object_cull.h index b6f0ca5cd31..2147877a860 100644 --- a/intern/cycles/blender/blender_object_cull.h +++ b/intern/cycles/blender/blender_object_cull.h @@ -17,8 +17,8 @@ #ifndef __BLENDER_OBJECT_CULL_H__ #define __BLENDER_OBJECT_CULL_H__ -#include "blender_sync.h" -#include "util_types.h" +#include "blender/blender_sync.h" +#include "util/util_types.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index dd2900a8d5b..00f8cb3cf1b 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -14,14 +14,14 @@ * limitations under the License. */ -#include "mesh.h" -#include "object.h" -#include "particles.h" +#include "render/mesh.h" +#include "render/object.h" +#include "render/particles.h" -#include "blender_sync.h" -#include "blender_util.h" +#include "blender/blender_sync.h" +#include "blender/blender_util.h" -#include "util_foreach.h" +#include "util/util_foreach.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 438abc49f88..d509e9de981 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -16,21 +16,21 @@ #include <Python.h> -#include "CCL_api.h" +#include "blender/CCL_api.h" -#include "blender_sync.h" -#include "blender_session.h" +#include "blender/blender_sync.h" +#include "blender/blender_session.h" -#include "util_foreach.h" -#include "util_logging.h" -#include "util_md5.h" -#include "util_opengl.h" -#include "util_path.h" -#include "util_string.h" -#include "util_types.h" +#include "util/util_foreach.h" +#include "util/util_logging.h" +#include "util/util_md5.h" +#include "util/util_opengl.h" +#include "util/util_path.h" +#include "util/util_string.h" +#include "util/util_types.h" #ifdef WITH_OSL -#include "osl.h" +#include "render/osl.h" #include <OSL/oslquery.h> #include <OSL/oslconfig.h> @@ -67,8 +67,10 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene) flags.cpu.sse3 = get_boolean(cscene, "debug_use_cpu_sse3"); flags.cpu.sse2 = get_boolean(cscene, "debug_use_cpu_sse2"); flags.cpu.qbvh = get_boolean(cscene, "debug_use_qbvh"); + flags.cpu.split_kernel = get_boolean(cscene, "debug_use_cpu_split_kernel"); /* Synchronize CUDA flags. */ flags.cuda.adaptive_compile = get_boolean(cscene, "debug_use_cuda_adaptive_compile"); + flags.cuda.split_kernel = get_boolean(cscene, "debug_use_cuda_split_kernel"); /* Synchronize OpenCL kernel type. */ switch(get_enum(cscene, "debug_opencl_kernel_type")) { case 0: @@ -104,6 +106,7 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene) } /* Synchronize other OpenCL flags. */ flags.opencl.debug = get_boolean(cscene, "debug_use_opencl_debug"); + flags.opencl.single_program = get_boolean(cscene, "debug_opencl_kernel_single_program"); return flags.opencl.device_type != opencl_device_type || flags.opencl.kernel_type != opencl_kernel_type; } @@ -641,7 +644,7 @@ static PyObject *debug_flags_reset_func(PyObject * /*self*/, PyObject * /*args*/ Py_RETURN_NONE; } -static PyObject *set_resumable_chunks_func(PyObject * /*self*/, PyObject *args) +static PyObject *set_resumable_chunk_func(PyObject * /*self*/, PyObject *args) { int num_resumable_chunks, current_resumable_chunk; if(!PyArg_ParseTuple(args, "ii", @@ -676,6 +679,53 @@ static PyObject *set_resumable_chunks_func(PyObject * /*self*/, PyObject *args) Py_RETURN_NONE; } +static PyObject *set_resumable_chunk_range_func(PyObject * /*self*/, PyObject *args) +{ + int num_chunks, start_chunk, end_chunk; + if(!PyArg_ParseTuple(args, "iii", + &num_chunks, + &start_chunk, + &end_chunk)) { + Py_RETURN_NONE; + } + + if(num_chunks <= 0) { + fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n"); + abort(); + Py_RETURN_NONE; + } + if(start_chunk < 1 || start_chunk > num_chunks) { + fprintf(stderr, "Cycles: Bad value for start chunk number.\n"); + abort(); + Py_RETURN_NONE; + } + if(end_chunk < 1 || end_chunk > num_chunks) { + fprintf(stderr, "Cycles: Bad value for start chunk number.\n"); + abort(); + Py_RETURN_NONE; + } + if(start_chunk > end_chunk) { + fprintf(stderr, "Cycles: End chunk should be higher than start one.\n"); + abort(); + Py_RETURN_NONE; + } + + VLOG(1) << "Initialized resumable render: " + << "num_resumable_chunks=" << num_chunks << ", " + << "start_resumable_chunk=" << start_chunk + << "end_resumable_chunk=" << end_chunk; + BlenderSession::num_resumable_chunks = num_chunks; + BlenderSession::start_resumable_chunk = start_chunk; + BlenderSession::end_resumable_chunk = end_chunk; + + printf("Cycles: Will render chunks %d to %d of %d\n", + start_chunk, + end_chunk, + num_chunks); + + Py_RETURN_NONE; +} + static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/) { vector<DeviceInfo>& devices = Device::available_devices(); @@ -715,7 +765,8 @@ static PyMethodDef methods[] = { {"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""}, /* Resumable render */ - {"set_resumable_chunks", set_resumable_chunks_func, METH_VARARGS, ""}, + {"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""}, + {"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""}, /* Compute Device selection */ {"get_device_types", get_device_types_func, METH_VARARGS, ""}, diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 2f30cbd961f..26f9bccd95d 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -16,36 +16,38 @@ #include <stdlib.h> -#include "background.h" -#include "buffers.h" -#include "camera.h" -#include "device.h" -#include "integrator.h" -#include "film.h" -#include "light.h" -#include "mesh.h" -#include "object.h" -#include "scene.h" -#include "session.h" -#include "shader.h" - -#include "util_color.h" -#include "util_foreach.h" -#include "util_function.h" -#include "util_hash.h" -#include "util_logging.h" -#include "util_progress.h" -#include "util_time.h" - -#include "blender_sync.h" -#include "blender_session.h" -#include "blender_util.h" +#include "render/background.h" +#include "render/buffers.h" +#include "render/camera.h" +#include "device/device.h" +#include "render/integrator.h" +#include "render/film.h" +#include "render/light.h" +#include "render/mesh.h" +#include "render/object.h" +#include "render/scene.h" +#include "render/session.h" +#include "render/shader.h" + +#include "util/util_color.h" +#include "util/util_foreach.h" +#include "util/util_function.h" +#include "util/util_hash.h" +#include "util/util_logging.h" +#include "util/util_progress.h" +#include "util/util_time.h" + +#include "blender/blender_sync.h" +#include "blender/blender_session.h" +#include "blender/blender_util.h" CCL_NAMESPACE_BEGIN bool BlenderSession::headless = false; int BlenderSession::num_resumable_chunks = 0; int BlenderSession::current_resumable_chunk = 0; +int BlenderSession::start_resumable_chunk = 0; +int BlenderSession::end_resumable_chunk = 0; BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, @@ -68,6 +70,7 @@ BlenderSession::BlenderSession(BL::RenderEngine& b_engine, background = true; last_redraw_time = 0.0; start_resize_time = 0.0; + last_status_time = 0.0; } BlenderSession::BlenderSession(BL::RenderEngine& b_engine, @@ -93,6 +96,7 @@ BlenderSession::BlenderSession(BL::RenderEngine& b_engine, background = false; last_redraw_time = 0.0; start_resize_time = 0.0; + last_status_time = 0.0; } BlenderSession::~BlenderSession() @@ -989,10 +993,14 @@ void BlenderSession::update_status_progress() if(substatus.size() > 0) status += " | " + substatus; - if(status != last_status) { + double current_time = time_dt(); + /* When rendering in a window, redraw the status at least once per second to keep the elapsed and remaining time up-to-date. + * For headless rendering, only report when something significant changes to keep the console output readable. */ + if(status != last_status || (!headless && (current_time - last_status_time) > 1.0)) { b_engine.update_stats("", (timestatus + scene + status).c_str()); b_engine.update_memory_stats(mem_used, mem_peak); last_status = status; + last_status_time = current_time; } if(progress != last_progress) { b_engine.update_progress(progress); @@ -1342,9 +1350,21 @@ void BlenderSession::update_resumable_tile_manager(int num_samples) return; } - int num_samples_per_chunk = (int)ceilf((float)num_samples / num_resumable_chunks); - int range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1); - int range_num_samples = num_samples_per_chunk; + const int num_samples_per_chunk = (int)ceilf((float)num_samples / num_resumable_chunks); + + int range_start_sample, range_num_samples; + if(current_resumable_chunk != 0) { + /* Single chunk rendering. */ + range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1); + range_num_samples = num_samples_per_chunk; + } + else { + /* Ranged-chunks. */ + const int num_chunks = end_resumable_chunk - start_resumable_chunk + 1; + range_start_sample = num_samples_per_chunk * (start_resumable_chunk - 1); + range_num_samples = num_chunks * num_samples_per_chunk; + } + /* Make sure we don't overshoot. */ if(range_start_sample + range_num_samples > num_samples) { range_num_samples = num_samples - range_num_samples; } diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 82fe218b4ce..22b21a18f2e 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -17,12 +17,12 @@ #ifndef __BLENDER_SESSION_H__ #define __BLENDER_SESSION_H__ -#include "device.h" -#include "scene.h" -#include "session.h" -#include "bake.h" +#include "device/device.h" +#include "render/scene.h" +#include "render/session.h" +#include "render/bake.h" -#include "util_vector.h" +#include "util/util_vector.h" CCL_NAMESPACE_BEGIN @@ -113,6 +113,7 @@ public: string last_status; string last_error; float last_progress; + double last_status_time; int width, height; double start_resize_time; @@ -137,6 +138,10 @@ public: /* Current resumable chunk index to render. */ static int current_resumable_chunk; + /* Alternative to single-chunk rendering to render a range of chunks. */ + static int start_resumable_chunk; + static int end_resumable_chunk; + protected: void do_write_update_render_result(BL::RenderResult& b_rr, BL::RenderLayer& b_rlay, diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index c9d4236a7f2..1ec82445b20 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -14,20 +14,21 @@ * limitations under the License. */ -#include "background.h" -#include "graph.h" -#include "light.h" -#include "nodes.h" -#include "osl.h" -#include "scene.h" -#include "shader.h" - -#include "blender_texture.h" -#include "blender_sync.h" -#include "blender_util.h" - -#include "util_debug.h" -#include "util_string.h" +#include "render/background.h" +#include "render/graph.h" +#include "render/light.h" +#include "render/nodes.h" +#include "render/osl.h" +#include "render/scene.h" +#include "render/shader.h" + +#include "blender/blender_texture.h" +#include "blender/blender_sync.h" +#include "blender/blender_util.h" + +#include "util/util_debug.h" +#include "util/util_string.h" +#include "util/util_task.h" CCL_NAMESPACE_BEGIN @@ -622,7 +623,8 @@ static ShaderNode *add_node(Scene *scene, bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED || b_image.source() == BL::Image::source_MOVIE || - b_engine.is_preview(); + (b_engine.is_preview() && + b_image.source() != BL::Image::source_SEQUENCE); if(is_builtin) { /* for builtin images we're using image datablock name to find an image to @@ -675,7 +677,8 @@ static ShaderNode *add_node(Scene *scene, bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED || b_image.source() == BL::Image::source_MOVIE || - b_engine.is_preview(); + (b_engine.is_preview() && + b_image.source() != BL::Image::source_SEQUENCE); if(is_builtin) { int scene_frame = b_scene.frame_current(); @@ -1168,6 +1171,13 @@ static void add_nodes(Scene *scene, /* Sync Materials */ +void BlenderSync::sync_materials_simpligy(Shader *shader) +{ + ShaderGraph *graph = shader->graph; + graph->simplify(scene); + shader->tag_update(scene); +} + void BlenderSync::sync_materials(bool update_all) { shader_map.set_default(scene->default_surface); @@ -1175,6 +1185,8 @@ void BlenderSync::sync_materials(bool update_all) /* material loop */ BL::BlendData::materials_iterator b_mat; + TaskPool pool; + for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) { Shader *shader; @@ -1210,9 +1222,31 @@ void BlenderSync::sync_materials(bool update_all) shader->displacement_method = (experimental) ? get_displacement_method(cmat) : DISPLACE_BUMP; shader->set_graph(graph); - shader->tag_update(scene); + + /* By simplifying the shader graph as soon as possible, some + * redundant shader nodes might be removed which prevents loading + * unnecessary attributes later. + * + * However, since graph simplification also accounts for e.g. mix + * weight, this would cause frequent expensive resyncs in interactive + * sessions, so for those sessions optimization is only performed + * right before compiling. + */ + if(!preview) { + pool.push(function_bind(&BlenderSync::sync_materials_simpligy, + this, + shader)); + } + else { + /* NOTE: Update tagging can access links which are being + * optimized out. + */ + shader->tag_update(scene); + } } } + + pool.wait_work(); } /* Sync World */ diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index d8043105cd8..3b071bf0e7d 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -14,29 +14,29 @@ * limitations under the License. */ -#include "background.h" -#include "camera.h" -#include "film.h" -#include "graph.h" -#include "integrator.h" -#include "light.h" -#include "mesh.h" -#include "nodes.h" -#include "object.h" -#include "scene.h" -#include "shader.h" -#include "curves.h" - -#include "device.h" - -#include "blender_sync.h" -#include "blender_session.h" -#include "blender_util.h" - -#include "util_debug.h" -#include "util_foreach.h" -#include "util_opengl.h" -#include "util_hash.h" +#include "render/background.h" +#include "render/camera.h" +#include "render/film.h" +#include "render/graph.h" +#include "render/integrator.h" +#include "render/light.h" +#include "render/mesh.h" +#include "render/nodes.h" +#include "render/object.h" +#include "render/scene.h" +#include "render/shader.h" +#include "render/curves.h" + +#include "device/device.h" + +#include "blender/blender_sync.h" +#include "blender/blender_session.h" +#include "blender/blender_util.h" + +#include "util/util_debug.h" +#include "util/util_foreach.h" +#include "util/util_opengl.h" +#include "util/util_hash.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 6984cbda259..62e2f8f563a 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -22,15 +22,15 @@ #include "RNA_access.h" #include "RNA_blender_cpp.h" -#include "blender_util.h" +#include "blender/blender_util.h" -#include "scene.h" -#include "session.h" +#include "render/scene.h" +#include "render/session.h" -#include "util_map.h" -#include "util_set.h" -#include "util_transform.h" -#include "util_vector.h" +#include "util/util_map.h" +#include "util/util_set.h" +#include "util/util_transform.h" +#include "util/util_vector.h" CCL_NAMESPACE_BEGIN @@ -96,6 +96,7 @@ public: private: /* sync */ void sync_lamps(bool update_all); + void sync_materials_simpligy(Shader *shader); void sync_materials(bool update_all); void sync_objects(BL::SpaceView3D& b_v3d, float motion_time = 0.0f); void sync_motion(BL::RenderSettings& b_render, diff --git a/intern/cycles/blender/blender_texture.cpp b/intern/cycles/blender/blender_texture.cpp index 3807e683c7c..b2e27b76189 100644 --- a/intern/cycles/blender/blender_texture.cpp +++ b/intern/cycles/blender/blender_texture.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "blender_texture.h" +#include "blender/blender_texture.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/blender/blender_texture.h b/intern/cycles/blender/blender_texture.h index ad96f9db8ed..734231a85ec 100644 --- a/intern/cycles/blender/blender_texture.h +++ b/intern/cycles/blender/blender_texture.h @@ -18,7 +18,7 @@ #define __BLENDER_TEXTURE_H__ #include <stdlib.h> -#include "blender_sync.h" +#include "blender/blender_sync.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index b67834cdea3..4d575330520 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -17,14 +17,15 @@ #ifndef __BLENDER_UTIL_H__ #define __BLENDER_UTIL_H__ -#include "mesh.h" +#include "render/mesh.h" -#include "util_map.h" -#include "util_path.h" -#include "util_set.h" -#include "util_transform.h" -#include "util_types.h" -#include "util_vector.h" +#include "util/util_algorithm.h" +#include "util/util_map.h" +#include "util/util_path.h" +#include "util/util_set.h" +#include "util/util_transform.h" +#include "util/util_types.h" +#include "util/util_vector.h" /* Hacks to hook into Blender API * todo: clean this up ... */ @@ -78,7 +79,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data, me.calc_normals_split(); } else { - me.split_faces(); + me.split_faces(false); } } if(subdivision_type == Mesh::SUBDIVISION_NONE) { @@ -786,6 +787,35 @@ struct ParticleSystemKey { } }; +class EdgeMap { +public: + EdgeMap() { + } + + void clear() { + edges_.clear(); + } + + void insert(int v0, int v1) { + get_sorted_verts(v0, v1); + edges_.insert(std::pair<int, int>(v0, v1)); + } + + bool exists(int v0, int v1) { + get_sorted_verts(v0, v1); + return edges_.find(std::pair<int, int>(v0, v1)) != edges_.end(); + } + +protected: + void get_sorted_verts(int& v0, int& v1) { + if(v0 > v1) { + swap(v0, v1); + } + } + + set< std::pair<int, int> > edges_; +}; + CCL_NAMESPACE_END #endif /* __BLENDER_UTIL_H__ */ |