diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a920016f45d3cbb77dd5f567d388c3714aca672..dd24ea7cb601e788b2cb8397f535c50228b7ef9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1515,6 +1515,7 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC") "/wd4267" # conversion from 'size_t' to 'type', possible loss of data "/wd4305" # truncation from 'type1' to 'type2' "/wd4800" # forcing value to bool 'true' or 'false' + "/wd4828" # The file contains a character that is illegal # errors: "/we4013" # 'function' undefined; assuming extern returning int "/we4133" # incompatible pointer types diff --git a/build_files/build_environment/cmake/boost.cmake b/build_files/build_environment/cmake/boost.cmake index 2c6bf195e07894217f76da7bac7116e47ea5dab2..46840b7ead457a414d18054f258683e7e4552e6f 100644 --- a/build_files/build_environment/cmake/boost.cmake +++ b/build_files/build_environment/cmake/boost.cmake @@ -53,17 +53,20 @@ if(WIN32) if(BUILD_MODE STREQUAL Release) set(BOOST_HARVEST_CMD ${BOOST_HARVEST_CMD} && ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/boost/include/boost-1_60/ ${HARVEST_TARGET}/boost/include/) endif() + set(BOOST_PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/boost/src/external_boost < ${PATCH_DIR}/boost.diff) elseif(APPLE) set(BOOST_CONFIGURE_COMMAND ./bootstrap.sh) set(BOOST_BUILD_COMMAND ./bjam) set(BOOST_BUILD_OPTIONS toolset=clang cxxflags=${PLATFORM_CXXFLAGS} linkflags=${PLATFORM_LDFLAGS} --disable-icu boost.locale.icu=off) set(BOOST_HARVEST_CMD echo .) + set(BOOST_PATCH_COMMAND echo .) else() set(BOOST_HARVEST_CMD echo .) set(BOOST_CONFIGURE_COMMAND ./bootstrap.sh) set(BOOST_BUILD_COMMAND ./bjam) set(BOOST_BUILD_OPTIONS cxxflags=${PLATFORM_CXXFLAGS} --disable-icu boost.locale.icu=off) + set(BOOST_PATCH_COMMAND echo .) endif() set(BOOST_OPTIONS @@ -96,6 +99,7 @@ ExternalProject_Add(external_boost URL_HASH MD5=${BOOST_MD5} PREFIX ${BUILD_DIR}/boost UPDATE_COMMAND "" + PATCH_COMMAND ${BOOST_PATCH_COMMAND} CONFIGURE_COMMAND ${BOOST_CONFIGURE_COMMAND} BUILD_COMMAND ${BOOST_BUILD_COMMAND} ${BOOST_BUILD_OPTIONS} -j${MAKE_THREADS} architecture=x86 address-model=${BOOST_ADDRESS_MODEL} variant=${BOOST_BUILD_TYPE} link=static threading=multi ${BOOST_OPTIONS} --prefix=${LIBDIR}/boost install BUILD_IN_SOURCE 1 diff --git a/build_files/build_environment/patches/boost.diff b/build_files/build_environment/patches/boost.diff new file mode 100644 index 0000000000000000000000000000000000000000..ea3ec035518d79a620fbd3629b1b93fb67914baa --- /dev/null +++ b/build_files/build_environment/patches/boost.diff @@ -0,0 +1,15 @@ +--- a/boost/config/compiler/visualc.hpp 2015-12-08 11:55:19 -0700 ++++ b/boost/config/compiler/visualc.hpp 2018-03-17 10:29:52 -0600 +@@ -287,12 +287,3 @@ + # define BOOST_COMPILER "Microsoft Visual C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION) + #endif + +-// +-// last known and checked version is 19.00.23026 (VC++ 2015 RTM): +-#if (_MSC_VER > 1900) +-# if defined(BOOST_ASSERT_CONFIG) +-# error "Unknown compiler version - please run the configure tests and report the results" +-# else +-# pragma message("Unknown compiler version - please run the configure tests and report the results") +-# endif +-#endif diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake index 7db26c3f7c0d6c99b8d1051606c24a087980279f..1a5e6a3158ada50f8c71be94f5b5e8a3cc95da8f 100644 --- a/build_files/cmake/config/blender_lite.cmake +++ b/build_files/cmake/config/blender_lite.cmake @@ -9,6 +9,7 @@ set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE) set(WITH_SYSTEM_GLEW ON CACHE BOOL "" FORCE) set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE) +set(WITH_BOOST OFF CACHE BOOL "" FORCE) set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE) set(WITH_BULLET OFF CACHE BOOL "" FORCE) set(WITH_CODEC_AVI OFF CACHE BOOL "" FORCE) @@ -54,4 +55,3 @@ set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE) set(WITH_SDL OFF CACHE BOOL "" FORCE) set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE) set(WITH_X11_XF86VMODE OFF CACHE BOOL "" FORCE) - diff --git a/doc/python_api/examples/bpy.props.1.py b/doc/python_api/examples/bpy.props.1.py index 5153462893002245435adb2cd50539facc85f6b4..dd3a3ebc4325bcc09bf0ee594ef995696d8dc7ba 100644 --- a/doc/python_api/examples/bpy.props.1.py +++ b/doc/python_api/examples/bpy.props.1.py @@ -2,30 +2,56 @@ Operator Example ++++++++++++++++ -A common use of custom properties is for python based :class:`Operator` classes. +A common use of custom properties is for python based :class:`Operator` +classes. Test this code by running it in the text editor, or by clicking the +button in the 3D Viewport's Tools panel. The latter will show the properties +in the Redo panel and allow you to change them. """ - import bpy -class DialogOperator(bpy.types.Operator): - bl_idname = "object.dialog_operator" +class OBJECT_OT_property_example(bpy.types.Operator): + bl_idname = "object.property_example" bl_label = "Property Example" + bl_options = {'REGISTER', 'UNDO'} my_float = bpy.props.FloatProperty(name="Some Floating Point") my_bool = bpy.props.BoolProperty(name="Toggle Option") my_string = bpy.props.StringProperty(name="String Value") def execute(self, context): - print("Dialog Runs") + self.report({'INFO'}, 'F: %.2f B: %s S: %r' % + (self.my_float, self.my_bool, self.my_string)) + print('My float:', self.my_float) + print('My bool:', self.my_bool) + print('My string:', self.my_string) return {'FINISHED'} - def invoke(self, context, event): - wm = context.window_manager - return wm.invoke_props_dialog(self) - -bpy.utils.register_class(DialogOperator) - -# test call -bpy.ops.object.dialog_operator('INVOKE_DEFAULT') +class OBJECT_PT_property_example(bpy.types.Panel): + bl_idname = "object_PT_property_example" + bl_label = "Property Example" + bl_space_type = 'VIEW_3D' + bl_region_type = 'TOOLS' + bl_category = "Tools" + + def draw(self, context): + # You can set the property values that should be used when the user + # presses the button in the UI. + props = self.layout.operator('object.property_example') + props.my_bool = True + props.my_string = "Shouldn't that be 47?" + + # You can set properties dynamically: + if context.object: + props.my_float = context.object.location.x + else: + props.my_float = 327 + + +bpy.utils.register_class(OBJECT_OT_property_example) +bpy.utils.register_class(OBJECT_PT_property_example) + +# Demo call. Be sure to also test in the 3D Viewport. +bpy.ops.object.property_example(my_float=47, my_bool=True, + my_string="Shouldn't that be 327?") diff --git a/doc/python_api/examples/bpy.props.5.py b/doc/python_api/examples/bpy.props.5.py index 87741cbab8ab3a0b887798c7d9e2bed644013985..a9e79fa0272459692f4550c3c07fa79e8eea1033 100644 --- a/doc/python_api/examples/bpy.props.5.py +++ b/doc/python_api/examples/bpy.props.5.py @@ -1,13 +1,12 @@ """ -Get/Set Example -+++++++++++++++ +Getter/Setter Example ++++++++++++++++++++++ -Get/Set functions can be used for boolean, int, float, string and enum properties. +Getter/setter functions can be used for boolean, int, float, string and enum properties. If these callbacks are defined the property will not be stored in the ID properties -automatically, instead the get/set functions will be called when the property is -read or written from the API. +automatically. Instead, the `get` and `set` functions will be called when the property +is respectively read or written from the API. """ - import bpy @@ -65,25 +64,24 @@ def set_enum(self, value): bpy.types.Scene.test_enum = bpy.props.EnumProperty(items=test_items, get=get_enum, set=set_enum) -# Testing - +# Testing the properties: scene = bpy.context.scene scene.test_float = 12.34 -print(scene.test_float) +print('test_float:', scene.test_float) scene.test_array = (True, False) -print([x for x in scene.test_array]) +print('test_array:', tuple(scene.test_array)) # scene.test_date = "blah" # this would fail, property is read-only -print(scene.test_date) +print('test_date:', scene.test_date) scene.test_enum = 'BLUE' -print(scene.test_enum) - - -# >>> 12.34000015258789 -# >>> [True, False] -# >>> 2013-01-05 16:33:52.135340 -# >>> setting value 3 -# >>> GREEN +print('test_enum:', scene.test_enum) + +# The above outputs: +# test_float: 12.34000015258789 +# test_array: (True, False) +# test_date: 2018-03-14 11:36:53.158653 +# setting value 3 +# test_enum: GREEN diff --git a/doc/python_api/rst/info_api_reference.rst b/doc/python_api/rst/info_api_reference.rst index 5ef5866c44a0808cf724a4f24995883b147da4f6..ab690a8ee062c96d510985297b4c57d35755659b 100644 --- a/doc/python_api/rst/info_api_reference.rst +++ b/doc/python_api/rst/info_api_reference.rst @@ -53,7 +53,7 @@ Here are some characteristics ID Data-Blocks share. Simple Data Access ------------------ -Lets start with a simple case, say you wan't a python script to adjust the objects location. +Lets start with a simple case, say you want a python script to adjust the objects location. Start by finding this setting in the interface ``Properties Window -> Object -> Transform -> Location`` diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 08c3e729ed9bd8d95bac8c5cbe1a83a511bfe172..50b07cabff4f726b2ca3a0c78cd996cf17a37fa5 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -417,19 +417,28 @@ MODULE_GROUPING = { # -------------------------------BLENDER---------------------------------------- blender_version_strings = [str(v) for v in bpy.app.version] +is_release = bpy.app.version_cycle in {"rc", "release"} # converting bytes to strings, due to T30154 BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8') BLENDER_DATE = str(bpy.app.build_date, 'utf_8') -BLENDER_VERSION_DOTS = ".".join(blender_version_strings) # '2.62.1' +if is_release: + # '2.62a' + BLENDER_VERSION_DOTS = ".".join(blender_version_strings[:2]) + bpy.app.version_char +else: + # '2.62.1' + BLENDER_VERSION_DOTS = ".".join(blender_version_strings) if BLENDER_REVISION != "Unknown": - BLENDER_VERSION_DOTS += " " + BLENDER_REVISION # '2.62.1 SHA1' + # '2.62a SHA1' (release) or '2.62.1 SHA1' (non-release) + BLENDER_VERSION_DOTS += " " + BLENDER_REVISION -BLENDER_VERSION_PATH = "_".join(blender_version_strings) # '2_62_1' -if bpy.app.version_cycle in {"rc", "release"}: +if is_release: # '2_62a_release' BLENDER_VERSION_PATH = "%s%s_release" % ("_".join(blender_version_strings[:2]), bpy.app.version_char) +else: + # '2_62_1' + BLENDER_VERSION_PATH = "_".join(blender_version_strings) # --------------------------DOWNLOADABLE FILES---------------------------------- diff --git a/extern/curve_fit_nd/intern/generic_heap.c b/extern/curve_fit_nd/intern/generic_heap.c index f41025318c49999310f1753cd63b1c44030bf71c..09ed84bea438b7d7d306384989f0fbb8c311d44f 100644 --- a/extern/curve_fit_nd/intern/generic_heap.c +++ b/extern/curve_fit_nd/intern/generic_heap.c @@ -305,3 +305,5 @@ void *HEAP_node_ptr(HeapNode *node) { return node->ptr; } + +/** \} */ diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp index 2d4b0d35e548a87bd45982a7fd55b3bb6fac988e..c682744f5fafb8ca1d92a9ab53d8e749fd99cfde 100644 --- a/intern/cycles/app/cycles_standalone.cpp +++ b/intern/cycles/app/cycles_standalone.cpp @@ -51,6 +51,7 @@ struct Options { SessionParams session_params; bool quiet; bool show_help, interactive, pause; + string output_path; } options; static void session_print(const string& str) @@ -86,6 +87,34 @@ static void session_print_status() session_print(status); } +static bool write_render(const uchar *pixels, int w, int h, int channels) +{ + string msg = string_printf("Writing image %s", options.output_path.c_str()); + session_print(msg); + + ImageOutput *out = ImageOutput::create(options.output_path); + if(!out) { + return false; + } + + ImageSpec spec(w, h, channels, TypeDesc::UINT8); + if(!out->open(options.output_path, spec)) { + return false; + } + + /* conversion for different top/bottom convention */ + out->write_image(TypeDesc::UINT8, + pixels + (h - 1) * w * channels, + AutoStride, + -w * channels, + AutoStride); + + out->close(); + delete out; + + return true; +} + static BufferParams& session_buffer_params() { static BufferParams buffer_params; @@ -120,6 +149,7 @@ static void scene_init() static void session_init() { + options.session_params.write_render_cb = write_render; options.session = new Session(options.session_params); if(options.session_params.background && !options.quiet) @@ -364,7 +394,7 @@ static void options_parse(int argc, const char **argv) "--background", &options.session_params.background, "Render in background, without user interface", "--quiet", &options.quiet, "In background mode, don't print progress messages", "--samples %d", &options.session_params.samples, "Number of samples to render", - "--output %s", &options.session_params.output_path, "File path to write output image", + "--output %s", &options.output_path, "File path to write output image", "--threads %d", &options.session_params.threads, "CPU Rendering Threads", "--width %d", &options.width, "Window width in pixel", "--height %d", &options.height, "Window height in pixel", diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 21ae07e23b846a4ca23be18a969ff178c969c6e1..a46955322e383f79854d8d9b5ecb5bbcb93be90b 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -40,6 +40,7 @@ #include "util/util_foreach.h" #include "util/util_path.h" +#include "util/util_projection.h" #include "util/util_transform.h" #include "util/util_xml.h" @@ -546,8 +547,10 @@ static void xml_read_transform(xml_node node, Transform& tfm) { if(node.attribute("matrix")) { vector<float> matrix; - if(xml_read_float_array(matrix, node, "matrix") && matrix.size() == 16) - tfm = tfm * transform_transpose((*(Transform*)&matrix[0])); + if(xml_read_float_array(matrix, node, "matrix") && matrix.size() == 16) { + ProjectionTransform projection = *(ProjectionTransform*)&matrix[0]; + tfm = tfm * projection_to_transform(projection_transpose(projection)); + } } if(node.attribute("translate")) { diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 5190c37b052f209de97f54bbb50bb6d4924c7213..585b159235e43ab48c39eb921683913e60ace1b7 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -546,6 +546,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=0, min=0, max=16, ) + cls.use_bvh_embree = BoolProperty( + name="Use Embree", + description="Use Embree as ray accelerator", + default=True, + ) cls.tile_order = EnumProperty( name="Tile Order", description="Tile order for rendering", @@ -572,6 +577,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): ('SHADOW', "Shadow", ""), ('NORMAL', "Normal", ""), ('UV', "UV", ""), + ('ROUGHNESS', "Roughness", ""), ('EMIT', "Emit", ""), ('ENVIRONMENT', "Environment", ""), ('DIFFUSE', "Diffuse", ""), @@ -1089,7 +1095,7 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): cls.motion_steps = IntProperty( name="Motion Steps", - description="Control accuracy of deformation motion blur, more steps gives more memory usage (actual number of steps is 2^(steps - 1))", + description="Control accuracy of motion blur, more steps gives more memory usage (actual number of steps is 2^(steps - 1))", min=1, soft_max=8, default=1, ) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index e3076a8ec2ce4b0ebcdc5b8a832f1a85d3b44e49..faefa648642205d5e3eb402a3618c7c5d56000b8 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -429,11 +429,17 @@ class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel): col.separator() col.label(text="Acceleration structure:") + row = col.row() + row.active = use_cpu(context) + row.prop(cscene, "use_bvh_embree") + row = col.row() col.prop(cscene, "debug_use_spatial_splits") - col.prop(cscene, "debug_use_hair_bvh") + row = col.row() + row.active = not cscene.use_bvh_embree + row.prop(cscene, "debug_use_hair_bvh") row = col.row() - row.active = not cscene.debug_use_spatial_splits + row.active = not cscene.debug_use_spatial_splits and not cscene.use_bvh_embree row.prop(cscene, "debug_bvh_time_steps") col = layout.column() @@ -809,7 +815,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel): def poll(cls, context): ob = context.object if CyclesButtonsPanel.poll(context) and ob: - if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}: + if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA'}: return True if ob.dupli_type == 'GROUP' and ob.dupli_group: return True @@ -841,11 +847,9 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel): layout.active = (rd.use_motion_blur and cob.use_motion_blur) row = layout.row() - row.prop(cob, "use_deform_motion", text="Deformation") - - sub = row.row() - sub.active = cob.use_deform_motion - sub.prop(cob, "motion_steps", text="Steps") + if ob.type != 'CAMERA': + row.prop(cob, "use_deform_motion", text="Deformation") + row.prop(cob, "motion_steps", text="Steps") class CYCLES_OBJECT_PT_cycles_settings(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py index 90cecec215df863cf3fb0eb026bdee08230e18d3..292f0a1fa90c2b22113f6a0ba8569b793ab735fa 100644 --- a/intern/cycles/blender/addon/version_update.py +++ b/intern/cycles/blender/addon/version_update.py @@ -17,6 +17,7 @@ # <pep8 compliant> import bpy +import math from bpy.app.handlers import persistent @@ -138,6 +139,56 @@ def displacement_principled_nodes(node): if node.subsurface_method != 'RANDOM_WALK': node.subsurface_method = 'BURLEY' +def square_roughness_node_insert(material, nodetree, traversed): + if nodetree in traversed: + return + traversed.add(nodetree) + + roughness_node_types = { + 'ShaderNodeBsdfAnisotropic', + 'ShaderNodeBsdfGlass', + 'ShaderNodeBsdfGlossy', + 'ShaderNodeBsdfRefraction'} + + # Update default values + for node in nodetree.nodes: + if node.bl_idname == 'ShaderNodeGroup': + square_roughness_node_insert(material, node.node_tree, traversed) + elif node.bl_idname in roughness_node_types: + roughness_input = node.inputs['Roughness'] + roughness_input.default_value = math.sqrt(max(roughness_input.default_value, 0.0)) + + # Gather roughness links to replace + roughness_links = [] + for link in nodetree.links: + if link.to_node.bl_idname in roughness_node_types and \ + link.to_socket.identifier == 'Roughness': + roughness_links.append(link) + + # Replace links with sqrt node + for link in roughness_links: + from_node = link.from_node + from_socket = link.from_socket + to_node = link.to_node + to_socket = link.to_socket + + nodetree.links.remove(link) + + node = nodetree.nodes.new(type='ShaderNodeMath') + node.operation = 'POWER' + node.location[0] = 0.5 * (from_node.location[0] + to_node.location[0]); + node.location[1] = 0.5 * (from_node.location[1] + to_node.location[1]); + + nodetree.links.new(from_socket, node.inputs[0]) + node.inputs[1].default_value = 0.5 + nodetree.links.new(node.outputs['Value'], to_socket) + +def square_roughness_nodes_insert(): + traversed = set() + for material in bpy.data.materials: + if check_is_new_shading_material(material): + square_roughness_node_insert(material, material.node_tree, traversed) + def mapping_node_order_flip(node): """ @@ -376,3 +427,7 @@ def do_versions(self): cmat.displacement_method = 'BUMP' foreach_cycles_node(displacement_principled_nodes) + + if bpy.data.version <= (2, 79, 3): + # Switch to squared roughness convention + square_roughness_nodes_insert() diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 62e950e3befc95734cca0746a6f809cf0ee04fe7..f00ade320e780b6e8a1a1fff2568d13933d08955 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -83,6 +83,8 @@ struct BlenderCamera { Transform matrix; float offscreen_dicing_scale; + + int motion_steps; }; static void blender_camera_init(BlenderCamera *bcam, @@ -226,6 +228,8 @@ static void blender_camera_from_object(BlenderCamera *bcam, bcam->sensor_fit = BlenderCamera::HORIZONTAL; else bcam->sensor_fit = BlenderCamera::VERTICAL; + + bcam->motion_steps = object_motion_steps(b_ob, b_ob); } else { /* from lamp not implemented yet */ @@ -246,8 +250,7 @@ static Transform blender_camera_matrix(const Transform& tfm, result = tfm * make_transform(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); + 0.0f, 1.0f, 0.0f, 0.0f); } else { /* Make it so environment camera needs to be pointed in the direction @@ -257,8 +260,7 @@ static Transform blender_camera_matrix(const Transform& tfm, result = tfm * make_transform( 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); + -1.0f, 0.0f, 0.0f, 0.0f); } } else { @@ -455,9 +457,7 @@ static void blender_camera_sync(Camera *cam, cam->matrix = blender_camera_matrix(bcam->matrix, bcam->type, bcam->panorama_type); - cam->motion.pre = cam->matrix; - cam->motion.post = cam->matrix; - cam->use_motion = false; + cam->motion.resize(bcam->motion_steps, cam->matrix); cam->use_perspective_motion = false; cam->shuttertime = bcam->shuttertime; cam->fov_pre = cam->fov; @@ -566,20 +566,15 @@ void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render, Transform tfm = get_transform(b_ob_matrix); tfm = blender_camera_matrix(tfm, cam->type, cam->panorama_type); - if(tfm != cam->matrix) { - VLOG(1) << "Camera " << b_ob.name() << " motion detected."; - if(motion_time == 0.0f) { - /* When motion blur is not centered in frame, cam->matrix gets reset. */ - cam->matrix = tfm; - } - else if(motion_time == -1.0f) { - cam->motion.pre = tfm; - cam->use_motion = true; - } - else if(motion_time == 1.0f) { - cam->motion.post = tfm; - cam->use_motion = true; - } + if(motion_time == 0.0f) { + /* When motion blur is not centered in frame, cam->matrix gets reset. */ + cam->matrix = tfm; + } + + /* Set transform in motion array. */ + int motion_step = cam->motion_step(motion_time); + if(motion_step >= 0) { + cam->motion[motion_step] = tfm; } if(cam->type == CAMERA_PERSPECTIVE) { diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index f7cb0b66d299af43852ebb5521dd0d39faf02085..daccb89f5a2936f77f161661fceb4baf4b5a0641 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -633,10 +633,10 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa } } -static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int time_index) +static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int motion_step) { VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name - << ", time index " << time_index; + << ", motion step " << motion_step; /* find attribute */ Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); @@ -651,7 +651,7 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int /* export motion vectors for curve keys */ size_t numkeys = mesh->curve_keys.size(); - float4 *mP = attr_mP->data_float4() + time_index*numkeys; + float4 *mP = attr_mP->data_float4() + motion_step*numkeys; bool have_motion = false; int i = 0; @@ -702,12 +702,12 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int } mesh->curve_attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION); } - else if(time_index > 0) { - VLOG(1) << "Filling in new motion vertex position for time_index " - << time_index; + else if(motion_step > 0) { + VLOG(1) << "Filling in new motion vertex position for motion_step " + << motion_step; /* motion, fill up previous steps that we might have skipped because * they had no motion, but we need them anyway now */ - for(int step = 0; step < time_index; step++) { + for(int step = 0; step < motion_step; step++) { float4 *mP = attr_mP->data_float4() + step*numkeys; for(int key = 0; key < numkeys; key++) { @@ -888,7 +888,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh& b_mesh, BL::Object& b_ob, bool motion, - int time_index) + int motion_step) { if(!motion) { /* Clear stored curve data */ @@ -951,7 +951,7 @@ void BlenderSync::sync_curves(Mesh *mesh, } else { if(motion) - ExportCurveSegmentsMotion(mesh, &CData, time_index); + ExportCurveSegmentsMotion(mesh, &CData, motion_step); else ExportCurveSegments(scene, mesh, &CData); } diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 998390e92a9d3609eb51be840ca8be24e66ddf8d..7d6ca18b074980b53bb61979fb488a0c2535c167 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -1248,36 +1248,10 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob, if(mesh_synced.find(mesh) == mesh_synced.end()) return; - /* for motion pass always compute, for motion blur it can be disabled */ - int time_index = 0; - - if(scene->need_motion() == Scene::MOTION_BLUR) { - if(!mesh->use_motion_blur) - return; - - /* see if this mesh needs motion data at this time */ - vector<float> object_times = object->motion_times(); - bool found = false; - - foreach(float object_time, object_times) { - if(motion_time == object_time) { - found = true; - break; - } - else - time_index++; - } - - if(!found) - return; - } - else { - if(motion_time == -1.0f) - time_index = 0; - else if(motion_time == 1.0f) - time_index = 1; - else - return; + /* Find time matching motion step required by mesh. */ + int motion_step = mesh->motion_step(motion_time); + if(motion_step < 0) { + return; } /* skip empty meshes */ @@ -1319,9 +1293,9 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob, float3 *P = &mesh->verts[0]; float3 *N = (attr_N)? attr_N->data_float3(): NULL; - memcpy(attr_mP->data_float3() + time_index*numverts, P, sizeof(float3)*numverts); + memcpy(attr_mP->data_float3() + motion_step*numverts, P, sizeof(float3)*numverts); if(attr_mN) - memcpy(attr_mN->data_float3() + time_index*numverts, N, sizeof(float3)*numverts); + memcpy(attr_mN->data_float3() + motion_step*numverts, N, sizeof(float3)*numverts); } } @@ -1331,7 +1305,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob, if(attr_mP) { float3 *keys = &mesh->curve_keys[0]; - memcpy(attr_mP->data_float3() + time_index*numkeys, keys, sizeof(float3)*numkeys); + memcpy(attr_mP->data_float3() + motion_step*numkeys, keys, sizeof(float3)*numkeys); } } @@ -1354,8 +1328,8 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob, new_attribute = true; } /* Load vertex data from mesh. */ - float3 *mP = attr_mP->data_float3() + time_index*numverts; - float3 *mN = (attr_mN)? attr_mN->data_float3() + time_index*numverts: NULL; + float3 *mP = attr_mP->data_float3() + motion_step*numverts; + float3 *mN = (attr_mN)? attr_mN->data_float3() + motion_step*numverts: NULL; /* NOTE: We don't copy more that existing amount of vertices to prevent * possible memory corruption. */ @@ -1384,13 +1358,13 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob, if(attr_mN) mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL); } - else if(time_index > 0) { + else if(motion_step > 0) { VLOG(1) << "Filling deformation motion for object " << b_ob.name(); /* motion, fill up previous steps that we might have skipped because * they had no motion, but we need them anyway now */ float3 *P = &mesh->verts[0]; float3 *N = (attr_N)? attr_N->data_float3(): NULL; - for(int step = 0; step < time_index; step++) { + for(int step = 0; step < motion_step; step++) { memcpy(attr_mP->data_float3() + step*numverts, P, sizeof(float3)*numverts); if(attr_mN) memcpy(attr_mN->data_float3() + step*numverts, N, sizeof(float3)*numverts); @@ -1400,7 +1374,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob, else { if(b_mesh.vertices.length() != numverts) { VLOG(1) << "Topology differs, discarding motion blur for object " - << b_ob.name() << " at time " << time_index; + << b_ob.name() << " at time " << motion_step; memcpy(mP, &mesh->verts[0], sizeof(float3)*numverts); if(mN != NULL) { memcpy(mN, attr_N->data_float3(), sizeof(float3)*numverts); @@ -1411,7 +1385,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob, /* hair motion */ if(numkeys) - sync_curves(mesh, b_mesh, b_ob, true, time_index); + sync_curves(mesh, b_mesh, b_ob, true, motion_step); /* free derived mesh */ b_data.meshes.remove(b_mesh, false, true, false); diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 38ef1bc52498e51e371733e1a200da6864510f5b..077ceb4ebef4a96bbf111f2f78fa5cbf4c63fc7e 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -327,22 +327,11 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, if(motion) { object = object_map.find(key); - if(object && (scene->need_motion() == Scene::MOTION_PASS || - object_use_motion(b_parent, b_ob))) - { - /* object transformation */ - if(tfm != object->tfm) { - VLOG(1) << "Object " << b_ob.name() << " motion detected."; - if(motion_time == -1.0f || motion_time == 1.0f) { - object->use_motion = true; - } - } - - if(motion_time == -1.0f) { - object->motion.pre = tfm; - } - else if(motion_time == 1.0f) { - object->motion.post = tfm; + if(object && object->use_motion()) { + /* Set transform at matching motion time step. */ + int time_index = object->motion_step(motion_time); + if(time_index >= 0) { + object->motion[time_index] = tfm; } /* mesh deformation */ @@ -389,25 +378,37 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, object->name = b_ob.name().c_str(); object->pass_id = b_ob.pass_index(); object->tfm = tfm; - object->motion.pre = transform_empty(); - object->motion.post = transform_empty(); - object->use_motion = false; + object->motion.clear(); /* motion blur */ - if(scene->need_motion() == Scene::MOTION_BLUR && object->mesh) { + Scene::MotionType need_motion = scene->need_motion(); + if(need_motion != Scene::MOTION_NONE && object->mesh) { Mesh *mesh = object->mesh; - mesh->use_motion_blur = false; + mesh->motion_steps = 0; + + uint motion_steps; - if(object_use_motion(b_parent, b_ob)) { - if(object_use_deform_motion(b_parent, b_ob)) { - mesh->motion_steps = object_motion_steps(b_ob); + if(scene->need_motion() == Scene::MOTION_BLUR) { + motion_steps = object_motion_steps(b_parent, b_ob); + if(motion_steps && object_use_deform_motion(b_parent, b_ob)) { + mesh->motion_steps = motion_steps; mesh->use_motion_blur = true; } + } + else { + motion_steps = 3; + mesh->motion_steps = motion_steps; + } + + object->motion.resize(motion_steps, transform_empty()); + + if(motion_steps) { + object->motion[motion_steps/2] = tfm; - vector<float> times = object->motion_times(); - foreach(float time, times) - motion_times.insert(time); + for(size_t step = 0; step < motion_steps; step++) { + motion_times.insert(object->motion_time(step)); + } } } @@ -694,6 +695,11 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render, /* note iteration over motion_times set happens in sorted order */ foreach(float relative_time, motion_times) { + /* center time is already handled. */ + if(relative_time == 0.0f) { + continue; + } + VLOG(1) << "Synchronizing motion for the relative time " << relative_time << "."; diff --git a/intern/cycles/blender/blender_object_cull.cpp b/intern/cycles/blender/blender_object_cull.cpp index 1d747de647aa821cf1705def42e2e01d93c0056e..bdf7dc469b256ecf33bead5b677243778b82ff48 100644 --- a/intern/cycles/blender/blender_object_cull.cpp +++ b/intern/cycles/blender/blender_object_cull.cpp @@ -96,7 +96,7 @@ bool BlenderObjectCulling::test(Scene *scene, BL::Object& b_ob, Transform& tfm) bool BlenderObjectCulling::test_camera(Scene *scene, float3 bb[8]) { Camera *cam = scene->camera; - Transform& worldtondc = cam->worldtondc; + const ProjectionTransform& worldtondc = cam->worldtondc; float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX), bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX); bool all_behind = true; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 9d1e87b763ccd782c8fb8fa2ece3065ae8f3e756..00d23b9095e5fa79000f8276642b3a0aa3f453ad 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -252,6 +252,8 @@ static ShaderEvalType get_shader_type(const string& pass_type) return SHADER_EVAL_NORMAL; else if(strcmp(shader_type, "UV")==0) return SHADER_EVAL_UV; + else if(strcmp(shader_type, "ROUGHNESS")==0) + return SHADER_EVAL_ROUGHNESS; else if(strcmp(shader_type, "DIFFUSE_COLOR")==0) return SHADER_EVAL_DIFFUSE_COLOR; else if(strcmp(shader_type, "GLOSSY_COLOR")==0) diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 283aa5600fd24d027f4c50eb767a4e41261398ee..a6e9cfbe617fadd1ab00b8a91e45da30b530b4e6 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -663,7 +663,9 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene, } params.bvh_layout = DebugFlags().cpu.bvh_layout; - +#ifdef WITH_EMBREE + params.bvh_layout = RNA_boolean_get(&cscene, "use_bvh_embree") ? BVH_LAYOUT_EMBREE : params.bvh_layout; +#endif return params; } diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index e7b71ae9310ec9f93dd122c3ea3d6b6fd0029f5b..1e7b0b32518e518d04fb9be3591a50389c1294dc 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -118,7 +118,7 @@ private: BL::Mesh& b_mesh, BL::Object& b_ob, bool motion, - int time_index = 0); + int motion_step = 0); Object *sync_object(BL::Object& b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject& b_dupli_ob, diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 363e19f7a20b6585961d537cec4c5f05f2be3398..c418b19a6373dfbcfcd57d498da28675fc960ccc 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -247,14 +247,15 @@ static inline float *image_get_float_pixels_for_frame(BL::Image& image, static inline Transform get_transform(const BL::Array<float, 16>& array) { - Transform tfm; + ProjectionTransform projection; - /* we assume both types to be just 16 floats, and transpose because blender - * use column major matrix order while we use row major */ - memcpy(&tfm, &array, sizeof(float)*16); - tfm = transform_transpose(tfm); + /* We assume both types to be just 16 floats, and transpose because blender + * use column major matrix order while we use row major. */ + memcpy(&projection, &array, sizeof(float)*16); + projection = projection_transpose(projection); - return tfm; + /* Drop last row, matrix is assumed to be affine transform. */ + return projection_to_transform(projection); } static inline float2 get_float2(const BL::Array<float, 2>& array) @@ -483,33 +484,34 @@ static inline void mesh_texture_space(BL::Mesh& b_mesh, loc = loc*size - make_float3(0.5f, 0.5f, 0.5f); } -/* object used for motion blur */ -static inline bool object_use_motion(BL::Object& b_parent, BL::Object& b_ob) +/* Object motion steps, returns 0 if no motion blur needed. */ +static inline uint object_motion_steps(BL::Object& b_parent, BL::Object& b_ob) { + /* Get motion enabled and steps from object itself. */ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); bool use_motion = get_boolean(cobject, "use_motion_blur"); - /* If motion blur is enabled for the object we also check - * whether it's enabled for the parent object as well. - * - * This way we can control motion blur from the dupligroup - * duplicator much easier. - */ - if(use_motion && b_parent.ptr.data != b_ob.ptr.data) { + if(!use_motion) { + return 0; + } + + uint steps = max(1, get_int(cobject, "motion_steps")); + + /* Also check parent object, so motion blur and steps can be + * controlled by dupligroup duplicator for linked groups. */ + if(b_parent.ptr.data != b_ob.ptr.data) { PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles"); use_motion &= get_boolean(parent_cobject, "use_motion_blur"); - } - return use_motion; -} -/* object motion steps */ -static inline uint object_motion_steps(BL::Object& b_ob) -{ - PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); - uint steps = get_int(cobject, "motion_steps"); + if(!use_motion) { + return 0; + } + + steps = max(steps, get_int(parent_cobject, "motion_steps")); + } - /* use uneven number of steps so we get one keyframe at the current frame, - * and ue 2^(steps - 1) so objects with more/fewer steps still have samples - * at the same times, to avoid sampling at many different times */ + /* Use uneven number of steps so we get one keyframe at the current frame, + * and use 2^(steps - 1) so objects with more/fewer steps still have samples + * at the same times, to avoid sampling at many different times. */ return (2 << (steps - 1)) + 1; } diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index c5c4c96979f3a847e25d3de292b3b2e07e33f37e..8c0a88e8e1b8e97ebcb04f35a17e748b048a353a 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -42,9 +42,9 @@ const char *bvh_layout_name(BVHLayout layout) switch(layout) { case BVH_LAYOUT_BVH2: return "BVH2"; case BVH_LAYOUT_BVH4: return "BVH4"; - case BVH_LAYOUT_EMBREE: return "EMBREE"; case BVH_LAYOUT_NONE: return "NONE"; case BVH_LAYOUT_ALL: return "ALL"; + case BVH_LAYOUT_EMBREE: return "EMBREE"; } LOG(DFATAL) << "Unsupported BVH layout was passed."; return ""; @@ -111,7 +111,7 @@ BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects) /* Building */ -void BVH::build(Progress& progress) +void BVH::build(Progress& progress, Stats*) { progress.set_substatus("Building BVH"); diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index 6078a26ef965c7199505119788c8a1b7b2d38231..d445bf2a68d2e8e00b389418f832e5c0619fee0c 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -25,6 +25,7 @@ CCL_NAMESPACE_BEGIN +class Stats; class BVHNode; struct BVHStackEntry; class BVHParams; @@ -85,21 +86,21 @@ public: static BVH *create(const BVHParams& params, const vector<Object*>& objects); virtual ~BVH() {} - virtual void build(Progress& progress); - virtual void refit(Progress& progress); + virtual void build(Progress& progress, Stats *stats=NULL); + void refit(Progress& progress); protected: BVH(const BVHParams& params, const vector<Object*>& objects); /* Refit range of primitives. */ - virtual void refit_primitives(int start, int end, BoundBox& bbox, uint& visibility); + void refit_primitives(int start, int end, BoundBox& bbox, uint& visibility); /* triangles and strands */ - virtual void pack_primitives(); - virtual void pack_triangle(int idx, float4 storage[3]); + void pack_primitives(); + void pack_triangle(int idx, float4 storage[3]); /* merge instance BVH's */ - virtual void pack_instances(size_t nodes_size, size_t leaf_nodes_size); + void pack_instances(size_t nodes_size, size_t leaf_nodes_size); /* for subclasses to implement */ virtual void pack_nodes(const BVHNode *root) = 0; diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp index dff4d45927c771a786904933efbda6f1c8c1f47e..d2b7047667dc4cc4cf689976ccbfa97bca6df9e9 100644 --- a/intern/cycles/bvh/bvh_embree.cpp +++ b/intern/cycles/bvh/bvh_embree.cpp @@ -45,188 +45,151 @@ CCL_NAMESPACE_BEGIN */ -/* occlusion filter function for single rays and packets */ -//void occlusionFilter(const RTCFilterFunctionNArguments* args) -//{ -// /* avoid crashing when debug visualizations are used */ -// if (args->context == nullptr) return; -// -// assert(args->N == 1); -// int* valid = args->valid; -// const IntersectContext* context = (const IntersectContext*) args->context; -// Ray* ray = (Ray*)args->ray; -// RTCHit* hit = (RTCHit*)args->hit; -// -// /* ignore inactive rays */ -// if (valid[0] != -1) return; -// -// Ray2* ray2 = (Ray2*) context->userRayExt; -// assert(ray2); -// -// for (unsigned int i=ray2->firstHit; i<ray2->lastHit; i++) { -// unsigned slot= i%HIT_LIST_LENGTH; -// if (ray2->hit_geomIDs[slot] == hit->geomID && ray2->hit_primIDs[slot] == hit->primID) { -// return; -// } -// } -// /* store hit in hit list */ -// unsigned int slot = ray2->lastHit%HIT_LIST_LENGTH; -// ray2->hit_geomIDs[slot] = hit->geomID; -// ray2->hit_primIDs[slot] = hit->primID; -// ray2->lastHit++; -// if (ray2->lastHit - ray2->firstHit >= HIT_LIST_LENGTH) -// ray2->firstHit++; -// -// Vec3fa h = ray->org + ray->dir * ray->tfar; -// -// /* calculate and accumulate transparency */ -// float T = transparencyFunction(h); -// T *= ray2->transparency; -// ray2->transparency = T; -// if (T != 0.0f) -// valid[0] = 0; -//} - void rtc_filter_func(const RTCFilterFunctionNArguments* args); - -void rtc_filter_func(const RTCFilterFunctionNArguments* args) { - +void rtc_filter_func(const RTCFilterFunctionNArguments* args) +{ /* avoid crashing when debug visualizations are used */ - if (args->context == nullptr) return; + if(args->context == nullptr) return; assert(args->N == 1); int* valid = args->valid; /* ignore inactive rays */ - if (valid[0] != -1) return; + if(valid[0] != -1) return; const IntersectContext* context = (const IntersectContext*) args->context; CCLRay* ray = (CCLRay*) context->userRayExt; RTCRay* eray = (RTCRay*) args->ray; RTCHit* ehit = (RTCHit*) args->hit; - + ray->ray = *eray; ray->hit = *ehit; KernelGlobals *kg = ray->kg; /* For all ray types: check if there is backfacing hair to ignore */ - if ((kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) - && !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) - && !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) && ehit->geomID & 1) { - if (dot(make_float3(eray->dir_x, eray->dir_y, eray->dir_z), make_float3(ehit->Ng_x, ehit->Ng_y, ehit->Ng_z)) > 0.0f) { - ehit->geomID = RTC_INVALID_GEOMETRY_ID; - valid[0] = 0; - return; - } - } - - if (ray->type == CCLRay::RAY_REGULAR) { - return; - } else if (ray->type == CCLRay::RAY_SHADOW_ALL) { - /* Append the intersection to the end of the array. */ - if (ray->num_hits < ray->max_hits) { - Intersection *isect = &ray->isect_s[ray->num_hits]; - ray->num_hits++; - ray->isect_to_ccl(isect); - int prim = kernel_tex_fetch(__prim_index, isect->prim); - int shader = 0; - if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) { - shader = kernel_tex_fetch(__tri_shader, prim); - } else { - float4 str = kernel_tex_fetch(__curves, prim); - shader = __float_as_int(str.z); - } - int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK) * SHADER_SIZE); - /* If no transparent shadows, all light is blocked. */ - if (flag & (SD_HAS_TRANSPARENT_SHADOW)) { - /* This tells Embree to continue tracing. */ - ehit->geomID = RTC_INVALID_GEOMETRY_ID; - valid[0] = 0; - } else { - ray->num_hits = ray->max_hits + 1; - } - } else { - /* Increase the number of hits beyond ray->max_hits - * so that the caller can detect this as opaque. */ - ray->num_hits++; - } - return; - } else if (ray->type == CCLRay::RAY_SSS) { - /* Only accept hits from the same object and triangles. */ - if (ehit->instID[0] / 2 != ray->sss_object_id || ehit->geomID & 1) { - /* This tells Embree to continue tracing. */ - ehit->geomID = RTC_INVALID_GEOMETRY_ID; - valid[0] = 0; - return; - } - - /* See triangle_intersect_subsurface() for the native equivalent. */ - for (int i = min(ray->max_hits, ray->ss_isect->num_hits) - 1; i >= 0; --i) { - if (ray->ss_isect->hits[i].t == eray->tfar) { - /* This tells Embree to continue tracing. */ - ehit->geomID = RTC_INVALID_GEOMETRY_ID; - valid[0] = 0; - return; - } - } - - ray->ss_isect->num_hits++; - int hit; - - if (ray->ss_isect->num_hits <= ray->max_hits) { - hit = ray->ss_isect->num_hits - 1; - } else { - /* reservoir sampling: if we are at the maximum number of - * hits, randomly replace element or skip it */ - hit = lcg_step_uint(ray->lcg_state) % ray->ss_isect->num_hits; - - if (hit >= ray->max_hits) { - /* This tells Embree to continue tracing. */ - ehit->geomID = RTC_INVALID_GEOMETRY_ID; - valid[0] = 0; - return; - } - } - /* record intersection */ - ray->isect_to_ccl(&ray->ss_isect->hits[hit]); - ray->ss_isect->Ng[hit].x = -ehit->Ng_x; - ray->ss_isect->Ng[hit].y = -ehit->Ng_y; - ray->ss_isect->Ng[hit].z = -ehit->Ng_z; - ray->ss_isect->Ng[hit] = normalize(ray->ss_isect->Ng[hit]); - /* this tells Embree to continue tracing */ - ehit->geomID = RTC_INVALID_GEOMETRY_ID; - valid[0] = 0; - return; - } else if (ray->type == CCLRay::RAY_VOLUME_ALL) { - /* Append the intersection to the end of the array-> */ - if (ray->num_hits < ray->max_hits) { - Intersection *isect = &ray->isect_s[ray->num_hits]; - ray->num_hits++; - ray->isect_to_ccl(isect); - /* Only primitives from volume object. */ - uint tri_object = (isect->object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, isect->prim) : isect->object; - int object_flag = kernel_tex_fetch(__object_flag, tri_object); - if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { - ray->num_hits--; - } - /* This tells Embree to continue tracing. */ - ehit->geomID = RTC_INVALID_GEOMETRY_ID; - valid[0] = 0; - return; - } - return; + if((kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + && !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) + && !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) && ehit->geomID & 1) { + if(dot(make_float3(eray->dir_x, eray->dir_y, eray->dir_z), make_float3(ehit->Ng_x, ehit->Ng_y, ehit->Ng_z)) > 0.0f) { + ehit->geomID = RTC_INVALID_GEOMETRY_ID; + valid[0] = 0; + return; + } + } + + if(ray->type == CCLRay::RAY_REGULAR) { + return; + } + else if(ray->type == CCLRay::RAY_SHADOW_ALL) { + /* Append the intersection to the end of the array. */ + if(ray->num_hits < ray->max_hits) { + Intersection *isect = &ray->isect_s[ray->num_hits]; + ray->num_hits++; + ray->isect_to_ccl(isect); + int prim = kernel_tex_fetch(__prim_index, isect->prim); + int shader = 0; + if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) { + shader = kernel_tex_fetch(__tri_shader, prim); + } + else { + float4 str = kernel_tex_fetch(__curves, prim); + shader = __float_as_int(str.z); + } + int flag = kernel_tex_fetch(__shaders, shader & SHADER_MASK).flags; + /* If no transparent shadows, all light is blocked. */ + if(flag & (SD_HAS_TRANSPARENT_SHADOW)) { + /* This tells Embree to continue tracing. */ + ehit->geomID = RTC_INVALID_GEOMETRY_ID; + valid[0] = 0; + } + else { + ray->num_hits = ray->max_hits + 1; + } + } + else { + /* Increase the number of hits beyond ray->max_hits + * so that the caller can detect this as opaque. */ + ray->num_hits++; + } + return; + } + else if(ray->type == CCLRay::RAY_SSS) { + /* Only accept hits from the same object and triangles. */ + if(ehit->instID[0] / 2 != ray->sss_object_id || ehit->geomID & 1) { + /* This tells Embree to continue tracing. */ + ehit->geomID = RTC_INVALID_GEOMETRY_ID; + valid[0] = 0; + return; + } + + /* See triangle_intersect_subsurface() for the native equivalent. */ + for (int i = min(ray->max_hits, ray->ss_isect->num_hits) - 1; i >= 0; --i) { + if(ray->ss_isect->hits[i].t == eray->tfar) { + /* This tells Embree to continue tracing. */ + ehit->geomID = RTC_INVALID_GEOMETRY_ID; + valid[0] = 0; + return; + } + } + + ray->ss_isect->num_hits++; + int hit; + + if(ray->ss_isect->num_hits <= ray->max_hits) { + hit = ray->ss_isect->num_hits - 1; + } + else { + /* reservoir sampling: if we are at the maximum number of + * hits, randomly replace element or skip it */ + hit = lcg_step_uint(ray->lcg_state) % ray->ss_isect->num_hits; + + if(hit >= ray->max_hits) { + /* This tells Embree to continue tracing. */ + ehit->geomID = RTC_INVALID_GEOMETRY_ID; + valid[0] = 0; + return; + } + } + /* record intersection */ + ray->isect_to_ccl(&ray->ss_isect->hits[hit]); + ray->ss_isect->Ng[hit].x = -ehit->Ng_x; + ray->ss_isect->Ng[hit].y = -ehit->Ng_y; + ray->ss_isect->Ng[hit].z = -ehit->Ng_z; + ray->ss_isect->Ng[hit] = normalize(ray->ss_isect->Ng[hit]); + /* this tells Embree to continue tracing */ + ehit->geomID = RTC_INVALID_GEOMETRY_ID; + valid[0] = 0; + return; + } else if(ray->type == CCLRay::RAY_VOLUME_ALL) { + /* Append the intersection to the end of the array-> */ + if(ray->num_hits < ray->max_hits) { + Intersection *isect = &ray->isect_s[ray->num_hits]; + ray->num_hits++; + ray->isect_to_ccl(isect); + /* Only primitives from volume object. */ + uint tri_object = (isect->object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, isect->prim) : isect->object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + ray->num_hits--; + } + /* This tells Embree to continue tracing. */ + ehit->geomID = RTC_INVALID_GEOMETRY_ID; + valid[0] = 0; + return; + } + return; } return; } bool rtc_memory_monitor_func(void* userPtr, const ssize_t bytes, const bool post); - -bool rtc_memory_monitor_func(void* userPtr, const ssize_t bytes, const bool) { +bool rtc_memory_monitor_func(void* userPtr, const ssize_t bytes, const bool) +{ BVHEmbree *bvh = (BVHEmbree*) userPtr; - if (bvh) { - bvh->mem_monitor(bytes); + if(bvh) { + bvh->mem_monitor(bytes); } return true; } @@ -234,12 +197,12 @@ bool rtc_memory_monitor_func(void* userPtr, const ssize_t bytes, const bool) { static double progress_start_time = 0.0f; bool rtc_progress_func(void* user_ptr, const double n); - -bool rtc_progress_func(void* user_ptr, const double n) { +bool rtc_progress_func(void* user_ptr, const double n) +{ Progress *progress = (Progress*) user_ptr; - if (time_dt() - progress_start_time < 0.25) - return true; + if(time_dt() - progress_start_time < 0.25) + return true; string msg = string_printf("Building BVH %.0f%%", n * 100.0); @@ -255,41 +218,42 @@ int BVHEmbree::rtc_shared_users = 0; thread_mutex BVHEmbree::rtc_shared_mutex; BVHEmbree::BVHEmbree(const BVHParams& params_, const vector<Object*>& objects_) -: BVH(params_, objects_), scene(NULL), mem_used(0), top_level(NULL), +: BVH(params_, objects_), scene(NULL), mem_used(0), top_level(NULL), stats(NULL), curve_subdivisions(params.curve_subdivisions), use_curves(params_.curve_flags & CURVE_KN_INTERPOLATE), -use_ribbons(params.curve_flags & CURVE_KN_RIBBONS), dynamic_scene(true) { +use_ribbons(params.curve_flags & CURVE_KN_RIBBONS), dynamic_scene(true) +{ _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); thread_scoped_lock lock(rtc_shared_mutex); - if (rtc_shared_users == 0) { - rtc_shared_device = rtcNewDevice("verbose=1"); - - /* Check here if Embree was built with the correct flags. */ - ssize_t ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED); - if (ret != 1) { - assert(0); - VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED flag. Ray visiblity will not work."; - } - ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED); - if (ret != 1) { - assert(0); - VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED flag. Renders may not look as expected."; - } - ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED); - if (ret != 1) { - assert(0); - VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED flag. Line primitives will not be rendered."; - } - ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED); - if (ret != 1) { - assert(0); - VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED flag. Triangle primitives will not be rendered."; - } - ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED); - if (ret != 0) { - assert(0); - VLOG(1) << "Embree is compiled with the RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED flag. Renders may not look as expected."; - } + if(rtc_shared_users == 0) { + rtc_shared_device = rtcNewDevice("verbose=1"); + + /* Check here if Embree was built with the correct flags. */ + ssize_t ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED); + if(ret != 1) { + assert(0); + VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED flag. Ray visiblity will not work."; + } + ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED); + if(ret != 1) { + assert(0); + VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED flag. Renders may not look as expected."; + } + ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED); + if(ret != 1) { + assert(0); + VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED flag. Line primitives will not be rendered."; + } + ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED); + if(ret != 1) { + assert(0); + VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED flag. Triangle primitives will not be rendered."; + } + ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED); + if(ret != 0) { + assert(0); + VLOG(1) << "Embree is compiled with the RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED flag. Renders may not look as expected."; + } } rtc_shared_users++; @@ -301,97 +265,112 @@ use_ribbons(params.curve_flags & CURVE_KN_RIBBONS), dynamic_scene(true) { params.bvh_layout = BVH_LAYOUT_EMBREE; } -BVHEmbree::~BVHEmbree() { - if (!params.top_level) { - destroy(scene); +BVHEmbree::~BVHEmbree() +{ + if(!params.top_level) { + destroy(scene); } } -void BVHEmbree::destroy(RTCScene scene) { - if (scene) { - rtcReleaseScene(scene); - scene = NULL; +void BVHEmbree::destroy(RTCScene scene) +{ + if(scene) { + rtcReleaseScene(scene); + scene = NULL; } thread_scoped_lock lock(rtc_shared_mutex); rtc_shared_users--; - if (rtc_shared_users == 0) { - rtcReleaseDevice(rtc_shared_device); - rtc_shared_device = NULL; + if(rtc_shared_users == 0) { + rtcReleaseDevice(rtc_shared_device); + rtc_shared_device = NULL; } } -void BVHEmbree::delete_rtcScene() { - if (scene) { - /* When this BVH is used as an instance in a top level BVH, don't delete now - * Let the top_level BVH know that it should delete it later. */ - if (top_level) { - top_level->add_delayed_delete_scene(scene); - } else { - rtcReleaseScene(scene); - if (delayed_delete_scenes.size()) { - - foreach(RTCScene s, delayed_delete_scenes) { - rtcReleaseScene(s); - } - } - delayed_delete_scenes.clear(); - } - scene = NULL; +void BVHEmbree::delete_rtcScene() +{ + if(scene) { + /* When this BVH is used as an instance in a top level BVH, don't delete now + * Let the top_level BVH know that it should delete it later. */ + if(top_level) { + top_level->add_delayed_delete_scene(scene); + } + else { + rtcReleaseScene(scene); + if(delayed_delete_scenes.size()) { + foreach(RTCScene s, delayed_delete_scenes) { + rtcReleaseScene(s); + } + } + delayed_delete_scenes.clear(); + } + scene = NULL; } } -void BVHEmbree::mem_monitor(ssize_t bytes) { +void BVHEmbree::mem_monitor(ssize_t bytes) +{ + if(stats) { + if(bytes > 0) { + stats->mem_alloc(bytes); + } else { + stats->mem_free(-bytes); + } + } mem_used += bytes; } -void BVHEmbree::build(Progress& progress) { +void BVHEmbree::build(Progress& progress, Stats *stats_) +{ + stats = stats_; + progress.set_substatus("Building BVH"); - if (scene) { - rtcReleaseScene(scene); - scene = NULL; + if(scene) { + rtcReleaseScene(scene); + scene = NULL; } RTCSceneFlags flags = RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST; - if (params.bvh_type == SceneParams::BVH_DYNAMIC) { - flags = (RTCSceneFlags) (flags | RTC_SCENE_FLAG_DYNAMIC); + if(params.bvh_type == SceneParams::BVH_DYNAMIC) { + flags = (RTCSceneFlags) (flags | RTC_SCENE_FLAG_DYNAMIC); } RTCBuildQuality buildQuality = (params.bvh_type == SceneParams::BVH_DYNAMIC ? RTC_BUILD_QUALITY_LOW : RTC_BUILD_QUALITY_MEDIUM); - if (params.use_spatial_split) { - buildQuality = RTC_BUILD_QUALITY_HIGH; + if(params.use_spatial_split) { + buildQuality = RTC_BUILD_QUALITY_HIGH; } scene = rtcNewScene(rtc_shared_device); - rtcSetSceneFlags(scene, flags); // EMBREE_FIXME: set proper scene flags - rtcSetSceneBuildQuality(scene, buildQuality); // EMBREE_FIXME: set proper build quality - // rtcCommitScene(scene); + rtcSetSceneFlags(scene, flags); + rtcSetSceneBuildQuality(scene, buildQuality); int i = 0; pack.object_node.clear(); foreach(Object *ob, objects) { - if (params.top_level) { - if (!ob->is_traceable()) { - ++i; - continue; - } - if (!ob->mesh->is_instanced()) { - add_object(ob, i); - } else { - add_instance(ob, i); - } - } else { - add_object(ob, i); - } - ++i; - if (progress.get_cancel()) return; - } - - if (progress.get_cancel()) { - delete_rtcScene(); - return; + if(params.top_level) { + if(!ob->is_traceable()) { + ++i; + continue; + } + if(!ob->mesh->is_instanced()) { + add_object(ob, i); + } + else { + add_instance(ob, i); + } + } + else { + add_object(ob, i); + } + ++i; + if(progress.get_cancel()) return; + } + + if(progress.get_cancel()) { + delete_rtcScene(); + return; } rtcSetSceneProgressMonitorFunction(scene, rtc_progress_func, &progress); @@ -399,117 +378,95 @@ void BVHEmbree::build(Progress& progress) { pack_primitives(); - if (progress.get_cancel()) { - delete_rtcScene(); - return; + if(progress.get_cancel()) { + delete_rtcScene(); + stats = NULL; + return; } progress.set_substatus("Packing geometry"); pack_nodes(NULL); -} -void BVHEmbree::add_object(Object *ob, int i) { - //RTCGeometry geom_id = NULL; + stats = NULL; +} - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) { - //size_t prim_offset = pack.prim_index.size(); - add_triangles(ob, i); +void BVHEmbree::add_object(Object *ob, int i) +{ + if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) { + add_triangles(ob, i); } - if (params.primitive_mask & PRIMITIVE_ALL_CURVE && ob->mesh->num_curves() > 0) { - // size_t prim_offset = pack.prim_index.size(); - add_curves(ob, i); + if(params.primitive_mask & PRIMITIVE_ALL_CURVE && ob->mesh->num_curves() > 0) { + add_curves(ob, i); } } -void BVHEmbree::add_instance(Object *ob, int i) { - if (!ob || !ob->mesh) { - assert(0); - return; +void BVHEmbree::add_instance(Object *ob, int i) +{ + if(!ob || !ob->mesh) { + assert(0); + return; } BVHEmbree *instance_bvh = (BVHEmbree*) (ob->mesh->bvh); - if (instance_bvh->top_level != this) { - instance_bvh->top_level = this; + if(instance_bvh->top_level != this) { + instance_bvh->top_level = this; } - const size_t num_motion_steps = ob->use_motion ? 3 : 1; - //unsigned int geom_id = i * 2; + const size_t num_motion_steps = ob->use_motion() ? ob->motion.size() : 1; RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_INSTANCE); // EMBREE_FIXME: check if geometry gets properly committed rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene); rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); - if (ob->use_motion) { - /* Drop animated scales. Embree knows how to apply motion blur to those, but Cycles doesn't. - * This is necessary to keep it consistent with Cycles' intersection refinement. - * Eventually, Cycles should either also know how to to scaling or rely on Embree to get - * transformation matrices for time steps. */ - MotionTransform decom; - Transform decom_single, comp; - transform_motion_decompose(&decom, &ob->motion, &ob->tfm); - decom_single.x = decom.pre.x; - decom_single.y = decom.pre.y; - decom_single.z = decom.mid.z; - decom_single.w = decom.mid.w; - transform_compose(&comp, &decom_single); - - rtcSetGeometryTransform(geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float*) &comp); - rtcSetGeometryTransform(geom_id, 1, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float*) &ob->tfm); - - decom_single.x = decom.post.x; - decom_single.y = decom.post.y; - transform_compose(&comp, &decom_single); - rtcSetGeometryTransform(geom_id, 2, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float*) &comp); + if(ob->use_motion()) { + for(size_t step = 0; step < num_motion_steps; ++step) + rtcSetGeometryTransform(geom_id, step, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float*)&ob->motion[step]); } else { - rtcSetGeometryTransform(geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float*) &ob->tfm); + rtcSetGeometryTransform(geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float*) &ob->tfm); } - - pack.prim_index.push_back_slow(-1); pack.prim_object.push_back_slow(i); pack.prim_type.push_back_slow(PRIMITIVE_NONE); pack.prim_tri_index.push_back_slow(-1); - rtcSetGeometryUserData(geom_id, (void*) instance_bvh->scene); rtcSetGeometryMask(geom_id, ob->visibility); rtcCommitGeometry(geom_id); rtcAttachGeometryByID(scene, geom_id, i * 2); rtcReleaseGeometry(geom_id); - //return geom_id; } -void BVHEmbree::add_triangles(Object *ob, int i) { +void BVHEmbree::add_triangles(Object *ob, int i) +{ size_t prim_offset = pack.prim_index.size(); Mesh *mesh = ob->mesh; const Attribute *attr_mP = NULL; size_t num_motion_steps = 1; - if (mesh->has_motion_blur()) { - attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (attr_mP) { - num_motion_steps = mesh->motion_steps; - if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) { - assert(0); - num_motion_steps = RTC_MAX_TIME_STEP_COUNT; - } - } + if(mesh->has_motion_blur()) { + attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if(attr_mP) { + num_motion_steps = mesh->motion_steps; + if(num_motion_steps > RTC_MAX_TIME_STEP_COUNT) { + assert(0); + num_motion_steps = RTC_MAX_TIME_STEP_COUNT; + } + } } const size_t num_triangles = mesh->num_triangles(); - // const size_t num_verts = mesh->verts.size(); - // unsigned int geom_id = i * 2; + RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_TRIANGLE); // EMBREE_FIXME: check if geometry gets properly committed rtcSetGeometryBuildQuality(geom_id, params.bvh_type == SceneParams::BVH_DYNAMIC ? RTC_BUILD_QUALITY_REFIT : RTC_BUILD_QUALITY_MEDIUM); rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); unsigned *rtc_indices = (unsigned*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof (int) * 3, num_triangles); for (size_t j = 0; j < num_triangles; j++) { - Mesh::Triangle t = mesh->get_triangle(j); - rtc_indices[j * 3] = t.v[0]; - rtc_indices[j * 3 + 1] = t.v[1]; - rtc_indices[j * 3 + 2] = t.v[2]; + Mesh::Triangle t = mesh->get_triangle(j); + rtc_indices[j * 3] = t.v[0]; + rtc_indices[j * 3 + 1] = t.v[1]; + rtc_indices[j * 3 + 2] = t.v[2]; } update_tri_vertex_buffer(geom_id, mesh); @@ -519,10 +476,10 @@ void BVHEmbree::add_triangles(Object *ob, int i) { pack.prim_index.reserve(pack.prim_index.size() + num_triangles); pack.prim_tri_index.reserve(pack.prim_index.size() + num_triangles); for (size_t j = 0; j < num_triangles; j++) { - pack.prim_object.push_back_reserved(i); - pack.prim_type.push_back_reserved(num_motion_steps > 1 ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE); - pack.prim_index.push_back_reserved(j); - pack.prim_tri_index.push_back_reserved(j); + pack.prim_object.push_back_reserved(i); + pack.prim_type.push_back_reserved(num_motion_steps > 1 ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE); + pack.prim_index.push_back_reserved(j); + pack.prim_tri_index.push_back_reserved(j); } rtcSetGeometryUserData(geom_id, (void*) prim_offset); @@ -534,60 +491,60 @@ void BVHEmbree::add_triangles(Object *ob, int i) { rtcReleaseGeometry(geom_id); } -void BVHEmbree::update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh) { +void BVHEmbree::update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh) +{ const Attribute *attr_mP = NULL; size_t num_motion_steps = 1; int t_mid = 0; - if (mesh->has_motion_blur()) { - attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (attr_mP) { - num_motion_steps = mesh->motion_steps; - t_mid = (num_motion_steps - 1) / 2; - if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) { - assert(0); - num_motion_steps = RTC_MAX_TIME_STEP_COUNT; - } - } + if(mesh->has_motion_blur()) { + attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if(attr_mP) { + num_motion_steps = mesh->motion_steps; + t_mid = (num_motion_steps - 1) / 2; + if(num_motion_steps > RTC_MAX_TIME_STEP_COUNT) { + assert(0); + num_motion_steps = RTC_MAX_TIME_STEP_COUNT; + } + } } const size_t num_verts = mesh->verts.size(); for (int t = 0; t < num_motion_steps; t++) { - //RTCBufferType buffer_type = RTC_BUFFER(RTC_BUFFER_TYPE_VERTEX, t); - const float3 *verts; - if (t == t_mid) { - verts = &mesh->verts[0]; - } else { - int t_ = (t > t_mid) ? (t - 1) : t; - verts = &attr_mP->data_float3()[t_ * num_verts]; - } - - //void *raw_buffer = rtcGetGeometryBufferData(geom_id, RTC_BUFFER_TYPE_VERTEX, t) /* EMBREE_FIXME: check if this should be rtcSetNewGeometryBuffer */; - float* raw_buffer = (float*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, sizeof (float) * 4, num_verts); - assert(raw_buffer); - - if (raw_buffer) { - float *rtc_verts = (float*) raw_buffer; - for (size_t j = 0; j < num_verts; j++) { - rtc_verts[0] = verts[j].x; - rtc_verts[1] = verts[j].y; - rtc_verts[2] = verts[j].z; - rtc_verts[3] = 0.0f; - rtc_verts += 4; - } - - } + const float3 *verts; + if(t == t_mid) { + verts = &mesh->verts[0]; + } else { + int t_ = (t > t_mid) ? (t - 1) : t; + verts = &attr_mP->data_float3()[t_ * num_verts]; + } + + float* raw_buffer = (float*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, sizeof (float) * 4, num_verts); + assert(raw_buffer); + + if(raw_buffer) { + float *rtc_verts = (float*) raw_buffer; + for (size_t j = 0; j < num_verts; j++) { + rtc_verts[0] = verts[j].x; + rtc_verts[1] = verts[j].y; + rtc_verts[2] = verts[j].z; + rtc_verts[3] = 0.0f; + rtc_verts += 4; + } + + } } } -void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh) { +void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh) +{ const Attribute *attr_mP = NULL; size_t num_motion_steps = 1; - if (mesh->has_motion_blur()) { - attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (attr_mP) { - num_motion_steps = mesh->motion_steps; - } + if(mesh->has_motion_blur()) { + attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if(attr_mP) { + num_motion_steps = mesh->motion_steps; + } } const size_t num_keys = mesh->curve_keys.size(); @@ -595,87 +552,89 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh /* Copy the CV data to Embree */ int t_mid = (num_motion_steps - 1) / 2; const float *curve_radius = &mesh->curve_radius[0]; - for (int t = 0; t < num_motion_steps; t++) { - //RTCBufferType buffer_type = RTC_BUFFER(RTC_BUFFER_TYPE_VERTEX, t); - const float3 *verts; - if (t == t_mid || attr_mP == NULL) { - verts = &mesh->curve_keys[0]; - } else { - int t_ = (t > t_mid) ? (t - 1) : t; - verts = &attr_mP->data_float3()[t_ * num_keys]; - } - - // void *raw_buffer = rtcGetGeometryBufferData(geom_id, RTC_BUFFER_TYPE_VERTEX, t) /* EMBREE_FIXME: check if this should be rtcSetNewGeometryBuffer */; - float* raw_buffer = (float*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT4, sizeof (float) * 4, num_keys); - assert(raw_buffer); - if (raw_buffer) { - float4 *rtc_verts = (float4*) raw_buffer; - if (use_curves) { - const size_t num_curves = mesh->num_curves(); - for (size_t j = 0; j < num_curves; j++) { - Mesh::Curve c = mesh->get_curve(j); - if (c.num_segments() > 0) { - const int& fk = c.first_key; - /* Create Embree's cubic splines that equal the cardinal splines that cycles uses */ - //static float fc = 1.0f / ((0.29f - 1.0f) * 6.0f); - const float fc = -0.2347417840375f; - rtc_verts[0] = float3_to_float4(verts[fk]); - rtc_verts[0].w = curve_radius[fk]; - rtc_verts[1] = float3_to_float4(-fc * (verts[fk + 1] - verts[fk]) + verts[fk]); - rtc_verts[1].w = lerp(curve_radius[fk], curve_radius[fk + 1], 0.33f); - size_t k = 1; - for (; k < c.num_segments(); k++) { - const float3 d = (verts[fk + k + 1] - verts[fk + k - 1]); - rtc_verts[k * 3 - 1] = float3_to_float4(fc * d + verts[fk + k]); - rtc_verts[k * 3 - 1].w = lerp(curve_radius[fk + k - 1], curve_radius[fk + k], 0.66f); - rtc_verts[k * 3] = float3_to_float4(verts[fk + k]); - rtc_verts[k * 3].w = curve_radius[fk + k]; - rtc_verts[k * 3 + 1] = float3_to_float4(-fc * d + verts[fk + k]); - rtc_verts[k * 3 + 1].w = lerp(curve_radius[fk + k], curve_radius[fk + k + 1], 0.33f); - } - rtc_verts[k * 3 - 1] = float3_to_float4(fc * (verts[fk + k] - verts[fk + k - 1]) + verts[fk + k]); - rtc_verts[k * 3 - 1].w = lerp(curve_radius[fk + k - 1], curve_radius[fk + k], 0.66f); - rtc_verts[k * 3] = float3_to_float4(verts[fk + k]); - rtc_verts[k * 3].w = curve_radius[fk + k]; - rtc_verts += c.num_segments()*3 + 1; - } else { - assert(0); - } - } - } else { - for (size_t j = 0; j < num_keys; j++) { - rtc_verts[j] = float3_to_float4(verts[j]); - rtc_verts[j].w = curve_radius[j]; - } - } - - } + for (int t = 0; t < num_motion_steps; t++) { //RTCBufferType buffer_type = RTC_BUFFER(RTC_BUFFER_TYPE_VERTEX, t); + const float3 *verts; + if(t == t_mid || attr_mP == NULL) { + verts = &mesh->curve_keys[0]; + } else { + int t_ = (t > t_mid) ? (t - 1) : t; + verts = &attr_mP->data_float3()[t_ * num_keys]; + } + + float* raw_buffer = (float*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT4, sizeof (float) * 4, num_keys); + assert(raw_buffer); + if(raw_buffer) { + float4 *rtc_verts = (float4*) raw_buffer; + if(use_curves) { + const size_t num_curves = mesh->num_curves(); + for (size_t j = 0; j < num_curves; j++) { + Mesh::Curve c = mesh->get_curve(j); + if(c.num_segments() > 0) { + const int& fk = c.first_key; + /* Create Embree's cubic splines that equal the cardinal splines that cycles uses */ + //static float fc = 1.0f / ((0.29f - 1.0f) * 6.0f); + const float fc = -0.2347417840375f; + rtc_verts[0] = float3_to_float4(verts[fk]); + rtc_verts[0].w = curve_radius[fk]; + rtc_verts[1] = float3_to_float4(-fc * (verts[fk + 1] - verts[fk]) + verts[fk]); + rtc_verts[1].w = lerp(curve_radius[fk], curve_radius[fk + 1], 0.33f); + size_t k = 1; + for (; k < c.num_segments(); k++) { + const float3 d = (verts[fk + k + 1] - verts[fk + k - 1]); + rtc_verts[k * 3 - 1] = float3_to_float4(fc * d + verts[fk + k]); + rtc_verts[k * 3 - 1].w = lerp(curve_radius[fk + k - 1], curve_radius[fk + k], 0.66f); + rtc_verts[k * 3] = float3_to_float4(verts[fk + k]); + rtc_verts[k * 3].w = curve_radius[fk + k]; + rtc_verts[k * 3 + 1] = float3_to_float4(-fc * d + verts[fk + k]); + rtc_verts[k * 3 + 1].w = lerp(curve_radius[fk + k], curve_radius[fk + k + 1], 0.33f); + } + rtc_verts[k * 3 - 1] = float3_to_float4(fc * (verts[fk + k] - verts[fk + k - 1]) + verts[fk + k]); + rtc_verts[k * 3 - 1].w = lerp(curve_radius[fk + k - 1], curve_radius[fk + k], 0.66f); + rtc_verts[k * 3] = float3_to_float4(verts[fk + k]); + rtc_verts[k * 3].w = curve_radius[fk + k]; + rtc_verts += c.num_segments()*3 + 1; + } + else { + assert(0); + } + } + } + else { + for (size_t j = 0; j < num_keys; j++) { + rtc_verts[j] = float3_to_float4(verts[j]); + rtc_verts[j].w = curve_radius[j]; + } + } + + } } } -void BVHEmbree::add_curves(Object* ob, int i) { +void BVHEmbree::add_curves(Object* ob, int i) +{ size_t prim_offset = pack.prim_index.size(); Mesh *mesh = ob->mesh; const Attribute *attr_mP = NULL; size_t num_motion_steps = 1; - if (mesh->has_motion_blur()) { - attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if (attr_mP) { - num_motion_steps = mesh->motion_steps; - } + if(mesh->has_motion_blur()) { + attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if(attr_mP) { + num_motion_steps = mesh->motion_steps; + } } const size_t num_curves = mesh->num_curves(); size_t num_keys = 0; size_t num_segments = 0; for (size_t j = 0; j < num_curves; j++) { - Mesh::Curve c = mesh->get_curve(j); - if (c.num_segments() > 0) { - num_segments += c.num_segments(); - num_keys += use_curves ? (c.num_segments() * 3 + 1) : c.num_keys; - } else { - assert(0); - } + Mesh::Curve c = mesh->get_curve(j); + if(c.num_segments() > 0) { + num_segments += c.num_segments(); + num_keys += use_curves ? (c.num_segments() * 3 + 1) : c.num_keys; + } + else { + assert(0); + } } /* Make room for Cycles specific data */ @@ -684,71 +643,63 @@ void BVHEmbree::add_curves(Object* ob, int i) { pack.prim_index.reserve(pack.prim_index.size() + num_segments); pack.prim_tri_index.reserve(pack.prim_index.size() + num_segments); - RTCGeometry geom_id; // = i * 2 + 1; - if (use_curves) { - // RTCGeometry geom_2; - - /* curve segments */ - if (use_ribbons) { - geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE); // EMBREE_FIXME: check if geometry gets properly committed - - } else { - geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE); // EMBREE_FIXME: check if geometry gets properly committed - - } - rtcSetGeometryTessellationRate(geom_id, curve_subdivisions); - - /* Split the Cycles curves into Embree hair segments, each with 4 CVs */ - // void* raw_buffer = rtcGetGeometryBufferData(geom_id, RTC_BUFFER_TYPE_INDEX, 0) /* EMBREE_FIXME: check if this should be rtcSetNewGeometryBuffer */; - // unsigned *rtc_indices = (unsigned*) raw_buffer; - unsigned *rtc_indices = (unsigned*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof (int), num_segments); - size_t rtc_index = 0; - size_t curve_start = 0; - for (size_t j = 0; j < num_curves; j++) { - Mesh::Curve c = mesh->get_curve(j); - for (size_t k = 0; k < c.num_segments(); k++) { - rtc_indices[rtc_index] = curve_start; - curve_start += 3; - /* Cycles specific data */ - pack.prim_object.push_back_reserved(i); - pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(num_motion_steps > 1 ? PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k)); - pack.prim_index.push_back_reserved(j); - pack.prim_tri_index.push_back_reserved(rtc_index); - - rtc_index++; - } - curve_start += 1; - } - - - - } else { - geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE); // EMBREE_FIXME: check if geometry gets properly committed - - /* Split the Cycles curves into Embree line segments, each with 2 CVs */ - //void* raw_buffer = rtcGetGeometryBufferData(geom_id, RTC_BUFFER_TYPE_INDEX, 0) /* EMBREE_FIXME: check if this should be rtcSetNewGeometryBuffer */; - //unsigned *rtc_indices = (unsigned*) raw_buffer; - unsigned *rtc_indices = (unsigned*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof (int), num_segments); - size_t rtc_index = 0; - for (size_t j = 0; j < num_curves; j++) { - Mesh::Curve c = mesh->get_curve(j); - for (size_t k = 0; k < c.num_segments(); k++) { - rtc_indices[rtc_index] = c.first_key + k; - /* Cycles specific data */ - pack.prim_object.push_back_reserved(i); - pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(num_motion_steps > 1 ? PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k)); - pack.prim_index.push_back_reserved(j); - pack.prim_tri_index.push_back_reserved(rtc_index); - - rtc_index++; - } - - } + RTCGeometry geom_id; + if(use_curves) { + /* curve segments */ + if(use_ribbons) { + geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE); + } + else { + geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE); + } + rtcSetGeometryTessellationRate(geom_id, curve_subdivisions); + + /* Split the Cycles curves into Embree hair segments, each with 4 CVs */ + unsigned *rtc_indices = (unsigned*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof (int), num_segments); + size_t rtc_index = 0; + size_t curve_start = 0; + for (size_t j = 0; j < num_curves; j++) { + Mesh::Curve c = mesh->get_curve(j); + for (size_t k = 0; k < c.num_segments(); k++) { + rtc_indices[rtc_index] = curve_start; + curve_start += 3; + /* Cycles specific data */ + pack.prim_object.push_back_reserved(i); + pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(num_motion_steps > 1 ? PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k)); + pack.prim_index.push_back_reserved(j); + pack.prim_tri_index.push_back_reserved(rtc_index); + + rtc_index++; + } + curve_start += 1; + } + + + + } + else { + geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE); // EMBREE_FIXME: check if geometry gets properly committed + + /* Split the Cycles curves into Embree line segments, each with 2 CVs */ + unsigned *rtc_indices = (unsigned*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof (int), num_segments); + size_t rtc_index = 0; + for (size_t j = 0; j < num_curves; j++) { + Mesh::Curve c = mesh->get_curve(j); + for (size_t k = 0; k < c.num_segments(); k++) { + rtc_indices[rtc_index] = c.first_key + k; + /* Cycles specific data */ + pack.prim_object.push_back_reserved(i); + pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(num_motion_steps > 1 ? PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k)); + pack.prim_index.push_back_reserved(j); + pack.prim_tri_index.push_back_reserved(rtc_index); + + rtc_index++; + } + } } update_curve_vertex_buffer(geom_id, mesh); - - + rtcSetGeometryBuildQuality(geom_id, params.bvh_type == SceneParams::BVH_DYNAMIC ? RTC_BUILD_QUALITY_REFIT : RTC_BUILD_QUALITY_MEDIUM); rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); @@ -756,26 +707,24 @@ void BVHEmbree::add_curves(Object* ob, int i) { rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_func); rtcSetGeometryMask(geom_id, ob->visibility); - rtcCommitGeometry(geom_id); rtcAttachGeometryByID(scene, geom_id, i * 2 + 1); rtcReleaseGeometry(geom_id); - - //return geom_id; } -void BVHEmbree::pack_nodes(const BVHNode *) { - if (!params.top_level) { - return; +void BVHEmbree::pack_nodes(const BVHNode *) +{ + if(!params.top_level) { + return; } for (size_t i = 0; i < pack.prim_index.size(); i++) { - if (pack.prim_index[i] != -1) { - if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE) - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset; - else - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; - } + if(pack.prim_index[i] != -1) { + if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE) + pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset; + else + pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; + } } size_t prim_offset = pack.prim_index.size(); @@ -791,16 +740,16 @@ void BVHEmbree::pack_nodes(const BVHNode *) { map<Mesh*, int> mesh_map; foreach(Object *ob, objects) { - Mesh *mesh = ob->mesh; - BVH *bvh = mesh->bvh; + Mesh *mesh = ob->mesh; + BVH *bvh = mesh->bvh; - if (mesh->need_build_bvh()) { - if (mesh_map.find(mesh) == mesh_map.end()) { - prim_index_size += bvh->pack.prim_index.size(); - prim_tri_verts_size += bvh->pack.prim_tri_verts.size(); - mesh_map[mesh] = 1; - } - } + if(mesh->need_build_bvh()) { + if(mesh_map.find(mesh) == mesh_map.end()) { + prim_index_size += bvh->pack.prim_index.size(); + prim_tri_verts_size += bvh->pack.prim_tri_verts.size(); + mesh_map[mesh] = 1; + } + } } mesh_map.clear(); @@ -821,100 +770,99 @@ void BVHEmbree::pack_nodes(const BVHNode *) { uint *pack_prim_tri_index = (pack.prim_tri_index.size()) ? &pack.prim_tri_index[0] : NULL; /* merge */ - // unsigned geom_id = 0; - foreach(Object *ob, objects) { - // geom_id += 2; - Mesh *mesh = ob->mesh; - - /* We assume that if mesh doesn't need own BVH it was already included - * into a top-level BVH and no packing here is needed. - */ - if (!mesh->need_build_bvh()) { - pack.object_node[object_offset++] = prim_offset; - continue; - } - - /* if mesh already added once, don't add it again, but used set - * node offset for this object */ - map<Mesh*, int>::iterator it = mesh_map.find(mesh); - - if (mesh_map.find(mesh) != mesh_map.end()) { - int noffset = it->second; - pack.object_node[object_offset++] = noffset; - continue; - } - - BVHEmbree *bvh = (BVHEmbree*) mesh->bvh; - - mem_monitor(bvh->mem_used); - - int mesh_tri_offset = mesh->tri_offset; - int mesh_curve_offset = mesh->curve_offset; - - /* fill in node indexes for instances */ - if (bvh->pack.root_index == -1) - pack.object_node[object_offset++] = prim_offset; //todo (Stefan) - else - pack.object_node[object_offset++] = prim_offset; // todo (Stefan) - - mesh_map[mesh] = pack.object_node[object_offset - 1]; - - /* merge primitive, object and triangle indexes */ - if (bvh->pack.prim_index.size()) { - size_t bvh_prim_index_size = bvh->pack.prim_index.size(); - int *bvh_prim_index = &bvh->pack.prim_index[0]; - int *bvh_prim_type = &bvh->pack.prim_type[0]; - uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0]; - uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0]; - - for (size_t i = 0; i < bvh_prim_index_size; i++) { - if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) { - pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset; - pack_prim_tri_index[pack_prim_index_offset] = -1; - } else { - pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; - pack_prim_tri_index[pack_prim_index_offset] = - bvh_prim_tri_index[i] + pack_prim_tri_verts_offset; - } - - pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i]; - pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i]; - pack_prim_object[pack_prim_index_offset] = 0; // unused for instances - - pack_prim_index_offset++; - } - } - - /* Merge triangle vertices data. */ - if (bvh->pack.prim_tri_verts.size()) { - const size_t prim_tri_size = bvh->pack.prim_tri_verts.size(); - memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset, - &bvh->pack.prim_tri_verts[0], - prim_tri_size * sizeof (float4)); - pack_prim_tri_verts_offset += prim_tri_size; - } - - prim_offset += bvh->pack.prim_index.size(); + Mesh *mesh = ob->mesh; + + /* We assume that if mesh doesn't need own BVH it was already included + * into a top-level BVH and no packing here is needed. + */ + if(!mesh->need_build_bvh()) { + pack.object_node[object_offset++] = prim_offset; + continue; + } + + /* if mesh already added once, don't add it again, but used set + * node offset for this object */ + map<Mesh*, int>::iterator it = mesh_map.find(mesh); + + if(mesh_map.find(mesh) != mesh_map.end()) { + int noffset = it->second; + pack.object_node[object_offset++] = noffset; + continue; + } + + BVHEmbree *bvh = (BVHEmbree*) mesh->bvh; + + mem_monitor(bvh->mem_used); + + int mesh_tri_offset = mesh->tri_offset; + int mesh_curve_offset = mesh->curve_offset; + + /* fill in node indexes for instances */ + if(bvh->pack.root_index == -1) + pack.object_node[object_offset++] = prim_offset; //todo (Stefan) + else + pack.object_node[object_offset++] = prim_offset; // todo (Stefan) + + mesh_map[mesh] = pack.object_node[object_offset - 1]; + + /* merge primitive, object and triangle indexes */ + if(bvh->pack.prim_index.size()) { + size_t bvh_prim_index_size = bvh->pack.prim_index.size(); + int *bvh_prim_index = &bvh->pack.prim_index[0]; + int *bvh_prim_type = &bvh->pack.prim_type[0]; + uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0]; + uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0]; + + for (size_t i = 0; i < bvh_prim_index_size; i++) { + if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) { + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset; + pack_prim_tri_index[pack_prim_index_offset] = -1; + } + else { + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; + pack_prim_tri_index[pack_prim_index_offset] = + bvh_prim_tri_index[i] + pack_prim_tri_verts_offset; + } + + pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i]; + pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i]; + pack_prim_object[pack_prim_index_offset] = 0; // unused for instances + + pack_prim_index_offset++; + } + } + + /* Merge triangle vertices data. */ + if(bvh->pack.prim_tri_verts.size()) { + const size_t prim_tri_size = bvh->pack.prim_tri_verts.size(); + memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset, + &bvh->pack.prim_tri_verts[0], + prim_tri_size * sizeof (float4)); + pack_prim_tri_verts_offset += prim_tri_size; + } + + prim_offset += bvh->pack.prim_index.size(); } } -void BVHEmbree::refit_nodes() { +void BVHEmbree::refit_nodes() +{ unsigned geom_id = 0; foreach(Object *ob, objects) { - if (!params.top_level || (ob->is_traceable() && !ob->mesh->is_instanced())) { - if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) { - update_tri_vertex_buffer(rtcGetGeometry(scene, geom_id), ob->mesh); - rtcCommitGeometry(rtcGetGeometry(scene, geom_id)); - } - - if (params.primitive_mask & PRIMITIVE_ALL_CURVE && ob->mesh->num_curves() > 0) { - update_curve_vertex_buffer(rtcGetGeometry(scene, geom_id + 1), ob->mesh); - rtcCommitGeometry(rtcGetGeometry(scene, geom_id + 1)); - } - } - geom_id += 2; + if(!params.top_level || (ob->is_traceable() && !ob->mesh->is_instanced())) { + if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) { + update_tri_vertex_buffer(rtcGetGeometry(scene, geom_id), ob->mesh); + rtcCommitGeometry(rtcGetGeometry(scene, geom_id)); + } + + if(params.primitive_mask & PRIMITIVE_ALL_CURVE && ob->mesh->num_curves() > 0) { + update_curve_vertex_buffer(rtcGetGeometry(scene, geom_id + 1), ob->mesh); + rtcCommitGeometry(rtcGetGeometry(scene, geom_id + 1)); + } + } + geom_id += 2; } rtcCommitScene(scene); } diff --git a/intern/cycles/bvh/bvh_embree.h b/intern/cycles/bvh/bvh_embree.h index b5ddc5407aa26ea7c6caa4607d8e6e4194fe2337..249eed8e021898cdb5e66e8890e97b1ccca50741 100644 --- a/intern/cycles/bvh/bvh_embree.h +++ b/intern/cycles/bvh/bvh_embree.h @@ -33,9 +33,10 @@ CCL_NAMESPACE_BEGIN class Mesh; -class BVHEmbree : public BVH { +class BVHEmbree : public BVH +{ public: - void build(Progress& progress); + void build(Progress& progress, Stats *stats); virtual ~BVHEmbree(); RTCScene scene; static void destroy(RTCScene); @@ -55,9 +56,7 @@ protected: ssize_t mem_used; - void add_delayed_delete_scene(RTCScene scene) { - delayed_delete_scenes.push_back(scene); - } + void add_delayed_delete_scene(RTCScene scene) { delayed_delete_scenes.push_back(scene); } BVHEmbree *top_level; private: void delete_rtcScene(); @@ -68,7 +67,7 @@ private: static int rtc_shared_users; static thread_mutex rtc_shared_mutex; - // Stats *stats; + Stats *stats; vector<RTCScene> delayed_delete_scenes; int curve_subdivisions; bool use_curves, use_ribbons, dynamic_scene; diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index f18c5e51fab5935a2010f7d5f4c71186f6b3fe8b..f80fa53f2ec2d4b167fb7d7ed4c5d90f6354515d 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -90,8 +90,10 @@ public: /* Same as above, but for triangle primitives. */ int num_motion_triangle_steps; + /* Same as in SceneParams. */ + int bvh_type; + /* These are needed for Embree. */ - int bvh_type; int curve_flags; int curve_subdivisions; @@ -129,7 +131,8 @@ public: num_motion_curve_steps = 0; num_motion_triangle_steps = 0; - bvh_type = 0; + bvh_type = 0; + curve_flags = 0; curve_subdivisions = 4; } diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 9beb330355d24aadd662b91c3bfd2d7b512ab2d5..fa1ee032efed3c473e9f72099ffb7163263c0a5d 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -692,6 +692,9 @@ public: int start_sample = tile.start_sample; int end_sample = tile.start_sample + tile.num_samples; + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); + for(int sample = start_sample; sample < end_sample; sample++) { if(task.get_cancel() || task_pool.canceled()) { if(task.need_finish_queue == false) @@ -1050,11 +1053,9 @@ void device_cpu_info(vector<DeviceInfo>& devices) if (system_cpu_support_sse2()) { info.bvh_layout_mask |= BVH_LAYOUT_BVH4; } - #ifdef WITH_EMBREE info.bvh_layout_mask |= BVH_LAYOUT_EMBREE; -#endif - +#endif /* WITH_EMBREE */ info.has_volume_decoupled = true; info.has_osl = true; info.has_half_images = true; diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp index a3a8fa5f382dcbf807c5ac120e2f2c1668f94136..37aae211e93e692b2c36ec708b2c5333cc474904 100644 --- a/intern/cycles/graph/node_type.cpp +++ b/intern/cycles/graph/node_type.cpp @@ -77,7 +77,7 @@ size_t SocketType::max_size() void *SocketType::zero_default_value() { - static Transform zero_transform = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}; + static Transform zero_transform = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}; return &zero_transform; } diff --git a/intern/cycles/graph/node_xml.cpp b/intern/cycles/graph/node_xml.cpp index d26b3b2c2c885dc66984bb94e5dd5ad0e7b332be..f4599e22d40f16887b20904d4d5c4adecc607d61 100644 --- a/intern/cycles/graph/node_xml.cpp +++ b/intern/cycles/graph/node_xml.cpp @@ -196,7 +196,7 @@ void xml_read_node(XMLReader& reader, Node *node, xml_node xml_node) case SocketType::TRANSFORM: { array<Transform> value; - xml_read_float_array<16>(value, attr); + xml_read_float_array<12>(value, attr); if(value.size() == 1) { node->set(socket, value[0]); } @@ -205,7 +205,7 @@ void xml_read_node(XMLReader& reader, Node *node, xml_node xml_node) case SocketType::TRANSFORM_ARRAY: { array<Transform> value; - xml_read_float_array<16>(value, attr); + xml_read_float_array<12>(value, attr); node->set(socket, value); break; } @@ -400,12 +400,10 @@ xml_node xml_write_node(Node *node, xml_node xml_root) { Transform tfm = node->get_transform(socket); std::stringstream ss; - for(int i = 0; i < 4; i++) { - ss << string_printf("%g %g %g %g", (double)tfm[i][0], (double)tfm[i][1], (double)tfm[i][2], (double)tfm[i][3]); - if(i != 3) { - ss << " "; - } + for(int i = 0; i < 3; i++) { + ss << string_printf("%g %g %g %g ", (double)tfm[i][0], (double)tfm[i][1], (double)tfm[i][2], (double)tfm[i][3]); } + ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0); attr = ss.str().c_str(); break; } @@ -416,11 +414,12 @@ xml_node xml_write_node(Node *node, xml_node xml_root) for(size_t j = 0; j < value.size(); j++) { const Transform& tfm = value[j]; - for(int i = 0; i < 4; i++) { - ss << string_printf("%g %g %g %g", (double)tfm[i][0], (double)tfm[i][1], (double)tfm[i][2], (double)tfm[i][3]); - if(j != value.size() - 1 || i != 3) { - ss << " "; - } + for(int i = 0; i < 3; i++) { + ss << string_printf("%g %g %g %g ", (double)tfm[i][0], (double)tfm[i][1], (double)tfm[i][2], (double)tfm[i][3]); + } + ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0); + if(j != value.size() - 1) { + ss << " "; } } attr = ss.str().c_str(); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 50ea03a1f8f48a78a7c2a6ab3ea00270a5f5cd06..9b7f4e00084e62c5e44f7eafa86801b89e6cf924 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -254,6 +254,7 @@ set(SRC_UTIL_HEADERS ../util/util_math_int3.h ../util/util_math_int4.h ../util/util_math_matrix.h + ../util/util_projection.h ../util/util_rect.h ../util/util_static_assert.h ../util/util_transform.h diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h index baa9d3642c9eae5b814f2a6711598ad0b21f9c38..02494b4b32cf2ab78e6fda70e1395992cf5aa9f3 100644 --- a/intern/cycles/kernel/bvh/bvh.h +++ b/intern/cycles/kernel/bvh/bvh.h @@ -175,15 +175,12 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg, isect->t = ray.t; CCLRay rtc_ray(ray, kg, visibility, CCLRay::RAY_REGULAR); - IntersectContext context; - InitIntersectContext(&context); context.userRayExt=&rtc_ray; + IntersectContext context; + InitIntersectContext(&context); + context.userRayExt = &rtc_ray; rtcIntersect1(kernel_data.bvh.scene, &context.context, (RTCRayHit*) &rtc_ray); - - rtc_ray.hit.Ng_x = -rtc_ray.hit.Ng_x; // EMBREE_FIXME: only correct for triangles,quads, and subdivision surfaces - rtc_ray.hit.Ng_y = -rtc_ray.hit.Ng_y; - rtc_ray.hit.Ng_z = -rtc_ray.hit.Ng_z; - + if(rtc_ray.hit.geomID != RTC_INVALID_GEOMETRY_ID && rtc_ray.hit.primID != RTC_INVALID_GEOMETRY_ID) { rtc_ray.isect_to_ccl(isect); return true; @@ -244,10 +241,11 @@ ccl_device_intersect void scene_intersect_local(KernelGlobals *kg, local_isect->num_hits = 0; rtc_ray.sss_object_id = local_object; - IntersectContext context; - InitIntersectContext(&context); context.userRayExt=&rtc_ray; + IntersectContext context; + InitIntersectContext(&context); + context.userRayExt = &rtc_ray; - rtcOccluded1(kernel_data.bvh.scene, &context.context, (RTCRay*) &rtc_ray); // EMBREE_FIXME: rtc_ray is occluded when rtc_ray.tfar < 0.0f + rtcOccluded1(kernel_data.bvh.scene, &context.context, (RTCRay*) &rtc_ray); return; } @@ -286,10 +284,11 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, rtc_ray.max_hits = max_hits; rtc_ray.num_hits = 0; - IntersectContext context; - InitIntersectContext(&context); context.userRayExt=&rtc_ray; + IntersectContext context; + InitIntersectContext(&context); + context.userRayExt = &rtc_ray; - rtcOccluded1(kernel_data.bvh.scene, &context.context, (RTCRay*) &rtc_ray); //EMBREE_FIXME: rtc_ray is occluded when rtc_ray.tfar < 0.0f + rtcOccluded1(kernel_data.bvh.scene, &context.context, (RTCRay*) &rtc_ray); if(rtc_ray.num_hits > max_hits) { return true; @@ -396,11 +395,11 @@ ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg, rtc_ray.max_hits = max_hits; rtc_ray.num_hits = 0; - IntersectContext context; - InitIntersectContext(&context); context.userRayExt=&rtc_ray; - - rtcOccluded1(kernel_data.bvh.scene, &context.context, (RTCRay*) &rtc_ray); // EMBREE_FIXME: rtc_ray is occluded when rtc_ray.tfar < 0.0f + IntersectContext context; + InitIntersectContext(&context); + context.userRayExt = &rtc_ray; + rtcOccluded1(kernel_data.bvh.scene, &context.context, (RTCRay*) &rtc_ray); return rtc_ray.num_hits; } #endif diff --git a/intern/cycles/kernel/bvh/bvh_embree_traversal.h b/intern/cycles/kernel/bvh/bvh_embree_traversal.h index 217bcad0a88533c8049b0c68b4c3e71d6680006a..70ed82c42991f56fb15925bed242d2f5dfcc1709 100644 --- a/intern/cycles/kernel/bvh/bvh_embree_traversal.h +++ b/intern/cycles/kernel/bvh/bvh_embree_traversal.h @@ -18,79 +18,80 @@ #include "embree3/rtcore_scene.h" struct RTC_ALIGN(16) CCLRay : public RTCRayHit { + typedef enum { + RAY_REGULAR = 0, + RAY_SHADOW_ALL = 1, + RAY_SSS = 2, + RAY_VOLUME_ALL = 3, - typedef enum { - RAY_REGULAR = 0, - RAY_SHADOW_ALL = 1, - RAY_SSS = 2, - RAY_VOLUME_ALL = 3, + } RayType; - } RayType; + // cycles extensions: + ccl::KernelGlobals *kg; + RayType type; - // cycles extensions: - ccl::KernelGlobals *kg; - RayType type; + // for shadow rays + ccl::Intersection *isect_s; + int max_hits; + int num_hits; - // for shadow rays - ccl::Intersection *isect_s; - int max_hits; - int num_hits; + // for SSS Rays: + ccl::LocalIntersection *ss_isect; + int sss_object_id; + ccl::uint *lcg_state; - // for SSS Rays: - ccl::LocalIntersection *ss_isect; - int sss_object_id; - ccl::uint *lcg_state; + CCLRay(const ccl::Ray& ccl_ray, ccl::KernelGlobals *kg_, const ccl::uint visibility, RayType type_) + { + ray.org_x = ccl_ray.P.x; + ray.org_y = ccl_ray.P.y; + ray.org_z = ccl_ray.P.z; + ray.dir_x = ccl_ray.D.x; + ray.dir_y = ccl_ray.D.y; + ray.dir_z = ccl_ray.D.z; + ray.tnear = 0.0f; + ray.tfar = ccl_ray.t; + ray.time = ccl_ray.time; + ray.mask = visibility; + hit.geomID = hit.primID = hit.instID[0] = RTC_INVALID_GEOMETRY_ID; - CCLRay(const ccl::Ray& ccl_ray, ccl::KernelGlobals *kg_, const ccl::uint visibility, RayType type_) { - ray.org_x = ccl_ray.P.x; - ray.org_y = ccl_ray.P.y; - ray.org_z = ccl_ray.P.z; - ray.dir_x = ccl_ray.D.x; - ray.dir_y = ccl_ray.D.y; - ray.dir_z = ccl_ray.D.z; - ray.tnear = 0.0f; - ray.tfar = ccl_ray.t; - ray.time = ccl_ray.time; - ray.mask = visibility; - hit.geomID = hit.primID = hit.instID[0] = RTC_INVALID_GEOMETRY_ID; - - kg = kg_; - type = type_; - max_hits = 1; - num_hits = 0; - isect_s = NULL; - ss_isect = NULL; - sss_object_id = -1; - lcg_state = NULL; - } - - void isect_to_ccl(ccl::Intersection * isect) { - bool is_hair = hit.geomID & 1; - isect->u = is_hair ? hit.u : 1.0f - hit.v - hit.u; - isect->v = is_hair ? hit.v : hit.u; - isect->t = ray.tfar; - isect->Ng = ccl::make_float3(hit.Ng_x, hit.Ng_y, hit.Ng_z); - if (hit.instID[0] != RTC_INVALID_GEOMETRY_ID) { - RTCScene inst_scene = (RTCScene) rtcGetGeometryUserData(rtcGetGeometry(kernel_data.bvh.scene, hit.instID[0])); - isect->prim = hit.primID + (intptr_t) rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit.geomID)) + kernel_tex_fetch(__object_node, hit.instID[0] / 2); - isect->object = hit.instID[0] / 2; - } else { - isect->prim = hit.primID + (intptr_t) rtcGetGeometryUserData(rtcGetGeometry(kernel_data.bvh.scene, hit.geomID)); - isect->object = OBJECT_NONE; + kg = kg_; + type = type_; + max_hits = 1; + num_hits = 0; + isect_s = NULL; + ss_isect = NULL; + sss_object_id = -1; + lcg_state = NULL; } - isect->type = kernel_tex_fetch(__prim_type, isect->prim); - } + + void isect_to_ccl(ccl::Intersection * isect) + { + bool is_hair = hit.geomID & 1; + isect->u = is_hair ? hit.u : 1.0f - hit.v - hit.u; + isect->v = is_hair ? hit.v : hit.u; + isect->t = ray.tfar; + isect->Ng = ccl::make_float3(hit.Ng_x, hit.Ng_y, hit.Ng_z); + if (hit.instID[0] != RTC_INVALID_GEOMETRY_ID) { + RTCScene inst_scene = (RTCScene) rtcGetGeometryUserData(rtcGetGeometry(kernel_data.bvh.scene, hit.instID[0])); + isect->prim = hit.primID + (intptr_t) rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit.geomID)) + kernel_tex_fetch(__object_node, hit.instID[0] / 2); + isect->object = hit.instID[0] / 2; + } else { + isect->prim = hit.primID + (intptr_t) rtcGetGeometryUserData(rtcGetGeometry(kernel_data.bvh.scene, hit.geomID)); + isect->object = OBJECT_NONE; + } + isect->type = kernel_tex_fetch(__prim_type, isect->prim); + } }; -/*! intersection context passed to intersect/occluded calls */ +/* Intersection context passed to intersect/occluded calls */ struct IntersectContext { RTCIntersectContext context; - void* userRayExt; //!< can be used to pass extended ray data to callbacks + void* userRayExt; }; __forceinline void InitIntersectContext(struct IntersectContext* context) { rtcInitIntersectContext(&context->context); context->userRayExt = NULL; -}; \ No newline at end of file +}; diff --git a/intern/cycles/kernel/bvh/bvh_nodes.h b/intern/cycles/kernel/bvh/bvh_nodes.h index 6c33dad5426e96da948993a173260137d447b09f..060b3934a41c26ee1a730e13bed87951d5002203 100644 --- a/intern/cycles/kernel/bvh/bvh_nodes.h +++ b/intern/cycles/kernel/bvh/bvh_nodes.h @@ -25,7 +25,6 @@ ccl_device_forceinline Transform bvh_unaligned_node_fetch_space(KernelGlobals *k space.x = kernel_tex_fetch(__bvh_nodes, child_addr+1); space.y = kernel_tex_fetch(__bvh_nodes, child_addr+2); space.z = kernel_tex_fetch(__bvh_nodes, child_addr+3); - space.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); return space; } diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h index efd6798ca5180d27a6bca3c977ae8db763e93a9d..cfc567ff9ca47db729e6fbf979071acf4c84e5b4 100644 --- a/intern/cycles/kernel/bvh/bvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h @@ -276,7 +276,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, shader = __float_as_int(str.z); } #endif - int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*SHADER_SIZE); + int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags; /* if no transparent shadows, all light is blocked */ if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) { diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h index 522213f30ca4151e3fa94af5c07c7b2a1342e296..46fd178aed6bd32ef6bafd138b8cce977d0e794c 100644 --- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h @@ -358,7 +358,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, shader = __float_as_int(str.z); } #endif - int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*SHADER_SIZE); + int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags; /* if no transparent shadows, all light is blocked */ if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) { diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h index c72595eed10f8f0083add53990ece92884069147..42c053704d546c8ded41011ca8e0df866388f90c 100644 --- a/intern/cycles/kernel/geom/geom_attribute.h +++ b/intern/cycles/kernel/geom/geom_attribute.h @@ -53,9 +53,7 @@ ccl_device_inline AttributeDescriptor attribute_not_found() ccl_device_inline uint object_attribute_map_offset(KernelGlobals *kg, int object) { - int offset = object*OBJECT_SIZE + 15; - float4 f = kernel_tex_fetch(__objects, offset); - return __float_as_uint(f.y); + return kernel_tex_fetch(__objects, object).attribute_map_offset; } ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id) @@ -105,7 +103,6 @@ ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderD tfm.x = kernel_tex_fetch(__attributes_float3, desc.offset + 0); tfm.y = kernel_tex_fetch(__attributes_float3, desc.offset + 1); tfm.z = kernel_tex_fetch(__attributes_float3, desc.offset + 2); - tfm.w = kernel_tex_fetch(__attributes_float3, desc.offset + 3); return tfm; } diff --git a/intern/cycles/kernel/geom/geom_curve_intersect.h b/intern/cycles/kernel/geom/geom_curve_intersect.h index d979d456959d8184f15a99535cc7c3d207476b4e..c03cd5ca9dd8ea782e25b2efe38a9754df19e394 100644 --- a/intern/cycles/kernel/geom/geom_curve_intersect.h +++ b/intern/cycles/kernel/geom/geom_curve_intersect.h @@ -170,8 +170,7 @@ ccl_device_forceinline bool cardinal_curve_intersect( htfm = make_transform( dir.z / d, 0, -dir.x /d, 0, -dir.x * dir.y /d, d, -dir.y * dir.z /d, 0, - dir.x, dir.y, dir.z, 0, - 0, 0, 0, 1); + dir.x, dir.y, dir.z, 0); float4 v00 = kernel_tex_fetch(__curves, prim); diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index 5f5882065eec89a1600149f106e056f3a5d5673c..22a3fd6c9aca1228c9e1881c4e3d13c43b93e775 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -28,62 +28,44 @@ CCL_NAMESPACE_BEGIN enum ObjectTransform { OBJECT_TRANSFORM = 0, - OBJECT_INVERSE_TRANSFORM = 4, - OBJECT_TRANSFORM_MOTION_PRE = 0, - OBJECT_TRANSFORM_MOTION_MID = 4, - OBJECT_TRANSFORM_MOTION_POST = 8, - OBJECT_PROPERTIES = 12, - OBJECT_DUPLI = 13 + OBJECT_INVERSE_TRANSFORM = 1, }; enum ObjectVectorTransform { - OBJECT_VECTOR_MOTION_PRE = 0, - OBJECT_VECTOR_MOTION_POST = 3 + OBJECT_PASS_MOTION_PRE = 0, + OBJECT_PASS_MOTION_POST = 1 }; /* Object to world space transformation */ ccl_device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type) { - int offset = object*OBJECT_SIZE + (int)type; - - Transform tfm; - tfm.x = kernel_tex_fetch(__objects, offset + 0); - tfm.y = kernel_tex_fetch(__objects, offset + 1); - tfm.z = kernel_tex_fetch(__objects, offset + 2); - tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); - - return tfm; + if(type == OBJECT_INVERSE_TRANSFORM) { + return kernel_tex_fetch(__objects, object).itfm; + } + else { + return kernel_tex_fetch(__objects, object).tfm; + } } /* Lamp to world space transformation */ ccl_device_inline Transform lamp_fetch_transform(KernelGlobals *kg, int lamp, bool inverse) { - int offset = lamp*LIGHT_SIZE + (inverse? 8 : 5); - - Transform tfm; - tfm.x = kernel_tex_fetch(__light_data, offset + 0); - tfm.y = kernel_tex_fetch(__light_data, offset + 1); - tfm.z = kernel_tex_fetch(__light_data, offset + 2); - tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); - - return tfm; + if(inverse) { + return kernel_tex_fetch(__lights, lamp).itfm; + } + else { + return kernel_tex_fetch(__lights, lamp).tfm; + } } /* Object to world space transformation for motion vectors */ -ccl_device_inline Transform object_fetch_vector_transform(KernelGlobals *kg, int object, enum ObjectVectorTransform type) +ccl_device_inline Transform object_fetch_motion_pass_transform(KernelGlobals *kg, int object, enum ObjectVectorTransform type) { - int offset = object*OBJECT_VECTOR_SIZE + (int)type; - - Transform tfm; - tfm.x = kernel_tex_fetch(__objects_vector, offset + 0); - tfm.y = kernel_tex_fetch(__objects_vector, offset + 1); - tfm.z = kernel_tex_fetch(__objects_vector, offset + 2); - tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); - - return tfm; + int offset = object*OBJECT_MOTION_PASS_SIZE + (int)type; + return kernel_tex_fetch(__object_motion_pass, offset); } /* Motion blurred object transformations */ @@ -91,33 +73,18 @@ ccl_device_inline Transform object_fetch_vector_transform(KernelGlobals *kg, int #ifdef __OBJECT_MOTION__ ccl_device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time) { - MotionTransform motion; - - int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE; - - motion.pre.x = kernel_tex_fetch(__objects, offset + 0); - motion.pre.y = kernel_tex_fetch(__objects, offset + 1); - motion.pre.z = kernel_tex_fetch(__objects, offset + 2); - motion.pre.w = kernel_tex_fetch(__objects, offset + 3); - - motion.mid.x = kernel_tex_fetch(__objects, offset + 4); - motion.mid.y = kernel_tex_fetch(__objects, offset + 5); - motion.mid.z = kernel_tex_fetch(__objects, offset + 6); - motion.mid.w = kernel_tex_fetch(__objects, offset + 7); - - motion.post.x = kernel_tex_fetch(__objects, offset + 8); - motion.post.y = kernel_tex_fetch(__objects, offset + 9); - motion.post.z = kernel_tex_fetch(__objects, offset + 10); - motion.post.w = kernel_tex_fetch(__objects, offset + 11); + const uint motion_offset = kernel_tex_fetch(__objects, object).motion_offset; + const ccl_global DecomposedTransform *motion = &kernel_tex_fetch(__object_motion, motion_offset); + const uint num_steps = kernel_tex_fetch(__objects, object).numsteps * 2 + 1; Transform tfm; #ifdef __EMBREE__ if(kernel_data.bvh.scene) { - transform_motion_interpolate_straight(&tfm, &motion, time); + transform_motion_array_interpolate_straight(&tfm, motion, num_steps, time); } else #endif - transform_motion_interpolate(&tfm, &motion, time); + transform_motion_array_interpolate(&tfm, motion, num_steps, time); return tfm; } @@ -243,9 +210,7 @@ ccl_device_inline float3 object_location(KernelGlobals *kg, const ShaderData *sd ccl_device_inline float object_surface_area(KernelGlobals *kg, int object) { - int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES; - float4 f = kernel_tex_fetch(__objects, offset); - return f.x; + return kernel_tex_fetch(__objects, object).surface_area; } /* Pass ID number of object */ @@ -255,9 +220,7 @@ ccl_device_inline float object_pass_id(KernelGlobals *kg, int object) if(object == OBJECT_NONE) return 0.0f; - int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES; - float4 f = kernel_tex_fetch(__objects, offset); - return f.y; + return kernel_tex_fetch(__objects, object).pass_id; } /* Per lamp random number for shader variation */ @@ -267,8 +230,7 @@ ccl_device_inline float lamp_random_number(KernelGlobals *kg, int lamp) if(lamp == LAMP_NONE) return 0.0f; - float4 f = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 4); - return f.y; + return kernel_tex_fetch(__lights, lamp).random; } /* Per object random number for shader variation */ @@ -278,9 +240,7 @@ ccl_device_inline float object_random_number(KernelGlobals *kg, int object) if(object == OBJECT_NONE) return 0.0f; - int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES; - float4 f = kernel_tex_fetch(__objects, offset); - return f.z; + return kernel_tex_fetch(__objects, object).random_number; } /* Particle ID from which this object was generated */ @@ -290,9 +250,7 @@ ccl_device_inline int object_particle_id(KernelGlobals *kg, int object) if(object == OBJECT_NONE) return 0; - int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES; - float4 f = kernel_tex_fetch(__objects, offset); - return __float_as_uint(f.w); + return kernel_tex_fetch(__objects, object).particle_index; } /* Generated texture coordinate on surface from where object was instanced */ @@ -302,9 +260,10 @@ ccl_device_inline float3 object_dupli_generated(KernelGlobals *kg, int object) if(object == OBJECT_NONE) return make_float3(0.0f, 0.0f, 0.0f); - int offset = object*OBJECT_SIZE + OBJECT_DUPLI; - float4 f = kernel_tex_fetch(__objects, offset); - return make_float3(f.x, f.y, f.z); + const ccl_global KernelObject *kobject = &kernel_tex_fetch(__objects, object); + return make_float3(kobject->dupli_generated[0], + kobject->dupli_generated[1], + kobject->dupli_generated[2]); } /* UV texture coordinate on surface from where object was instanced */ @@ -314,27 +273,24 @@ ccl_device_inline float3 object_dupli_uv(KernelGlobals *kg, int object) if(object == OBJECT_NONE) return make_float3(0.0f, 0.0f, 0.0f); - int offset = object*OBJECT_SIZE + OBJECT_DUPLI; - float4 f = kernel_tex_fetch(__objects, offset + 1); - return make_float3(f.x, f.y, 0.0f); + const ccl_global KernelObject *kobject = &kernel_tex_fetch(__objects, object); + return make_float3(kobject->dupli_uv[0], + kobject->dupli_uv[1], + 0.0f); } /* Information about mesh for motion blurred triangles and curves */ ccl_device_inline void object_motion_info(KernelGlobals *kg, int object, int *numsteps, int *numverts, int *numkeys) { - int offset = object*OBJECT_SIZE + OBJECT_DUPLI; - if(numkeys) { - float4 f = kernel_tex_fetch(__objects, offset); - *numkeys = __float_as_int(f.w); + *numkeys = kernel_tex_fetch(__objects, object).numkeys; } - float4 f = kernel_tex_fetch(__objects, offset + 1); if(numsteps) - *numsteps = __float_as_int(f.z); + *numsteps = kernel_tex_fetch(__objects, object).numsteps; if(numverts) - *numverts = __float_as_int(f.w); + *numverts = kernel_tex_fetch(__objects, object).numverts; } /* Offset to an objects patch map */ @@ -344,76 +300,56 @@ ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object) if(object == OBJECT_NONE) return 0; - int offset = object*OBJECT_SIZE + 15; - float4 f = kernel_tex_fetch(__objects, offset); - return __float_as_uint(f.x); + return kernel_tex_fetch(__objects, object).patch_map_offset; } /* Pass ID for shader */ ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd) { - return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE + 1); + return kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).pass_id; } /* Particle data from which object was instanced */ ccl_device_inline uint particle_index(KernelGlobals *kg, int particle) { - int offset = particle*PARTICLE_SIZE; - float4 f = kernel_tex_fetch(__particles, offset + 0); - return __float_as_uint(f.x); + return kernel_tex_fetch(__particles, particle).index; } ccl_device float particle_age(KernelGlobals *kg, int particle) { - int offset = particle*PARTICLE_SIZE; - float4 f = kernel_tex_fetch(__particles, offset + 0); - return f.y; + return kernel_tex_fetch(__particles, particle).age; } ccl_device float particle_lifetime(KernelGlobals *kg, int particle) { - int offset = particle*PARTICLE_SIZE; - float4 f = kernel_tex_fetch(__particles, offset + 0); - return f.z; + return kernel_tex_fetch(__particles, particle).lifetime; } ccl_device float particle_size(KernelGlobals *kg, int particle) { - int offset = particle*PARTICLE_SIZE; - float4 f = kernel_tex_fetch(__particles, offset + 0); - return f.w; + return kernel_tex_fetch(__particles, particle).size; } ccl_device float4 particle_rotation(KernelGlobals *kg, int particle) { - int offset = particle*PARTICLE_SIZE; - float4 f = kernel_tex_fetch(__particles, offset + 1); - return f; + return kernel_tex_fetch(__particles, particle).rotation; } ccl_device float3 particle_location(KernelGlobals *kg, int particle) { - int offset = particle*PARTICLE_SIZE; - float4 f = kernel_tex_fetch(__particles, offset + 2); - return make_float3(f.x, f.y, f.z); + return float4_to_float3(kernel_tex_fetch(__particles, particle).location); } ccl_device float3 particle_velocity(KernelGlobals *kg, int particle) { - int offset = particle*PARTICLE_SIZE; - float4 f2 = kernel_tex_fetch(__particles, offset + 2); - float4 f3 = kernel_tex_fetch(__particles, offset + 3); - return make_float3(f2.w, f3.x, f3.y); + return float4_to_float3(kernel_tex_fetch(__particles, particle).velocity); } ccl_device float3 particle_angular_velocity(KernelGlobals *kg, int particle) { - int offset = particle*PARTICLE_SIZE; - float4 f3 = kernel_tex_fetch(__particles, offset + 3); - float4 f4 = kernel_tex_fetch(__particles, offset + 4); - return make_float3(f3.z, f3.w, f4.x); + return float4_to_float3(kernel_tex_fetch(__particles, particle).angular_velocity); } /* Object intersection in BVH */ diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h index 60a1e483b847056ba968a697af07e10df02e96ef..c159be928856c211d051ef15fc1d2426f7ef88f8 100644 --- a/intern/cycles/kernel/geom/geom_primitive.h +++ b/intern/cycles/kernel/geom/geom_primitive.h @@ -193,10 +193,10 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData * * transformation was set match the world/object space of motion_pre/post */ Transform tfm; - tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE); + tfm = object_fetch_motion_pass_transform(kg, sd->object, OBJECT_PASS_MOTION_PRE); motion_pre = transform_point(&tfm, motion_pre); - tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST); + tfm = object_fetch_motion_pass_transform(kg, sd->object, OBJECT_PASS_MOTION_POST); motion_post = transform_point(&tfm, motion_post); float3 motion_center; @@ -204,14 +204,14 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData * /* camera motion, for perspective/orthographic motion.pre/post will be a * world-to-raster matrix, for panorama it's world-to-camera */ if(kernel_data.cam.type != CAMERA_PANORAMA) { - tfm = kernel_data.cam.worldtoraster; - motion_center = transform_perspective(&tfm, center); + ProjectionTransform projection = kernel_data.cam.worldtoraster; + motion_center = transform_perspective(&projection, center); - tfm = kernel_data.cam.motion.pre; - motion_pre = transform_perspective(&tfm, motion_pre); + projection = kernel_data.cam.perspective_pre; + motion_pre = transform_perspective(&projection, motion_pre); - tfm = kernel_data.cam.motion.post; - motion_post = transform_perspective(&tfm, motion_post); + projection = kernel_data.cam.perspective_post; + motion_post = transform_perspective(&projection, motion_post); } else { tfm = kernel_data.cam.worldtocamera; @@ -220,13 +220,13 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData * motion_center.x *= kernel_data.cam.width; motion_center.y *= kernel_data.cam.height; - tfm = kernel_data.cam.motion.pre; + tfm = kernel_data.cam.motion_pass_pre; motion_pre = normalize(transform_point(&tfm, motion_pre)); motion_pre = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_pre)); motion_pre.x *= kernel_data.cam.width; motion_pre.y *= kernel_data.cam.height; - tfm = kernel_data.cam.motion.post; + tfm = kernel_data.cam.motion_pass_post; motion_post = normalize(transform_point(&tfm, motion_post)); motion_post = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_post)); motion_post.x *= kernel_data.cam.width; diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h index 286d898992e658b251f507c1ce9d7e6bc59b1176..a4e47384b25cbda9cf1fe43cceb0fd539720ef22 100644 --- a/intern/cycles/kernel/geom/geom_volume.h +++ b/intern/cycles/kernel/geom/geom_volume.h @@ -68,7 +68,7 @@ ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *s if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); - if(r.w != 0.0f && r.w != 1.0f) { + if(r.w > 1e-8f && r.w != 1.0f) { /* For RGBA colors, unpremultiply after interpolation. */ return float4_to_float3(r) / r.w; } diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index b3c2450d10e13848ad28943c0da9bbdf5577dfeb..79e6d1b4862ac96130e3f34ce4a09519dc1b6df2 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -330,15 +330,30 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, switch(type) { /* data passes */ case SHADER_EVAL_NORMAL: + case SHADER_EVAL_ROUGHNESS: + case SHADER_EVAL_EMISSION: { - float3 N = sd.N; - if((sd.flag & SD_HAS_BUMP)) { - shader_eval_surface(kg, &sd, &state, 0); - N = shader_bsdf_average_normal(kg, &sd); + if(type != SHADER_EVAL_NORMAL || (sd.flag & SD_HAS_BUMP)) { + int path_flag = (type == SHADER_EVAL_EMISSION) ? PATH_RAY_EMISSION : 0; + shader_eval_surface(kg, &sd, &state, path_flag); } - /* encoding: normal = (2 * color) - 1 */ - out = N * 0.5f + make_float3(0.5f, 0.5f, 0.5f); + if(type == SHADER_EVAL_NORMAL) { + float3 N = sd.N; + if(sd.flag & SD_HAS_BUMP) { + N = shader_bsdf_average_normal(kg, &sd); + } + + /* encoding: normal = (2 * color) - 1 */ + out = N * 0.5f + make_float3(0.5f, 0.5f, 0.5f); + } + else if(type == SHADER_EVAL_ROUGHNESS) { + float roughness = shader_bsdf_average_roughness(&sd); + out = make_float3(roughness, roughness, roughness); + } + else { + out = shader_emissive_eval(kg, &sd); + } break; } case SHADER_EVAL_UV: @@ -346,13 +361,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, out = primitive_uv(kg, &sd); break; } - case SHADER_EVAL_EMISSION: - { - shader_eval_surface(kg, &sd, &state, PATH_RAY_EMISSION); - out = shader_emissive_eval(kg, &sd); - break; - } - #ifdef __PASSES__ /* light passes */ case SHADER_EVAL_AO: diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 96cdb04d95548e43cf62f30223d6b82386717f98..b73ad47dad37b2c8e9c01c8c5d951239fbfa5ce9 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -42,7 +42,7 @@ ccl_device float2 camera_sample_aperture(ccl_constant KernelCamera *cam, float u ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray) { /* create ray form raster position */ - Transform rastertocamera = kernel_data.cam.rastertocamera; + ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera; float3 raster = make_float3(raster_x, raster_y, 0.0f); float3 Pcamera = transform_perspective(&rastertocamera, raster); @@ -54,13 +54,13 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo * interpolated field of view. */ if(ray->time < 0.5f) { - Transform rastertocamera_pre = kernel_data.cam.perspective_motion.pre; + ProjectionTransform rastertocamera_pre = kernel_data.cam.perspective_pre; float3 Pcamera_pre = transform_perspective(&rastertocamera_pre, raster); Pcamera = interp(Pcamera_pre, Pcamera, ray->time * 2.0f); } else { - Transform rastertocamera_post = kernel_data.cam.perspective_motion.post; + ProjectionTransform rastertocamera_post = kernel_data.cam.perspective_post; float3 Pcamera_post = transform_perspective(&rastertocamera_post, raster); Pcamera = interp(Pcamera, Pcamera_post, (ray->time - 0.5f) * 2.0f); @@ -91,17 +91,12 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo Transform cameratoworld = kernel_data.cam.cameratoworld; #ifdef __CAMERA_MOTION__ - if(kernel_data.cam.have_motion) { -# ifdef __KERNEL_OPENCL__ - const MotionTransform tfm = kernel_data.cam.motion; - transform_motion_interpolate(&cameratoworld, - &tfm, - ray->time); -# else - transform_motion_interpolate(&cameratoworld, - &kernel_data.cam.motion, - ray->time); -# endif + if(kernel_data.cam.num_motion_steps) { + transform_motion_array_interpolate( + &cameratoworld, + kernel_tex_array(__camera_motion), + kernel_data.cam.num_motion_steps, + ray->time); } #endif @@ -175,7 +170,7 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray) { /* create ray form raster position */ - Transform rastertocamera = kernel_data.cam.rastertocamera; + ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera; float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); float3 P; @@ -203,17 +198,12 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl Transform cameratoworld = kernel_data.cam.cameratoworld; #ifdef __CAMERA_MOTION__ - if(kernel_data.cam.have_motion) { -# ifdef __KERNEL_OPENCL__ - const MotionTransform tfm = kernel_data.cam.motion; - transform_motion_interpolate(&cameratoworld, - &tfm, - ray->time); -# else - transform_motion_interpolate(&cameratoworld, - &kernel_data.cam.motion, - ray->time); -# endif + if(kernel_data.cam.num_motion_steps) { + transform_motion_array_interpolate( + &cameratoworld, + kernel_tex_array(__camera_motion), + kernel_data.cam.num_motion_steps, + ray->time); } #endif @@ -239,11 +229,12 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl /* Panorama Camera */ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam, + const ccl_global DecomposedTransform *cam_motion, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray) { - Transform rastertocamera = cam->rastertocamera; + ProjectionTransform rastertocamera = cam->rastertocamera; float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); /* create ray form raster position */ @@ -281,17 +272,12 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam, Transform cameratoworld = cam->cameratoworld; #ifdef __CAMERA_MOTION__ - if(cam->have_motion) { -# ifdef __KERNEL_OPENCL__ - const MotionTransform tfm = cam->motion; - transform_motion_interpolate(&cameratoworld, - &tfm, - ray->time); -# else - transform_motion_interpolate(&cameratoworld, - &cam->motion, - ray->time); -# endif + if(cam->num_motion_steps) { + transform_motion_array_interpolate( + &cameratoworld, + cam_motion, + cam->num_motion_steps, + ray->time); } #endif @@ -410,12 +396,16 @@ ccl_device_inline void camera_sample(KernelGlobals *kg, #endif /* sample */ - if(kernel_data.cam.type == CAMERA_PERSPECTIVE) + if(kernel_data.cam.type == CAMERA_PERSPECTIVE) { camera_sample_perspective(kg, raster_x, raster_y, lens_u, lens_v, ray); - else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) + } + else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) { camera_sample_orthographic(kg, raster_x, raster_y, lens_u, lens_v, ray); - else - camera_sample_panorama(&kernel_data.cam, raster_x, raster_y, lens_u, lens_v, ray); + } + else { + const ccl_global DecomposedTransform *cam_motion = kernel_tex_array(__camera_motion); + camera_sample_panorama(&kernel_data.cam, cam_motion, raster_x, raster_y, lens_u, lens_v, ray); + } } /* Utilities */ @@ -460,7 +450,7 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd, if(sd->object == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE) P += camera_position(kg); - Transform tfm = kernel_data.cam.worldtondc; + ProjectionTransform tfm = kernel_data.cam.worldtondc; return transform_perspective(&tfm, P); } else { diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index 61cd90e9d2af8e15a20344fb7d97682e38430e2f..d26b668cb11248062b29e1d9a281c15169b2e674 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -118,6 +118,7 @@ template<typename T> struct texture { #define kernel_tex_fetch_ssef(tex, index) (kg->tex.fetch_ssef(index)) #define kernel_tex_fetch_ssei(tex, index) (kg->tex.fetch_ssei(index)) #define kernel_tex_lookup(tex, t, offset, size) (kg->tex.lookup(t, offset, size)) +#define kernel_tex_array(tex) (kg->tex.data) #define kernel_data (kg->__data) diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h index 9bd7a572f5fdd48659a46b7851bf0f3566accf28..ac63bcf7ac9657a1398cb0dc83ec0dc482c748fe 100644 --- a/intern/cycles/kernel/kernel_compat_cuda.h +++ b/intern/cycles/kernel/kernel_compat_cuda.h @@ -137,6 +137,7 @@ ccl_device_inline uint ccl_num_groups(uint d) /* Use arrays for regular data. */ #define kernel_tex_fetch(t, index) t[(index)] +#define kernel_tex_array(t) (t) #define kernel_data __data diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h index b02e3bc576d8e3018f3a596a8fea36e304c66301..671c47e2225fa2001aa89d2ed0b4c94f3b29acba 100644 --- a/intern/cycles/kernel/kernel_compat_opencl.h +++ b/intern/cycles/kernel/kernel_compat_opencl.h @@ -144,7 +144,8 @@ /* data lookup defines */ #define kernel_data (*kg->data) -#define kernel_tex_fetch(tex, index) ((const ccl_global tex##_t*)(kg->buffers[kg->tex.cl_buffer] + kg->tex.data))[(index)] +#define kernel_tex_array(tex) ((const ccl_global tex##_t*)(kg->buffers[kg->tex.cl_buffer] + kg->tex.data)) +#define kernel_tex_fetch(tex, index) kernel_tex_array(tex)[(index)] /* define NULL */ #define NULL 0 diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 5875249b4049469451a8701bb6bdc9c7c0719de0..a5556c3be8fbe3d51164c94708e245a703dd69e0 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -29,7 +29,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, /* setup shading at emitter */ float3 eval; - int shader_flag = kernel_tex_fetch(__shader_flag, (ls->shader & SHADER_MASK)*SHADER_SIZE); + int shader_flag = kernel_tex_fetch(__shaders, (ls->shader & SHADER_MASK)).flags; #ifdef __BACKGROUND_MIS__ if(ls->type == LIGHT_BACKGROUND) { @@ -51,9 +51,9 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, #endif if(shader_flag & SD_HAS_CONSTANT_EMISSION) { - eval.x = __int_as_float(kernel_tex_fetch(__shader_flag, (ls->shader & SHADER_MASK)*SHADER_SIZE + 2)); - eval.y = __int_as_float(kernel_tex_fetch(__shader_flag, (ls->shader & SHADER_MASK)*SHADER_SIZE + 3)); - eval.z = __int_as_float(kernel_tex_fetch(__shader_flag, (ls->shader & SHADER_MASK)*SHADER_SIZE + 4)); + eval.x = kernel_tex_fetch(__shaders, (ls->shader & SHADER_MASK)).constant_emission[0]; + eval.y = kernel_tex_fetch(__shaders, (ls->shader & SHADER_MASK)).constant_emission[1]; + eval.z = kernel_tex_fetch(__shaders, (ls->shader & SHADER_MASK)).constant_emission[2]; if((ls->prim != PRIM_NONE) && dot(ls->Ng, I) < 0.0f) { ls->Ng = -ls->Ng; } diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index dfa3150dc920fb3a96f703de14e929de1366b17e..efab69ee37dfdf29bd39f2da64051ba14e58b1ea 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -255,11 +255,11 @@ ccl_device_inline bool background_portal_data_fetch_and_check_side(KernelGlobals float3 *lightpos, float3 *dir) { - float4 data0 = kernel_tex_fetch(__light_data, (index + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 0); - float4 data3 = kernel_tex_fetch(__light_data, (index + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 3); + int portal = kernel_data.integrator.portal_offset + index; + const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); - *lightpos = make_float3(data0.y, data0.z, data0.w); - *dir = make_float3(data3.y, data3.z, data3.w); + *lightpos = make_float3(klight->co[0], klight->co[1], klight->co[2]); + *dir = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]); /* Check whether portal is on the right side. */ if(dot(*dir, P - *lightpos) > 1e-4f) @@ -291,11 +291,10 @@ ccl_device_inline float background_portal_pdf(KernelGlobals *kg, } num_possible++; - float4 data1 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 1); - float4 data2 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 2); - - float3 axisu = make_float3(data1.y, data1.z, data1.w); - float3 axisv = make_float3(data2.y, data2.z, data2.w); + int portal = kernel_data.integrator.portal_offset + p; + const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); + float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); + float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]); if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL, NULL, NULL)) continue; @@ -346,10 +345,10 @@ ccl_device float3 background_portal_sample(KernelGlobals *kg, if(portal == 0) { /* p is the portal to be sampled. */ - float4 data1 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 1); - float4 data2 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 2); - float3 axisu = make_float3(data1.y, data1.z, data1.w); - float3 axisv = make_float3(data2.y, data2.z, data2.w); + int portal = kernel_data.integrator.portal_offset + p; + const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); + float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); + float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]); *pdf = area_light_sample(P, &lightpos, axisu, axisv, @@ -479,14 +478,10 @@ ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, flo return disk_light_sample(normalize(P - center), randu, randv)*radius; } -ccl_device float spot_light_attenuation(float4 data1, float4 data2, LightSample *ls) +ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, LightSample *ls) { - float3 dir = make_float3(data2.y, data2.z, data2.w); float3 I = ls->Ng; - float spot_angle = data1.w; - float spot_smooth = data2.x; - float attenuation = dot(dir, I); if(attenuation <= spot_angle) { @@ -518,12 +513,10 @@ ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, float3 P, LightSample *ls) { - float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0); - float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1); - - LightType type = (LightType)__float_as_int(data0.x); + const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + LightType type = (LightType)klight->type; ls->type = type; - ls->shader = __float_as_int(data1.x); + ls->shader = klight->shader_id; ls->object = PRIM_NONE; ls->prim = PRIM_NONE; ls->lamp = lamp; @@ -532,10 +525,10 @@ ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, if(type == LIGHT_DISTANT) { /* distant light */ - float3 lightD = make_float3(data0.y, data0.z, data0.w); + float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]); float3 D = lightD; - float radius = data1.y; - float invarea = data1.w; + float radius = klight->distant.radius; + float invarea = klight->distant.invarea; if(radius > 0.0f) D = distant_light_sample(D, radius, randu, randv); @@ -562,10 +555,10 @@ ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, } #endif else { - ls->P = make_float3(data0.y, data0.z, data0.w); + ls->P = make_float3(klight->co[0], klight->co[1], klight->co[2]); if(type == LIGHT_POINT || type == LIGHT_SPOT) { - float radius = data1.y; + float radius = klight->spot.radius; if(radius > 0.0f) /* sphere light */ @@ -574,14 +567,19 @@ ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, ls->D = normalize_len(ls->P - P, &ls->t); ls->Ng = -ls->D; - float invarea = data1.z; + float invarea = klight->spot.invarea; ls->eval_fac = (0.25f*M_1_PI_F)*invarea; ls->pdf = invarea; if(type == LIGHT_SPOT) { /* spot light attenuation */ - float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2); - ls->eval_fac *= spot_light_attenuation(data1, data2, ls); + float3 dir = make_float3(klight->spot.dir[0], + klight->spot.dir[1], + klight->spot.dir[2]); + ls->eval_fac *= spot_light_attenuation(dir, + klight->spot.spot_angle, + klight->spot.spot_smooth, + ls); if(ls->eval_fac == 0.0f) { return false; } @@ -594,12 +592,15 @@ ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, } else { /* area light */ - float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2); - float4 data3 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 3); - - float3 axisu = make_float3(data1.y, data1.z, data1.w); - float3 axisv = make_float3(data2.y, data2.z, data2.w); - float3 D = make_float3(data3.y, data3.z, data3.w); + float3 axisu = make_float3(klight->area.axisu[0], + klight->area.axisu[1], + klight->area.axisu[2]); + float3 axisv = make_float3(klight->area.axisv[0], + klight->area.axisv[1], + klight->area.axisv[2]); + float3 D = make_float3(klight->area.dir[0], + klight->area.dir[1], + klight->area.dir[2]); if(dot(ls->P - P, D) > 0.0f) { return false; @@ -618,7 +619,7 @@ ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, ls->Ng = D; ls->D = normalize_len(ls->P - P, &ls->t); - float invarea = data2.x; + float invarea = klight->area.invarea; ls->eval_fac = 0.25f*invarea; } } @@ -630,12 +631,10 @@ ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls) { - float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0); - float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1); - - LightType type = (LightType)__float_as_int(data0.x); + const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + LightType type = (LightType)klight->type; ls->type = type; - ls->shader = __float_as_int(data1.x); + ls->shader = klight->shader_id; ls->object = PRIM_NONE; ls->prim = PRIM_NONE; ls->lamp = lamp; @@ -648,7 +647,7 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, if(type == LIGHT_DISTANT) { /* distant light */ - float radius = data1.y; + float radius = klight->distant.radius; if(radius == 0.0f) return false; @@ -670,9 +669,9 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, * P */ - float3 lightD = make_float3(data0.y, data0.z, data0.w); + float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]); float costheta = dot(-lightD, D); - float cosangle = data1.z; + float cosangle = klight->distant.cosangle; if(costheta < cosangle) return false; @@ -683,13 +682,14 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, ls->t = FLT_MAX; /* compute pdf */ - float invarea = data1.w; + float invarea = klight->distant.invarea; ls->pdf = invarea/(costheta*costheta*costheta); ls->eval_fac = ls->pdf; } else if(type == LIGHT_POINT || type == LIGHT_SPOT) { - float3 lightP = make_float3(data0.y, data0.z, data0.w); - float radius = data1.y; + float3 lightP = make_float3(klight->co[0], klight->co[1], klight->co[2]); + + float radius = klight->spot.radius; /* sphere light */ if(radius == 0.0f) @@ -704,14 +704,19 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, ls->Ng = -D; ls->D = D; - float invarea = data1.z; + float invarea = klight->spot.invarea; ls->eval_fac = (0.25f*M_1_PI_F)*invarea; ls->pdf = invarea; if(type == LIGHT_SPOT) { /* spot light attenuation */ - float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2); - ls->eval_fac *= spot_light_attenuation(data1, data2, ls); + float3 dir = make_float3(klight->spot.dir[0], + klight->spot.dir[1], + klight->spot.dir[2]); + ls->eval_fac *= spot_light_attenuation(dir, + klight->spot.spot_angle, + klight->spot.spot_smooth, + ls); if(ls->eval_fac == 0.0f) return false; @@ -726,22 +731,25 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, } else if(type == LIGHT_AREA) { /* area light */ - float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2); - float4 data3 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 3); - - float invarea = data2.x; + float invarea = klight->area.invarea; if(invarea == 0.0f) return false; - float3 axisu = make_float3(data1.y, data1.z, data1.w); - float3 axisv = make_float3(data2.y, data2.z, data2.w); - float3 Ng = make_float3(data3.y, data3.z, data3.w); + float3 axisu = make_float3(klight->area.axisu[0], + klight->area.axisu[1], + klight->area.axisu[2]); + float3 axisv = make_float3(klight->area.axisv[0], + klight->area.axisv[1], + klight->area.axisv[2]); + float3 Ng = make_float3(klight->area.dir[0], + klight->area.dir[1], + klight->area.dir[2]); /* one sided */ if(dot(D, Ng) >= 0.0f) return false; - float3 light_P = make_float3(data0.y, data0.z, data0.w); + float3 light_P = make_float3(klight->co[0], klight->co[1], klight->co[2]); if(!ray_quad_intersect(P, D, 0.0f, t, light_P, axisu, axisv, Ng, @@ -784,7 +792,8 @@ ccl_device_inline bool triangle_world_space_vertices(KernelGlobals *kg, int obje #ifdef __INSTANCING__ if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { # ifdef __OBJECT_MOTION__ - Transform tfm = object_fetch_transform_motion_test(kg, object, time, NULL); + float object_time = (time >= 0.0f) ? time : 0.5f; + Transform tfm = object_fetch_transform_motion_test(kg, object, object_time, NULL); # else Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); # endif @@ -1040,7 +1049,7 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu) int half_len = len >> 1; int middle = first + half_len; - if(r < kernel_tex_fetch(__light_distribution, middle).x) { + if(r < kernel_tex_fetch(__light_distribution, middle).totarea) { len = half_len; } else { @@ -1055,8 +1064,8 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu) /* Rescale to reuse random number. this helps the 2D samples within * each area light be stratified as well. */ - float distr_min = kernel_tex_fetch(__light_distribution, index).x; - float distr_max = kernel_tex_fetch(__light_distribution, index+1).x; + float distr_min = kernel_tex_fetch(__light_distribution, index).totarea; + float distr_max = kernel_tex_fetch(__light_distribution, index+1).totarea; *randu = (r - distr_min)/(distr_max - distr_min); return index; @@ -1066,8 +1075,7 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu) ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce) { - float4 data4 = kernel_tex_fetch(__light_data, index*LIGHT_SIZE + 4); - return (bounce > __float_as_int(data4.x)); + return (bounce > kernel_tex_fetch(__lights, index).max_bounces); } ccl_device_noinline bool light_sample(KernelGlobals *kg, @@ -1082,12 +1090,12 @@ ccl_device_noinline bool light_sample(KernelGlobals *kg, int index = light_distribution_sample(kg, &randu); /* fetch light data */ - float4 l = kernel_tex_fetch(__light_distribution, index); - int prim = __float_as_int(l.y); + const ccl_global KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution, index); + int prim = kdistribution->prim; if(prim >= 0) { - int object = __float_as_int(l.w); - int shader_flag = __float_as_int(l.z); + int object = kdistribution->mesh_light.object_id; + int shader_flag = kdistribution->mesh_light.shader_flag; triangle_light_sample(kg, prim, object, randu, randv, time, ls, P); ls->shader |= shader_flag; @@ -1106,8 +1114,7 @@ ccl_device_noinline bool light_sample(KernelGlobals *kg, ccl_device int light_select_num_samples(KernelGlobals *kg, int index) { - float4 data3 = kernel_tex_fetch(__light_data, index*LIGHT_SIZE + 3); - return __float_as_int(data3.x); + return kernel_tex_fetch(__lights, index).samples; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_math.h b/intern/cycles/kernel/kernel_math.h index bd0e23b77057fb22ba96841b3f1b35eba548387a..96391db7649eb0115d34a097fa02708603b20162 100644 --- a/intern/cycles/kernel/kernel_math.h +++ b/intern/cycles/kernel/kernel_math.h @@ -21,6 +21,7 @@ #include "util/util_math.h" #include "util/util_math_fast.h" #include "util/util_math_intersect.h" +#include "util/util_projection.h" #include "util/util_texture.h" #include "util/util_transform.h" diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index b1f66852b7f1029c6942ac189dd81ed3a91cba62..937a50cba8b55d2a5415e066b3744bd80c7df4a5 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -114,7 +114,7 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg, sd->I = -ray->D; - sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE); + sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; #ifdef __INSTANCING__ if(isect->object != OBJECT_NONE) { @@ -199,7 +199,7 @@ void shader_setup_from_subsurface( motion_triangle_shader_setup(kg, sd, isect, ray, true); } - sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE); + sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; # ifdef __INSTANCING__ if(isect->object != OBJECT_NONE) { @@ -276,7 +276,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg, sd->time = time; sd->ray_length = t; - sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE); + sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; sd->object_flag = 0; if(sd->object != OBJECT_NONE) { sd->object_flag |= kernel_tex_fetch(__object_flag, @@ -386,7 +386,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat sd->Ng = -ray->D; sd->I = -ray->D; sd->shader = kernel_data.background.surface_shader; - sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE); + sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; sd->object_flag = 0; sd->time = ray->time; sd->ray_length = 0.0f; @@ -763,6 +763,26 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, ShaderData *sd, return label; } +ccl_device float shader_bsdf_average_roughness(ShaderData *sd) +{ + float roughness = 0.0f; + float sum_weight = 0.0f; + + for(int i = 0; i < sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + + if(CLOSURE_IS_BSDF(sc->type)) { + /* sqrt once to undo the squaring from multiplying roughness on the + * two axes, and once for the squared roughness convention. */ + float weight = fabsf(average(sc->weight)); + roughness += weight * sqrtf(safe_sqrtf(bsdf_get_roughness_squared(sc))); + sum_weight += weight; + } + } + + return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f; +} + ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness) { for(int i = 0; i < sd->num_closure; i++) { @@ -875,7 +895,7 @@ ccl_device float3 shader_bsdf_average_normal(KernelGlobals *kg, ShaderData *sd) 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); + N += sc->N*fabsf(average(sc->weight)); } return (is_zero(N))? sd->N : normalize(N); @@ -892,11 +912,11 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc; eval += sc->weight*ao_factor; - N += bsdf->N*average(sc->weight); + N += bsdf->N*fabsf(average(sc->weight)); } else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) { eval += sc->weight; - N += sd->N*average(sc->weight); + N += sd->N*fabsf(average(sc->weight)); } } @@ -1181,7 +1201,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg, sd->shader = stack[i].shader; sd->flag &= ~SD_SHADER_FLAGS; - sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE); + sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; sd->object_flag &= ~SD_OBJECT_FLAGS; if(sd->object != OBJECT_NONE) { @@ -1254,7 +1274,7 @@ ccl_device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect shader = __float_as_int(str.z); } #endif - int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*SHADER_SIZE); + int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags; return (flag & SD_HAS_TRANSPARENT_SHADOW) != 0; } diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 74b659557e5c29c2bc1ec742206b87e67e234c34..9047b93a0b2281cb5751b840541657f88e818776 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -31,8 +31,13 @@ KERNEL_TEX(uint, __object_node) KERNEL_TEX(float2, __prim_time) /* objects */ -KERNEL_TEX(float4, __objects) -KERNEL_TEX(float4, __objects_vector) +KERNEL_TEX(KernelObject, __objects) +KERNEL_TEX(Transform, __object_motion_pass) +KERNEL_TEX(DecomposedTransform, __object_motion) +KERNEL_TEX(uint, __object_flag) + +/* cameras */ +KERNEL_TEX(DecomposedTransform, __camera_motion) /* triangles */ KERNEL_TEX(uint, __tri_shader) @@ -55,18 +60,17 @@ KERNEL_TEX(float4, __attributes_float3) KERNEL_TEX(uchar4, __attributes_uchar4) /* lights */ -KERNEL_TEX(float4, __light_distribution) -KERNEL_TEX(float4, __light_data) +KERNEL_TEX(KernelLightDistribution, __light_distribution) +KERNEL_TEX(KernelLight, __lights) KERNEL_TEX(float2, __light_background_marginal_cdf) KERNEL_TEX(float2, __light_background_conditional_cdf) /* particles */ -KERNEL_TEX(float4, __particles) +KERNEL_TEX(KernelParticle, __particles) /* shaders */ KERNEL_TEX(uint4, __svm_nodes) -KERNEL_TEX(uint, __shader_flag) -KERNEL_TEX(uint, __object_flag) +KERNEL_TEX(KernelShader, __shaders) /* lookup tables */ KERNEL_TEX(float, __lookup_table) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 9df13804ea4ae745bed2c9100775ac92d3c397c1..64fef8aa41893e6de82225570d91c30ae3880ed4 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -40,14 +40,10 @@ CCL_NAMESPACE_BEGIN /* Constants */ -#define OBJECT_SIZE 16 -#define OBJECT_VECTOR_SIZE 6 -#define LIGHT_SIZE 11 -#define FILTER_TABLE_SIZE 1024 -#define RAMP_TABLE_SIZE 256 -#define SHUTTER_TABLE_SIZE 256 -#define PARTICLE_SIZE 5 -#define SHADER_SIZE 5 +#define OBJECT_MOTION_PASS_SIZE 2 +#define FILTER_TABLE_SIZE 1024 +#define RAMP_TABLE_SIZE 256 +#define SHUTTER_TABLE_SIZE 256 #define BSSRDF_MIN_RADIUS 1e-8f #define BSSRDF_MAX_HITS 4 @@ -275,6 +271,7 @@ typedef enum ShaderEvalType { /* data passes */ SHADER_EVAL_NORMAL, SHADER_EVAL_UV, + SHADER_EVAL_ROUGHNESS, SHADER_EVAL_DIFFUSE_COLOR, SHADER_EVAL_GLOSSY_COLOR, SHADER_EVAL_TRANSMISSION_COLOR, @@ -936,7 +933,7 @@ enum ShaderDataFlag { SD_HAS_BUMP = (1 << 25), /* Has true displacement. */ SD_HAS_DISPLACEMENT = (1 << 26), - /* Has constant emission (value stored in __shader_flag) */ + /* Has constant emission (value stored in __shaders) */ SD_HAS_CONSTANT_EMISSION = (1 << 27), /* Needs to access attributes */ SD_NEED_ATTRIBUTES = (1 << 28), @@ -1174,7 +1171,7 @@ typedef struct KernelCamera { /* matrices */ Transform cameratoworld; - Transform rastertocamera; + ProjectionTransform rastertocamera; /* differentials */ float4 dx; @@ -1188,7 +1185,7 @@ typedef struct KernelCamera { /* motion blur */ float shuttertime; - int have_motion, have_perspective_motion; + int num_motion_steps, have_perspective_motion; /* clipping */ float nearclip; @@ -1208,22 +1205,22 @@ typedef struct KernelCamera { int is_inside_volume; /* more matrices */ - Transform screentoworld; - Transform rastertoworld; - /* work around cuda sm 2.0 crash, this seems to - * cross some limit in combination with motion - * Transform ndctoworld; */ - Transform worldtoscreen; - Transform worldtoraster; - Transform worldtondc; + ProjectionTransform screentoworld; + ProjectionTransform rastertoworld; + ProjectionTransform ndctoworld; + ProjectionTransform worldtoscreen; + ProjectionTransform worldtoraster; + ProjectionTransform worldtondc; Transform worldtocamera; - MotionTransform motion; + /* Stores changes in the projeciton matrix. Use for camera zoom motion + * blur and motion pass output for perspective camera. */ + ProjectionTransform perspective_pre; + ProjectionTransform perspective_post; - /* Denotes changes in the projective matrix, namely in rastertocamera. - * Used for camera zoom motion blur, - */ - PerspectiveMotionTransform perspective_motion; + /* Transforms for motion pass. */ + Transform motion_pass_pre; + Transform motion_pass_post; int shutter_table_offset; @@ -1452,6 +1449,110 @@ typedef struct KernelData { } KernelData; static_assert_align(KernelData, 16); +/* Kernel data structures. */ + +typedef struct KernelObject { + Transform tfm; + Transform itfm; + + float surface_area; + float pass_id; + float random_number; + int particle_index; + + float dupli_generated[3]; + float dupli_uv[2]; + + int numkeys; + int numsteps; + int numverts; + + uint patch_map_offset; + uint attribute_map_offset; + uint motion_offset; + uint pad; +} KernelObject;; +static_assert_align(KernelObject, 16); + +typedef struct KernelSpotLight { + float radius; + float invarea; + float spot_angle; + float spot_smooth; + float dir[3]; +} KernelSpotLight; + +/* PointLight is SpotLight with only radius and invarea being used. */ + +typedef struct KernelAreaLight { + float axisu[3]; + float invarea; + float axisv[3]; + float dir[3]; +} KernelAreaLight; + +typedef struct KernelDistantLight { + float radius; + float cosangle; + float invarea; +} KernelDistantLight; + +typedef struct KernelLight { + int type; + float co[3]; + int shader_id; + int samples; + float max_bounces; + float random; + Transform tfm; + Transform itfm; + union { + KernelSpotLight spot; + KernelAreaLight area; + KernelDistantLight distant; + }; +} KernelLight; +static_assert_align(KernelLight, 16); + +typedef struct KernelLightDistribution { + float totarea; + int prim; + union { + struct { + int shader_flag; + int object_id; + } mesh_light; + struct { + float pad; + float size; + } lamp; + }; +} KernelLightDistribution; +static_assert_align(KernelLightDistribution, 16); + +typedef struct KernelParticle { + int index; + float age; + float lifetime; + float size; + float4 rotation; + /* Only xyz are used of the following. float4 instead of float3 are used + * to ensure consistent padding/alignment across devices. */ + float4 location; + float4 velocity; + float4 angular_velocity; +} KernelParticle; +static_assert_align(KernelParticle, 16); + +typedef struct KernelShader { + float constant_emission[3]; + float pad1; + int flags; + int pass_id; + int pad2, pad3; +} KernelShader; +static_assert_align(KernelShader, 16); + /* Declarations required for split kernel */ /* Macro for queues */ diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 058e7dccafdb0251a5f27b4da6b9b1e0bba0566e..88360e5f1ae5afde85cdcd4b4cd8789f1c6e8612 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -104,7 +104,7 @@ ccl_device float kernel_volume_channel_get(float3 value, int channel) ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, ccl_addr_space VolumeStack *stack) { for(int i = 0; stack[i].shader != SHADER_NONE; i++) { - int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*SHADER_SIZE); + int shader_flag = kernel_tex_fetch(__shaders, (stack[i].shader & SHADER_MASK)).flags; if(shader_flag & SD_HETEROGENEOUS_VOLUME) { return true; @@ -134,7 +134,7 @@ ccl_device int volume_stack_sampling_method(KernelGlobals *kg, VolumeStack *stac int method = -1; for(int i = 0; stack[i].shader != SHADER_NONE; i++) { - int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*SHADER_SIZE); + int shader_flag = kernel_tex_fetch(__shaders, (stack[i].shader & SHADER_MASK)).flags; if(shader_flag & SD_VOLUME_MIS) { return SD_VOLUME_MIS; diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index ae4c521659c7c17c781e79d67fe79f16a436a843..0c5e5e30e479168a3fc366fe9c4033a12f088451 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -62,11 +62,17 @@ CCL_NAMESPACE_BEGIN /* RenderServices implementation */ -#define COPY_MATRIX44(m1, m2) { \ - CHECK_TYPE(m1, OSL::Matrix44*); \ - CHECK_TYPE(m2, Transform*); \ - memcpy(m1, m2, sizeof(*m2)); \ -} (void)0 +static void copy_matrix(OSL::Matrix44& m, const Transform& tfm) +{ + ProjectionTransform t = projection_transpose(ProjectionTransform(tfm)); + memcpy(&m, &t, sizeof(m)); +} + +static void copy_matrix(OSL::Matrix44& m, const ProjectionTransform& tfm) +{ + ProjectionTransform t = projection_transpose(tfm); + memcpy(&m, &t, sizeof(m)); +} /* static ustrings */ ustring OSLRenderServices::u_distance("distance"); @@ -167,14 +173,12 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result #else Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); #endif - tfm = transform_transpose(tfm); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, tfm); return true; } else if(sd->type == PRIMITIVE_LAMP) { - Transform tfm = transform_transpose(sd->ob_tfm); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, sd->ob_tfm); return true; } @@ -203,14 +207,12 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 #else Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); #endif - itfm = transform_transpose(itfm); - COPY_MATRIX44(&result, &itfm); + copy_matrix(result, itfm); return true; } else if(sd->type == PRIMITIVE_LAMP) { - Transform tfm = transform_transpose(sd->ob_itfm); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, sd->ob_itfm); return true; } @@ -224,23 +226,19 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result KernelGlobals *kg = kernel_globals; if(from == u_ndc) { - Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.ndctoworld); return true; } else if(from == u_raster) { - Transform tfm = transform_transpose(kernel_data.cam.rastertoworld); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.rastertoworld); return true; } else if(from == u_screen) { - Transform tfm = transform_transpose(kernel_data.cam.screentoworld); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.screentoworld); return true; } else if(from == u_camera) { - Transform tfm = transform_transpose(kernel_data.cam.cameratoworld); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.cameratoworld); return true; } else if(from == u_world) { @@ -256,23 +254,19 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 KernelGlobals *kg = kernel_globals; if(to == u_ndc) { - Transform tfm = transform_transpose(kernel_data.cam.worldtondc); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.worldtondc); return true; } else if(to == u_raster) { - Transform tfm = transform_transpose(kernel_data.cam.worldtoraster); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.worldtoraster); return true; } else if(to == u_screen) { - Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.worldtoscreen); return true; } else if(to == u_camera) { - Transform tfm = transform_transpose(kernel_data.cam.worldtocamera); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.worldtocamera); return true; } else if(to == u_world) { @@ -298,14 +292,12 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result KernelGlobals *kg = sd->osl_globals; Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); #endif - tfm = transform_transpose(tfm); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, tfm); return true; } else if(sd->type == PRIMITIVE_LAMP) { - Transform tfm = transform_transpose(sd->ob_tfm); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, sd->ob_tfm); return true; } @@ -329,14 +321,12 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 KernelGlobals *kg = sd->osl_globals; Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); #endif - tfm = transform_transpose(tfm); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, tfm); return true; } else if(sd->type == PRIMITIVE_LAMP) { - Transform tfm = transform_transpose(sd->ob_itfm); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, sd->ob_itfm); return true; } @@ -350,23 +340,19 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result KernelGlobals *kg = kernel_globals; if(from == u_ndc) { - Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.ndctoworld); return true; } else if(from == u_raster) { - Transform tfm = transform_transpose(kernel_data.cam.rastertoworld); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.rastertoworld); return true; } else if(from == u_screen) { - Transform tfm = transform_transpose(kernel_data.cam.screentoworld); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.screentoworld); return true; } else if(from == u_camera) { - Transform tfm = transform_transpose(kernel_data.cam.cameratoworld); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.cameratoworld); return true; } @@ -378,23 +364,19 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 KernelGlobals *kg = kernel_globals; if(to == u_ndc) { - Transform tfm = transform_transpose(kernel_data.cam.worldtondc); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.worldtondc); return true; } else if(to == u_raster) { - Transform tfm = transform_transpose(kernel_data.cam.worldtoraster); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.worldtoraster); return true; } else if(to == u_screen) { - Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.worldtoscreen); return true; } else if(to == u_camera) { - Transform tfm = transform_transpose(kernel_data.cam.worldtocamera); - COPY_MATRIX44(&result, &tfm); + copy_matrix(result, kernel_data.cam.worldtocamera); return true; } @@ -570,8 +552,7 @@ static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, static bool set_attribute_matrix(const Transform& tfm, TypeDesc type, void *val) { if(type == TypeDesc::TypeMatrix) { - Transform transpose = transform_transpose(tfm); - memcpy(val, &transpose, sizeof(Transform)); + copy_matrix(*(OSL::Matrix44*)val, tfm); return true; } diff --git a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl index bef6d7e8809216f2dc2f1b62e2d6b93a37a2fc21..21e28ece65dca10128a1143cf25840492586a699 100644 --- a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl @@ -33,27 +33,28 @@ shader node_anisotropic_bsdf( T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal); /* compute roughness */ - float RoughnessU, RoughnessV; + float roughness = Roughness * Roughness; + float roughness_u, roughness_v; float aniso = clamp(Anisotropy, -0.99, 0.99); if (aniso < 0.0) { - RoughnessU = Roughness / (1.0 + aniso); - RoughnessV = Roughness * (1.0 + aniso); + roughness_u = roughness / (1.0 + aniso); + roughness_v = roughness * (1.0 + aniso); } else { - RoughnessU = Roughness * (1.0 - aniso); - RoughnessV = Roughness / (1.0 - aniso); + roughness_u = roughness * (1.0 - aniso); + roughness_v = roughness / (1.0 - aniso); } if (distribution == "sharp") BSDF = Color * reflection(Normal); else if (distribution == "beckmann") - BSDF = Color * microfacet_beckmann_aniso(Normal, T, RoughnessU, RoughnessV); + BSDF = Color * microfacet_beckmann_aniso(Normal, T, roughness_u, roughness_v); else if (distribution == "GGX") - BSDF = Color * microfacet_ggx_aniso(Normal, T, RoughnessU, RoughnessV); + BSDF = Color * microfacet_ggx_aniso(Normal, T, roughness_u, roughness_v); else if (distribution == "Multiscatter GGX") - BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, RoughnessU, RoughnessV, Color); + BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, roughness_u, roughness_v, Color); else - BSDF = Color * ashikhmin_shirley(Normal, T, RoughnessU, RoughnessV); + BSDF = Color * ashikhmin_shirley(Normal, T, roughness_u, roughness_v); } diff --git a/intern/cycles/kernel/shaders/node_glass_bsdf.osl b/intern/cycles/kernel/shaders/node_glass_bsdf.osl index a9723a8300a02cb185aa5bc82c9f5ceab06ccd17..2e713861c58dfb25fe372886052b00218115c074 100644 --- a/intern/cycles/kernel/shaders/node_glass_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_glass_bsdf.osl @@ -29,16 +29,17 @@ shader node_glass_bsdf( float eta = backfacing() ? 1.0 / f : f; float cosi = dot(I, Normal); float Fr = fresnel_dielectric_cos(cosi, eta); + float roughness = Roughness * Roughness; if (distribution == "sharp") BSDF = Color * (Fr * reflection(Normal) + (1.0 - Fr) * refraction(Normal, eta)); else if (distribution == "beckmann") - BSDF = Color * (Fr * microfacet_beckmann(Normal, Roughness) + - (1.0 - Fr) * microfacet_beckmann_refraction(Normal, Roughness, eta)); + BSDF = Color * (Fr * microfacet_beckmann(Normal, roughness) + + (1.0 - Fr) * microfacet_beckmann_refraction(Normal, roughness, eta)); else if (distribution == "Multiscatter GGX") - BSDF = Color * microfacet_multi_ggx_glass(Normal, Roughness, eta, Color); + BSDF = Color * microfacet_multi_ggx_glass(Normal, roughness, eta, Color); else if (distribution == "GGX") - BSDF = Color * (Fr * microfacet_ggx(Normal, Roughness) + - (1.0 - Fr) * microfacet_ggx_refraction(Normal, Roughness, eta)); + BSDF = Color * (Fr * microfacet_ggx(Normal, roughness) + + (1.0 - Fr) * microfacet_ggx_refraction(Normal, roughness, eta)); } diff --git a/intern/cycles/kernel/shaders/node_glossy_bsdf.osl b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl index f4ea7e7dc6a39f2a3d60e38f5c6c8cc266634af1..7415211b56d7ecb326c5cdded89b6085ae09f810 100644 --- a/intern/cycles/kernel/shaders/node_glossy_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl @@ -24,16 +24,18 @@ shader node_glossy_bsdf( normal Normal = N, output closure color BSDF = 0) { + float roughness = Roughness * Roughness; + if (distribution == "sharp") BSDF = Color * reflection(Normal); else if (distribution == "beckmann") - BSDF = Color * microfacet_beckmann(Normal, Roughness); + BSDF = Color * microfacet_beckmann(Normal, roughness); else if (distribution == "GGX") - BSDF = Color * microfacet_ggx(Normal, Roughness); + BSDF = Color * microfacet_ggx(Normal, roughness); else if (distribution == "Multiscatter GGX") - BSDF = Color * microfacet_multi_ggx(Normal, Roughness, Color); + BSDF = Color * microfacet_multi_ggx(Normal, roughness, Color); else - BSDF = Color * ashikhmin_shirley(Normal, vector(0, 0, 0), Roughness, Roughness); + BSDF = Color * ashikhmin_shirley(Normal, vector(0, 0, 0), roughness, roughness); } diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl index 828becf18181aba8fc85c7460cc45f03a21a8461..eaab728224383d1cc0d81e19722638507d70ada7 100644 --- a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl @@ -26,12 +26,13 @@ shader node_refraction_bsdf( { float f = max(IOR, 1e-5); float eta = backfacing() ? 1.0 / f : f; + float roughness = Roughness * Roughness; if (distribution == "sharp") BSDF = Color * refraction(Normal, eta); else if (distribution == "beckmann") - BSDF = Color * microfacet_beckmann_refraction(Normal, Roughness, eta); + BSDF = Color * microfacet_beckmann_refraction(Normal, roughness, eta); else if (distribution == "GGX") - BSDF = Color * microfacet_ggx_refraction(Normal, Roughness, eta); + BSDF = Color * microfacet_ggx_refraction(Normal, roughness, eta); } diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index a54095ed127f0b3909fbf998eeb232664db25a6b..886a1333fa34087d2c114878226eceec13ca0ccf 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -468,10 +468,12 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * break; } + float roughness = sqr(param1); + bsdf->N = N; bsdf->T = make_float3(0.0f, 0.0f, 0.0f); - bsdf->alpha_x = param1; - bsdf->alpha_y = param1; + bsdf->alpha_x = roughness; + bsdf->alpha_y = roughness; bsdf->ior = 0.0f; bsdf->extra = NULL; @@ -525,8 +527,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * sd->flag |= bsdf_refraction_setup(bsdf); } else { - bsdf->alpha_x = param1; - bsdf->alpha_y = param1; + float roughness = sqr(param1); + bsdf->alpha_x = roughness; + bsdf->alpha_y = roughness; bsdf->ior = eta; if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) @@ -557,7 +560,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * /* fresnel */ float cosNO = dot(N, sd->I); float fresnel = fresnel_dielectric_cos(cosNO, eta); - float roughness = param1; + float roughness = sqr(param1); /* reflection */ #ifdef __CAUSTICS_TRICKS__ @@ -611,8 +614,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * bsdf->extra = extra; bsdf->T = make_float3(0.0f, 0.0f, 0.0f); - bsdf->alpha_x = param1; - bsdf->alpha_y = param1; + float roughness = sqr(param1); + bsdf->alpha_x = roughness; + bsdf->alpha_y = roughness; float eta = fmaxf(param2, 1e-5f); bsdf->ior = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; @@ -648,7 +652,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F); /* compute roughness */ - float roughness = param1; + float roughness = sqr(param1); float anisotropy = clamp(param2, -0.99f, 0.99f); if(anisotropy < 0.0f) { diff --git a/intern/cycles/kernel/svm/svm_mapping.h b/intern/cycles/kernel/svm/svm_mapping.h index 0a890545af45db3286e1cf9b7d4d6c1ba5638d93..42a7ae9946f401b967fc9b6f3c421d8dfab86a24 100644 --- a/intern/cycles/kernel/svm/svm_mapping.h +++ b/intern/cycles/kernel/svm/svm_mapping.h @@ -26,7 +26,6 @@ ccl_device void svm_node_mapping(KernelGlobals *kg, ShaderData *sd, float *stack tfm.x = read_node_float(kg, offset); tfm.y = read_node_float(kg, offset); tfm.z = read_node_float(kg, offset); - tfm.w = read_node_float(kg, offset); float3 r = transform_point(&tfm, v); stack_store_float3(stack, out_offset, r); diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index c94327401f52c8a65d64819874c79c2cfa54ae5a..6ff39e5f587ad23151a8972c4c58564d7fdc5144 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -42,7 +42,6 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg, tfm.x = read_node_float(kg, offset); tfm.y = read_node_float(kg, offset); tfm.z = read_node_float(kg, offset); - tfm.w = read_node_float(kg, offset); data = transform_point(&tfm, data); } break; @@ -123,7 +122,6 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, tfm.x = read_node_float(kg, offset); tfm.y = read_node_float(kg, offset); tfm.z = read_node_float(kg, offset); - tfm.w = read_node_float(kg, offset); data = transform_point(&tfm, data); } break; @@ -207,7 +205,6 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, tfm.x = read_node_float(kg, offset); tfm.y = read_node_float(kg, offset); tfm.z = read_node_float(kg, offset); - tfm.w = read_node_float(kg, offset); data = transform_point(&tfm, data); } break; diff --git a/intern/cycles/kernel/svm/svm_voxel.h b/intern/cycles/kernel/svm/svm_voxel.h index d967516a5c9b4546e494173a87f60ccff0b81e89..43b433683e06d7c07dca12317730de2e423cc3de 100644 --- a/intern/cycles/kernel/svm/svm_voxel.h +++ b/intern/cycles/kernel/svm/svm_voxel.h @@ -39,7 +39,6 @@ ccl_device void svm_node_tex_voxel(KernelGlobals *kg, tfm.x = read_node_float(kg, offset); tfm.y = read_node_float(kg, offset); tfm.z = read_node_float(kg, offset); - tfm.w = read_node_float(kg, offset); co = transform_point(&tfm, co); } diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp index 1fef7a0188fb982f28e0022568a0659caeef727f..927e04abc7f4d9c5298c0e5ffa7efc1dd0507e5e 100644 --- a/intern/cycles/render/bake.cpp +++ b/intern/cycles/render/bake.cpp @@ -247,7 +247,7 @@ void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/) int BakeManager::aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type) { - if(type == SHADER_EVAL_UV) { + if(type == SHADER_EVAL_UV || type == SHADER_EVAL_ROUGHNESS) { return 1; } else if(type == SHADER_EVAL_NORMAL) { diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 84d10cc477ee4ff23a7b8e54df3fa29fc0608b9a..6f560380b40325bd3537aab4551586280e1e7ff2 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -21,7 +21,6 @@ #include "util/util_foreach.h" #include "util/util_hash.h" -#include "util/util_image.h" #include "util/util_math.h" #include "util/util_opengl.h" #include "util/util_time.h" @@ -448,37 +447,5 @@ bool DisplayBuffer::draw_ready() return (draw_width != 0 && draw_height != 0); } -void DisplayBuffer::write(const string& filename) -{ - int w = draw_width; - int h = draw_height; - - if(w == 0 || h == 0) - return; - - if(half_float) - return; - - /* read buffer from device */ - uchar4 *pixels = rgba_byte.copy_from_device(0, w, h); - - /* write image */ - ImageOutput *out = ImageOutput::create(filename); - ImageSpec spec(w, h, 4, TypeDesc::UINT8); - - out->open(filename, spec); - - /* conversion for different top/bottom convention */ - out->write_image(TypeDesc::UINT8, - (uchar*)(pixels + (h-1)*w), - AutoStride, - -w*sizeof(uchar4), - AutoStride); - - out->close(); - - delete out; -} - CCL_NAMESPACE_END diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index 028bfb83735d549062449de8e21f5bf2f768d055..dfc98fe20619e40707a7d89a58728d284819c928 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -113,7 +113,6 @@ public: ~DisplayBuffer(); void reset(BufferParams& params); - void write(const string& filename); void draw_set(int width, int height); void draw(Device *device, const DeviceDrawParams& draw_params); diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index a2fda12ec8506c500cbe35b811bab306bea9d299..38936ffc094f35e72ea3be9eb0f672e54db2c080 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -82,6 +82,7 @@ NODE_DEFINE(Camera) SOCKET_FLOAT(bladesrotation, "Blades Rotation", 0.0f); SOCKET_TRANSFORM(matrix, "Matrix", transform_identity()); + SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>()); SOCKET_FLOAT(aperture_ratio, "Aperture Ratio", 1.0f); @@ -151,9 +152,6 @@ Camera::Camera() height = 512; resolution = 1; - motion.pre = transform_identity(); - motion.post = transform_identity(); - use_motion = false; use_perspective_motion = false; shutter_curve.resize(RAMP_TABLE_SIZE); @@ -163,12 +161,12 @@ Camera::Camera() compute_auto_viewplane(); - screentoworld = transform_identity(); - rastertoworld = transform_identity(); - ndctoworld = transform_identity(); - rastertocamera = transform_identity(); + screentoworld = projection_identity(); + rastertoworld = projection_identity(); + ndctoworld = projection_identity(); + rastertocamera = projection_identity(); cameratoworld = transform_identity(); - worldtoraster = transform_identity(); + worldtoraster = projection_identity(); dx = make_float3(0.0f, 0.0f, 0.0f); dy = make_float3(0.0f, 0.0f, 0.0f); @@ -241,18 +239,18 @@ void Camera::update(Scene *scene) Transform full_rastertoscreen = transform_inverse(full_screentoraster); /* screen to camera */ - Transform cameratoscreen; + ProjectionTransform cameratoscreen; if(type == CAMERA_PERSPECTIVE) - cameratoscreen = transform_perspective(fov, nearclip, farclip); + cameratoscreen = projection_perspective(fov, nearclip, farclip); else if(type == CAMERA_ORTHOGRAPHIC) - cameratoscreen = transform_orthographic(nearclip, farclip); + cameratoscreen = projection_orthographic(nearclip, farclip); else - cameratoscreen = transform_identity(); + cameratoscreen = projection_identity(); - Transform screentocamera = transform_inverse(cameratoscreen); + ProjectionTransform screentocamera = projection_inverse(cameratoscreen); rastertocamera = screentocamera * rastertoscreen; - Transform full_rastertocamera = screentocamera * full_rastertoscreen; + ProjectionTransform full_rastertocamera = screentocamera * full_rastertoscreen; cameratoraster = screentoraster * cameratoscreen; cameratoworld = matrix; @@ -270,10 +268,10 @@ void Camera::update(Scene *scene) /* differentials */ if(type == CAMERA_ORTHOGRAPHIC) { - dx = transform_direction(&rastertocamera, make_float3(1, 0, 0)); - dy = transform_direction(&rastertocamera, make_float3(0, 1, 0)); - full_dx = transform_direction(&full_rastertocamera, make_float3(1, 0, 0)); - full_dy = transform_direction(&full_rastertocamera, make_float3(0, 1, 0)); + dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0)); + dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0)); + full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0)); + full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0)); } else if(type == CAMERA_PERSPECTIVE) { dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) - @@ -302,23 +300,6 @@ void Camera::update(Scene *scene) frustum_top_normal = normalize(make_float3(0.0f, v.z, -v.y)); } - /* TODO(sergey): Support other types of camera. */ - if(type == CAMERA_PERSPECTIVE) { - /* TODO(sergey): Move to an utility function and de-duplicate with - * calculation above. - */ - Transform screentocamera_pre = - transform_inverse(transform_perspective(fov_pre, - nearclip, - farclip)); - Transform screentocamera_post = - transform_inverse(transform_perspective(fov_post, - nearclip, - farclip)); - perspective_motion.pre = screentocamera_pre * rastertoscreen; - perspective_motion.post = screentocamera_post * rastertoscreen; - } - /* Compute kernel camera data. */ KernelCamera *kcam = &kernel_camera; @@ -331,41 +312,65 @@ void Camera::update(Scene *scene) kcam->worldtoscreen = worldtoscreen; kcam->worldtoraster = worldtoraster; kcam->worldtondc = worldtondc; + kcam->ndctoworld = ndctoworld; /* camera motion */ - kcam->have_motion = 0; + kcam->num_motion_steps = 0; kcam->have_perspective_motion = 0; + kernel_camera_motion.clear(); + + /* Test if any of the transforms are actually different. */ + bool have_motion = false; + for(size_t i = 0; i < motion.size(); i++) { + have_motion = have_motion || motion[i] != matrix; + } if(need_motion == Scene::MOTION_PASS) { /* TODO(sergey): Support perspective (zoom, fov) motion. */ if(type == CAMERA_PANORAMA) { - if(use_motion) { - kcam->motion.pre = transform_inverse(motion.pre); - kcam->motion.post = transform_inverse(motion.post); + if(have_motion) { + kcam->motion_pass_pre = transform_inverse(motion[0]); + kcam->motion_pass_post = transform_inverse(motion[motion.size()-1]); } else { - kcam->motion.pre = kcam->worldtocamera; - kcam->motion.post = kcam->worldtocamera; + kcam->motion_pass_pre = kcam->worldtocamera; + kcam->motion_pass_post = kcam->worldtocamera; } } else { - if(use_motion) { - kcam->motion.pre = cameratoraster * transform_inverse(motion.pre); - kcam->motion.post = cameratoraster * transform_inverse(motion.post); + if(have_motion) { + kcam->perspective_pre = cameratoraster * transform_inverse(motion[0]); + kcam->perspective_post = cameratoraster * transform_inverse(motion[motion.size()-1]); } else { - kcam->motion.pre = worldtoraster; - kcam->motion.post = worldtoraster; + kcam->perspective_pre = worldtoraster; + kcam->perspective_post = worldtoraster; } } } else if(need_motion == Scene::MOTION_BLUR) { - if(use_motion) { - transform_motion_decompose(&kcam->motion, &motion, &matrix); - kcam->have_motion = 1; + if(have_motion) { + kernel_camera_motion.resize(motion.size()); + transform_motion_decompose(kernel_camera_motion.data(), motion.data(), motion.size()); + kcam->num_motion_steps = motion.size(); } - if(use_perspective_motion) { - kcam->perspective_motion = perspective_motion; + + /* TODO(sergey): Support other types of camera. */ + if(use_perspective_motion && type == CAMERA_PERSPECTIVE) { + /* TODO(sergey): Move to an utility function and de-duplicate with + * calculation above. + */ + ProjectionTransform screentocamera_pre = + projection_inverse(projection_perspective(fov_pre, + nearclip, + farclip)); + ProjectionTransform screentocamera_post = + projection_inverse(projection_perspective(fov_post, + nearclip, + farclip)); + + kcam->perspective_pre = screentocamera_pre * rastertoscreen; + kcam->perspective_post = screentocamera_post * rastertoscreen; kcam->have_perspective_motion = 1; } } @@ -470,6 +475,16 @@ void Camera::device_update(Device * /* device */, } dscene->data.cam = kernel_camera; + + size_t num_motion_steps = kernel_camera_motion.size(); + if(num_motion_steps) { + DecomposedTransform *camera_motion = dscene->camera_motion.alloc(num_motion_steps); + memcpy(camera_motion, kernel_camera_motion.data(), sizeof(*camera_motion) * num_motion_steps); + dscene->camera_motion.copy_to_device(); + } + else { + dscene->camera_motion.free(); + } } void Camera::device_update_volume(Device * /*device*/, @@ -496,10 +511,11 @@ void Camera::device_update_volume(Device * /*device*/, } void Camera::device_free(Device * /*device*/, - DeviceScene * /*dscene*/, + DeviceScene *dscene, Scene *scene) { scene->lookup_tables->remove_table(&shutter_table_offset); + dscene->camera_motion.free(); } bool Camera::modified(const Camera& cam) @@ -510,7 +526,6 @@ bool Camera::modified(const Camera& cam) bool Camera::motion_modified(const Camera& cam) { return !((motion == cam.motion) && - (use_motion == cam.use_motion) && (use_perspective_motion == cam.use_perspective_motion)); } @@ -606,7 +621,7 @@ float Camera::world_to_raster_size(float3 P) res = min(len(full_dx), len(full_dy)); if(offscreen_dicing_scale > 1.0f) { - float3 p = transform_perspective(&worldtocamera, P); + float3 p = transform_point(&worldtocamera, P); float3 v = transform_perspective(&rastertocamera, make_float3(width, height, 0.0f)); /* Create point clamped to frustum */ @@ -707,17 +722,17 @@ float Camera::world_to_raster_size(float3 P) * may be a better way to do this, but calculating differentials from the * point directly ahead seems to produce good enough results. */ #if 0 - float2 dir = direction_to_panorama(&kernel_camera, normalize(D)); + float2 dir = direction_to_panorama(&kernel_camera, kernel_camera_motion.data(), normalize(D)); float3 raster = transform_perspective(&cameratoraster, make_float3(dir.x, dir.y, 0.0f)); ray.t = 1.0f; - camera_sample_panorama(&kernel_camera, raster.x, raster.y, 0.0f, 0.0f, &ray); + camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), raster.x, raster.y, 0.0f, 0.0f, &ray); if(ray.t == 0.0f) { /* No differentials, just use from directly ahead. */ - camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); + camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); } #else - camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); + camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); #endif differential_transfer(&ray.dP, ray.dP, ray.D, ray.dD, ray.D, dist); @@ -729,4 +744,27 @@ float Camera::world_to_raster_size(float3 P) return res; } +bool Camera::use_motion() const +{ + return motion.size() > 1; +} + +float Camera::motion_time(int step) const +{ + return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f; +} + +int Camera::motion_step(float time) const +{ + if(use_motion()) { + for(int step = 0; step < motion.size(); step++) { + if(time == motion_time(step)) { + return step; + } + } + } + + return -1; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 4ec0fe3bc6ebfd74deffd2e1f999bc38f5d9ce6e..37d05c01bd935ccde1428da529bec86220b4615e 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -22,6 +22,7 @@ #include "graph/node.h" #include "util/util_boundbox.h" +#include "util/util_projection.h" #include "util/util_transform.h" #include "util/util_types.h" @@ -140,24 +141,23 @@ public: Transform matrix; /* motion */ - MotionTransform motion; - bool use_motion, use_perspective_motion; + array<Transform> motion; + bool use_perspective_motion; float fov_pre, fov_post; - PerspectiveMotionTransform perspective_motion; /* computed camera parameters */ - Transform screentoworld; - Transform rastertoworld; - Transform ndctoworld; + ProjectionTransform screentoworld; + ProjectionTransform rastertoworld; + ProjectionTransform ndctoworld; Transform cameratoworld; - Transform worldtoraster; - Transform worldtoscreen; - Transform worldtondc; + ProjectionTransform worldtoraster; + ProjectionTransform worldtoscreen; + ProjectionTransform worldtondc; Transform worldtocamera; - Transform rastertocamera; - Transform cameratoraster; + ProjectionTransform rastertocamera; + ProjectionTransform cameratoraster; float3 dx; float3 dy; @@ -176,6 +176,7 @@ public: /* Kernel camera data, copied here for dicing. */ KernelCamera kernel_camera; + array<DecomposedTransform> kernel_camera_motion; /* functions */ Camera(); @@ -199,6 +200,11 @@ public: /* Calculates the width of a pixel at point in world space. */ float world_to_raster_size(float3 P); + /* Motion blur. */ + float motion_time(int step) const; + int motion_step(float time) const; + bool use_motion() const; + private: /* Private utility functions. */ float3 transform_raster_to_world(float raster_x, float raster_y); diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index b62453cf5fc9a0241bd00a9c11559adeccfed747..8dec7e4ea643b78f28aefd5907a6fcb35e1b538e 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -288,7 +288,7 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce VLOG(1) << "Total " << num_distribution << " of light distribution primitives."; /* emission area */ - float4 *distribution = dscene->light_distribution.alloc(num_distribution + 1); + KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1); float totarea = 0.0f; /* triangles */ @@ -334,10 +334,10 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce : scene->default_surface; if(shader->use_mis && shader->has_surface_emission) { - distribution[offset].x = totarea; - distribution[offset].y = __int_as_float(i + mesh->tri_offset); - distribution[offset].z = __int_as_float(shader_flag); - distribution[offset].w = __int_as_float(object_id); + distribution[offset].totarea = totarea; + distribution[offset].prim = i + mesh->tri_offset; + distribution[offset].mesh_light.shader_flag = shader_flag; + distribution[offset].mesh_light.object_id = object_id; offset++; Mesh::Triangle t = mesh->get_triangle(i); @@ -372,10 +372,10 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce if(!light->is_enabled) continue; - distribution[offset].x = totarea; - distribution[offset].y = __int_as_float(~light_index); - distribution[offset].z = 1.0f; - distribution[offset].w = light->size; + distribution[offset].totarea = totarea; + distribution[offset].prim = ~light_index; + distribution[offset].lamp.pad = 1.0f; + distribution[offset].lamp.size = light->size; totarea += lightarea; if(light->size > 0.0f && light->use_mis) @@ -390,15 +390,15 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce } /* normalize cumulative distribution functions */ - distribution[num_distribution].x = totarea; - distribution[num_distribution].y = 0.0f; - distribution[num_distribution].z = 0.0f; - distribution[num_distribution].w = 0.0f; + distribution[num_distribution].totarea = totarea; + distribution[num_distribution].prim = 0.0f; + distribution[num_distribution].lamp.pad = 0.0f; + distribution[num_distribution].lamp.size = 0.0f; if(totarea > 0.0f) { for(size_t i = 0; i < num_distribution; i++) - distribution[i].x /= totarea; - distribution[num_distribution].x = 1.0f; + distribution[i].totarea /= totarea; + distribution[num_distribution].totarea = 1.0f; } if(progress.get_cancel()) return; @@ -620,7 +620,7 @@ void LightManager::device_update_points(Device *, } } - float4 *light_data = dscene->light_data.alloc(num_lights*LIGHT_SIZE); + KernelLight *klights = dscene->lights.alloc(num_lights); if(num_lights == 0) { VLOG(1) << "No effective light, ignoring points update."; @@ -637,8 +637,8 @@ void LightManager::device_update_points(Device *, float3 co = light->co; Shader *shader = (light->shader) ? light->shader : scene->default_light; int shader_id = scene->shader_manager->get_shader_id(shader); - float samples = __int_as_float(light->samples); - float max_bounces = __int_as_float(light->max_bounces); + int samples = light->samples; + int max_bounces = light->max_bounces; float random = (float)light->random_id * (1.0f/(float)0xFFFFFFFF); if(!light->cast_shadow) @@ -661,6 +661,9 @@ void LightManager::device_update_points(Device *, use_light_visibility = true; } + klights[light_index].type = light->type; + klights[light_index].samples = samples; + if(light->type == LIGHT_POINT) { shader_id &= ~SHADER_AREA_LIGHT; @@ -670,10 +673,12 @@ void LightManager::device_update_points(Device *, if(light->use_mis && radius > 0.0f) shader_id |= SHADER_USE_MIS; - light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); - light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f); - light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); + klights[light_index].co[0] = co.x; + klights[light_index].co[1] = co.y; + klights[light_index].co[2] = co.z; + + klights[light_index].spot.radius = radius; + klights[light_index].spot.invarea = invarea; } else if(light->type == LIGHT_DISTANT) { shader_id &= ~SHADER_AREA_LIGHT; @@ -690,10 +695,13 @@ void LightManager::device_update_points(Device *, if(light->use_mis && area > 0.0f) shader_id |= SHADER_USE_MIS; - light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z); - light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea); - light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); + klights[light_index].co[0] = dir.x; + klights[light_index].co[1] = dir.y; + klights[light_index].co[2] = dir.z; + + klights[light_index].distant.invarea = invarea; + klights[light_index].distant.radius = radius; + klights[light_index].distant.cosangle = cosangle; } else if(light->type == LIGHT_BACKGROUND) { uint visibility = scene->background->visibility; @@ -717,11 +725,6 @@ void LightManager::device_update_points(Device *, shader_id |= SHADER_EXCLUDE_SCATTER; use_light_visibility = true; } - - light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f); - light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f); - light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); } else if(light->type == LIGHT_AREA) { float3 axisu = light->axisu*(light->sizeu*light->size); @@ -735,10 +738,20 @@ void LightManager::device_update_points(Device *, if(light->use_mis && area > 0.0f) shader_id |= SHADER_USE_MIS; - light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); - light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z); - light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z); - light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z); + klights[light_index].co[0] = co.x; + klights[light_index].co[1] = co.y; + klights[light_index].co[2] = co.z; + + klights[light_index].area.axisu[0] = axisu.x; + klights[light_index].area.axisu[1] = axisu.y; + klights[light_index].area.axisu[2] = axisu.z; + klights[light_index].area.axisv[0] = axisv.x; + klights[light_index].area.axisv[1] = axisv.y; + klights[light_index].area.axisv[2] = axisv.z; + klights[light_index].area.invarea = invarea; + klights[light_index].area.dir[0] = dir.x; + klights[light_index].area.dir[1] = dir.y; + klights[light_index].area.dir[2] = dir.z; } else if(light->type == LIGHT_SPOT) { shader_id &= ~SHADER_AREA_LIGHT; @@ -754,18 +767,26 @@ void LightManager::device_update_points(Device *, if(light->use_mis && radius > 0.0f) shader_id |= SHADER_USE_MIS; - light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); - light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle); - light_data[light_index*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z); - light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); + klights[light_index].co[0] = co.x; + klights[light_index].co[1] = co.y; + klights[light_index].co[2] = co.z; + + klights[light_index].spot.radius = radius; + klights[light_index].spot.invarea = invarea; + klights[light_index].spot.spot_angle = spot_angle; + klights[light_index].spot.spot_smooth = spot_smooth; + klights[light_index].spot.dir[0] = dir.x; + klights[light_index].spot.dir[1] = dir.y; + klights[light_index].spot.dir[2] = dir.z; } - light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, random, 0.0f, 0.0f); + klights[light_index].shader_id = shader_id; + + klights[light_index].max_bounces = max_bounces; + klights[light_index].random = random; - Transform tfm = light->tfm; - Transform itfm = transform_inverse(tfm); - memcpy(&light_data[light_index*LIGHT_SIZE + 5], &tfm, sizeof(float4)*3); - memcpy(&light_data[light_index*LIGHT_SIZE + 8], &itfm, sizeof(float4)*3); + klights[light_index].tfm = light->tfm; + klights[light_index].itfm = transform_inverse(light->tfm); light_index++; } @@ -782,21 +803,27 @@ void LightManager::device_update_points(Device *, float3 axisu = light->axisu*(light->sizeu*light->size); float3 axisv = light->axisv*(light->sizev*light->size); float area = len(axisu)*len(axisv); - float invarea = (area > 0.0f) ? 1.0f / area : 1.0f; + float invarea = (area > 0.0f)? 1.0f/area: 1.0f; float3 dir = light->dir; dir = safe_normalize(dir); - light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); - light_data[light_index*LIGHT_SIZE + 1] = make_float4(area, axisu.x, axisu.y, axisu.z); - light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z); - light_data[light_index*LIGHT_SIZE + 3] = make_float4(-1, dir.x, dir.y, dir.z); - light_data[light_index*LIGHT_SIZE + 4] = make_float4(-1, 0.0f, 0.0f, 0.0f); - - Transform tfm = light->tfm; - Transform itfm = transform_inverse(tfm); - memcpy(&light_data[light_index*LIGHT_SIZE + 5], &tfm, sizeof(float4)*3); - memcpy(&light_data[light_index*LIGHT_SIZE + 8], &itfm, sizeof(float4)*3); + klights[light_index].co[0] = co.x; + klights[light_index].co[1] = co.y; + klights[light_index].co[2] = co.z; + + klights[light_index].area.axisu[0] = axisu.x; + klights[light_index].area.axisu[1] = axisu.y; + klights[light_index].area.axisu[2] = axisu.z; + klights[light_index].area.axisv[0] = axisv.x; + klights[light_index].area.axisv[1] = axisv.y; + klights[light_index].area.axisv[2] = axisv.z; + klights[light_index].area.invarea = invarea; + klights[light_index].area.dir[0] = dir.x; + klights[light_index].area.dir[1] = dir.y; + klights[light_index].area.dir[2] = dir.z; + klights[light_index].tfm = light->tfm; + klights[light_index].itfm = transform_inverse(light->tfm); light_index++; } @@ -806,7 +833,7 @@ void LightManager::device_update_points(Device *, VLOG(1) << "Number of lights without contribution: " << num_scene_lights - light_index; - dscene->light_data.copy_to_device(); + dscene->lights.copy_to_device(); } void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) @@ -842,7 +869,7 @@ void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *sce void LightManager::device_free(Device *, DeviceScene *dscene) { dscene->light_distribution.free(); - dscene->light_data.free(); + dscene->lights.free(); dscene->light_background_marginal_cdf.free(); dscene->light_background_conditional_cdf.free(); } diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 87bff1fbfb1bdce4405ec59aa9d112e98cc5d43e..1f33cef7c57028a7de76f0eb6f4cfb0ba19039a9 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -884,15 +884,8 @@ void Mesh::add_undisplaced() } } -void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal) +void Mesh::pack_shaders(Scene *scene, uint *tri_shader) { - Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL); - if(attr_vN == NULL) { - /* Happens on objects with just hair. */ - return; - } - - float3 *vN = attr_vN->data_float3(); uint shader_id = 0; uint last_shader = -1; bool last_smooth = false; @@ -900,10 +893,6 @@ void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal) size_t triangles_size = num_triangles(); int *shader_ptr = shader.data(); - bool do_transform = transform_applied; - Transform ntfm = transform_normal; - - /* save shader */ for(size_t i = 0; i < triangles_size; i++) { if(shader_ptr[i] != last_shader || last_smooth != smooth[i]) { last_shader = shader_ptr[i]; @@ -915,7 +904,20 @@ void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal) tri_shader[i] = shader_id; } +} + +void Mesh::pack_normals(float4 *vnormal) +{ + Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL); + if(attr_vN == NULL) { + /* Happens on objects with just hair. */ + return; + } + + bool do_transform = transform_applied; + Transform ntfm = transform_normal; + float3 *vN = attr_vN->data_float3(); size_t verts_size = verts.size(); for(size_t i = 0; i < verts_size; i++) { @@ -1129,6 +1131,32 @@ bool Mesh::has_true_displacement() const return false; } +float Mesh::motion_time(int step) const +{ + return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f; +} + +int Mesh::motion_step(float time) const +{ + if(motion_steps > 1) { + int attr_step = 0; + + for(int step = 0; step < motion_steps; step++) { + float step_time = motion_time(step); + if(step_time == time) { + return attr_step; + } + + /* Center step is stored in a separate attribute. */ + if(step != motion_steps / 2) { + attr_step++; + } + } + } + + return -1; +} + bool Mesh::need_build_bvh() const { return !transform_applied || has_surface_bssrdf; @@ -1148,14 +1176,12 @@ bool Mesh::is_instanced() const MeshManager::MeshManager() { - bvh = NULL; need_update = true; need_flags_update = true; } MeshManager::~MeshManager() { - delete bvh; } void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<AttributeRequestSet>& mesh_attributes) @@ -1459,11 +1485,11 @@ static void update_attribute_element_offset(Mesh *mesh, Transform *tfm = mattr->data_transform(); offset = attr_float3_offset; - assert(attr_float3.size() >= offset + size * 4); - for(size_t k = 0; k < size*4; k++) { + assert(attr_float3.size() >= offset + size * 3); + for(size_t k = 0; k < size*3; k++) { attr_float3[offset+k] = (&tfm->x)[k]; } - attr_float3_offset += size * 4; + attr_float3_offset += size * 3; } else { float4 *data = mattr->data_float4(); @@ -1761,9 +1787,9 @@ void MeshManager::device_update_mesh(Device *, float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size); foreach(Mesh *mesh, scene->meshes) { - mesh->pack_normals(scene, - &tri_shader[mesh->tri_offset], - &vnormal[mesh->vert_offset]); + mesh->pack_shaders(scene, + &tri_shader[mesh->tri_offset]); + mesh->pack_normals(&vnormal[mesh->vert_offset]); mesh->pack_verts(tri_prim_index, &tri_vindex[mesh->tri_offset], &tri_patch[mesh->tri_offset], @@ -1861,11 +1887,8 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * } #endif - if (bvh != NULL) - delete bvh; - - bvh = BVH::create(bparams, scene->objects); - bvh->build(progress); + BVH *bvh = BVH::create(bparams, scene->objects); + bvh->build(progress, &device->stats); if(progress.get_cancel()) { #ifdef WITH_EMBREE @@ -1938,6 +1961,8 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * dscene->data.bvh.scene = NULL; } #endif + + delete bvh; } void MeshManager::device_update_preprocess(Device *device, @@ -2074,7 +2099,9 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen VLOG(1) << "Total " << scene->meshes.size() << " meshes."; - /* Update normals. */ + bool true_displacement_used = false; + size_t total_tess_needed = 0; + foreach(Mesh *mesh, scene->meshes) { foreach(Shader *shader, mesh->used_shaders) { if(shader->need_update_mesh) @@ -2082,6 +2109,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen } if(mesh->need_update) { + /* Update normals. */ mesh->add_face_normals(); mesh->add_vertex_normals(); @@ -2089,57 +2117,53 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen mesh->add_undisplaced(); } + /* Test if we need tesselation. */ + if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE && + mesh->num_subd_verts == 0 && + mesh->subd_params) + { + total_tess_needed++; + } + + /* Test if we need displacement. */ + if(mesh->has_true_displacement()) { + true_displacement_used = true; + } + if(progress.get_cancel()) return; } } /* Tessellate meshes that are using subdivision */ - size_t total_tess_needed = 0; - foreach(Mesh *mesh, scene->meshes) { - if(mesh->need_update && - mesh->subdivision_type != Mesh::SUBDIVISION_NONE && - mesh->num_subd_verts == 0 && - mesh->subd_params) - { - total_tess_needed++; - } - } + if(total_tess_needed) { + size_t i = 0; + foreach(Mesh *mesh, scene->meshes) { + if(mesh->need_update && + mesh->subdivision_type != Mesh::SUBDIVISION_NONE && + mesh->num_subd_verts == 0 && + mesh->subd_params) + { + string msg = "Tessellating "; + if(mesh->name == "") + msg += string_printf("%u/%u", (uint)(i+1), (uint)total_tess_needed); + else + msg += string_printf("%s %u/%u", mesh->name.c_str(), (uint)(i+1), (uint)total_tess_needed); - size_t i = 0; - foreach(Mesh *mesh, scene->meshes) { - if(mesh->need_update && - mesh->subdivision_type != Mesh::SUBDIVISION_NONE && - mesh->num_subd_verts == 0 && - mesh->subd_params) - { - string msg = "Tessellating "; - if(mesh->name == "") - msg += string_printf("%u/%u", (uint)(i+1), (uint)total_tess_needed); - else - msg += string_printf("%s %u/%u", mesh->name.c_str(), (uint)(i+1), (uint)total_tess_needed); + progress.set_status("Updating Mesh", msg); - progress.set_status("Updating Mesh", msg); + DiagSplit dsplit(*mesh->subd_params); + mesh->tessellate(&dsplit); - DiagSplit dsplit(*mesh->subd_params); - mesh->tessellate(&dsplit); + i++; - i++; + if(progress.get_cancel()) return; + } - if(progress.get_cancel()) return; } } /* Update images needed for true displacement. */ - bool true_displacement_used = false; bool old_need_object_flags_update = false; - foreach(Mesh *mesh, scene->meshes) { - if(mesh->need_update && - mesh->has_true_displacement()) - { - true_displacement_used = true; - break; - } - } if(true_displacement_used) { VLOG(1) << "Updating images used for true displacement."; device_update_displacement_images(device, scene, progress); @@ -2165,11 +2189,17 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen /* Update displacement. */ bool displacement_done = false; + size_t num_bvh = 0; + foreach(Mesh *mesh, scene->meshes) { - if(mesh->need_update && - displace(device, dscene, scene, mesh, progress)) - { - displacement_done = true; + if(mesh->need_update) { + if(displace(device, dscene, scene, mesh, progress)) { + displacement_done = true; + } + + if(mesh->need_build_bvh()) { + num_bvh++; + } } } @@ -2184,17 +2214,9 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen if(progress.get_cancel()) return; } - /* Update bvh. */ - size_t num_bvh = 0; - foreach(Mesh *mesh, scene->meshes) { - if(mesh->need_update && mesh->need_build_bvh()) { - num_bvh++; - } - } - TaskPool pool; - i = 0; + size_t i = 0; foreach(Mesh *mesh, scene->meshes) { if(mesh->need_update) { pool.push(function_bind(&Mesh::compute_bvh, diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 62cda1c19b7ec2341b10d86839484fbd3623a451..f3cf78fec4f0321473473afdd5eb5d938692f26d 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -279,7 +279,8 @@ public: void add_vertex_normals(); void add_undisplaced(); - void pack_normals(Scene *scene, uint *shader, float4 *vnormal); + void pack_shaders(Scene *scene, uint *shader); + void pack_normals(float4 *vnormal); void pack_verts(const vector<uint>& tri_prim_index, uint4 *tri_vindex, uint *tri_patch, @@ -304,6 +305,11 @@ public: bool has_motion_blur() const; bool has_true_displacement() const; + /* Convert between normalized -1..1 motion time and index + * in the VERTEX_MOTION attribute. */ + float motion_time(int step) const; + int motion_step(float time) const; + /* Check whether the mesh should have own BVH built separately. Briefly, * own BVH is needed for mesh, if: * diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp index f2347c7961094d331555bca7ce9f2b49f3c3b231..3571beb40d66df53b44e52f7e30d07b5f9d543ea 100644 --- a/intern/cycles/render/mesh_volume.cpp +++ b/intern/cycles/render/mesh_volume.cpp @@ -152,22 +152,22 @@ public: void add_node_with_padding(int x, int y, int z); void create_mesh(vector<float3> &vertices, - vector<int> &indices, - vector<float3> &face_normals); + vector<int> &indices, + vector<float3> &face_normals); private: void generate_vertices_and_quads(vector<int3> &vertices_is, - vector<QuadData> &quads); + vector<QuadData> &quads); void deduplicate_vertices(vector<int3> &vertices, - vector<QuadData> &quads); + vector<QuadData> &quads); void convert_object_space(const vector<int3> &vertices, - vector<float3> &out_vertices); + vector<float3> &out_vertices); void convert_quads_to_tris(const vector<QuadData> &quads, - vector<int> &tris, - vector<float3> &face_normals); + vector<int> &tris, + vector<float3> &face_normals); }; VolumeMeshBuilder::VolumeMeshBuilder(VolumeParams *volume_params) @@ -224,8 +224,8 @@ void VolumeMeshBuilder::add_node_with_padding(int x, int y, int z) } void VolumeMeshBuilder::create_mesh(vector<float3> &vertices, - vector<int> &indices, - vector<float3> &face_normals) + vector<int> &indices, + vector<float3> &face_normals) { /* We create vertices in index space (is), and only convert them to object * space when done. */ @@ -260,8 +260,8 @@ void VolumeMeshBuilder::generate_vertices_and_quads( /* Compute min and max coords of the node in index space. */ int3 min = make_int3((x - pad_offset.x)*CUBE_SIZE, - (y - pad_offset.y)*CUBE_SIZE, - (z - pad_offset.z)*CUBE_SIZE); + (y - pad_offset.y)*CUBE_SIZE, + (z - pad_offset.z)*CUBE_SIZE); /* Maximum is just CUBE_SIZE voxels away from minimum on each axis. */ int3 max = make_int3(min.x + CUBE_SIZE, min.y + CUBE_SIZE, min.z + CUBE_SIZE); @@ -316,7 +316,7 @@ void VolumeMeshBuilder::generate_vertices_and_quads( } void VolumeMeshBuilder::deduplicate_vertices(vector<int3> &vertices, - vector<QuadData> &quads) + vector<QuadData> &quads) { vector<int3> sorted_vertices = vertices; std::sort(sorted_vertices.begin(), sorted_vertices.end()); @@ -355,7 +355,7 @@ void VolumeMeshBuilder::deduplicate_vertices(vector<int3> &vertices, } void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices, - vector<float3> &out_vertices) + vector<float3> &out_vertices) { out_vertices.reserve(vertices.size()); @@ -369,8 +369,8 @@ void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices, } void VolumeMeshBuilder::convert_quads_to_tris(const vector<QuadData> &quads, - vector<int> &tris, - vector<float3> &face_normals) + vector<int> &tris, + vector<float3> &face_normals) { int index_offset = 0; tris.resize(quads.size()*6); @@ -399,8 +399,8 @@ struct VoxelAttributeGrid { }; void MeshManager::create_volume_mesh(Scene *scene, - Mesh *mesh, - Progress& progress) + Mesh *mesh, + Progress& progress) { string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str()); progress.set_status("Updating Mesh", msg); @@ -470,8 +470,8 @@ void MeshManager::create_volume_mesh(Scene *scene, const int3 resolution = volume_params.resolution; float3 start_point = make_float3(0.0f, 0.0f, 0.0f); float3 cell_size = make_float3(1.0f/resolution.x, - 1.0f/resolution.y, - 1.0f/resolution.z); + 1.0f/resolution.y, + 1.0f/resolution.z); if(attr) { const Transform *tfm = attr->data_transform(); @@ -575,12 +575,12 @@ void MeshManager::create_volume_mesh(Scene *scene, /* Print stats. */ VLOG(1) << "Memory usage volume mesh: " - << ((vertices.size() + face_normals.size())*sizeof(float3) + indices.size()*sizeof(int))/(1024.0*1024.0) - << "Mb."; + << ((vertices.size() + face_normals.size())*sizeof(float3) + indices.size()*sizeof(int))/(1024.0*1024.0) + << "Mb."; VLOG(1) << "Memory usage volume grid: " - << (resolution.x*resolution.y*resolution.z*sizeof(float))/(1024.0*1024.0) - << "Mb."; + << (resolution.x*resolution.y*resolution.z*sizeof(float))/(1024.0*1024.0) + << "Mb."; } CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 41c9730e6fb18092fe5dabebdebcd330020ce7ab..d732189af664a721d6991302c2d0dc12bbb8fb51 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -117,8 +117,7 @@ Transform TextureMapping::compute_transform() case NORMAL: /* no translation for normals, and inverse transpose */ mat = rmat*smat; - mat = transform_inverse(mat); - mat = transform_transpose(mat); + mat = transform_transposed_inverse(mat); break; } @@ -153,7 +152,6 @@ void TextureMapping::compile(SVMCompiler& compiler, int offset_in, int offset_ou compiler.add_node(tfm.x); compiler.add_node(tfm.y); compiler.add_node(tfm.z); - compiler.add_node(tfm.w); if(use_minmax) { compiler.add_node(NODE_MIN_MAX, offset_out, offset_out); @@ -193,9 +191,7 @@ void TextureMapping::compile_end(SVMCompiler& compiler, ShaderInput *vector_in, void TextureMapping::compile(OSLCompiler &compiler) { if(!skip()) { - Transform tfm = transform_transpose(compute_transform()); - - compiler.parameter("mapping", tfm); + compiler.parameter("mapping", compute_transform()); compiler.parameter("use_mapping", 1); } } @@ -1434,7 +1430,6 @@ void PointDensityTextureNode::compile(SVMCompiler& compiler) compiler.add_node(tfm.x); compiler.add_node(tfm.y); compiler.add_node(tfm.z); - compiler.add_node(tfm.w); } } else { @@ -1478,7 +1473,7 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler) compiler.parameter("filename", string_printf("@%d", slot).c_str()); } if(space == NODE_TEX_VOXEL_SPACE_WORLD) { - compiler.parameter("mapping", transform_transpose(tfm)); + compiler.parameter("mapping", tfm); compiler.parameter("use_mapping", 1); } compiler.parameter(this, "interpolation"); @@ -1558,8 +1553,7 @@ void MappingNode::compile(SVMCompiler& compiler) void MappingNode::compile(OSLCompiler& compiler) { - Transform tfm = transform_transpose(tex_mapping.compute_transform()); - compiler.parameter("Matrix", tfm); + compiler.parameter("Matrix", tex_mapping.compute_transform()); compiler.parameter_point("mapping_min", tex_mapping.min); compiler.parameter_point("mapping_max", tex_mapping.max); compiler.parameter("use_minmax", tex_mapping.use_minmax); @@ -1864,7 +1858,7 @@ NODE_DEFINE(AnisotropicBsdfNode) SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT); - SOCKET_IN_FLOAT(roughness, "Roughness", 0.2f); + SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f); SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f); SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f); @@ -1924,7 +1918,7 @@ NODE_DEFINE(GlossyBsdfNode) distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID); distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID); SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID); - SOCKET_IN_FLOAT(roughness, "Roughness", 0.2f); + SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f); SOCKET_OUT_CLOSURE(BSDF, "BSDF"); @@ -3220,7 +3214,6 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler) compiler.add_node(ob_itfm.x); compiler.add_node(ob_itfm.y); compiler.add_node(ob_itfm.z); - compiler.add_node(ob_itfm.w); } } @@ -3259,7 +3252,7 @@ void TextureCoordinateNode::compile(OSLCompiler& compiler) if(compiler.output_type() == SHADER_TYPE_VOLUME) compiler.parameter("is_volume", true); compiler.parameter(this, "use_transform"); - Transform ob_itfm = transform_transpose(transform_inverse(ob_tfm)); + Transform ob_itfm = transform_transposed_inverse(ob_tfm); compiler.parameter("object_itfm", ob_itfm); compiler.parameter(this, "from_dupli"); @@ -5792,6 +5785,15 @@ DisplacementNode::DisplacementNode() { } +void DisplacementNode::constant_fold(const ConstantFolder& folder) +{ + if(folder.all_inputs_constant()) { + if((height - midlevel == 0.0f) || (scale == 0.0f)) { + folder.make_zero(); + } + } +} + void DisplacementNode::compile(SVMCompiler& compiler) { ShaderInput *height_in = input("Height"); @@ -5843,6 +5845,16 @@ VectorDisplacementNode::VectorDisplacementNode() { } +void VectorDisplacementNode::constant_fold(const ConstantFolder& folder) +{ + if(folder.all_inputs_constant()) { + if((vector == make_float3(0.0f, 0.0f, 0.0f) && midlevel == 0.0f) || + (scale == 0.0f)) { + folder.make_zero(); + } + } +} + void VectorDisplacementNode::attributes(Shader *shader, AttributeRequestSet *attributes) { if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) { diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 33df28663416896e375f09b9f6eb60fb354f06ac..58c3d472cd31fb4b264efd6dd9ddab7507bfbb5c 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -1063,6 +1063,7 @@ public: class DisplacementNode : public ShaderNode { public: SHADER_NODE_CLASS(DisplacementNode) + void constant_fold(const ConstantFolder& folder); virtual int get_feature() { return NODE_FEATURE_BUMP; } @@ -1079,6 +1080,7 @@ public: SHADER_NODE_CLASS(VectorDisplacementNode) void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_attribute_dependency() { return true; } + void constant_fold(const ConstantFolder& folder); virtual int get_feature() { return NODE_FEATURE_BUMP; } diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index b981d2b88496682f3fc68b3cedfd61dd32f6c8a8..138de250c5f55a39305b3dd89723172ed575a61a 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -33,6 +33,52 @@ CCL_NAMESPACE_BEGIN +/* Global state of object transform update. */ + +struct UpdateObjectTransformState { + /* Global state used by device_update_object_transform(). + * Common for both threaded and non-threaded update. + */ + + /* Type of the motion required by the scene settings. */ + Scene::MotionType need_motion; + + /* Mapping from particle system to a index in packed particle array. + * Only used for read. + */ + map<ParticleSystem*, int> particle_offset; + + /* Mesh area. + * Used to avoid calculation of mesh area multiple times. Used for both + * read and write. Acquire surface_area_lock to keep it all thread safe. + */ + map<Mesh*, float> surface_area_map; + + /* Motion offsets for each object. */ + array<uint> motion_offset; + + /* Packed object arrays. Those will be filled in. */ + uint *object_flag; + KernelObject *objects; + Transform *object_motion_pass; + DecomposedTransform *object_motion; + + /* Flags which will be synchronized to Integrator. */ + bool have_motion; + bool have_curves; + + /* ** Scheduling queue. ** */ + + Scene *scene; + + /* Some locks to keep everything thread-safe. */ + thread_spin_lock queue_lock; + thread_spin_lock surface_area_lock; + + /* First unused object index in the queue. */ + int queue_start_object; +}; + /* Object */ NODE_DEFINE(Object) @@ -48,6 +94,7 @@ NODE_DEFINE(Object) SOCKET_BOOLEAN(hide_on_missing_motion, "Hide on Missing Motion", false); SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f)); + SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>()); SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false); @@ -60,45 +107,54 @@ Object::Object() particle_system = NULL; particle_index = 0; bounds = BoundBox::empty; - motion.pre = transform_empty(); - motion.mid = transform_empty(); - motion.post = transform_empty(); - use_motion = false; } Object::~Object() { } -void Object::compute_bounds(bool motion_blur) +void Object::update_motion() { - BoundBox mbounds = mesh->bounds; + if(!use_motion()) { + return; + } - if(motion_blur && use_motion) { - MotionTransform mtfm = motion; + bool have_motion = false; - if(hide_on_missing_motion) { - /* Hide objects that have no valid previous or next transform, for - * example particle that stop existing. TODO: add support for this - * case in the kernel so we don't get render artifacts. */ - if(mtfm.pre == transform_empty() || - mtfm.post == transform_empty()) { - bounds = BoundBox::empty; + for(size_t i = 0; i < motion.size(); i++) { + if(motion[i] == transform_empty()) { + if(hide_on_missing_motion) { + /* Hide objects that have no valid previous or next + * transform, for example particle that stop existing. It + * would be better to handle this in the kernel and make + * objects invisible outside certain motion steps. */ + tfm = transform_empty(); + motion.clear(); return; } + else { + /* Otherwise just copy center motion. */ + motion[i] = tfm; + } } - /* In case of missing motion information for previous/next frame, - * assume there is no motion. */ - if(mtfm.pre == transform_empty()) { - mtfm.pre = tfm; - } - if(mtfm.post == transform_empty()) { - mtfm.post = tfm; - } + /* Test if any of the transforms are actually different. */ + have_motion = have_motion || motion[i] != tfm; + } - MotionTransform decomp; - transform_motion_decompose(&decomp, &mtfm, &tfm); + /* Clear motion array if there is no actual motion. */ + if(!have_motion) { + motion.clear(); + } +} + +void Object::compute_bounds(bool motion_blur) +{ + BoundBox mbounds = mesh->bounds; + + if(motion_blur && use_motion()) { + array<DecomposedTransform> decomp(motion.size()); + transform_motion_decompose(decomp.data(), motion.data(), motion.size()); bounds = BoundBox::empty; @@ -108,11 +164,12 @@ void Object::compute_bounds(bool motion_blur) for(float t = 0.0f; t < 1.0f; t += (1.0f/128.0f)) { Transform ttfm; - transform_motion_interpolate(&ttfm, &decomp, t); + transform_motion_array_interpolate(&ttfm, decomp.data(), motion.size(), t); bounds.grow(mbounds.transformed(&ttfm)); } } else { + /* No motion blur case. */ if(mesh->transform_applied) { bounds = mbounds; } @@ -132,7 +189,7 @@ void Object::apply_transform(bool apply_to_motion) /* store matrix to transform later. when accessing these as attributes we * do not want the transform to be applied for consistency between static * and dynamic BVH, so we do it on packing. */ - mesh->transform_normal = transform_transpose(transform_inverse(tfm)); + mesh->transform_normal = transform_transposed_inverse(tfm); /* apply to mesh vertices */ for(size_t i = 0; i < mesh->verts.size(); i++) @@ -232,27 +289,30 @@ void Object::tag_update(Scene *scene) scene->object_manager->need_update = true; } -vector<float> Object::motion_times() +bool Object::use_motion() const { - /* compute times at which we sample motion for this object */ - vector<float> times; - - if(!mesh || mesh->motion_steps == 1) - return times; + return (motion.size() > 1); +} - int motion_steps = mesh->motion_steps; +float Object::motion_time(int step) const +{ + return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f; +} - for(int step = 0; step < motion_steps; step++) { - if(step != motion_steps / 2) { - float time = 2.0f * step / (motion_steps - 1) - 1.0f; - times.push_back(time); +int Object::motion_step(float time) const +{ + if(use_motion()) { + for(size_t step = 0; step < motion.size(); step++) { + if(time == motion_time(step)) { + return step; + } } } - return times; + return -1; } -bool Object::is_traceable() +bool Object::is_traceable() const { /* Mesh itself can be empty,can skip all such objects. */ if(!bounds.valid() || bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) { @@ -289,8 +349,8 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s Object *ob, int object_index) { - float4 *objects = state->objects; - float4 *objects_vector = state->objects_vector; + KernelObject& kobject = state->objects[object_index]; + Transform *object_motion_pass = state->object_motion_pass; Mesh *mesh = ob->mesh; uint flag = 0; @@ -357,15 +417,13 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s } } - /* Pack in texture. */ - int offset = object_index*OBJECT_SIZE; - - /* OBJECT_TRANSFORM */ - memcpy(&objects[offset], &tfm, sizeof(float4)*3); - /* OBJECT_INVERSE_TRANSFORM */ - memcpy(&objects[offset+4], &itfm, sizeof(float4)*3); - /* OBJECT_PROPERTIES */ - objects[offset+12] = make_float4(surface_area, pass_id, random_number, __int_as_float(particle_index)); + kobject.tfm = tfm; + kobject.itfm = itfm; + kobject.surface_area = surface_area; + kobject.pass_id = pass_id; + kobject.random_number = random_number; + kobject.particle_index = particle_index; + kobject.motion_offset = 0; if(mesh->use_motion_blur) { state->have_motion = true; @@ -375,50 +433,56 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s } if(state->need_motion == Scene::MOTION_PASS) { - /* Motion transformations, is world/object space depending if mesh - * comes with deformed position in object space, or if we transform - * the shading point in world space. - */ - MotionTransform mtfm = ob->motion; + /* Clear motion array if there is no actual motion. */ + ob->update_motion(); - /* In case of missing motion information for previous/next frame, - * assume there is no motion. */ - if(!ob->use_motion || mtfm.pre == transform_empty()) { - mtfm.pre = ob->tfm; + /* Compute motion transforms. */ + Transform tfm_pre, tfm_post; + if(ob->use_motion()) { + tfm_pre = ob->motion[0]; + tfm_post = ob->motion[ob->motion.size() - 1]; } - if(!ob->use_motion || mtfm.post == transform_empty()) { - mtfm.post = ob->tfm; + else { + tfm_pre = tfm; + tfm_post = tfm; } + /* Motion transformations, is world/object space depending if mesh + * comes with deformed position in object space, or if we transform + * the shading point in world space. */ if(!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) { - mtfm.pre = mtfm.pre * itfm; - mtfm.post = mtfm.post * itfm; + tfm_pre = tfm_pre * itfm; + tfm_post = tfm_post * itfm; } - memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+0], &mtfm.pre, sizeof(float4)*3); - memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+3], &mtfm.post, sizeof(float4)*3); + int motion_pass_offset = object_index*OBJECT_MOTION_PASS_SIZE; + object_motion_pass[motion_pass_offset + 0] = tfm_pre; + object_motion_pass[motion_pass_offset + 1] = tfm_post; } else if(state->need_motion == Scene::MOTION_BLUR) { - if(ob->use_motion) { - /* decompose transformations for interpolation. */ - MotionTransform decomp; + if(ob->use_motion()) { + kobject.motion_offset = state->motion_offset[object_index]; - transform_motion_decompose(&decomp, &ob->motion, &ob->tfm); - memcpy(&objects[offset], &decomp, sizeof(float4)*12); + /* Decompose transforms for interpolation. */ + DecomposedTransform *decomp = state->object_motion + kobject.motion_offset; + transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size()); flag |= SD_OBJECT_MOTION; state->have_motion = true; } } /* Dupli object coords and motion info. */ + kobject.dupli_generated[0] = ob->dupli_generated[0]; + kobject.dupli_generated[1] = ob->dupli_generated[1]; + kobject.dupli_generated[2] = ob->dupli_generated[2]; + kobject.numkeys = mesh->curve_keys.size(); + kobject.dupli_uv[0] = ob->dupli_uv[0]; + kobject.dupli_uv[1] = ob->dupli_uv[1]; int totalsteps = mesh->motion_steps; - int numsteps = (totalsteps - 1)/2; - int numverts = mesh->verts.size(); - int numkeys = mesh->curve_keys.size(); - - objects[offset+13] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], __int_as_float(numkeys)); - objects[offset+14] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], __int_as_float(numsteps), __int_as_float(numverts)); - objects[offset+15] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + kobject.numsteps = (totalsteps - 1)/2; + kobject.numverts = mesh->verts.size();; + kobject.patch_map_offset = 0; + kobject.attribute_map_offset = 0; /* Object flag. */ if(ob->use_holdout) { @@ -475,7 +539,6 @@ void ObjectManager::device_update_object_transform_task( void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, - uint *object_flag, Progress& progress) { UpdateObjectTransformState state; @@ -485,13 +548,29 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, state.scene = scene; state.queue_start_object = 0; - state.object_flag = object_flag; - state.objects = dscene->objects.alloc(OBJECT_SIZE*scene->objects.size()); + state.objects = dscene->objects.alloc(scene->objects.size()); + state.object_flag = dscene->object_flag.alloc(scene->objects.size()); + state.object_motion = NULL; + state.object_motion_pass = NULL; + if(state.need_motion == Scene::MOTION_PASS) { - state.objects_vector = dscene->objects_vector.alloc(OBJECT_VECTOR_SIZE*scene->objects.size()); + state.object_motion_pass = dscene->object_motion_pass.alloc(OBJECT_MOTION_PASS_SIZE*scene->objects.size()); } - else { - state.objects_vector = NULL; + else if(state.need_motion == Scene::MOTION_BLUR) { + /* Set object offsets into global object motion array. */ + uint *motion_offsets = state.motion_offset.resize(scene->objects.size()); + uint motion_offset = 0; + + foreach(Object *ob, scene->objects) { + *motion_offsets = motion_offset; + motion_offsets++; + + /* Clear motion array if there is no actual motion. */ + ob->update_motion(); + motion_offset += ob->motion.size(); + } + + state.object_motion = dscene->object_motion.alloc(motion_offset); } /* Particle system device offsets @@ -534,7 +613,10 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, dscene->objects.copy_to_device(); if(state.need_motion == Scene::MOTION_PASS) { - dscene->objects_vector.copy_to_device(); + dscene->object_motion_pass.copy_to_device(); + } + else if(state.need_motion == Scene::MOTION_BLUR) { + dscene->object_motion.copy_to_device(); } dscene->data.bvh.have_motion = state.have_motion; @@ -554,12 +636,9 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc if(scene->objects.size() == 0) return; - /* object info flag */ - uint *object_flag = dscene->object_flag.alloc(scene->objects.size()); - /* set object transform matrices, before applying static transforms */ progress.set_status("Updating Objects", "Copying Transformations to device"); - device_update_transforms(dscene, scene, object_flag, progress); + device_update_transforms(dscene, scene, progress); if(progress.get_cancel()) return; @@ -567,7 +646,7 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc /* todo: do before to support getting object level coords? */ if(scene->params.bvh_type == SceneParams::BVH_STATIC) { progress.set_status("Updating Objects", "Applying Static Transformations"); - apply_static_transforms(dscene, scene, object_flag, progress); + apply_static_transforms(dscene, scene, progress); } } @@ -586,9 +665,10 @@ void ObjectManager::device_update_flags(Device *, if(scene->objects.size() == 0) return; - /* object info flag */ + /* Object info flag. */ uint *object_flag = dscene->object_flag.data(); + /* Object volume intersection. */ vector<Object *> volume_objects; bool has_volume_objects = false; foreach(Object *object, scene->objects) { @@ -642,7 +722,7 @@ void ObjectManager::device_update_flags(Device *, ++object_index; } - /* allocate object flag */ + /* Copy object flag. */ dscene->object_flag.copy_to_device(); } @@ -652,27 +732,26 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc return; } - uint4* objects = (uint4*)dscene->objects.data(); + KernelObject *kobjects = dscene->objects.data(); bool update = false; int object_index = 0; foreach(Object *object, scene->objects) { Mesh* mesh = object->mesh; - int offset = object_index*OBJECT_SIZE + 15; if(mesh->patch_table) { uint patch_map_offset = 2*(mesh->patch_table_offset + mesh->patch_table->total_size() - mesh->patch_table->num_nodes * PATCH_NODE_SIZE) - mesh->patch_offset; - if(objects[offset].x != patch_map_offset) { - objects[offset].x = patch_map_offset; + if(kobjects[object_index].patch_map_offset != patch_map_offset) { + kobjects[object_index].patch_map_offset = patch_map_offset; update = true; } } - if(objects[offset].y != mesh->attr_map_offset) { - objects[offset].y = mesh->attr_map_offset; + if(kobjects[object_index].attribute_map_offset != mesh->attr_map_offset) { + kobjects[object_index].attribute_map_offset = mesh->attr_map_offset; update = true; } @@ -687,11 +766,12 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc void ObjectManager::device_free(Device *, DeviceScene *dscene) { dscene->objects.free(); - dscene->objects_vector.free(); + dscene->object_motion_pass.free(); + dscene->object_motion.free(); dscene->object_flag.free(); } -void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress) +void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress& progress) { /* todo: normals and displacement should be done before applying transform! */ /* todo: create objects/meshes in right order! */ @@ -715,6 +795,8 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u if(progress.get_cancel()) return; + uint *object_flag = dscene->object_flag.data(); + /* apply transforms for objects with single user meshes */ foreach(Object *object, scene->objects) { /* Annoying feedback loop here: we can't use is_instanced() because @@ -725,7 +807,7 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u if((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) && !object->mesh->has_true_displacement() && object->mesh->subdivision_type == Mesh::SUBDIVISION_NONE) { - if(!(motion_blur && object->use_motion)) { + if(!(motion_blur && object->use_motion())) { if(!object->mesh->transform_applied) { object->apply_transform(apply_to_motion); object->mesh->transform_applied = true; diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index acdb1b641238441ed4c2b7b03bf81a74129d1282..c7212ae25f915baefc538af9760b1f887ce084cf 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -35,6 +35,7 @@ class ParticleSystem; class Progress; class Scene; struct Transform; +struct UpdateObjectTransformState; /* Object */ @@ -49,8 +50,7 @@ public: int pass_id; vector<ParamValue> attributes; uint visibility; - MotionTransform motion; - bool use_motion; + array<Transform> motion; bool hide_on_missing_motion; bool use_holdout; bool is_shadow_catcher; @@ -69,12 +69,17 @@ public: void compute_bounds(bool motion_blur); void apply_transform(bool apply_to_motion); - vector<float> motion_times(); + /* Convert between normalized -1..1 motion time and index + * in the motion array. */ + bool use_motion() const; + float motion_time(int step) const; + int motion_step(float time) const; + void update_motion(); /* Check whether object is traceable and it worth adding it to * kernel scene. */ - bool is_traceable(); + bool is_traceable() const; /* Combine object's visibility with all possible internal run-time * determined flags which denotes trace-time visibility. @@ -95,7 +100,6 @@ public: void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_update_transforms(DeviceScene *dscene, Scene *scene, - uint *object_flag, Progress& progress); void device_update_flags(Device *device, @@ -109,49 +113,9 @@ public: void tag_update(Scene *scene); - void apply_static_transforms(DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress); + void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress& progress); protected: - /* Global state of object transform update. */ - struct UpdateObjectTransformState { - /* Global state used by device_update_object_transform(). - * Common for both threaded and non-threaded update. - */ - - /* Type of the motion required by the scene settings. */ - Scene::MotionType need_motion; - - /* Mapping from particle system to a index in packed particle array. - * Only used for read. - */ - map<ParticleSystem*, int> particle_offset; - - /* Mesh area. - * Used to avoid calculation of mesh area multiple times. Used for both - * read and write. Acquire surface_area_lock to keep it all thread safe. - */ - map<Mesh*, float> surface_area_map; - - /* Packed object arrays. Those will be filled in. */ - uint *object_flag; - float4 *objects; - float4 *objects_vector; - - /* Flags which will be synchronized to Integrator. */ - bool have_motion; - bool have_curves; - - /* ** Scheduling queue. ** */ - - Scene *scene; - - /* Some locks to keep everything thread-safe. */ - thread_spin_lock queue_lock; - thread_spin_lock surface_area_lock; - - /* First unused object index in the queue. */ - int queue_start_object; - }; void device_update_object_transform(UpdateObjectTransformState *state, Object *ob, const int object_index); diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 9e931280691d79a25f19617f93b6df7bdca9d86c..f1a22350060b547735508edf0e4a552d508bbf86 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -34,6 +34,7 @@ #include "util/util_md5.h" #include "util/util_path.h" #include "util/util_progress.h" +#include "util/util_projection.h" #endif @@ -832,7 +833,9 @@ void OSLCompiler::parameter(ShaderNode* node, const char *name) case SocketType::TRANSFORM: { Transform value = node->get_transform(socket); - ss->Parameter(uname, TypeDesc::TypeMatrix, &value); + ProjectionTransform projection(value); + projection = projection_transpose(projection); + ss->Parameter(uname, TypeDesc::TypeMatrix, &projection); break; } case SocketType::BOOLEAN_ARRAY: @@ -900,7 +903,11 @@ void OSLCompiler::parameter(ShaderNode* node, const char *name) case SocketType::TRANSFORM_ARRAY: { const array<Transform>& value = node->get_transform_array(socket); - ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, value.size()), value.data()); + array<ProjectionTransform> fvalue(value.size()); + for(size_t i = 0; i < value.size(); i++) { + fvalue[i] = projection_transpose(ProjectionTransform(value[i])); + } + ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, fvalue.size()), fvalue.data()); break; } case SocketType::CLOSURE: @@ -967,7 +974,9 @@ void OSLCompiler::parameter(const char *name, ustring s) void OSLCompiler::parameter(const char *name, const Transform& tfm) { OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; - ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&tfm); + ProjectionTransform projection(tfm); + projection = projection_transpose(projection); + ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&projection); } void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen) diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp index 3ee620c9d0120672c8626edf04138a2ef4cb5857..e4be3306d7e472dd32130791807a4ab37d3bb798 100644 --- a/intern/cycles/render/particles.cpp +++ b/intern/cycles/render/particles.cpp @@ -62,14 +62,10 @@ void ParticleSystemManager::device_update_particles(Device *, DeviceScene *dscen for(size_t j = 0; j < scene->particle_systems.size(); j++) num_particles += scene->particle_systems[j]->particles.size(); - float4 *particles = dscene->particles.alloc(PARTICLE_SIZE*num_particles); + KernelParticle *kparticles = dscene->particles.alloc(num_particles); /* dummy particle */ - particles[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - particles[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - particles[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - particles[3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - particles[4] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + memset(kparticles, 0, sizeof(KernelParticle)); int i = 1; for(size_t j = 0; j < scene->particle_systems.size(); j++) { @@ -78,13 +74,15 @@ void ParticleSystemManager::device_update_particles(Device *, DeviceScene *dscen for(size_t k = 0; k < psys->particles.size(); k++) { /* pack in texture */ Particle& pa = psys->particles[k]; - int offset = i*PARTICLE_SIZE; - particles[offset] = make_float4(__uint_as_float(pa.index), pa.age, pa.lifetime, pa.size); - particles[offset+1] = pa.rotation; - particles[offset+2] = make_float4(pa.location.x, pa.location.y, pa.location.z, pa.velocity.x); - particles[offset+3] = make_float4(pa.velocity.y, pa.velocity.z, pa.angular_velocity.x, pa.angular_velocity.y); - particles[offset+4] = make_float4(pa.angular_velocity.z, 0.0f, 0.0f, 0.0f); + kparticles[i].index = pa.index; + kparticles[i].age = pa.age; + kparticles[i].lifetime = pa.lifetime; + kparticles[i].size = pa.size; + kparticles[i].rotation = pa.rotation; + kparticles[i].location = float3_to_float4(pa.location); + kparticles[i].velocity = float3_to_float4(pa.velocity); + kparticles[i].angular_velocity = float3_to_float4(pa.angular_velocity); i++; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 1e5866e2806adc2efb07d9ba858608a71b6bb188..2393f9db8aa7046e78a28ec8eba46a1abe7e2bae 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -60,19 +60,21 @@ DeviceScene::DeviceScene(Device *device) curve_keys(device, "__curve_keys", MEM_TEXTURE), patches(device, "__patches", MEM_TEXTURE), objects(device, "__objects", MEM_TEXTURE), - objects_vector(device, "__objects_vector", MEM_TEXTURE), + object_motion_pass(device, "__object_motion_pass", MEM_TEXTURE), + object_motion(device, "__object_motion", MEM_TEXTURE), + object_flag(device, "__object_flag", MEM_TEXTURE), + camera_motion(device, "__camera_motion", MEM_TEXTURE), attributes_map(device, "__attributes_map", MEM_TEXTURE), attributes_float(device, "__attributes_float", MEM_TEXTURE), attributes_float3(device, "__attributes_float3", MEM_TEXTURE), attributes_uchar4(device, "__attributes_uchar4", MEM_TEXTURE), light_distribution(device, "__light_distribution", MEM_TEXTURE), - light_data(device, "__light_data", MEM_TEXTURE), + lights(device, "__lights", MEM_TEXTURE), light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_TEXTURE), light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_TEXTURE), particles(device, "__particles", MEM_TEXTURE), svm_nodes(device, "__svm_nodes", MEM_TEXTURE), - shader_flag(device, "__shader_flag", MEM_TEXTURE), - object_flag(device, "__object_flag", MEM_TEXTURE), + shaders(device, "__shaders", MEM_TEXTURE), lookup_table(device, "__lookup_table", MEM_TEXTURE), sobol_directions(device, "__sobol_directions", MEM_TEXTURE) { @@ -213,6 +215,11 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel() || device->have_error()) return; + progress.set_status("Updating Hair Systems"); + curve_system_manager->device_update(device, &dscene, this, progress); + + if(progress.get_cancel() || device->have_error()) return; + progress.set_status("Updating Particle Systems"); particle_system_manager->device_update(device, &dscene, this, progress); diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index ea9485ff23064fd73660378117f654d2be98d5e7..9700732f9484203d0a7b650ba855ad112223b49f 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -86,8 +86,13 @@ public: device_vector<uint> patches; /* objects */ - device_vector<float4> objects; - device_vector<float4> objects_vector; + device_vector<KernelObject> objects; + device_vector<Transform> object_motion_pass; + device_vector<DecomposedTransform> object_motion; + device_vector<uint> object_flag; + + /* cameras */ + device_vector<DecomposedTransform> camera_motion; /* attributes */ device_vector<uint4> attributes_map; @@ -96,18 +101,17 @@ public: device_vector<uchar4> attributes_uchar4; /* lights */ - device_vector<float4> light_distribution; - device_vector<float4> light_data; + device_vector<KernelLightDistribution> light_distribution; + device_vector<KernelLight> lights; device_vector<float2> light_background_marginal_cdf; device_vector<float2> light_background_conditional_cdf; /* particles */ - device_vector<float4> particles; + device_vector<KernelParticle> particles; /* shaders */ device_vector<int4> svm_nodes; - device_vector<uint> shader_flag; - device_vector<uint> object_flag; + device_vector<KernelShader> shaders; /* lookup tables */ device_vector<float> lookup_table; @@ -158,7 +162,6 @@ public: bool use_bvh_spatial_split; bool use_bvh_unaligned_nodes; int num_bvh_time_steps; - bool persistent_data; int texture_limit; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index e8d9558c38df25c61b12ab394b1de50161840464..bb636dd962abbc5e9c1a26ad700ba14a67367bc5 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -55,7 +55,7 @@ Session::Session(const SessionParams& params_) device = Device::create(params.device, stats, params.background); - if(params.background && params.output_path.empty()) { + if(params.background && !params.write_render_cb) { buffers = NULL; display = NULL; } @@ -101,7 +101,7 @@ Session::~Session() wait(); } - if(!params.output_path.empty()) { + if(params.write_render_cb) { /* tonemap and write out image if requested */ delete display; @@ -109,8 +109,10 @@ Session::~Session() display->reset(buffers->params); tonemap(params.samples); - progress.set_status("Writing Image", params.output_path); - display->write(params.output_path); + int w = display->draw_width; + int h = display->draw_height; + uchar4 *pixels = display->rgba_byte.copy_from_device(0, w, h); + params.write_render_cb((uchar*)pixels, w, h, 4); } /* clean up */ @@ -656,13 +658,13 @@ DeviceRequestedFeatures Session::get_requested_device_features() */ requested_features.use_hair = false; requested_features.use_object_motion = false; - requested_features.use_camera_motion = scene->camera->use_motion; + requested_features.use_camera_motion = scene->camera->use_motion(); foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; if(mesh->num_curves()) { requested_features.use_hair = true; } - requested_features.use_object_motion |= object->use_motion | mesh->use_motion_blur; + requested_features.use_object_motion |= object->use_motion() | mesh->use_motion_blur; requested_features.use_camera_motion |= mesh->use_motion_blur; #ifdef WITH_OPENSUBDIV if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) { diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 8495d95666b772b598a77b4f213c06a371611701..e63cad0d9777c8b6dfebc533efad3df8905b1309 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -45,7 +45,6 @@ public: DeviceInfo device; bool background; bool progressive_refine; - string output_path; bool progressive; bool experimental; @@ -71,11 +70,15 @@ public: ShadingSystem shadingsystem; + function<bool(const uchar *pixels, + int width, + int height, + int channels)> write_render_cb; + SessionParams() { background = false; progressive_refine = false; - output_path = ""; progressive = false; experimental = false; @@ -106,7 +109,6 @@ public: { return !(device == params.device && background == params.background && progressive_refine == params.progressive_refine - && output_path == params.output_path /* && samples == params.samples */ && progressive == params.progressive && experimental == params.experimental diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 578c61a3e7958f6b761e473620fd077fa7d8479d..ec52c51e337f16112f37040541685542b15d0aae 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -432,14 +432,12 @@ void ShaderManager::device_update_common(Device *device, Scene *scene, Progress& /*progress*/) { - dscene->shader_flag.free(); + dscene->shaders.free(); if(scene->shaders.size() == 0) return; - uint shader_flag_size = scene->shaders.size()*SHADER_SIZE; - uint *shader_flag = dscene->shader_flag.alloc(shader_flag_size); - uint i = 0; + KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size()); bool has_volumes = false; bool has_transparent_shadow = false; @@ -487,16 +485,17 @@ void ShaderManager::device_update_common(Device *device, flag |= SD_HAS_CONSTANT_EMISSION; /* regular shader */ - shader_flag[i++] = flag; - shader_flag[i++] = shader->pass_id; - shader_flag[i++] = __float_as_int(constant_emission.x); - shader_flag[i++] = __float_as_int(constant_emission.y); - shader_flag[i++] = __float_as_int(constant_emission.z); + kshader->flags = flag; + kshader->pass_id = shader->pass_id; + kshader->constant_emission[0] = constant_emission.x; + kshader->constant_emission[1] = constant_emission.y; + kshader->constant_emission[2] = constant_emission.z; + kshader++; has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0; } - dscene->shader_flag.copy_to_device(); + dscene->shaders.copy_to_device(); /* lookup tables */ KernelTables *ktables = &dscene->data.tables; @@ -525,7 +524,7 @@ void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *sce { scene->lookup_tables->remove_table(&beckmann_table_offset); - dscene->shader_flag.free(); + dscene->shaders.free(); } void ShaderManager::add_default(Scene *scene) diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index 66c4f22a7e2fcaf5b44174a7368405307d967f8f..24043e2231bc6c121c55126da62d6d3549c45bc9 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -67,6 +67,7 @@ set(SRC_HEADERS util_param.h util_path.h util_progress.h + util_projection.h util_queue.h util_rect.h util_set.h diff --git a/intern/cycles/util/util_projection.h b/intern/cycles/util/util_projection.h new file mode 100644 index 0000000000000000000000000000000000000000..dbcb9877a48d289f63443996e5f6b777f4614078 --- /dev/null +++ b/intern/cycles/util/util_projection.h @@ -0,0 +1,177 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __UTIL_PROJECTION_H__ +#define __UTIL_PROJECTION_H__ + +#include "util/util_transform.h" + +CCL_NAMESPACE_BEGIN + +/* 4x4 projection matrix, perspective or orthographic. */ + +typedef struct ProjectionTransform { + float4 x, y, z, w; /* rows */ + +#ifndef __KERNEL_GPU__ + ProjectionTransform() + { + } + + explicit ProjectionTransform(const Transform& tfm) + : x(tfm.x), + y(tfm.y), + z(tfm.z), + w(make_float4(0.0f, 0.0f, 0.0f, 1.0f)) + { + } +#endif +} ProjectionTransform; + +typedef struct PerspectiveMotionTransform { + ProjectionTransform pre; + ProjectionTransform post; +} PerspectiveMotionTransform; + +/* Functions */ + +ccl_device_inline float3 transform_perspective(const ProjectionTransform *t, const float3 a) +{ + float4 b = make_float4(a.x, a.y, a.z, 1.0f); + float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b)); + float w = dot(t->w, b); + + return (w != 0.0f)? c/w: make_float3(0.0f, 0.0f, 0.0f); +} + +ccl_device_inline float3 transform_perspective_direction(const ProjectionTransform *t, const float3 a) +{ + float3 c = make_float3( + a.x*t->x.x + a.y*t->x.y + a.z*t->x.z, + a.x*t->y.x + a.y*t->y.y + a.z*t->y.z, + a.x*t->z.x + a.y*t->z.y + a.z*t->z.z); + + return c; +} + +#ifndef __KERNEL_GPU__ + +ccl_device_inline Transform projection_to_transform(const ProjectionTransform& a) +{ + Transform tfm = {a.x, a.y, a.z}; + return tfm; +} + +ccl_device_inline ProjectionTransform projection_transpose(const ProjectionTransform& a) +{ + ProjectionTransform t; + + t.x.x = a.x.x; t.x.y = a.y.x; t.x.z = a.z.x; t.x.w = a.w.x; + t.y.x = a.x.y; t.y.y = a.y.y; t.y.z = a.z.y; t.y.w = a.w.y; + t.z.x = a.x.z; t.z.y = a.y.z; t.z.z = a.z.z; t.z.w = a.w.z; + t.w.x = a.x.w; t.w.y = a.y.w; t.w.z = a.z.w; t.w.w = a.w.w; + + return t; +} + +ProjectionTransform projection_inverse(const ProjectionTransform& a); + +ccl_device_inline ProjectionTransform make_projection( + float a, float b, float c, float d, + float e, float f, float g, float h, + float i, float j, float k, float l, + float m, float n, float o, float p) +{ + ProjectionTransform t; + + t.x.x = a; t.x.y = b; t.x.z = c; t.x.w = d; + t.y.x = e; t.y.y = f; t.y.z = g; t.y.w = h; + t.z.x = i; t.z.y = j; t.z.z = k; t.z.w = l; + t.w.x = m; t.w.y = n; t.w.z = o; t.w.w = p; + + return t; +} +ccl_device_inline ProjectionTransform projection_identity() +{ + return make_projection( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); +} + +ccl_device_inline ProjectionTransform operator*(const ProjectionTransform& a, const ProjectionTransform& b) +{ + ProjectionTransform c = projection_transpose(b); + ProjectionTransform t; + + t.x = make_float4(dot(a.x, c.x), dot(a.x, c.y), dot(a.x, c.z), dot(a.x, c.w)); + t.y = make_float4(dot(a.y, c.x), dot(a.y, c.y), dot(a.y, c.z), dot(a.y, c.w)); + t.z = make_float4(dot(a.z, c.x), dot(a.z, c.y), dot(a.z, c.z), dot(a.z, c.w)); + t.w = make_float4(dot(a.w, c.x), dot(a.w, c.y), dot(a.w, c.z), dot(a.w, c.w)); + + return t; +} + +ccl_device_inline ProjectionTransform operator*(const ProjectionTransform& a, const Transform& b) +{ + return a * ProjectionTransform(b); +} + +ccl_device_inline ProjectionTransform operator*(const Transform& a, const ProjectionTransform& b) +{ + return ProjectionTransform(a) * b; +} + +ccl_device_inline void print_projection(const char *label, const ProjectionTransform& t) +{ + print_float4(label, t.x); + print_float4(label, t.y); + print_float4(label, t.z); + print_float4(label, t.w); + printf("\n"); +} + +ccl_device_inline ProjectionTransform projection_perspective(float fov, float n, float f) +{ + ProjectionTransform persp = make_projection( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, f / (f - n), -f*n / (f - n), + 0, 0, 1, 0); + + float inv_angle = 1.0f/tanf(0.5f*fov); + + Transform scale = transform_scale(inv_angle, inv_angle, 1); + + return scale * persp; +} + +ccl_device_inline ProjectionTransform projection_orthographic(float znear, float zfar) +{ + Transform t = + transform_scale(1.0f, 1.0f, 1.0f / (zfar-znear)) * + transform_translate(0.0f, 0.0f, -znear); + + return ProjectionTransform(t); +} + +#endif /* __KERNEL_GPU__ */ + +CCL_NAMESPACE_END + +#endif /* __UTIL_PROJECTION_H__ */ + diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index c127054533999a4b3585a9ca7d5e156002d778bc..206c3da23ebd013c236ffbef14fc7458b283d037 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -46,6 +46,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "util/util_projection.h" #include "util/util_transform.h" #include "util/util_boundbox.h" @@ -129,9 +130,9 @@ static bool transform_matrix4_gj_inverse(float R[][4], float M[][4]) return true; } -Transform transform_inverse(const Transform& tfm) +ProjectionTransform projection_inverse(const ProjectionTransform& tfm) { - Transform tfmR = transform_identity(); + ProjectionTransform tfmR = projection_identity(); float M[4][4], R[4][4]; memcpy(R, &tfmR, sizeof(R)); @@ -145,7 +146,7 @@ Transform transform_inverse(const Transform& tfm) M[2][2] += 1e-8f; if(UNLIKELY(!transform_matrix4_gj_inverse(R, M))) { - return transform_identity(); + return projection_identity(); } } @@ -154,6 +155,19 @@ Transform transform_inverse(const Transform& tfm) return tfmR; } +Transform transform_inverse(const Transform& tfm) +{ + ProjectionTransform projection(tfm); + return projection_to_transform(projection_inverse(projection)); +} + +Transform transform_transposed_inverse(const Transform& tfm) +{ + ProjectionTransform projection(tfm); + ProjectionTransform iprojection = projection_inverse(projection); + return projection_to_transform(projection_transpose(iprojection)); +} + /* Motion Transform */ float4 transform_to_quat(const Transform& tfm) @@ -202,14 +216,14 @@ float4 transform_to_quat(const Transform& tfm) return qt; } -static void transform_decompose(Transform *decomp, const Transform *tfm) +static void transform_decompose(DecomposedTransform *decomp, const Transform *tfm) { /* extract translation */ decomp->y = make_float4(tfm->x.w, tfm->y.w, tfm->z.w, 0.0f); /* extract rotation */ Transform M = *tfm; - M.x.w = 0.0f; M.y.w = 0.0f; M.z.w = 0.0f; M.w.w = 1.0f; + M.x.w = 0.0f; M.y.w = 0.0f; M.z.w = 0.0f; Transform R = M; float norm; @@ -217,9 +231,9 @@ static void transform_decompose(Transform *decomp, const Transform *tfm) do { Transform Rnext; - Transform Rit = transform_inverse(transform_transpose(R)); + Transform Rit = transform_transposed_inverse(R); - for(int i = 0; i < 4; i++) + for(int i = 0; i < 3; i++) for(int j = 0; j < 4; j++) Rnext[i][j] = 0.5f * (R[i][j] + Rit[i][j]); @@ -247,18 +261,18 @@ static void transform_decompose(Transform *decomp, const Transform *tfm) decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z); } -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid) +void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size) { - transform_decompose(&decomp->pre, &motion->pre); - transform_decompose(&decomp->mid, mid); - transform_decompose(&decomp->post, &motion->post); - - /* ensure rotation around shortest angle, negated quaternions are the same - * but this means we don't have to do the check in quat_interpolate */ - if(dot(decomp->pre.x, decomp->mid.x) < 0.0f) - decomp->pre.x = -decomp->pre.x; - if(dot(decomp->mid.x, decomp->post.x) < 0.0f) - decomp->mid.x = -decomp->mid.x; + for(size_t i = 0; i < size; i++) { + transform_decompose(decomp + i, motion + i); + + if(i > 0) { + /* Ensure rotation around shortest angle, negated quaternions are the same + * but this means we don't have to do the check in quat_interpolate */ + if(dot(decomp[i-1].x, decomp[i].x) < 0.0f) + decomp[i-1].x = -decomp[i-1].x; + } + } } Transform transform_from_viewplane(BoundBox2D& viewplane) diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index 6f0238b98e384631b4c4731d653bb846fa524c9f..4124d3d78a12a6c39bf4fdc6b50d7b275f8a418b 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -26,10 +26,10 @@ CCL_NAMESPACE_BEGIN -/* Data Types */ +/* Affine transformation, stored as 4x3 matrix. */ typedef struct Transform { - float4 x, y, z, w; /* rows */ + float4 x, y, z; #ifndef __KERNEL_GPU__ float4 operator[](int i) const { return *(&x + i); } @@ -37,32 +37,16 @@ typedef struct Transform { #endif } Transform; -/* transform decomposed in rotation/translation/scale. we use the same data +/* Transform decomposed in rotation/translation/scale. we use the same data * structure as Transform, and tightly pack decomposition into it. first the * rotation (4), then translation (3), then 3x3 scale matrix (9). */ -typedef struct ccl_may_alias MotionTransform { - Transform pre; - Transform mid; - Transform post; -} MotionTransform; - -typedef struct PerspectiveMotionTransform { - Transform pre; - Transform post; -} PerspectiveMotionTransform; +typedef struct DecomposedTransform { + float4 x, y, z, w; +} DecomposedTransform; /* Functions */ -ccl_device_inline float3 transform_perspective(const Transform *t, const float3 a) -{ - float4 b = make_float4(a.x, a.y, a.z, 1.0f); - float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b)); - float w = dot(t->w, b); - - return (w != 0.0f)? c/w: make_float3(0.0f, 0.0f, 0.0f); -} - ccl_device_inline float3 transform_point(const Transform *t, const float3 a) { /* TODO(sergey): Disabled for now, causes crashes in certain cases. */ @@ -73,7 +57,7 @@ ccl_device_inline float3 transform_point(const Transform *t, const float3 a) x = _mm_loadu_ps(&t->x.x); y = _mm_loadu_ps(&t->y.x); z = _mm_loadu_ps(&t->z.x); - w = _mm_loadu_ps(&t->w.x); + w = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f); _MM_TRANSPOSE4_PS(x, y, z, w); @@ -129,29 +113,15 @@ ccl_device_inline float3 transform_direction_transposed(const Transform *t, cons return make_float3(dot(x, a), dot(y, a), dot(z, a)); } -ccl_device_inline Transform transform_transpose(const Transform a) -{ - Transform t; - - t.x.x = a.x.x; t.x.y = a.y.x; t.x.z = a.z.x; t.x.w = a.w.x; - t.y.x = a.x.y; t.y.y = a.y.y; t.y.z = a.z.y; t.y.w = a.w.y; - t.z.x = a.x.z; t.z.y = a.y.z; t.z.z = a.z.z; t.z.w = a.w.z; - t.w.x = a.x.w; t.w.y = a.y.w; t.w.z = a.z.w; t.w.w = a.w.w; - - return t; -} - ccl_device_inline Transform make_transform(float a, float b, float c, float d, float e, float f, float g, float h, - float i, float j, float k, float l, - float m, float n, float o, float p) + float i, float j, float k, float l) { Transform t; t.x.x = a; t.x.y = b; t.x.z = c; t.x.w = d; t.y.x = e; t.y.y = f; t.y.z = g; t.y.w = h; t.z.x = i; t.z.y = j; t.z.z = k; t.z.w = l; - t.w.x = m; t.w.y = n; t.w.z = o; t.w.w = p; return t; } @@ -165,21 +135,22 @@ ccl_device_inline Transform make_transform_frame(float3 N) const float3 dy = normalize(cross(N, dx)); return make_transform(dx.x, dx.y, dx.z, 0.0f, dy.x, dy.y, dy.z, 0.0f, - N.x , N.y, N.z, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); + N.x , N.y, N.z, 0.0f); } #ifndef __KERNEL_GPU__ ccl_device_inline Transform operator*(const Transform a, const Transform b) { - Transform c = transform_transpose(b); - Transform t; + float4 c_x = make_float4(b.x.x, b.y.x, b.z.x, 0.0f); + float4 c_y = make_float4(b.x.y, b.y.y, b.z.y, 0.0f); + float4 c_z = make_float4(b.x.z, b.y.z, b.z.z, 0.0f); + float4 c_w = make_float4(b.x.w, b.y.w, b.z.w, 1.0f); - t.x = make_float4(dot(a.x, c.x), dot(a.x, c.y), dot(a.x, c.z), dot(a.x, c.w)); - t.y = make_float4(dot(a.y, c.x), dot(a.y, c.y), dot(a.y, c.z), dot(a.y, c.w)); - t.z = make_float4(dot(a.z, c.x), dot(a.z, c.y), dot(a.z, c.z), dot(a.z, c.w)); - t.w = make_float4(dot(a.w, c.x), dot(a.w, c.y), dot(a.w, c.z), dot(a.w, c.w)); + Transform t; + t.x = make_float4(dot(a.x, c_x), dot(a.x, c_y), dot(a.x, c_z), dot(a.x, c_w)); + t.y = make_float4(dot(a.y, c_x), dot(a.y, c_y), dot(a.y, c_z), dot(a.y, c_w)); + t.z = make_float4(dot(a.z, c_x), dot(a.z, c_y), dot(a.z, c_z), dot(a.z, c_w)); return t; } @@ -189,7 +160,6 @@ ccl_device_inline void print_transform(const char *label, const Transform& t) print_float4(label, t.x); print_float4(label, t.y); print_float4(label, t.z); - print_float4(label, t.w); printf("\n"); } @@ -198,8 +168,7 @@ ccl_device_inline Transform transform_translate(float3 t) return make_transform( 1, 0, 0, t.x, 0, 1, 0, t.y, - 0, 0, 1, t.z, - 0, 0, 0, 1); + 0, 0, 1, t.z); } ccl_device_inline Transform transform_translate(float x, float y, float z) @@ -212,8 +181,7 @@ ccl_device_inline Transform transform_scale(float3 s) return make_transform( s.x, 0, 0, 0, 0, s.y, 0, 0, - 0, 0, s.z, 0, - 0, 0, 0, 1); + 0, 0, s.z, 0); } ccl_device_inline Transform transform_scale(float x, float y, float z) @@ -221,21 +189,6 @@ ccl_device_inline Transform transform_scale(float x, float y, float z) return transform_scale(make_float3(x, y, z)); } -ccl_device_inline Transform transform_perspective(float fov, float n, float f) -{ - Transform persp = make_transform( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, f / (f - n), -f*n / (f - n), - 0, 0, 1, 0); - - float inv_angle = 1.0f/tanf(0.5f*fov); - - Transform scale = transform_scale(inv_angle, inv_angle, 1); - - return scale * persp; -} - ccl_device_inline Transform transform_rotate(float angle, float3 axis) { float s = sinf(angle); @@ -258,9 +211,7 @@ ccl_device_inline Transform transform_rotate(float angle, float3 axis) axis.z*axis.x*t - s*axis.y, axis.z*axis.y*t + s*axis.x, axis.z*axis.z*t + c, - 0.0f, - - 0.0f, 0.0f, 0.0f, 1.0f); + 0.0f); } /* Euler is assumed to be in XYZ order. */ @@ -272,12 +223,6 @@ ccl_device_inline Transform transform_euler(float3 euler) transform_rotate(euler.x, make_float3(1.0f, 0.0f, 0.0f)); } -ccl_device_inline Transform transform_orthographic(float znear, float zfar) -{ - return transform_scale(1.0f, 1.0f, 1.0f / (zfar-znear)) * - transform_translate(0.0f, 0.0f, -znear); -} - ccl_device_inline Transform transform_identity() { return transform_scale(1.0f, 1.0f, 1.0f); @@ -306,20 +251,20 @@ ccl_device_inline void transform_set_column(Transform *t, int column, float3 val } Transform transform_inverse(const Transform& a); +Transform transform_transposed_inverse(const Transform& a); ccl_device_inline bool transform_uniform_scale(const Transform& tfm, float& scale) { /* the epsilon here is quite arbitrary, but this function is only used for - * surface area and bump, where we except it to not be so sensitive */ - Transform ttfm = transform_transpose(tfm); + * surface area and bump, where we expect it to not be so sensitive */ float eps = 1e-6f; float sx = len_squared(float4_to_float3(tfm.x)); float sy = len_squared(float4_to_float3(tfm.y)); float sz = len_squared(float4_to_float3(tfm.z)); - float stx = len_squared(float4_to_float3(ttfm.x)); - float sty = len_squared(float4_to_float3(ttfm.y)); - float stz = len_squared(float4_to_float3(ttfm.z)); + float stx = len_squared(transform_get_column(&tfm, 0)); + float sty = len_squared(transform_get_column(&tfm, 1)); + float stz = len_squared(transform_get_column(&tfm, 2)); if(fabsf(sx - sy) < eps && fabsf(sx - sz) < eps && fabsf(sx - stx) < eps && fabsf(sx - sty) < eps && @@ -355,7 +300,6 @@ ccl_device_inline Transform transform_clear_scale(const Transform& tfm) ccl_device_inline Transform transform_empty() { return make_transform( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); @@ -414,12 +358,11 @@ ccl_device_inline Transform transform_quick_inverse(Transform M) R.x = make_float4(Rx.x, Rx.y, Rx.z, dot(Rx, T)); R.y = make_float4(Ry.x, Ry.y, Ry.z, dot(Ry, T)); R.z = make_float4(Rz.x, Rz.y, Rz.z, dot(Rz, T)); - R.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); return R; } -ccl_device_inline void transform_compose(Transform *tfm, const Transform *decomp) +ccl_device_inline void transform_compose(Transform *tfm, const DecomposedTransform *decomp) { /* rotation */ float q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc; @@ -452,114 +395,64 @@ ccl_device_inline void transform_compose(Transform *tfm, const Transform *decomp tfm->x = make_float4(dot(rotation_x, scale_x), dot(rotation_x, scale_y), dot(rotation_x, scale_z), decomp->y.x); tfm->y = make_float4(dot(rotation_y, scale_x), dot(rotation_y, scale_y), dot(rotation_y, scale_z), decomp->y.y); tfm->z = make_float4(dot(rotation_z, scale_x), dot(rotation_z, scale_y), dot(rotation_z, scale_z), decomp->y.z); - tfm->w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); } -/* Disabled for now, need arc-length parametrization for constant speed motion. - * #define CURVED_MOTION_INTERPOLATE */ - -ccl_device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t) +/* Interpolate from array of decomposed transforms. */ +ccl_device void transform_motion_array_interpolate(Transform *tfm, + const ccl_global DecomposedTransform *motion, + uint numsteps, + float time) { - /* possible optimization: is it worth it adding a check to skip scaling? - * it's probably quite uncommon to have scaling objects. or can we skip - * just shearing perhaps? */ - Transform decomp; - -#ifdef CURVED_MOTION_INTERPOLATE - /* 3 point bezier curve interpolation for position */ - float3 Ppre = float4_to_float3(motion->pre.y); - float3 Pmid = float4_to_float3(motion->mid.y); - float3 Ppost = float4_to_float3(motion->post.y); - - float3 Pcontrol = 2.0f*Pmid - 0.5f*(Ppre + Ppost); - float3 P = Ppre*t*t + Pcontrol*2.0f*t*(1.0f - t) + Ppost*(1.0f - t)*(1.0f - t); - - decomp.y.x = P.x; - decomp.y.y = P.y; - decomp.y.z = P.z; -#endif - - /* linear interpolation for rotation and scale */ - if(t < 0.5f) { - t *= 2.0f; + /* Figure out which steps we need to interpolate. */ + int maxstep = numsteps-1; + int step = min((int)(time*maxstep), maxstep-1); + float t = time*maxstep - step; - decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t); -#ifdef CURVED_MOTION_INTERPOLATE - decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w; -#else - decomp.y = (1.0f - t)*motion->pre.y + t*motion->mid.y; -#endif - decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z; - decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w; - } - else { - t = (t - 0.5f)*2.0f; + const ccl_global DecomposedTransform *a = motion + step; + const ccl_global DecomposedTransform *b = motion + step + 1; - decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t); -#ifdef CURVED_MOTION_INTERPOLATE - decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w; -#else - decomp.y = (1.0f - t)*motion->mid.y + t*motion->post.y; -#endif - decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z; - decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w; - } + /* Interpolate rotation, translation and scale. */ + DecomposedTransform decomp; + decomp.x = quat_interpolate(a->x, b->x, t); + decomp.y = (1.0f - t)*a->y + t*b->y; + decomp.z = (1.0f - t)*a->z + t*b->z; + decomp.w = (1.0f - t)*a->w + t*b->w; - /* compose rotation, translation, scale into matrix */ + /* Compose rotation, translation, scale into matrix. */ transform_compose(tfm, &decomp); } -ccl_device void transform_motion_interpolate_straight(Transform *tfm, const MotionTransform *motion, float t) +ccl_device void transform_motion_array_interpolate_straight(Transform *tfm, const ccl_global DecomposedTransform *motion, uint numsteps, float time) { - Transform decomp; - Transform step1, step2; - - decomp.x = motion->mid.x; - decomp.y = motion->mid.y; - decomp.z = motion->mid.z; - decomp.w = motion->mid.w; - - /* linear interpolation for rotation and scale */ - if(t < 0.5f) { - t *= 2.0f; + /* Figure out which steps we need to interpolate. */ + int maxstep = numsteps - 1; + int step = min((int)(time*maxstep), maxstep - 1); + float t = time * maxstep - step; - transform_compose(&step2, &decomp); - - decomp.x = motion->pre.x; - decomp.y = motion->pre.y; - - transform_compose(&step1, &decomp); - } - else { - t = (t - 0.5f)*2.0f; - - transform_compose(&step1, &decomp); + const ccl_global DecomposedTransform *a = motion + step; + const ccl_global DecomposedTransform *b = motion + step + 1; + Transform step1, step2; - decomp.x = motion->post.x; - decomp.y = motion->post.y; - - transform_compose(&step2, &decomp); - } + transform_compose(&step1, a); + transform_compose(&step2, b); /* matrix lerp */ tfm->x = (1.0f - t) * step1.x + t * step2.x; tfm->y = (1.0f - t) * step1.y + t * step2.y; tfm->z = (1.0f - t) * step1.z + t * step2.z; - tfm->w = (1.0f - t) * step1.w + t * step2.w; - } #ifndef __KERNEL_GPU__ class BoundBox2D; -ccl_device_inline bool operator==(const MotionTransform& A, const MotionTransform& B) +ccl_device_inline bool operator==(const DecomposedTransform& A, const DecomposedTransform& B) { - return (A.pre == B.pre && A.post == B.post); + return memcmp(&A, &B, sizeof(DecomposedTransform)) == 0; } float4 transform_to_quat(const Transform& tfm); -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid); +void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size); Transform transform_from_viewplane(BoundBox2D& viewplane); #endif diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h index 625c19c7c46422c156daddc8e7861058e3fd2cc8..e98e4e3418141a287995a1a8f0e2cc018b19ab1d 100644 --- a/intern/cycles/util/util_vector.h +++ b/intern/cycles/util/util_vector.h @@ -215,6 +215,18 @@ public: return data_; } + T* resize(size_t newsize, const T& value) + { + size_t oldsize = size(); + resize(newsize); + + for(size_t i = oldsize; i < size(); i++) { + data_[i] = value; + } + + return data_; + } + void clear() { if(data_ != NULL) { diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h index 9c06c8a6d67ccd44119880f91240b1a781a18ef4..1eb6c3ba2dca1aff0660eae270c7575334850686 100644 --- a/intern/ffmpeg/ffmpeg_compat.h +++ b/intern/ffmpeg/ffmpeg_compat.h @@ -48,6 +48,16 @@ #include <libswscale/swscale.h> +/* Stupid way to distinguish FFmpeg from Libav: + * - FFmpeg's MICRO version starts from 100 and goes up, while + * - Libav's micro is always below 100. + */ +#if LIBAVCODEC_VERSION_MICRO >= 100 +# define AV_USING_FFMPEG +#else +# define AV_USING_LIBAV +#endif + #if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 105)) # define FFMPEG_HAVE_AVIO 1 #endif @@ -428,8 +438,45 @@ void av_frame_free(AVFrame **frame) #endif FFMPEG_INLINE -AVRational av_get_r_frame_rate_compat(const AVStream *stream) +const char* av_get_metadata_key_value(AVDictionary *metadata, const char *key) { + if (metadata == NULL) { + return NULL; + } + AVDictionaryEntry *tag = NULL; + while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { + if (!strcmp(tag->key, key)) { + return tag->value; + } + } + return NULL; +} + +FFMPEG_INLINE +bool av_check_encoded_with_ffmpeg(AVFormatContext *ctx) +{ + const char* encoder = av_get_metadata_key_value(ctx->metadata, "ENCODER"); + if (encoder != NULL && !strncmp(encoder, "Lavf", 4)) { + return true; + } + return false; +} + +FFMPEG_INLINE +AVRational av_get_r_frame_rate_compat(AVFormatContext *ctx, + const AVStream *stream) +{ + /* If the video is encoded with FFmpeg and we are decoding with FFmpeg + * as well it seems to be more reliable to use r_frame_rate (tbr). + * + * For other cases we fall back to avg_frame_rate (fps) when possible. + */ +#ifdef AV_USING_FFMPEG + if (av_check_encoded_with_ffmpeg(ctx)) { + return stream->r_frame_rate; + } +#endif + #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 23, 1) /* For until r_frame_rate was deprecated use it. */ return stream->r_frame_rate; diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 5a97da28d1752624b2fab233537356d61bbfc16c..ba569ff4166b5d2acb27f6ff4409ecd97bad4c2f 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -177,10 +177,12 @@ elseif(WITH_X11) intern/GHOST_DisplayManagerX11.cpp intern/GHOST_SystemX11.cpp intern/GHOST_WindowX11.cpp + intern/GHOST_TaskbarX11.cpp intern/GHOST_DisplayManagerX11.h intern/GHOST_SystemX11.h intern/GHOST_WindowX11.h + intern/GHOST_TaskbarX11.h ) if(NOT WITH_GL_EGL) diff --git a/intern/ghost/intern/GHOST_TaskbarX11.cpp b/intern/ghost/intern/GHOST_TaskbarX11.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b47068df39f51517d23f3eac521e2be349baaf08 --- /dev/null +++ b/intern/ghost/intern/GHOST_TaskbarX11.cpp @@ -0,0 +1,130 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Lukas Stockner + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_TaskbarX11.cpp + * \ingroup GHOST + */ + +#include "GHOST_TaskbarX11.h" + +#include <dlfcn.h> +#include <cstdio> +#include <cassert> +#include <cstdlib> + +typedef void*(*unity_get_entry_t)(const char*); +typedef void(*unity_set_progress_t)(void*, double); +typedef void(*unity_set_progress_visible_t)(void*, int); +typedef int(*unity_event_loop_t)(void*, int); + +static unity_get_entry_t unity_get_entry; +static unity_set_progress_t unity_set_progress; +static unity_set_progress_visible_t unity_set_progress_visible; +static unity_event_loop_t unity_event_loop; + +static bool libunity_initialized = false; +static bool libunity_available = false; +void* libunity_handle = NULL; + +void GHOST_TaskBarX11::free() +{ + if(libunity_handle) { + dlclose(libunity_handle); + libunity_handle = NULL; + } +} + +bool GHOST_TaskBarX11::init() +{ + if(libunity_initialized) { + return libunity_available; + } + + libunity_initialized = true; + + const char *libunity_names[] = {"libunity.so.4", "libunity.so.6", "libunity.so.9", "libunity.so", NULL}; + for(int i = 0; libunity_names[i]; i++) { + libunity_handle = dlopen(libunity_names[i], RTLD_LAZY); + if(libunity_handle) { + break; + } + } + + if(!libunity_handle) { + return false; + } + + unity_get_entry = (unity_get_entry_t) dlsym(libunity_handle, "unity_launcher_entry_get_for_desktop_id"); + if(!unity_get_entry) { + fprintf(stderr, "failed to load libunity: %s\n", dlerror()); + return false; + } + unity_set_progress = (unity_set_progress_t) dlsym(libunity_handle, "unity_launcher_entry_set_progress"); + if(!unity_set_progress) { + fprintf(stderr, "failed to load libunity: %s\n", dlerror()); + return false; + } + unity_set_progress_visible = (unity_set_progress_visible_t) dlsym(libunity_handle, "unity_launcher_entry_set_progress_visible"); + if(!unity_set_progress_visible) { + fprintf(stderr, "failed to load libunity: %s\n", dlerror()); + return false; + } + unity_event_loop = (unity_event_loop_t) dlsym(libunity_handle, "g_main_context_iteration"); + if(!unity_event_loop) { + fprintf(stderr, "failed to load libunity: %s\n", dlerror()); + return false; + } + + atexit(GHOST_TaskBarX11::free); + + libunity_available = true; + return true; +} + +GHOST_TaskBarX11::GHOST_TaskBarX11(const char *name) +{ + if(GHOST_TaskBarX11::init()) { + handle = unity_get_entry(name); + } + else { + handle = NULL; + } +} + +bool GHOST_TaskBarX11::is_valid() +{ + return (handle != NULL); +} + +void GHOST_TaskBarX11::set_progress(double progress) +{ + assert(is_valid()); + unity_set_progress(handle, progress); +} + +void GHOST_TaskBarX11::set_progress_enabled(bool enabled) +{ + assert(is_valid()); + unity_set_progress_visible(handle, enabled ? 1 : 0); + unity_event_loop(NULL, 0); +} \ No newline at end of file diff --git a/intern/ghost/intern/GHOST_TaskbarX11.h b/intern/ghost/intern/GHOST_TaskbarX11.h new file mode 100644 index 0000000000000000000000000000000000000000..ed0e5f9b3295cd6043c0b46c63b66235b7a2b77c --- /dev/null +++ b/intern/ghost/intern/GHOST_TaskbarX11.h @@ -0,0 +1,45 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Lukas Stockner + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_TaskbarX11.h + * \ingroup GHOST + */ +#ifndef __GHOST_TASKBARX11_H__ +#define __GHOST_TASKBARX11_H__ + +class GHOST_TaskBarX11 +{ +public: + static bool init(); + static void free(); + + GHOST_TaskBarX11(const char *name); + + bool is_valid(); + void set_progress(double progress); + void set_progress_enabled(bool enabled); +private: + void *handle; +}; + +#endif /*__GHOST_TASKBARX11_H__*/ diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 1abdec374035854d198ff0dc97cf2b6629274e1a..13fef7d1db1d5fd0cf13805d85dad0ef692015c9 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -334,6 +334,7 @@ GHOST_WindowX11(GHOST_SystemX11 *system, m_empty_cursor(None), m_custom_cursor(None), m_visible_cursor(None), + m_taskbar("blender.desktop"), #ifdef WITH_XDND m_dropTarget(NULL), #endif @@ -1717,3 +1718,24 @@ getDPIHint() int dpi = pixelDiagonal / inchDiagonal; return dpi; } + +GHOST_TSuccess GHOST_WindowX11::setProgressBar(float progress) +{ + if (m_taskbar.is_valid()) { + m_taskbar.set_progress(progress); + m_taskbar.set_progress_enabled(true); + return GHOST_kSuccess; + } + + return GHOST_kFailure; +} + +GHOST_TSuccess GHOST_WindowX11::endProgressBar() +{ + if (m_taskbar.is_valid()) { + m_taskbar.set_progress_enabled(false); + return GHOST_kSuccess; + } + + return GHOST_kFailure; +} diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 5c54c1e8162bb3746ca20f12a90234db2c43c6a3..236fe0b76b00cce36d3dce00b133a0473c34ffbd 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -41,6 +41,8 @@ # include <X11/extensions/XInput.h> #endif +#include "GHOST_TaskbarX11.h" + #include <map> class STR_String; @@ -166,6 +168,9 @@ public: invalidate( ); + GHOST_TSuccess setProgressBar(float progress); + GHOST_TSuccess endProgressBar(); + /** * Destructor. * Closes the window and disposes resources allocated. @@ -347,6 +352,8 @@ private: /** Cache of XC_* ID's to XCursor structures */ std::map<unsigned int, Cursor> m_standard_cursors; + GHOST_TaskBarX11 m_taskbar; + #ifdef WITH_XDND GHOST_DropTargetX11 *m_dropTarget; #endif diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index ce3d6fffbb3eb5bfcc727022b1ad7ed721307ac9..e61a6abbbca51a14c37184e35257858c90d39e62 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1513,12 +1513,15 @@ class USERPREF_PT_addons(Panel): split.operator( "wm.url_open", text="Documentation", icon='HELP', ).url = info["wiki_url"] - split.operator( - "wm.url_open", text="Report a Bug", icon='URL', - ).url = info.get( - "tracker_url", - "https://developer.blender.org/maniphest/task/edit/form/2", - ) + # Only add "Report a Bug" button if tracker_url is set + # or the add-on is bundled (use official tracker then). + if info.get("tracker_url") or not user_addon: + split.operator( + "wm.url_open", text="Report a Bug", icon='URL', + ).url = info.get( + "tracker_url", + "https://developer.blender.org/maniphest/task/edit/form/2", + ) if user_addon: split.operator( "wm.addon_remove", text="Remove", icon='CANCEL', diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 6cd93e19e95d9a3cc5f4682fe9555952fe0c12ba..b5d906b2968cbc4c96d7c93f2a9f7ef750120a4e 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -28,7 +28,7 @@ * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 279 -#define BLENDER_SUBVERSION 3 +#define BLENDER_SUBVERSION 4 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 6 diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index f3d44164b1e493423e21f878a5689ce3dbf91633..832b41646131e91eb8f2c63da1263bd368d47493 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -125,12 +125,17 @@ enum { G_DEBUG_DEPSGRAPH_BUILD = (1 << 8), /* depsgraph construction messages */ G_DEBUG_DEPSGRAPH_EVAL = (1 << 9), /* depsgraph evaluation messages */ G_DEBUG_DEPSGRAPH_TAG = (1 << 10), /* depsgraph tagging messages */ - G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 11), /* single threaded depsgraph */ - G_DEBUG_DEPSGRAPH = (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_EVAL | G_DEBUG_DEPSGRAPH_TAG), - G_DEBUG_SIMDATA = (1 << 12), /* sim debug data display */ - G_DEBUG_GPU_MEM = (1 << 13), /* gpu memory in status bar */ - G_DEBUG_GPU = (1 << 14), /* gpu debug */ - G_DEBUG_IO = (1 << 15), /* IO Debugging (for Collada, ...)*/ + G_DEBUG_DEPSGRAPH_TIME = (1 << 11), /* depsgraph timing statistics and messages */ + G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 12), /* single threaded depsgraph */ + G_DEBUG_DEPSGRAPH_PRETTY = (1 << 13), /* use pretty colors in depsgraph messages */ + G_DEBUG_DEPSGRAPH = (G_DEBUG_DEPSGRAPH_BUILD | + G_DEBUG_DEPSGRAPH_EVAL | + G_DEBUG_DEPSGRAPH_TAG | + G_DEBUG_DEPSGRAPH_TIME), + G_DEBUG_SIMDATA = (1 << 14), /* sim debug data display */ + G_DEBUG_GPU_MEM = (1 << 15), /* gpu memory in status bar */ + G_DEBUG_GPU = (1 << 16), /* gpu debug */ + G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...)*/ }; #define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \ diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 39e6b1457552f24eab047b73a448d60e7d090baa..a9ca5cc8bbbc32d1d484f63aedf998adfe3e1551 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -58,19 +58,19 @@ int BKE_icon_id_ensure(struct ID *id); int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview); /* retrieve icon for id */ -struct Icon *BKE_icon_get(int icon_id); +struct Icon *BKE_icon_get(const int icon_id); /* set icon for id if not already defined */ /* used for inserting the internal icons */ -void BKE_icon_set(int icon_id, struct Icon *icon); +void BKE_icon_set(const int icon_id, struct Icon *icon); /* remove icon and free data if library object becomes invalid */ void BKE_icon_id_delete(struct ID *id); -void BKE_icon_delete(int icon_id); +void BKE_icon_delete(const int icon_id); /* report changes - icon needs to be recalculated */ -void BKE_icon_changed(int icon_id); +void BKE_icon_changed(const int icon_id); /* free all icons */ void BKE_icons_free(void); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 05ba3ac1df4a7c9ff395ca45d7ce5c4ec8ba50ec..efad8e48e3dd7f6e430862f655d903b45d5ff4f1 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -573,7 +573,6 @@ void BKE_node_preview_set_pixel(struct bNodePreview *preview, const f /** \} */ - /* -------------------------------------------------------------------- */ /** \name Node Type Access * \{ */ @@ -603,6 +602,7 @@ void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufu void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *)); void node_type_compatibility(struct bNodeType *ntype, short compatibility); +/** \} */ /* -------------------------------------------------------------------- */ /** \name Node Generic Functions @@ -692,7 +692,7 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, /* -------------------------------------------------------------------- */ /** \name Shader Nodes - */ + * \{ */ struct ShadeInput; struct ShadeResult; @@ -816,7 +816,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria /* -------------------------------------------------------------------- */ /** \name Composite Nodes - */ + * \{ */ /* output socket defines */ #define RRES_OUT_IMAGE 0 @@ -1000,7 +1000,7 @@ void ntreeCompositColorBalanceSyncFromCDL(bNodeTree *ntree, bNode *node); /* -------------------------------------------------------------------- */ /** \name Texture Nodes - */ + * \{ */ struct TexResult; diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 4d232e9ed6ca2d8d1c10938b25117d0ff391a168..5578290c41ab3d69680096557cccd1677bdddf08 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -127,10 +127,12 @@ struct Object *BKE_object_pose_armature_get(struct Object *ob); void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob, struct Object *par, float parentmat[4][4]); void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob); -void BKE_object_where_is_calc_ex(struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]); +void BKE_object_where_is_calc_ex( + struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]); void BKE_object_where_is_calc_time(struct Scene *scene, struct Object *ob, float ctime); -void BKE_object_where_is_calc_time_ex(struct Scene *scene, struct Object *ob, float ctime, - struct RigidBodyWorld *rbw, float r_originmat[3][3]); +void BKE_object_where_is_calc_time_ex( + struct Scene *scene, struct Object *ob, float ctime, + struct RigidBodyWorld *rbw, float r_originmat[3][3]); void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float obmat[4][4]); /* possibly belong in own moduke? */ @@ -146,15 +148,18 @@ void BKE_object_dimensions_set(struct Object *ob, const float value[3]); void BKE_object_empty_draw_type_set(struct Object *ob, const int value); void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set); void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); -bool BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); +bool BKE_object_minmax_dupli( + struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); /* sometimes min-max isn't enough, we need to loop over each point */ -void BKE_object_foreach_display_point(struct Object *ob, float obmat[4][4], - void (*func_cb)(const float[3], void *), void *user_data); -void BKE_scene_foreach_display_point(struct Scene *scene, - struct View3D *v3d, - const short flag, - void (*func_cb)(const float[3], void *), void *user_data); +void BKE_object_foreach_display_point( + struct Object *ob, float obmat[4][4], + void (*func_cb)(const float[3], void *), void *user_data); +void BKE_scene_foreach_display_point( + struct Scene *scene, + struct View3D *v3d, + const short flag, + void (*func_cb)(const float[3], void *), void *user_data); bool BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob); @@ -170,49 +175,61 @@ typedef struct ObjectTfmProtectedChannels { float rotAngle, drotAngle; } ObjectTfmProtectedChannels; -void BKE_object_tfm_protected_backup(const struct Object *ob, - ObjectTfmProtectedChannels *obtfm); +void BKE_object_tfm_protected_backup( + const struct Object *ob, + ObjectTfmProtectedChannels *obtfm); -void BKE_object_tfm_protected_restore(struct Object *ob, - const ObjectTfmProtectedChannels *obtfm, - const short protectflag); +void BKE_object_tfm_protected_restore( + struct Object *ob, + const ObjectTfmProtectedChannels *obtfm, + const short protectflag); /* Dependency graph evaluation callbacks. */ -void BKE_object_eval_local_transform(struct EvaluationContext *eval_ctx, - struct Object *ob); -void BKE_object_eval_parent(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob); -void BKE_object_eval_constraints(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob); +void BKE_object_eval_local_transform( + struct EvaluationContext *eval_ctx, + struct Object *ob); +void BKE_object_eval_parent( + struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); +void BKE_object_eval_constraints( + struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob); -bool BKE_object_eval_proxy_copy(struct EvaluationContext *eval_ctx, - struct Object *object); -void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx, - struct Object *ob); -void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob); - -void BKE_object_eval_cloth(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *object); - - -void BKE_object_eval_transform_all(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *object); - -void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob); +bool BKE_object_eval_proxy_copy( + struct EvaluationContext *eval_ctx, + struct Object *object); +void BKE_object_eval_uber_transform( + struct EvaluationContext *eval_ctx, + struct Object *ob); +void BKE_object_eval_uber_data( + struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); + +void BKE_object_eval_cloth( + struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *object); + + +void BKE_object_eval_transform_all( + struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *object); + +void BKE_object_handle_data_update( + struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); void BKE_object_handle_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); -void BKE_object_handle_update_ex(struct EvaluationContext *eval_ctx, - struct Scene *scene, struct Object *ob, - struct RigidBodyWorld *rbw, - const bool do_proxy_update); +void BKE_object_handle_update_ex( + struct EvaluationContext *eval_ctx, + struct Scene *scene, struct Object *ob, + struct RigidBodyWorld *rbw, + const bool do_proxy_update); void BKE_object_sculpt_modifiers_changed(struct Object *ob); int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot); @@ -255,7 +272,8 @@ typedef enum eObjectSet { OB_SET_ALL /* All Objects */ } eObjectSet; -struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter); +struct LinkNode *BKE_object_relational_superset( + struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter); struct LinkNode *BKE_object_groups(struct Object *ob); void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object); @@ -263,9 +281,10 @@ struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot); bool BKE_object_modifier_use_time(struct Object *ob, struct ModifierData *md); -bool BKE_object_modifier_update_subframe(struct Scene *scene, struct Object *ob, bool update_mesh, - int parent_recursion, float frame, - int type); +bool BKE_object_modifier_update_subframe( + struct Scene *scene, struct Object *ob, bool update_mesh, + int parent_recursion, float frame, + int type); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 095ef6fa1bdf4a76784c91fd4f3d7895b2142b92..e2c371348e547958bb0d540f5bcad9ace80fd176 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -76,6 +76,8 @@ #include "atomic_ops.h" +#include "DEG_depsgraph.h" + /* ***************************************** */ /* AnimData API */ @@ -2918,15 +2920,13 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) /* ************** */ /* Evaluation API */ -#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) printf - void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id) { AnimData *adt = BKE_animdata_from_id(id); Scene *scene = NULL; /* XXX: this is only needed for flushing RNA updates, * which should get handled as part of the dependency graph instead... */ - DEBUG_PRINT("%s on %s, time=%f\n\n", __func__, id->name, (double)eval_ctx->ctime); + DEG_debug_print_eval_time(__func__, id->name, id, eval_ctx->ctime); BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM); } @@ -2939,11 +2939,8 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, PointerRNA id_ptr; bool ok = false; - DEBUG_PRINT("%s on %s (%s[%d])\n", - __func__, - id->name, - fcu->rna_path, - fcu->array_index); + DEG_debug_print_eval_subdata_index( + __func__, id->name, id, "fcu", fcu->rna_path, fcu, fcu->array_index); RNA_id_pointer_create(id, &id_ptr); @@ -2976,5 +2973,3 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, } } } - -#undef DEBUG_PRINT diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 2e9b2f7d20fa526514c1af02d1662ad8137d9868..e6bb0d6b7ce8b1bfeb33876d8d8a2eb74ecab4a4 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -53,12 +53,6 @@ #include "DEG_depsgraph.h" -#ifdef WITH_LEGACY_DEPSGRAPH -# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH_EVAL) printf -#else -# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) printf -#endif - /* ********************** SPLINE IK SOLVER ******************* */ /* Temporary evaluation tree data used for Spline IK */ @@ -565,7 +559,7 @@ void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx), { bPoseChannel *pchan; - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEG_debug_print_eval(__func__, ob->id.name, ob); BLI_assert(ob->type == OB_ARMATURE); @@ -587,7 +581,7 @@ void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx), Object *ob, bPose *UNUSED(pose)) { - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEG_debug_print_eval(__func__, ob->id.name, ob); BLI_assert(ob->type == OB_ARMATURE); const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ bArmature *arm = (bArmature *)ob->data; @@ -608,7 +602,8 @@ void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx), Object *ob, bPoseChannel *pchan) { - DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name); + DEG_debug_print_eval_subdata( + __func__, ob->id.name, ob, "pchan", pchan->name, pchan); BLI_assert(ob->type == OB_ARMATURE); bArmature *arm = (bArmature *)ob->data; if (arm->edbo || (arm->flag & ARM_RESTPOS)) { @@ -643,7 +638,8 @@ void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx), Object *ob, bPoseChannel *pchan) { - DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name); + DEG_debug_print_eval_subdata( + __func__, ob->id.name, ob, "pchan", pchan->name, pchan); bArmature *arm = (bArmature *)ob->data; if (arm->flag & ARM_RESTPOS) { return; @@ -663,7 +659,7 @@ void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx), bPoseChannel *pchan) { float imat[4][4]; - DEBUG_PRINT("%s on pchan %s\n", __func__, pchan->name); + DEG_debug_print_eval(__func__, pchan->name, pchan); if (pchan->bone) { invert_m4_m4(imat, pchan->bone->arm_mat); mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat); @@ -675,7 +671,8 @@ void BKE_pose_iktree_evaluate(EvaluationContext *UNUSED(eval_ctx), Object *ob, bPoseChannel *rootchan) { - DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name); + DEG_debug_print_eval_subdata( + __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan); BLI_assert(ob->type == OB_ARMATURE); const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ bArmature *arm = (bArmature *)ob->data; @@ -689,8 +686,10 @@ void BKE_pose_splineik_evaluate(EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *ob, bPoseChannel *rootchan) + { - DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name); + DEG_debug_print_eval_subdata( + __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan); BLI_assert(ob->type == OB_ARMATURE); const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ bArmature *arm = (bArmature *)ob->data; @@ -706,7 +705,7 @@ void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx), bPose *UNUSED(pose)) { float ctime = BKE_scene_frame_get(scene); /* not accurate... */ - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEG_debug_print_eval(__func__, ob->id.name, ob); BLI_assert(ob->type == OB_ARMATURE); /* 6. release the IK tree */ @@ -718,7 +717,7 @@ void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx), void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob) { BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL); - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEG_debug_print_eval(__func__, ob->id.name, ob); if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { printf("Proxy copy error, lib Object: %s proxy Object: %s\n", ob->id.name + 2, ob->proxy_from->id.name + 2); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index f0759748fee27d9f4e6cf0fa1042e84b72fc937e..943cab0a9fc96a615c6d85786220694168cd4980 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -65,6 +65,8 @@ #include "BKE_object.h" #include "BKE_material.h" +#include "DEG_depsgraph.h" + /* globals */ /* local */ @@ -5253,9 +5255,7 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *t void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx), Curve *curve) { - if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) { - printf("%s on %s\n", __func__, curve->id.name); - } + DEG_debug_print_eval(__func__, curve->id.name, curve); if (curve->bb == NULL || (curve->bb->flag & BOUNDBOX_DIRTY)) { BKE_curve_texspace_calc(curve); } diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index a98a1b13402d410795860512df06594c4040b97d..7302d62d20fd356574f63ecbf254765ac3749619 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -431,23 +431,28 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size) } } -void BKE_icon_changed(int id) +void BKE_icon_changed(const int icon_id) { Icon *icon = NULL; - if (!id || G.background) return; + if (!icon_id || G.background) return; - icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(id)); + icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id)); if (icon) { - PreviewImage *prv = BKE_previewimg_id_ensure((ID *)icon->obj); + /* We *only* expect ID-tied icons here, not non-ID icon/preview! */ + BLI_assert(icon->type != 0); + + /* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() here , + * we only want to ensure *existing* preview images are properly tagged as changed/invalid, that's all. */ + PreviewImage **p_prv = BKE_previewimg_id_get_p((ID *)icon->obj); - /* all previews changed */ - if (prv) { + /* If we have previews, they all are now invalid changed. */ + if (p_prv && *p_prv) { int i; for (i = 0; i < NUM_ICON_SIZES; ++i) { - prv->flag[i] |= PRV_CHANGED; - prv->changed_timestamp[i]++; + (*p_prv)->flag[i] |= PRV_CHANGED; + (*p_prv)->changed_timestamp[i]++; } } } @@ -547,7 +552,7 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) return preview->icon_id; } -Icon *BKE_icon_get(int icon_id) +Icon *BKE_icon_get(const int icon_id) { Icon *icon = NULL; @@ -561,7 +566,7 @@ Icon *BKE_icon_get(int icon_id) return icon; } -void BKE_icon_set(int icon_id, struct Icon *icon) +void BKE_icon_set(const int icon_id, struct Icon *icon) { void **val_p; @@ -584,7 +589,7 @@ void BKE_icon_id_delete(struct ID *id) /** * Remove icon and free data. */ -void BKE_icon_delete(int icon_id) +void BKE_icon_delete(const int icon_id) { Icon *icon; diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 45b41fa01ed88596a4e53756c4f7eecdfd97b630..5c13ba7907da34c8c02a944694719f48a7b45820 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -878,9 +878,10 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is if (prop1->len != prop2->len) return false; - for (i = 0; i < prop1->len; i++) - if (!IDP_EqualsProperties(&array1[i], &array2[i])) + for (i = 0; i < prop1->len; i++) { + if (!IDP_EqualsProperties_ex(&array1[i], &array2[i], is_strict)) return false; + } return true; } case IDP_ID: diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 9875b74548aed0956522d8225015fc8623dff593..889f65da6891591cc8aad7b24bfa183b51fb4817 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -46,6 +46,7 @@ #include "BKE_global.h" #include "BKE_mask.h" +#include "DEG_depsgraph.h" unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) { @@ -897,11 +898,9 @@ void BKE_mask_layer_evaluate_deform(MaskLayer *masklay, const float ctime) } } -#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) printf - void BKE_mask_eval_animation(struct EvaluationContext *eval_ctx, Mask *mask) { - DEBUG_PRINT("%s on %s (%p)\n", __func__, mask->id.name, mask); + DEG_debug_print_eval(__func__, mask->id.name, mask); for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) @@ -912,7 +911,7 @@ void BKE_mask_eval_animation(struct EvaluationContext *eval_ctx, Mask *mask) void BKE_mask_eval_update(struct EvaluationContext *eval_ctx, Mask *mask) { - DEBUG_PRINT("%s on %s (%p)\n", __func__, mask->id.name, mask); + DEG_debug_print_eval(__func__, mask->id.name, mask); for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 34cc4809db30ce62712335a715830163f06012be..c8b44511edd2871b7d62252b32a805ac966e09ec 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2636,9 +2636,7 @@ Mesh *BKE_mesh_new_from_object( void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx), Mesh *mesh) { - if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) { - printf("%s on %s\n", __func__, mesh->id.name); - } + DEG_debug_print_eval(__func__, mesh->id.name, mesh); if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) { BKE_mesh_texspace_calc(mesh); } diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 69a55256e5e226a0baa7e4245114222492d8c6d4..a67c9de6deba97ae7ba26f4feb2e8028f2d680bd 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -2533,6 +2533,7 @@ void BKE_mesh_calc_volume( } } +/** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 607307554da383c754c6cf626921cea2789f9420..9ed715d75910d360d625b4c3b57e38af3839ea2c 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -73,12 +73,12 @@ #include "IMB_imbuf.h" #include "IMB_moviecache.h" +#include "DEG_depsgraph.h" + #ifdef WITH_OPENEXR # include "intern/openexr/openexr_multi.h" #endif -#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) printf - /*********************** movieclip buffer loaders *************************/ static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen) @@ -1611,6 +1611,6 @@ bool BKE_movieclip_put_frame_if_possible(MovieClip *clip, void BKE_movieclip_eval_update(struct EvaluationContext *UNUSED(eval_ctx), MovieClip *clip) { - DEBUG_PRINT("%s on %s (%p)\n", __func__, clip->id.name, clip); + DEG_debug_print_eval(__func__, clip->id.name, clip); BKE_tracking_dopesheet_tag_update(&clip->tracking); } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 85cf7d8560dabfbbc65a915a3390acd68246c465..e2e28d4b251ded1169ed6e4886990edff9ec82ae 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -61,18 +61,12 @@ #include "DEG_depsgraph.h" -#ifdef WITH_LEGACY_DEPSGRAPH -# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH_EVAL) printf -#else -# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) printf -#endif - static ThreadMutex material_lock = BLI_MUTEX_INITIALIZER; void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx), Object *ob) { - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEG_debug_print_eval(__func__, ob->id.name, ob); /* calculate local matrix */ BKE_object_to_mat4(ob, ob->obmat); @@ -90,7 +84,7 @@ void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx), float tmat[4][4]; float locmat[4][4]; - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEG_debug_print_eval(__func__, ob->id.name, ob); /* get local matrix (but don't calculate it, as that was done already!) */ // XXX: redundant? @@ -119,7 +113,7 @@ void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx), bConstraintOb *cob; float ctime = BKE_scene_frame_get(scene); - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEG_debug_print_eval(__func__, ob->id.name, ob); /* evaluate constraints stack */ /* TODO: split this into: @@ -137,7 +131,7 @@ void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx), void BKE_object_eval_done(EvaluationContext *UNUSED(eval_ctx), Object *ob) { - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEG_debug_print_eval(__func__, ob->id.name, ob); /* Set negative scale flag in object. */ if (is_negative_m4(ob->obmat)) ob->transflag |= OB_NEG_SCALE; @@ -332,7 +326,7 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx, Scene *scene, Object *ob) { - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEG_debug_print_eval(__func__, ob->id.name, ob); BLI_assert(ob->type != OB_ARMATURE); BKE_object_handle_data_update(eval_ctx, scene, ob); @@ -343,7 +337,7 @@ void BKE_object_eval_cloth(EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *object) { - DEBUG_PRINT("%s on %s\n", __func__, object->id.name); + DEG_debug_print_eval(__func__, object->id.name, object); BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH); } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 2a1e0f559d7990d65c105ef063253fa490e51d04..1a18528ba846671bc9240352b3d6ff6f9f1ac239 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -93,6 +93,7 @@ #include "PIL_time.h" #include "RE_shader_ext.h" +#include "DEG_depsgraph.h" /* fluid sim particle import */ #ifdef WITH_MOD_FLUID @@ -4405,8 +4406,6 @@ void BKE_particle_system_eval_init(EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *ob) { - if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) { - printf("%s on %s\n", __func__, ob->id.name); - } + DEG_debug_print_eval(__func__, ob->id.name, ob); BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH); } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 56e65b6f2c51eedb20b0151156649e6b6091da89..c10f54a99eb970b5f3fa49232fbfc121e16df950 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -66,6 +66,8 @@ #include "BKE_rigidbody.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" + /* ************************************** */ /* Memory Management */ @@ -1689,11 +1691,7 @@ void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx), Scene *scene) { float ctime = BKE_scene_frame_get(scene); - - if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) { - printf("%s at %f\n", __func__, ctime); - } - + DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime); /* rebuild sim data (i.e. after resetting to start of timeline) */ if (BKE_scene_check_rigidbody_active(scene)) { BKE_rigidbody_rebuild_world(scene, ctime); @@ -1704,11 +1702,7 @@ void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx), Scene *scene) { float ctime = BKE_scene_frame_get(scene); - - if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) { - printf("%s at %f\n", __func__, ctime); - } - + DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime); /* evaluate rigidbody sim */ if (BKE_scene_check_rigidbody_active(scene)) { BKE_rigidbody_do_simulation(scene, ctime); @@ -1721,11 +1715,7 @@ void BKE_rigidbody_object_sync_transforms(EvaluationContext *UNUSED(eval_ctx), { RigidBodyWorld *rbw = scene->rigidbody_world; float ctime = BKE_scene_frame_get(scene); - - if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) { - printf("%s on %s\n", __func__, ob->id.name); - } - + DEG_debug_print_eval_time(__func__, ob->id.name, ob, ctime); /* read values pushed into RBO from sim/cache... */ BKE_rigidbody_sync_transforms(rbw, ob, ctime); } diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index 825acb18e91c97252648616b566b1e0e14130609..8e94b8197ef495ede23ad31f1b1d41231c426bc6 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -62,9 +62,10 @@ * Doing the realloc in a macro isn't so simple, * so use a function the macros can use. */ -void _bli_array_grow_func(void **arr_p, const void *arr_static, - const int sizeof_arr_p, const int arr_count, const int num, - const char *alloc_str); +void _bli_array_grow_func( + void **arr_p, const void *arr_static, + const int sizeof_arr_p, const int arr_len, const int num, + const char *alloc_str); /* -------------------------------------------------------------------- */ @@ -74,18 +75,18 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, /** use ``sizeof(*(arr))`` to ensure the array exists and is an array */ #define BLI_array_declare(arr) \ - int _##arr##_count = ((void)(sizeof(*(arr))), 0); \ + int _##arr##_len = ((void)(sizeof(*(arr))), 0); \ void *_##arr##_static = NULL /** * this will use stack space, up to maxstatic array elements, before * switching to dynamic heap allocation */ #define BLI_array_staticdeclare(arr, maxstatic) \ - int _##arr##_count = 0; \ + int _##arr##_len = 0; \ char _##arr##_static[maxstatic * sizeof(*(arr))] /** returns the logical size of the array, not including buffering. */ -#define BLI_array_count(arr) ((void)0, _##arr##_count) +#define BLI_array_len(arr) ((void)0, _##arr##_len) /** * Grow the array by a fixed number of items. @@ -95,23 +96,23 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, #define BLI_array_reserve(arr, num) (void)( \ (((void *)(arr) == NULL) && \ ((void *)(_##arr##_static) != NULL) && \ - /* don't add _##arr##_count below because it must be zero */ \ - (_bli_array_totalsize_static(arr) >= _##arr##_count + (num))) ? \ + /* don't add _##arr##_len below because it must be zero */ \ + (_bli_array_totalsize_static(arr) >= _##arr##_len + (num))) ? \ /* we have an empty array and a static var big enough */ \ (void)(arr = (void *)_##arr##_static) \ : \ /* use existing static array or allocate */ \ - (LIKELY(_bli_array_totalsize(arr) >= _##arr##_count + (num)) ? \ + (LIKELY(_bli_array_totalsize(arr) >= _##arr##_len + (num)) ? \ (void)0 /* do nothing */ : \ _bli_array_grow_func((void **)&(arr), _##arr##_static, \ - sizeof(*(arr)), _##arr##_count, num, \ + sizeof(*(arr)), _##arr##_len, num, \ "BLI_array." #arr)) \ ) /** returns length of array */ #define BLI_array_grow_items(arr, num) \ - (BLI_array_reserve(arr, num), (_##arr##_count += num)) + (BLI_array_reserve(arr, num), (_##arr##_len += num)) #define BLI_array_grow_one(arr) \ BLI_array_grow_items(arr, 1) @@ -119,7 +120,7 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, /** appends an item to the array. */ #define BLI_array_append(arr, item) ( \ (void) BLI_array_grow_one(arr), \ - (void) (arr[_##arr##_count - 1] = item) \ + (void) (arr[_##arr##_len - 1] = item) \ ) /** @@ -127,13 +128,13 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, * item is not a pointer, but actual data value.*/ #define BLI_array_append_r(arr, item) ( \ (void) BLI_array_grow_one(arr), \ - (void) (arr[_##arr##_count - 1] = item), \ - (&arr[_##arr##_count - 1]) \ + (void) (arr[_##arr##_len - 1] = item), \ + (&arr[_##arr##_len - 1]) \ ) /** appends (grows) & returns a pointer to the uninitialized memory */ #define BLI_array_append_ret(arr) \ - (BLI_array_reserve(arr, 1), &arr[(_##arr##_count++)]) + (BLI_array_reserve(arr, 1), &arr[(_##arr##_len++)]) #define BLI_array_free(arr) { \ if (arr && (char *)arr != _##arr##_static) { \ @@ -143,26 +144,26 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, } ((void)0) #define BLI_array_pop(arr) ( \ - (arr && _##arr##_count) ? \ - arr[--_##arr##_count] : \ + (arr && _##arr##_len) ? \ + arr[--_##arr##_len] : \ NULL \ ) /** - * resets the logical size of an array to zero, but doesn't + * Resets the logical size of an array to zero, but doesn't * free the memory. */ #define BLI_array_clear(arr) \ - { _##arr##_count = 0; } (void)0 + { _##arr##_len = 0; } ((void)0) /** - * set the count of the array, doesn't actually increase the allocated array + * Set the length of the array, doesn't actually increase the allocated array * size. don't use this unless you know what you're doing. */ -#define BLI_array_count_set(arr, count) \ - { _##arr##_count = (count); }(void)0 +#define BLI_array_len_set(arr, len) \ + { _##arr##_len = (len); } ((void)0) /** only to prevent unused warnings */ #define BLI_array_fake_user(arr) \ - ((void)_##arr##_count, \ + ((void)_##arr##_len, \ (void)_##arr##_static) /** \} */ @@ -191,7 +192,7 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, #define BLI_array_fixedstack_free(arr) \ if (_##arr##_is_static) { \ MEM_freeN(arr); \ - } (void)0 + } ((void)0) /** \} */ diff --git a/source/blender/blenlib/BLI_assert.h b/source/blender/blenlib/BLI_assert.h new file mode 100644 index 0000000000000000000000000000000000000000..9fb0954e77fee5daaf20465b05320b2b534cc76e --- /dev/null +++ b/source/blender/blenlib/BLI_assert.h @@ -0,0 +1,111 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_ASSERT_H__ +#define __BLI_ASSERT_H__ + +/** \file BLI_assert.h + * \ingroup bli + * + * Defines: + * - #BLI_assert + * - #BLI_STATIC_ASSERT + * - #BLI_STATIC_ASSERT_ALIGN + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NDEBUG /* for BLI_assert */ +#include <stdio.h> +#endif + +/* BLI_assert(), default only to print + * for aborting need to define WITH_ASSERT_ABORT + */ +/* For 'abort' only. */ +#include <stdlib.h> + +#ifndef NDEBUG +# include "BLI_system.h" +# ifdef WITH_ASSERT_ABORT +# define _BLI_DUMMY_ABORT abort +# else +# define _BLI_DUMMY_ABORT() (void)0 +# endif +# if defined(__GNUC__) || defined(_MSC_VER) /* check __func__ is available */ +# define BLI_assert(a) \ + (void)((!(a)) ? ( \ + ( \ + BLI_system_backtrace(stderr), \ + fprintf(stderr, \ + "BLI_assert failed: %s:%d, %s(), at \'%s\'\n", \ + __FILE__, __LINE__, __func__, "" #a), \ + _BLI_DUMMY_ABORT(), \ + NULL)) : NULL) +# else +# define BLI_assert(a) \ + (void)((!(a)) ? ( \ + ( \ + fprintf(stderr, \ + "BLI_assert failed: %s:%d, at \'%s\'\n", \ + __FILE__, __LINE__, "" #a), \ + _BLI_DUMMY_ABORT(), \ + NULL)) : NULL) +# endif +#else +# define BLI_assert(a) (void)0 +#endif + +/* C++ can't use _Static_assert, expects static_assert() but c++0x only, + * Coverity also errors out. */ +#if (!defined(__cplusplus)) && \ + (!defined(__COVERITY__)) && \ + (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */ +# define BLI_STATIC_ASSERT(a, msg) __extension__ _Static_assert(a, msg); +#else +/* Code adapted from http://www.pixelbeat.org/programming/gcc/static_assert.html */ +/* Note we need the two concats below because arguments to ## are not expanded, so we need to + * expand __LINE__ with one indirection before doing the actual concatenation. */ +# define ASSERT_CONCAT_(a, b) a##b +# define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) + /* These can't be used after statements in c89. */ +# if defined(__COUNTER__) /* MSVC */ +# define BLI_STATIC_ASSERT(a, msg) \ + ; enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1 / (int)(!!(a)) }; +# else /* older gcc, clang... */ + /* This can't be used twice on the same line so ensure if using in headers + * that the headers are not included twice (by wrapping in #ifndef...#endif) + * Note it doesn't cause an issue when used on same line of separate modules + * compiled with gcc -combine -fwhole-program. */ +# define BLI_STATIC_ASSERT(a, msg) \ + ; enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(a)) }; +# endif +#endif + +#define BLI_STATIC_ASSERT_ALIGN(st, align) \ + BLI_STATIC_ASSERT((sizeof(st) % (align) == 0), "Structure must be strictly aligned") + +#ifdef __cplusplus +} +#endif + +#endif /* __BLI_ASSERT_H__ */ diff --git a/source/blender/blenlib/BLI_console.h b/source/blender/blenlib/BLI_console.h new file mode 100644 index 0000000000000000000000000000000000000000..bf433f78f70010be83786a34ccbc29694942bd31 --- /dev/null +++ b/source/blender/blenlib/BLI_console.h @@ -0,0 +1,42 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2018 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Srrgey Sharybin. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_CONSOLE_H__ +#define __BLI_CONSOLE_H__ + +/** \file BLI_console.h + * \ingroup bli + * \brief Set of utility functions and constants to work with consoles. + */ + +/* Format string where one could BLI_snprintf() R, G and B values + * and get proper marker to start colored output in the console. + */ +#define TRUECOLOR_ANSI_COLOR_FORMAT "\x1b[38;2;%d;%d;%dm" + +/* Marker which indicates that colored output is finished. */ +#define TRUECOLOR_ANSI_COLOR_FINISH "\x1b[0m" + +#endif /* __BLI_CONSOLE_H__ */ diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index ec591c6bb483104011c229b82b94424b8c5d7e03..7003eb039dd5f5eb253dbf8a39bde11f8354f4f8 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -199,6 +199,8 @@ void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp); void *BLI_gset_lookup(GSet *gh, const void *key) ATTR_WARN_UNUSED_RESULT; void *BLI_gset_pop_key(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT; +/** \} */ + /** \name GSet Iterator * \{ */ @@ -286,7 +288,7 @@ double BLI_gset_calc_quality(GSet *gs); * * \note '_p' suffix denotes void pointer arg, * so we can have functions that take correctly typed args too. - * \{ */ + */ unsigned int BLI_ghashutil_ptrhash(const void *key); bool BLI_ghashutil_ptrcmp(const void *a, const void *b); diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h index fa79481e25cbc87b3c25fc82dc22ac2669770b39..f74010479a98f6c5f616720013d0d839032da3dd 100644 --- a/source/blender/blenlib/BLI_hash.h +++ b/source/blender/blenlib/BLI_hash.h @@ -68,4 +68,16 @@ BLI_INLINE float BLI_hash_int_01(unsigned int k) return (float)BLI_hash_int(k) * (1.0f / (float)0xFFFFFFFF); } +BLI_INLINE void BLI_hash_pointer_to_color(const void *ptr, int *r, int *g, int *b) +{ + size_t val = (size_t)ptr; + const size_t hash_a = BLI_hash_int(val & 0x0000ffff); + const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 32)); + const size_t hash = + hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); + *r = (hash & 0xff0000) >> 16; + *g = (hash & 0x00ff00) >> 8; + *b = hash & 0x0000ff; +} + #endif // __BLI_HASH_H__ diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 3b24cae018d21ed90c088f10b1c3b145738d1b35..6f8e48d83b22c062d3e31d2b11bbdb31ea88b3d0 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -35,6 +35,7 @@ #endif #include <math.h> +#include "BLI_assert.h" #include "BLI_math_inline.h" #ifndef M_PI diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 890849babc3092533e86650176dc675607479626..46b3748c7cef0e5ba984f1e9e4c735f606273a09 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -41,9 +41,8 @@ extern "C" { #include "BLI_compiler_compat.h" #include "BLI_utildefines_variadic.h" -#ifndef NDEBUG /* for BLI_assert */ -#include <stdio.h> -#endif +/* We could remove in future. */ +#include "BLI_assert.h" /* useful for finding bad use of min/max */ #if 0 @@ -615,74 +614,6 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size); # define UNUSED_VARS_NDEBUG UNUSED_VARS #endif - -/* BLI_assert(), default only to print - * for aborting need to define WITH_ASSERT_ABORT - */ -/* For 'abort' only. */ -#include <stdlib.h> - -#ifndef NDEBUG -# include "BLI_system.h" -# ifdef WITH_ASSERT_ABORT -# define _BLI_DUMMY_ABORT abort -# else -# define _BLI_DUMMY_ABORT() (void)0 -# endif -# if defined(__GNUC__) || defined(_MSC_VER) /* check __func__ is available */ -# define BLI_assert(a) \ - (void)((!(a)) ? ( \ - ( \ - BLI_system_backtrace(stderr), \ - fprintf(stderr, \ - "BLI_assert failed: %s:%d, %s(), at \'%s\'\n", \ - __FILE__, __LINE__, __func__, STRINGIFY(a)), \ - _BLI_DUMMY_ABORT(), \ - NULL)) : NULL) -# else -# define BLI_assert(a) \ - (void)((!(a)) ? ( \ - ( \ - fprintf(stderr, \ - "BLI_assert failed: %s:%d, at \'%s\'\n", \ - __FILE__, __LINE__, STRINGIFY(a)), \ - _BLI_DUMMY_ABORT(), \ - NULL)) : NULL) -# endif -#else -# define BLI_assert(a) (void)0 -#endif - -/* C++ can't use _Static_assert, expects static_assert() but c++0x only, - * Coverity also errors out. */ -#if (!defined(__cplusplus)) && \ - (!defined(__COVERITY__)) && \ - (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */ -# define BLI_STATIC_ASSERT(a, msg) __extension__ _Static_assert(a, msg); -#else -/* Code adapted from http://www.pixelbeat.org/programming/gcc/static_assert.html */ -/* Note we need the two concats below because arguments to ## are not expanded, so we need to - * expand __LINE__ with one indirection before doing the actual concatenation. */ -# define ASSERT_CONCAT_(a, b) a##b -# define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) - /* These can't be used after statements in c89. */ -# if defined(__COUNTER__) /* MSVC */ -# define BLI_STATIC_ASSERT(a, msg) \ - ; enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1 / (int)(!!(a)) }; -# else /* older gcc, clang... */ - /* This can't be used twice on the same line so ensure if using in headers - * that the headers are not included twice (by wrapping in #ifndef...#endif) - * Note it doesn't cause an issue when used on same line of separate modules - * compiled with gcc -combine -fwhole-program. */ -# define BLI_STATIC_ASSERT(a, msg) \ - ; enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(a)) }; -# endif -#endif - - -#define BLI_STATIC_ASSERT_ALIGN(st, align) \ - BLI_STATIC_ASSERT((sizeof(st) % (align) == 0), "Structure must be strictly aligned") - /* hints for branch prediction, only use in code that runs a _lot_ where */ #ifdef __GNUC__ # define LIKELY(x) __builtin_expect(!!(x), 1) diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index d137de58e178dfee2d553ea0987fcc99e4270ced..33a8379def533f8e190fd08ee34ab813a9b3859d 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -138,6 +138,7 @@ set(SRC BLI_compiler_attrs.h BLI_compiler_compat.h BLI_compiler_typecheck.h + BLI_console.h BLI_convexhull_2d.h BLI_dial_2d.h BLI_dlrbTree.h diff --git a/source/blender/blenlib/intern/BLI_array.c b/source/blender/blenlib/intern/BLI_array.c index f681d222e695789c3307db595b0f7c9ac7e78964..d16dd36763da2391b914270391070090145a5ac2 100644 --- a/source/blender/blenlib/intern/BLI_array.c +++ b/source/blender/blenlib/intern/BLI_array.c @@ -66,21 +66,23 @@ /** * This function is only to be called via macros. * - * \note The caller must adjust \a arr_count + * \note The caller must adjust \a arr_len */ -void _bli_array_grow_func(void **arr_p, const void *arr_static, - const int sizeof_arr_p, const int arr_count, const int num, - const char *alloc_str) +void _bli_array_grow_func( + void **arr_p, const void *arr_static, + const int sizeof_arr_p, const int arr_len, const int num, + const char *alloc_str) { void *arr = *arr_p; void *arr_tmp; - arr_tmp = MEM_mallocN(sizeof_arr_p * - ((num < arr_count) ? - (arr_count * 2 + 2) : (arr_count + num)), alloc_str); + arr_tmp = MEM_mallocN( + sizeof_arr_p * + ((num < arr_len) ? + (arr_len * 2 + 2) : (arr_len + num)), alloc_str); if (arr) { - memcpy(arr_tmp, arr, sizeof_arr_p * arr_count); + memcpy(arr_tmp, arr, sizeof_arr_p * arr_len); if (arr != arr_static) { MEM_freeN(arr); @@ -91,6 +93,6 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, /* caller must do */ #if 0 - arr_count += num; + arr_len += num; #endif } diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index fc8e786e5ffb593cdd7aaa26c5d3ed5e564559b9..ec75c1401590c1bf7aec3df800eb54bceb1f4370 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -1345,7 +1345,7 @@ void *BLI_gset_lookup(GSet *gs, const void *key) /** * Returns the pointer to the key if it's found, removing it from the GSet. - * \node Caller must handle freeing. + * \note Caller must handle freeing. */ void *BLI_gset_pop_key(GSet *gs, const void *key) { diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index d6c587806033cae6ed864f0f59695bcafa206943..06e8ade68a218f7665524f92c03d4063a8c07ab4 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -856,9 +856,8 @@ static void non_recursive_bvh_div_nodes_task_cb( else { break; } - - parent->totnode = (char)(k + 1); } + parent->totnode = (char)k; } /** @@ -1924,6 +1923,7 @@ void BLI_bvhtree_ray_cast_all( BLI_bvhtree_ray_cast_all_ex(tree, co, dir, radius, hit_dist, callback, userdata, BVH_RAYCAST_DEFAULT); } +/** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c index acf15b1c892efa3960199a635d9591953c16232f..df93dad4c320538f1c5b2be83860baba81b0c4bb 100644 --- a/source/blender/blenlib/intern/array_store.c +++ b/source/blender/blenlib/intern/array_store.c @@ -299,7 +299,7 @@ typedef struct BChunk { } BChunk; /** - * Links to store #BChunk data in #BChunkList.chunks. + * Links to store #BChunk data in #BChunkList.chunk_refs. */ typedef struct BChunkRef { struct BChunkRef *next, *prev; @@ -749,6 +749,7 @@ static void bchunk_list_fill_from_array( ASSERT_CHUNKLIST_DATA(chunk_list, data); } +/** \} */ /* --------------------------------------------------------------------------- * Internal Table Lookup Functions @@ -1013,6 +1014,10 @@ static const BChunkRef *table_lookup( /** \} */ +/** \name Main Data De-Duplication Function + * + * \{ */ + /** * \param data: Data to store in the returned value. * \param data_len_original: Length of data in bytes. @@ -1504,6 +1509,8 @@ void BLI_array_store_clear( BLI_mempool_clear(bs->memory.chunk); } +/** \} */ + /** \name BArrayStore Statistics * \{ */ diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 1f517471407ef272d628b6bd8e48d22b1081bdc3..eed06c7841b3dc69173462990e044d0e9b2c455c 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -368,10 +368,8 @@ MINLINE int compare_ff_relative(float a, float b, const float max_diff, const in { union {float f; int i;} ua, ub; -#if 0 /* No BLI_assert in INLINE :/ */ BLI_assert(sizeof(float) == sizeof(int)); BLI_assert(max_ulps < (1 << 22)); -#endif if (fabsf(a - b) <= max_diff) { return 1; diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c index 37fdcd7878a5f45f6f77946ad15078cfcb44436d..9b16756134e3285820104db3a44a2de1c2edf1af 100644 --- a/source/blender/blenlib/intern/math_bits_inline.c +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -34,7 +34,7 @@ MINLINE int bitscan_forward_i(int a) { BLI_assert(a != 0); -# ifdef _MSC_VER +#ifdef _MSC_VER unsigned long ctz; _BitScanForward(&ctz, a); return ctz; @@ -63,7 +63,7 @@ MINLINE unsigned int bitscan_forward_clear_uint(unsigned int *a) MINLINE int bitscan_reverse_i(int a) { BLI_assert(a != 0); -# ifdef _MSC_VER +#ifdef _MSC_VER unsigned long clz; _BitScanReverse(&clz, a); return clz; diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c index 9eb2ebc0bab59d595b77c0462c3251cbe7457188..17f3205aaff10a77ee2c0c85cc508f70efa385f1 100644 --- a/source/blender/blenlib/intern/polyfill_2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c @@ -265,7 +265,8 @@ static void polyedge_rotate( struct HalfEdge *e) { /** CCW winding, rotate internal edge to new vertical state. - * <pre> + * + * \code{.unparsed} * Before After * X X * / \ /|\ @@ -276,7 +277,7 @@ static void polyedge_rotate( * e2\ /e1 e2\ | /e1 * \ / \|/ * X X - * </pre> + * \endcode */ struct HalfEdge *ed[6]; uint ed_index[6]; diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 6022732025b7994372a2d1b52a20e7763867020b..c0e4b8f8168fb6b7f2c6d1cfd33cfcc73360a89b 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -208,7 +208,7 @@ size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) } /** - * Portable replacement for #vsnprintf + * Portable replacement for `vsnprintf`. */ size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) { @@ -503,7 +503,7 @@ int BLI_strcaseeq(const char *a, const char *b) } /** - * Portable replacement for #strcasestr (not available in MSVC) + * Portable replacement for `strcasestr` (not available in MSVC) */ char *BLI_strcasestr(const char *s, const char *find) { diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index 53c0c560c0d321a30b2c17426c45ccefe1a64c50..5d3c6b35ac1b8cdedf22bc43b449c9745ac30f91 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -1310,11 +1310,11 @@ static void parallel_mempool_func( /** * This function allows to parallelize for loops over Mempool items. * - * \param pool The iterable BLI_mempool to loop over. - * \param userdata Common userdata passed to all instances of \a func. - * \param func Callback function. - * \param use_threading If \a true, actually split-execute loop in threads, else just do a sequential forloop - * (allows caller to use any kind of test to switch on parallelization or not). + * \param mempool: The iterable BLI_mempool to loop over. + * \param userdata: Common userdata passed to all instances of \a func. + * \param func: Callback function. + * \param use_threading: If \a true, actually split-execute loop in threads, else just do a sequential for loop + * (allows caller to use any kind of test to switch on parallelization or not). * * \note There is no static scheduling here. */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d6868e67fc72380969a794f0b5526910f00a79d8..e1059a50412ceb546c6079f4de56104ee78a8dbd 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -8241,6 +8241,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short id->us = ID_FAKE_USERS(id); id->icon_id = 0; id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */ + id->recalc = 0; /* this case cannot be direct_linked: it's just the ID part */ if (bhead->code == ID_ID) { diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index aba0160622f714ab206721e7fa4d896ec4239cca..c4b29e91fb421b9af01e61f5d8e81838786d8430 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1282,8 +1282,8 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) } /* create region face */ - f_new = BLI_array_count(edges) ? - BM_face_create_ngon(bm, v1, v2, edges, BLI_array_count(edges), faces[0], BM_CREATE_NOP) : NULL; + f_new = BLI_array_len(edges) ? + BM_face_create_ngon(bm, v1, v2, edges, BLI_array_len(edges), faces[0], BM_CREATE_NOP) : NULL; if (UNLIKELY(f_new == NULL)) { /* Invalid boundary region to join faces */ goto error; @@ -1347,11 +1347,11 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) /* delete old geometry */ if (do_del) { - for (i = 0; i < BLI_array_count(deledges); i++) { + for (i = 0; i < BLI_array_len(deledges); i++) { BM_edge_kill(bm, deledges[i]); } - for (i = 0; i < BLI_array_count(delverts); i++) { + for (i = 0; i < BLI_array_len(delverts); i++) { BM_vert_kill(bm, delverts[i]); } } diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 20c49d70b027c68f243218eb8f81d9a10aa20648..7f7f48e37bd08416d59c62b9bf00055c3de574f8 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -521,7 +521,7 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (* } /** - * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normals_vnos + * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normal_vcos */ static void bm_mesh_edges_sharp_tag( BMesh *bm, diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 1cd51528e0620b39e401944d042e1c42fd1a2da4..961cc4587840bd4abcfab486bf8475185ba14955 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -482,8 +482,8 @@ BMEdge *BM_vert_collapse_faces( BLI_array_append(faces, f); } - if (BLI_array_count(faces) >= 2) { - BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces), true); + if (BLI_array_len(faces) >= 2) { + BMFace *f2 = BM_faces_join(bm, faces, BLI_array_len(faces), true); if (f2) { BMLoop *l_a, *l_b; @@ -499,7 +499,7 @@ BMEdge *BM_vert_collapse_faces( } } - BLI_assert(BLI_array_count(faces) < 8); + BLI_assert(BLI_array_len(faces) < 8); BLI_array_free(faces); } @@ -608,7 +608,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) } while (l != e->l); /* flag existing faces so we can differentiate oldfaces from new faces */ - for (i = 0; i < BLI_array_count(oldfaces); i++) { + for (i = 0; i < BLI_array_len(oldfaces); i++) { BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP); oldfaces[i] = BM_face_copy(bm, bm, oldfaces[i], true, true); BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP); @@ -639,7 +639,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) int i, j; /* interpolate new/changed loop data from copied old faces */ - for (i = 0; i < BLI_array_count(oldfaces); i++) { + for (i = 0; i < BLI_array_len(oldfaces); i++) { float f_center_old[3]; BM_face_calc_center_mean(oldfaces[i], f_center_old); @@ -671,7 +671,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) } /* destroy the old faces */ - for (i = 0; i < BLI_array_count(oldfaces); i++) { + for (i = 0; i < BLI_array_len(oldfaces); i++) { BM_face_verts_kill(bm, oldfaces[i]); } diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 41775bdf2d0ed4fda526d0fb67152bff5a771f8d..85dfd3f58e28348498664d38bb005a2fd06ab56f 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -665,7 +665,7 @@ bool BM_face_split_edgenet( BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT); } while ((l_iter = l_iter->next) != l_first); - if (BLI_array_count(face_arr)) { + if (BLI_array_len(face_arr)) { bmesh_face_swap_data(f, face_arr[0]); BM_face_kill(bm, face_arr[0]); face_arr[0] = f; @@ -674,13 +674,13 @@ bool BM_face_split_edgenet( BM_ELEM_API_FLAG_DISABLE(f, FACE_NET); } - for (i = 0; i < BLI_array_count(face_arr); i++) { + for (i = 0; i < BLI_array_len(face_arr); i++) { BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET); } if (r_face_arr) { *r_face_arr = face_arr; - *r_face_arr_len = BLI_array_count(face_arr); + *r_face_arr_len = BLI_array_len(face_arr); } else { if (face_arr) { @@ -860,7 +860,7 @@ static void bvhtree_test_edges_isect_2d_ray_cb( /** * Store values for: * - #bm_face_split_edgenet_find_connection - * - #test_edges_isect_2d + * - #test_edges_isect_2d_vert * ... which don't change each call. */ struct EdgeGroup_FindConnection_Args { diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 32f726df01d03a82d3dbc113922c25ae8aac4e30..3a76f4ca271fa926f4ba5bbfcaba5b5c7936905d 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1526,9 +1526,9 @@ float BM_loop_calc_face_angle(const BMLoop *l) * * Calculate the normal at this loop corner or fallback to the face normal on straight lines. * - * \param l The loop to calculate the normal at - * \param epsilon: Value to avoid numeric errors (1e-5f works well). - * \param r_normal Resulting normal + * \param l: The loop to calculate the normal at. + * \param epsilon_sq: Value to avoid numeric errors (1e-5f works well). + * \param r_normal: Resulting normal. */ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3]) { diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 5a2f07be70a1a7603d638d356f4124f335f3bb90..816d2e8d009c7fc68b3cad179ac081914a2838d6 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -179,7 +179,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) } BMW_end(®walker); - for (i = 0; i < BLI_array_count(faces); i++) { + for (i = 0; i < BLI_array_len(faces); i++) { f_iter = faces[i]; BMO_face_flag_disable(bm, f_iter, FACE_TAG); BMO_face_flag_enable(bm, f_iter, FACE_ORIG); @@ -198,7 +198,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) /* track how many faces we should end up with */ int totface_target = bm->totface; - for (i = 0; i < BLI_array_count(regions); i++) { + for (i = 0; i < BLI_array_len(regions); i++) { BMFace *f_new; int tot = 0; @@ -259,7 +259,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) cleanup: /* free/cleanup */ - for (i = 0; i < BLI_array_count(regions); i++) { + for (i = 0; i < BLI_array_len(regions); i++) { if (regions[i]) MEM_freeN(regions[i]); } diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index 744ef866128b6766932e4bd2a9cfad2d254954f1..931ac684b07156b5aa97a59e3f2ccb1fe723bbd0 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -179,22 +179,22 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) if (!count) { edges1 = edges; - BLI_array_count_set(edges1, BLI_array_count(edges)); + BLI_array_len_set(edges1, BLI_array_len(edges)); } else { edges2 = edges; - BLI_array_count_set(edges2, BLI_array_count(edges)); + BLI_array_len_set(edges2, BLI_array_len(edges)); } BLI_array_clear(edges); count++; } - if (edges1 && BLI_array_count(edges1) > 2 && - BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1])) + if (edges1 && BLI_array_len(edges1) > 2 && + BM_edge_share_vert_check(edges1[0], edges1[BLI_array_len(edges1) - 1])) { - if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) + if (edges2 && BLI_array_len(edges2) > 2 && + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1])) { BLI_array_free(edges1); BLI_array_free(edges2); @@ -206,8 +206,8 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) } } - if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) + if (edges2 && BLI_array_len(edges2) > 2 && + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1])) { edges2 = NULL; } @@ -218,23 +218,23 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) float dvec1[3]; float dvec2[3]; - if (BLI_array_count(edges1) == 1) { + if (BLI_array_len(edges1) == 1) { v1 = edges1[0]->v1; v2 = edges1[0]->v2; } else { v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1; - i = BLI_array_count(edges1) - 1; + i = BLI_array_len(edges1) - 1; v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1; } - if (BLI_array_count(edges2) == 1) { + if (BLI_array_len(edges2) == 1) { v3 = edges2[0]->v1; v4 = edges2[0]->v2; } else { v3 = BM_vert_in_edge(edges2[1], edges2[0]->v1) ? edges2[0]->v2 : edges2[0]->v1; - i = BLI_array_count(edges2) - 1; + i = BLI_array_len(edges2) - 1; v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1; } @@ -265,9 +265,9 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) else if (edges1) { BMVert *v1, *v2; - if (BLI_array_count(edges1) > 1) { + if (BLI_array_len(edges1) > 1) { v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1; - i = BLI_array_count(edges1) - 1; + i = BLI_array_len(edges1) - 1; v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1; e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE); BMO_edge_flag_enable(bm, e, ELE_NEW); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 7d3419b591014c5064e59d62b92ef574185d8df5..8f998797a16c81890b19c56e4133c346e7c374b4 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -1157,7 +1157,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) loops[a] = l; } - vlen = BLI_array_count(loops); + vlen = BLI_array_len(loops); /* find the boundary of one of the split edges */ for (a = 1; a < vlen; a++) { @@ -1236,9 +1236,9 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) * - concave corner of an ngon. * - 2 edges being used in 2+ ngons. */ -// BM_face_splits_check_legal(bm, face, loops_split, BLI_array_count(loops_split)); +// BM_face_splits_check_legal(bm, face, loops_split, BLI_array_len(loops_split)); - for (j = 0; j < BLI_array_count(loops_split); j++) { + for (j = 0; j < BLI_array_len(loops_split); j++) { if (loops_split[j][0]) { BMFace *f_new; BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == NULL); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index beee9065eceeb6316143e346cdcf1389e40b666d..457e74ce1aa020cadea1b308e4e983b113ae5501 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -3209,7 +3209,7 @@ static void build_center_ngon(BMesh *bm, BevVert *bv, int mat_nr) BLI_array_append(ve, NULL); } } while ((v = v->next) != vm->boundstart); - bev_create_ngon(bm, vv, BLI_array_count(vv), vf, frep, ve, mat_nr, true); + bev_create_ngon(bm, vv, BLI_array_len(vv), vf, frep, ve, mat_nr, true); BLI_array_free(vv); BLI_array_free(vf); @@ -3960,7 +3960,7 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i) BLI_array_append(sucs, bme2); } } - nsucs = BLI_array_count(sucs); + nsucs = BLI_array_len(sucs); bestj = j = i; for (sucindex = 0; sucindex < nsucs; sucindex++) { @@ -4500,15 +4500,15 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) } } if (do_rebuild) { - n = BLI_array_count(vv); + n = BLI_array_len(vv); f_new = bev_create_ngon(bm, vv, n, NULL, f, NULL, -1, true); - for (k = 0; k < BLI_array_count(vv_fix); k++) { + for (k = 0; k < BLI_array_len(vv_fix); k++) { bev_merge_uvs(bm, vv_fix[k]); } /* copy attributes from old edges */ - BLI_assert(n == BLI_array_count(ee)); + BLI_assert(n == BLI_array_len(ee)); bme_prev = ee[n - 1]; for (k = 0; k < n; k++) { bme_new = BM_edge_exists(vv[k], vv[(k + 1) % n]); diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index 97d3b6b29b89f3e3c52070b47b9fa43aa4104965..a59665f897fd8a77a59990f6e0369e76063f3448 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -771,7 +771,7 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_ addSampler(sampler); - std::string target = get_joint_id(bone, ob_arm) + "/transform"; + std::string target = get_joint_id(ob_arm, bone) + "/transform"; addChannel(COLLADABU::URI(empty, sampler_id), target); closeAnimation(); @@ -1926,15 +1926,21 @@ void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, i bool AnimationExporter::validateConstraints(bConstraint *con) { - bool valid = true; const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); /* these we can skip completely (invalid constraints...) */ - if (cti == NULL) valid = false; - if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false; + if (cti == NULL) + return false; + if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) + return false; + /* these constraints can't be evaluated anyway */ - if (cti->evaluate_constraint == NULL) valid = false; + if (cti->evaluate_constraint == NULL) + return false; + /* influence == 0 should be ignored */ - if (con->enforce == 0.0f) valid = false; + if (con->enforce == 0.0f) + return false; - return valid; + /* validation passed */ + return true; } diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index ed3d953166fc8d034f16a24f57a5946b9be87ca5..f7ea8342eae63fa84353e61f22123d1189744c8c 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -70,14 +70,15 @@ FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path) fcu->array_index = array_index; return fcu; } - -void AnimationImporter::create_bezt(FCurve *fcu, float frame, float output) + +void AnimationImporter::add_bezt(FCurve *fcu, float frame, float value, eBezTriple_Interpolation ipo) { + //float fps = (float)FPS; BezTriple bez; memset(&bez, 0, sizeof(BezTriple)); bez.vec[1][0] = frame; - bez.vec[1][1] = output; - bez.ipo = U.ipo_new; /* use default interpolation mode here... */ + bez.vec[1][1] = value; + bez.ipo = ipo; /* use default interpolation mode here... */ bez.f1 = bez.f2 = bez.f3 = SELECT; bez.h1 = bez.h2 = HD_AUTO; insert_bezt_fcurve(fcu, &bez, 0); @@ -401,7 +402,7 @@ virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act) eul_to_quat(quat, eul); for (int k = 0; k < 4; k++) - create_bezt(quatcu[k], frame, quat[k]); + create_bezt(quatcu[k], frame, quat[k], U.ipo_new); } } @@ -1560,7 +1561,8 @@ Object *AnimationImporter::translate_animation_OLD(COLLADAFW::Node *node, copy_m4_m4(mat, matfra); } - float val[4], rot[4], loc[3], scale[3]; + float val[4] = {}; + float rot[4], loc[3], scale[3]; switch (tm_type) { case COLLADAFW::Transformation::ROTATE: @@ -1832,14 +1834,14 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float } COLLADABU::Math::Matrix4 matrix; - int i = 0, j = 0; + int mi = 0, mj = 0; for (std::vector<FCurve *>::iterator it = curves.begin(); it != curves.end(); it++) { - matrix.setElement(i, j, evaluate_fcurve(*it, fra)); - j++; - if (j == 4) { - i++; - j = 0; + matrix.setElement(mi, mj, evaluate_fcurve(*it, fra)); + mj++; + if (mj == 4) { + mi++; + mj = 0; } fcurve_is_used(*it); } @@ -2006,19 +2008,6 @@ void AnimationImporter::add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurv action_groups_add_channel(act, grp, fcu); } -void AnimationImporter::add_bezt(FCurve *fcu, float fra, float value) -{ - //float fps = (float)FPS; - BezTriple bez; - memset(&bez, 0, sizeof(BezTriple)); - bez.vec[1][0] = fra; - bez.vec[1][1] = value; - bez.ipo = BEZT_IPO_LIN; /* use default interpolation mode here... */ - bez.f1 = bez.f2 = bez.f3 = SELECT; - bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, 0); - calchandles_fcurve(fcu); -} void AnimationImporter::set_import_from_version(std::string import_from_version) { diff --git a/source/blender/collada/AnimationImporter.h b/source/blender/collada/AnimationImporter.h index 15dee8ff5f46e4e817d7e3921702fe659e7a5dc9..7dc4131dd69971a672bcc28a5054ed4af6323935 100644 --- a/source/blender/collada/AnimationImporter.h +++ b/source/blender/collada/AnimationImporter.h @@ -78,7 +78,7 @@ private: FCurve *create_fcurve(int array_index, const char *rna_path); - void create_bezt(FCurve *fcu, float frame, float output); + void add_bezt(FCurve *fcu, float frame, float value, eBezTriple_Interpolation ipo=BEZT_IPO_LIN); // create one or several fcurves depending on the number of parameters being animated void animation_to_fcurves(COLLADAFW::AnimationCurve *curve); @@ -214,8 +214,6 @@ public: void add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu); - void add_bezt(FCurve *fcu, float fra, float value); - void extra_data_importer(std::string elementName); }; diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index d2495a8cb9f4dc38d8ad522bb8f94dbab21f8f7c..92ec8b470a833ebdbfb0b6201feec1663db67dc9 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -89,7 +89,7 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce, void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) { if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) - ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm))); + ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(ob_arm, bone))); else { for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { write_bone_URLs(ins, ob_arm, child); @@ -165,9 +165,9 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, std::list<Object *>& child_objects) { if (!(this->export_settings->deform_bones_only && bone->flag & BONE_NO_DEFORM)) { - std::string node_id = get_joint_id(bone, ob_arm); + std::string node_id = get_joint_id(ob_arm, bone); std::string node_name = std::string(bone->name); - std::string node_sid = get_joint_sid(bone, ob_arm); + std::string node_sid = get_joint_sid(bone); COLLADASW::Node node(mSW); diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 0ea8324ed7c5dcdca6cc3fc4234971abf93a8799..c62aa0541768757bd492894355c2ec491c6b779c 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -282,12 +282,11 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); BoneExtended *dominant_child = NULL; int maxlen = 0; - Bone *child; if (parentbone == NULL) return; - child = (Bone *)parentbone->childbase.first; + Bone *child = (Bone *)parentbone->childbase.first; if (child && (import_settings->find_chains || child->next==NULL)) { for (; child; child = child->next) { BoneExtended *be = extended_bones[child->name]; @@ -337,8 +336,8 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone } } } - for (Bone *child = (Bone *)parentbone->childbase.first; child; child = child->next) { - ArmatureImporter::connect_bone_chains(armature, child, UNLIMITED_CHAIN_MAX); + for (Bone *ch = (Bone *)parentbone->childbase.first; ch; ch = ch->next) { + ArmatureImporter::connect_bone_chains(armature, ch, UNLIMITED_CHAIN_MAX); } } else if (maxlen>1 && maxlen > this->import_settings->min_chain_length) { @@ -348,8 +347,8 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone else { /* can't connect this Bone. Proceed with children ... */ if (pbe) pbe->set_leaf_bone(true); - for (Bone *child = (Bone *)parentbone->childbase.first; child; child = child->next) { - ArmatureImporter::connect_bone_chains(armature, child, UNLIMITED_CHAIN_MAX); + for (Bone *ch = (Bone *)parentbone->childbase.first; ch; ch = ch->next) { + ArmatureImporter::connect_bone_chains(armature, ch, UNLIMITED_CHAIN_MAX); } } diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 4afe71f47ba8a51828095402e84541449749eb5d..14e8e0323a857d6d44ef79d1a59e9845abe38317 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -71,7 +71,7 @@ bool ControllerExporter::is_skinned_mesh(Object *ob) void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) { if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) - ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm))); + ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(ob_arm, bone))); else { for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { write_bone_URLs(ins, ob_arm, child); @@ -458,7 +458,7 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defb for (def = (bDeformGroup *)defbase->first; def; def = def->next) { Bone *bone = get_bone_from_defgroup(ob_arm, def); if (bone) - source.appendValues(get_joint_sid(bone, ob_arm)); + source.appendValues(get_joint_sid(bone)); } source.finish(); diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index f7fdfb06a405413c35553f42b64a94be05beab84..08ac6e65c116445dd2eaa42fb9f905af7c43bcd3 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -190,8 +190,8 @@ void DocumentImporter::finish() std::vector<Object *> *objects_to_scale = new std::vector<Object *>(); /** TODO Break up and put into 2-pass parsing of DAE */ - std::vector<const COLLADAFW::VisualScene *>::iterator it; - for (it = vscenes.begin(); it != vscenes.end(); it++) { + std::vector<const COLLADAFW::VisualScene *>::iterator sit; + for (sit = vscenes.begin(); sit != vscenes.end(); sit++) { PointerRNA sceneptr, unit_settings; PropertyRNA *system, *scale; @@ -222,7 +222,7 @@ void DocumentImporter::finish() } // Write nodes to scene - const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); + const COLLADAFW::NodePointerArray& roots = (*sit)->getRootNodes(); for (unsigned int i = 0; i < roots.getCount(); i++) { std::vector<Object *> *objects_done = write_node(roots[i], NULL, sce, NULL, false); objects_to_scale->insert(objects_to_scale->end(), objects_done->begin(), objects_done->end()); @@ -247,8 +247,8 @@ void DocumentImporter::finish() armature_importer.fix_animation(); #endif - for (std::vector<const COLLADAFW::VisualScene *>::iterator it = vscenes.begin(); it != vscenes.end(); it++) { - const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); + for (std::vector<const COLLADAFW::VisualScene *>::iterator vsit = vscenes.begin(); vsit != vscenes.end(); vsit++) { + const COLLADAFW::NodePointerArray& roots = (*vsit)->getRootNodes(); for (unsigned int i = 0; i < roots.getCount(); i++) { translate_anim_recursive(roots[i], NULL, NULL); @@ -256,13 +256,12 @@ void DocumentImporter::finish() } if (libnode_ob.size()) { - Scene *sce = CTX_data_scene(mContext); fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size()); // free all library_nodes - std::vector<Object *>::iterator it; - for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { - Object *ob = *it; + std::vector<Object *>::iterator lit; + for (lit = libnode_ob.begin(); lit != libnode_ob.end(); lit++) { + Object *ob = *lit; Base *base = BKE_scene_base_find(sce, ob); if (base) { @@ -475,9 +474,9 @@ void DocumentImporter::create_constraints(ExtraTags *et, Object *ob) { if (et && et->isProfile("blender")) { std::string name; - short* type = 0; - et->setData("type", type); - BKE_constraint_add_for_object(ob, "Test_con", *type); + short type = 0; + et->setData("type", &type); + BKE_constraint_add_for_object(ob, "Test_con", type); } } @@ -588,8 +587,8 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA ++lamp_done; } while (controller_done < controller.getCount()) { - COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry *)controller[controller_done]; - ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map); + COLLADAFW::InstanceGeometry *geometry = (COLLADAFW::InstanceGeometry *)controller[controller_done]; + ob = mesh_importer.create_mesh_object(node, geometry, true, uid_material_map, material_texture_mapping_map); if (ob == NULL) { report_unknown_reference(*node, "instance_controller"); } diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 73b00fd07ecf6dfd3b729d01e1fee77d26ddc48c..bc0275001d36eccd5d8b5bdecc1596d8d4b9dd2c 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -149,8 +149,8 @@ void GeometryExporter::operator()(Object *ob) } else { bool all_uv_layers = !this->export_settings->active_uv_only; - std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers); - createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind); + std::set<Image *> uv_image_set = bc_getUVImages(ob, all_uv_layers); + createPolylists(uv_image_set, has_uvs, has_color, ob, me, geom_id, norind); } } diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index 93be7de62361d500241f5ef6d38de6ecaf794452..99547551a128ed658cb41c85eef194fbfcfead0f 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -203,8 +203,8 @@ bool ImagesExporter::hasImages(Scene *sce) for (node = this->export_settings->export_set; node; node = node->next) { Object *ob = (Object *)node->link; - int a; - for (a = 0; a < ob->totcol; a++) { + + for (int a = 0; a < ob->totcol; a++) { Material *ma = give_current_material(ob, a + 1); // no material, but check all of the slots diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 6ca53c64299e75f89f98ed295b3b96a79792c261..2e265125a43a8a99f0ed580bdee9bf329a9501bc 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -552,7 +552,7 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len) { CustomData edata; MEdge *medge; - int i, totedge; + int totedge; if (len == 0) return; @@ -572,7 +572,7 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len) /* set default flags */ medge = &mesh->medge[mesh->totedge]; - for (i = 0; i < len; i++, medge++) + for (int i = 0; i < len; i++, medge++) medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; mesh->totedge = totedge; @@ -606,12 +606,12 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) unsigned int edge_count = mp->getFaceCount(); unsigned int *indices = mp->getPositionIndices().getData(); - for (int i = 0; i < edge_count; i++, med++) { + for (int j = 0; j < edge_count; j++, med++) { med->bweight = 0; med->crease = 0; med->flag |= ME_LOOSEEDGE; - med->v1 = indices[2 * i]; - med->v2 = indices[2 * i + 1]; + med->v1 = indices[2 * j]; + med->v2 = indices[2 * j + 1]; } } } diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp index 8974acb346053c5b0acfd5f1a51db95aca71d79a..f2cc56777d84477b6c441a845c79db00b716c973 100644 --- a/source/blender/collada/collada_internal.cpp +++ b/source/blender/collada/collada_internal.cpp @@ -327,12 +327,12 @@ std::string get_light_id(Object *ob) return translate_id(id_name(ob)) + "-light"; } -std::string get_joint_id(Bone *bone, Object *ob_arm) +std::string get_joint_id(Object *ob, Bone *bone) { - return translate_id(id_name(ob_arm) + "_" + bone->name); + return translate_id(id_name(ob) + "_" + bone->name); } -std::string get_joint_sid(Bone *bone, Object *ob_arm) +std::string get_joint_sid(Bone *bone) { return translate_id(bone->name); } diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h index 5f3fa34edc1e12f31154b0c32f46592dcf8124c2..fc848100b791d82b0d4e6e6e69918d58704c9b21 100644 --- a/source/blender/collada/collada_internal.h +++ b/source/blender/collada/collada_internal.h @@ -97,8 +97,8 @@ extern std::string get_geometry_id(Object *ob, bool use_instantiation); extern std::string get_light_id(Object *ob); -extern std::string get_joint_id(Bone *bone, Object *ob_arm); -extern std::string get_joint_sid(Bone *bone, Object *ob_arm); +extern std::string get_joint_id(Object *ob, Bone *bone); +extern std::string get_joint_sid(Bone *bone); extern std::string get_camera_id(Object *ob); diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index 0837f14727565fe0946a28cf2cd25be961f25012..72e90f49748c65789f34893a4c6ace6407176c4e 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -208,6 +208,32 @@ void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func, void DEG_editors_update_pre(struct Main *bmain, struct Scene *scene, bool time); +/* Evaluation Debug ------------------------------ */ + +void DEG_debug_print_eval(const char* function_name, + const char* object_name, + const void* object_address); + +void DEG_debug_print_eval_subdata(const char *function_name, + const char *object_name, + const void *object_address, + const char *subdata_comment, + const char *subdata_name, + const void *subdata_address); + +void DEG_debug_print_eval_subdata_index(const char *function_name, + const char *object_name, + const void *object_address, + const char *subdata_comment, + const char *subdata_name, + const void *subdata_address, + const int subdata_index); + +void DEG_debug_print_eval_time(const char* function_name, + const char* object_name, + const void* object_address, + float time); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 2e87786639cb9a9bb52a6f373715cce7f275aaea..66ddaa6b0d5ac4a2256692068ce9f60c5b9f74f2 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -35,6 +35,8 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" +#include "BLI_console.h" +#include "BLI_hash.h" #include "BLI_ghash.h" #include "BLI_listbase.h" @@ -458,6 +460,31 @@ void deg_editors_scene_update(Main *bmain, Scene *scene, bool updated) } } +bool deg_terminal_do_color(void) +{ + return (G.debug & G_DEBUG_DEPSGRAPH_PRETTY) != 0; +} + +string deg_color_for_pointer(const void *pointer) +{ + if (!deg_terminal_do_color()) { + return ""; + } + int r, g, b; + BLI_hash_pointer_to_color(pointer, &r, &g, &b); + char buffer[64]; + BLI_snprintf(buffer, sizeof(buffer), TRUECOLOR_ANSI_COLOR_FORMAT, r, g, b); + return string(buffer); +} + +string deg_color_end(void) +{ + if (!deg_terminal_do_color()) { + return ""; + } + return string(TRUECOLOR_ANSI_COLOR_FINISH); +} + } // namespace DEG /* **************** */ @@ -494,3 +521,85 @@ void DEG_editors_update_pre(Main *bmain, Scene *scene, bool time) DEG::deg_editor_update_scene_pre_cb(bmain, scene, time); } } + +/* Evaluation and debug */ + +void DEG_debug_print_eval(const char *function_name, + const char *object_name, + const void *object_address) +{ + if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) { + return; + } + printf("%s on %s %s(%p)%s\n", + function_name, + object_name, + DEG::deg_color_for_pointer(object_address).c_str(), + object_address, + DEG::deg_color_end().c_str()); +} + +void DEG_debug_print_eval_subdata(const char *function_name, + const char *object_name, + const void *object_address, + const char *subdata_comment, + const char *subdata_name, + const void *subdata_address) +{ + if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) { + return; + } + printf("%s on %s %s(%p)%s %s %s %s(%p)%s\n", + function_name, + object_name, + DEG::deg_color_for_pointer(object_address).c_str(), + object_address, + DEG::deg_color_end().c_str(), + subdata_comment, + subdata_name, + DEG::deg_color_for_pointer(subdata_address).c_str(), + subdata_address, + DEG::deg_color_end().c_str()); +} + +void DEG_debug_print_eval_subdata_index(const char *function_name, + const char *object_name, + const void *object_address, + const char *subdata_comment, + const char *subdata_name, + const void *subdata_address, + const int subdata_index) +{ + if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) { + return; + } + printf("%s on %s %s(%p)^%s %s %s[%d] %s(%p)%s\n", + function_name, + object_name, + DEG::deg_color_for_pointer(object_address).c_str(), + object_address, + DEG::deg_color_end().c_str(), + subdata_comment, + subdata_name, + subdata_index, + DEG::deg_color_for_pointer(subdata_address).c_str(), + subdata_address, + DEG::deg_color_end().c_str()); +} + +void DEG_debug_print_eval_time(const char *function_name, + const char *object_name, + const void *object_address, + float time) +{ + if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) { + return; + } + printf("%s on %s %s(%p)%s at time %f\n", + function_name, + object_name, + DEG::deg_color_for_pointer(object_address).c_str(), + object_address, + DEG::deg_color_end().c_str(), + time); +} diff --git a/source/blender/depsgraph/intern/depsgraph_intern.h b/source/blender/depsgraph/intern/depsgraph_intern.h index 2ac97c53db79c28affb3185489ff311f6188ec74..89432e17f87c548d4c52ad5b7129716de6b27d2c 100644 --- a/source/blender/depsgraph/intern/depsgraph_intern.h +++ b/source/blender/depsgraph/intern/depsgraph_intern.h @@ -116,4 +116,8 @@ void deg_editors_scene_update(struct Main *bmain, struct Scene *scene, bool upda } \ } while (0) +bool deg_terminal_do_color(void); +string deg_color_for_pointer(const void *pointer); +string deg_color_end(void); + } // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 18ad4d1598595768b50f266d52ea9748a499c684..5f7bb4c3de5fca71a0b96ebe3608a834fedbd391 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -260,6 +260,7 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx, __func__, layers, graph->layers); + const bool do_time_debug = ((G.debug & G_DEBUG_DEPSGRAPH_TIME) != 0); /* Set time for the current graph evaluation context. */ TimeSourceDepsNode *time_src = graph->find_time_source(); eval_ctx->ctime = time_src->cfra; @@ -268,7 +269,7 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx, state.eval_ctx = eval_ctx; state.graph = graph; state.layers = layers; - state.do_stats = (G.debug_value != 0); + state.do_stats = do_time_debug; /* Set up task scheduler and pull for threaded evaluation. */ TaskScheduler *task_scheduler; bool need_free_scheduler; diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 4d68053fbc8fe72acd664eb19136b4b7b84de5e1..e9ab949dc95c93e9b63503931aada685edbfb3a0 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -3085,7 +3085,7 @@ static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool e for (ale = anim_data.first; ale; ale = ale->next) { FCurve *fcu_inner = (FCurve *)ale->key_data; - if (fcu_inner) { + if (fcu_inner != NULL && fcu_inner->bezt != NULL) { for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) { bezt->f2 = bezt->f1 = bezt->f3 = 0; } diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index cd7e3b4cb3922dcbe7bf04e32bcaf80f0f9738cd..32635541a3559f048f7b4e54759476514a0797b6 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -313,7 +313,7 @@ typedef struct BoneFlipNameData { * * \param arm: Armature the bones belong to * \param bones_names: List of BoneConflict elems. - * \param do_flip_numbers: if set, try to get rid of dot-numbers at end of bone names. + * \param do_strip_numbers: if set, try to get rid of dot-numbers at end of bone names. */ void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names, const bool do_strip_numbers) { diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index 587ae6991a228a8dba3263ee2f3d5ae4f77a4bd3..d9d5fa395d67846e10d5d695516f5fe2584edb3d 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -833,7 +833,6 @@ typedef struct tPoseLib_PreviewData { bAction *act; /* poselib to use */ TimeMarker *marker; /* 'active' pose */ - int selcount; /* number of selected elements to work on */ int totcount; /* total number of elements to work on */ short state; /* state of main loop */ @@ -866,7 +865,8 @@ enum { /* defines for tPoseLib_PreviewData->flag values */ enum { PL_PREVIEW_FIRSTTIME = (1 << 0), - PL_PREVIEW_SHOWORIGINAL = (1 << 1) + PL_PREVIEW_SHOWORIGINAL = (1 << 1), + PL_PREVIEW_ANY_BONE_SELECTED = (1 << 2), }; /* ---------------------------- */ @@ -886,7 +886,20 @@ static void poselib_backup_posecopy(tPoseLib_PreviewData *pld) { bActionGroup *agrp; bPoseChannel *pchan; - + bool selected = false; + + /* determine whether any bone is selected. */ + LISTBASE_FOREACH (bPoseChannel *, bchan, &pld->pose->chanbase) { + selected = bchan->bone != NULL && bchan->bone->flag & BONE_SELECTED; + if (selected) { + pld->flag |= PL_PREVIEW_ANY_BONE_SELECTED; + break; + } + } + if (!selected) { + pld->flag &= ~PL_PREVIEW_ANY_BONE_SELECTED; + } + /* for each posechannel that has an actionchannel in */ for (agrp = pld->act->groups.first; agrp; agrp = agrp->next) { /* try to find posechannel */ @@ -908,8 +921,6 @@ static void poselib_backup_posecopy(tPoseLib_PreviewData *pld) BLI_addtail(&pld->backups, plb); /* mark as being affected */ - if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) - pld->selcount++; pld->totcount++; } } @@ -970,6 +981,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) KeyframeEditData ked = {{NULL}}; KeyframeEditFunc group_ok_cb; int frame = 1; + const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED; /* get the frame */ if (pld->marker) @@ -982,8 +994,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); ked.f1 = ((float)frame) - 0.5f; ked.f2 = ((float)frame) + 0.5f; - - + /* start applying - only those channels which have a key at this point in time! */ for (agrp = act->groups.first; agrp; agrp = agrp->next) { /* check if group has any keyframes */ @@ -995,7 +1006,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) bool ok = 0; /* check if this bone should get any animation applied */ - if (pld->selcount == 0) { + if (!any_bone_selected) { /* if no bones are selected, then any bone is ok */ ok = 1; } @@ -1008,7 +1019,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) ok = 1; } } - + if (ok) animsys_evaluate_action_group(ptr, act, agrp, NULL, (float)frame); } @@ -1027,14 +1038,15 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID); ListBase dsources = {NULL, NULL}; bool autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id); - + const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED; + /* start tagging/keying */ for (agrp = act->groups.first; agrp; agrp = agrp->next) { /* only for selected bones unless there aren't any selected, in which case all are included */ pchan = BKE_pose_channel_find_name(pose, agrp->name); if (pchan) { - if ((pld->selcount == 0) || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) { + if (!any_bone_selected || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) { if (autokey) { /* add datasource override for the PoseChannel, to be used later */ ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 84698b33e259a0ade90435af983b95c7009b9523..40d796aeed1283c4819f2047638434f6e53873e0 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -47,6 +47,7 @@ struct bDeformGroup; struct MDeformVert; struct Scene; struct Mesh; +struct MTexPoly; struct UvVertMap; struct UvMapVert; struct BMEditMesh; @@ -79,7 +80,7 @@ void EDBM_mesh_normals_update(struct BMEditMesh *em); void EDBM_mesh_clear(struct BMEditMesh *em); void EDBM_selectmode_to_scene(struct bContext *C); -void EDBM_mesh_make(struct ToolSettings *ts, struct Object *ob, const bool add_key_index); +void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index); void EDBM_mesh_free(struct BMEditMesh *em); void EDBM_mesh_load(struct Object *ob); struct DerivedMesh *EDBM_mesh_deform_dm_get(struct BMEditMesh *em); @@ -112,8 +113,10 @@ struct UvElementMap *BM_uv_element_map_create( void BM_uv_element_map_free(struct UvElementMap *vmap); struct UvElement *BM_uv_element_get(struct UvElementMap *map, struct BMFace *efa, struct BMLoop *l); -bool EDBM_mtexpoly_check(struct BMEditMesh *em); -struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace **r_act_efa, const bool sloppy, const bool selected); +bool EDBM_uv_check(struct BMEditMesh *em); +struct BMFace *EDBM_uv_active_face_get( + struct BMEditMesh *em, const bool sloppy, const bool selected, + struct MTexPoly **r_tf); void BM_uv_vert_map_free(struct UvVertMap *vmap); struct UvMapVert *BM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v); @@ -137,8 +140,9 @@ bool EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, sh bool EDBM_backbuf_check(unsigned int index); void EDBM_backbuf_free(void); -bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2], short tot, - short xmin, short ymin, short xmax, short ymax); +bool EDBM_backbuf_border_mask_init( + struct ViewContext *vc, const int mcords[][2], short tot, + short xmin, short ymin, short xmax, short ymax); bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); struct BMVert *EDBM_vert_find_nearest_ex( @@ -218,9 +222,11 @@ typedef struct MirrTopoStore_t { int prev_ob_mode; } MirrTopoStore_t; -bool ED_mesh_mirrtopo_recalc_check(struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store); -void ED_mesh_mirrtopo_init(struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store, - const bool skip_em_vert_array_init); +bool ED_mesh_mirrtopo_recalc_check( + struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store); +void ED_mesh_mirrtopo_init( + struct Mesh *me, struct DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store, + const bool skip_em_vert_array_init); void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store); diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 354a9655a48051246a8767c65e05abc1c0cef42d..d2d4732eedb9870ef9434d387ac070945ff77990 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -49,48 +49,63 @@ struct wmKeyConfig; void ED_operatortypes_uvedit(void); void ED_keymap_uvedit(struct wmKeyConfig *keyconf); -void ED_uvedit_assign_image(struct Main *bmain, struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma); +void ED_uvedit_assign_image( + struct Main *bmain, struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma); bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]); void ED_uvedit_select_all(struct BMesh *bm); -bool ED_object_get_active_image(struct Object *ob, int mat_nr, - struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree); +bool ED_object_get_active_image( + struct Object *ob, int mat_nr, + struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree); void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int mat_nr, struct Image *ima); bool ED_uvedit_test(struct Object *obedit); /* visibility and selection */ bool uvedit_face_visible_test(struct Scene *scene, struct Image *ima, struct BMFace *efa, struct MTexPoly *tf); -bool uvedit_face_select_test(struct Scene *scene, struct BMFace *efa, - const int cd_loop_uv_offset); -bool uvedit_edge_select_test(struct Scene *scene, struct BMLoop *l, - const int cd_loop_uv_offset); -bool uvedit_uv_select_test(struct Scene *scene, struct BMLoop *l, - const int cd_loop_uv_offset); +bool uvedit_face_select_test( + struct Scene *scene, struct BMFace *efa, + const int cd_loop_uv_offset); +bool uvedit_edge_select_test( + struct Scene *scene, struct BMLoop *l, + const int cd_loop_uv_offset); +bool uvedit_uv_select_test( + struct Scene *scene, struct BMLoop *l, + const int cd_loop_uv_offset); /* uv face */ -bool uvedit_face_select_set(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select, - const bool do_history, const int cd_loop_uv_offset); -bool uvedit_face_select_enable(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, - const bool do_history, const int cd_loop_uv_offset); -bool uvedit_face_select_disable(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, - const int cd_loop_uv_offset); +bool uvedit_face_select_set( + struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select, + const bool do_history, const int cd_loop_uv_offset); +bool uvedit_face_select_enable( + struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, + const bool do_history, const int cd_loop_uv_offset); +bool uvedit_face_select_disable( + struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, + const int cd_loop_uv_offset); /* uv edge */ -void uvedit_edge_select_set(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select, - const bool do_history, const int cd_loop_uv_offset); -void uvedit_edge_select_enable(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, - const bool do_history, const int cd_loop_uv_offset); -void uvedit_edge_select_disable(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, - const int cd_loop_uv_offset); +void uvedit_edge_select_set( + struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select, + const bool do_history, const int cd_loop_uv_offset); +void uvedit_edge_select_enable( + struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, + const bool do_history, const int cd_loop_uv_offset); +void uvedit_edge_select_disable( + struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, + const int cd_loop_uv_offset); /* uv vert */ -void uvedit_uv_select_set(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select, - const bool do_history, const int cd_loop_uv_offset); -void uvedit_uv_select_enable(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, - const bool do_history, const int cd_loop_uv_offset); -void uvedit_uv_select_disable(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, - const int cd_loop_uv_offset); - -bool ED_uvedit_nearest_uv(struct Scene *scene, struct Object *obedit, struct Image *ima, - const float co[2], float r_uv[2]); +void uvedit_uv_select_set( + struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, const bool select, + const bool do_history, const int cd_loop_uv_offset); +void uvedit_uv_select_enable( + struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, + const bool do_history, const int cd_loop_uv_offset); +void uvedit_uv_select_disable( + struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l, + const int cd_loop_uv_offset); + +bool ED_uvedit_nearest_uv( + struct Scene *scene, struct Object *obedit, struct Image *ima, + const float co[2], float r_uv[2]); void ED_uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy); @@ -100,7 +115,9 @@ void ED_uvedit_live_unwrap_re_solve(void); void ED_uvedit_live_unwrap_end(short cancel); void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit); -void ED_uvedit_pack_islands(struct Scene *scene, struct Object *ob, struct BMesh *bm, bool selected, bool correct_aspect, bool do_rotate); +void ED_uvedit_pack_islands( + struct Scene *scene, struct Object *ob, struct BMesh *bm, + bool selected, bool correct_aspect, bool do_rotate); void ED_uvedit_unwrap_cube_project( struct BMesh *bm, float cube_size, bool use_select, const float center[3]); @@ -109,8 +126,11 @@ void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel) /* uvedit_draw.c */ -void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]); -void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact); +void ED_image_draw_cursor( + struct ARegion *ar, const float cursor[2]); +void ED_uvedit_draw_main( + struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, + struct Object *obedit, struct Object *obact); /* uvedit_buttons.c */ void ED_uvedit_buttons_register(struct ARegionType *art); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 0357fc8ff01fc873972bb07ad546c7e1c4602d4e..62244979c126d46a0bebf798d8ae933eb83992c7 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1301,7 +1301,7 @@ int UI_idcode_icon_get(const int idcode) { switch (idcode) { case ID_AC: - return ICON_ANIM_DATA; + return ICON_ACTION; case ID_AR: return ICON_ARMATURE_DATA; case ID_BR: diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index ca4ab30a08d74791d656575a9820109123439261..08181af2ef316cfcb56656ca8a2fb7beb1c021af 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -59,6 +59,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "ED_object.h" + #include "UI_interface.h" #include "UI_resources.h" @@ -543,6 +545,22 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op) } } + /* Switch to object mode to avoid being stuck in other modes (T54326). */ + if (CTX_data_mode_enum(C) != CTX_MODE_OBJECT) { + Object *obedit = CTX_data_edit_object(C); + + if (obedit != NULL) { + ED_object_mode_toggle(C, obedit->mode); + } + else { + Object *ob = CTX_data_active_object(C); + + if (ob) { + ED_object_mode_toggle(C, ob->mode); + } + } + } + bool ok = ABC_import(C, filename, scale, is_sequence, set_frame_range, sequence_len, offset, validate_meshes, as_background_job); diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 8783367ef7ef522175b8ac96f0567367d2c640a9..725d31a64ba927c4937de0964f1526ae7d546afd 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -58,6 +58,7 @@ set(SRC editmesh_undo.c editmesh_utils.c mesh_data.c + mesh_mirror.c mesh_ops.c meshtools.c diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 87c8c55b0a1571a59aefa0496cc489ec8791bd52..c453284a617b8d00caa8f155a3c11cf6dbd05902 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -24,7 +24,6 @@ * \ingroup edmesh */ - #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" @@ -41,7 +40,6 @@ #include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_context.h" -#include "BKE_editmesh.h" #include "BIF_gl.h" @@ -605,258 +603,3 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags) paintvert_flush_flags(ob); } } - -/* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */ -/* note, this is not the best place for the function to be but moved - * here for the purpose of syncing with bmesh */ - -typedef unsigned int MirrTopoHash_t; - -typedef struct MirrTopoVert_t { - MirrTopoHash_t hash; - int v_index; -} MirrTopoVert_t; - -static int mirrtopo_hash_sort(const void *l1, const void *l2) -{ - if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2) return 1; - else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2) return -1; - return 0; -} - -static int mirrtopo_vert_sort(const void *v1, const void *v2) -{ - if (((MirrTopoVert_t *)v1)->hash > ((MirrTopoVert_t *)v2)->hash) return 1; - else if (((MirrTopoVert_t *)v1)->hash < ((MirrTopoVert_t *)v2)->hash) return -1; - return 0; -} - -bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store) -{ - int totvert; - int totedge; - - if (dm) { - totvert = dm->getNumVerts(dm); - totedge = dm->getNumEdges(dm); - } - else if (me->edit_btmesh) { - totvert = me->edit_btmesh->bm->totvert; - totedge = me->edit_btmesh->bm->totedge; - } - else { - totvert = me->totvert; - totedge = me->totedge; - } - - if ((mesh_topo_store->index_lookup == NULL) || - (mesh_topo_store->prev_ob_mode != ob_mode) || - (totvert != mesh_topo_store->prev_vert_tot) || - (totedge != mesh_topo_store->prev_edge_tot)) - { - return true; - } - else { - return false; - } - -} - -void ED_mesh_mirrtopo_init(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store, - const bool skip_em_vert_array_init) -{ - MEdge *medge = NULL, *med; - BMEditMesh *em = dm ? NULL : me->edit_btmesh; - - /* editmode*/ - BMEdge *eed; - BMIter iter; - - int a, last; - int totvert, totedge; - int tot_unique = -1, tot_unique_prev = -1; - int tot_unique_edges = 0, tot_unique_edges_prev; - - MirrTopoHash_t *topo_hash = NULL; - MirrTopoHash_t *topo_hash_prev = NULL; - MirrTopoVert_t *topo_pairs; - MirrTopoHash_t topo_pass = 1; - - intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */ - - /* reallocate if needed */ - ED_mesh_mirrtopo_free(mesh_topo_store); - - mesh_topo_store->prev_ob_mode = ob_mode; - - if (em) { - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - - totvert = em->bm->totvert; - } - else { - totvert = dm ? dm->getNumVerts(dm) : me->totvert; - } - - topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr"); - - /* Initialize the vert-edge-user counts used to detect unique topology */ - if (em) { - totedge = me->edit_btmesh->bm->totedge; - - BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2); - topo_hash[i1]++; - topo_hash[i2]++; - } - } - else { - totedge = dm ? dm->getNumEdges(dm) : me->totedge; - medge = dm ? dm->getEdgeArray(dm) : me->medge; - - for (a = 0, med = medge; a < totedge; a++, med++) { - const unsigned int i1 = med->v1, i2 = med->v2; - topo_hash[i1]++; - topo_hash[i2]++; - } - } - - topo_hash_prev = MEM_dupallocN(topo_hash); - - tot_unique_prev = -1; - tot_unique_edges_prev = -1; - while (1) { - /* use the number of edges per vert to give verts unique topology IDs */ - - tot_unique_edges = 0; - - /* This can make really big numbers, wrapping around here is fine */ - if (em) { - BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2); - topo_hash[i1] += topo_hash_prev[i2] * topo_pass; - topo_hash[i2] += topo_hash_prev[i1] * topo_pass; - tot_unique_edges += (topo_hash[i1] != topo_hash[i2]); - } - } - else { - for (a = 0, med = medge; a < totedge; a++, med++) { - const unsigned int i1 = med->v1, i2 = med->v2; - topo_hash[i1] += topo_hash_prev[i2] * topo_pass; - topo_hash[i2] += topo_hash_prev[i1] * topo_pass; - tot_unique_edges += (topo_hash[i1] != topo_hash[i2]); - } - } - memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert); - - /* sort so we can count unique values */ - qsort(topo_hash_prev, totvert, sizeof(MirrTopoHash_t), mirrtopo_hash_sort); - - tot_unique = 1; /* account for skiping the first value */ - for (a = 1; a < totvert; a++) { - if (topo_hash_prev[a - 1] != topo_hash_prev[a]) { - tot_unique++; - } - } - - if ((tot_unique <= tot_unique_prev) && (tot_unique_edges <= tot_unique_edges_prev)) { - /* Finish searching for unique values when 1 loop dosnt give a - * higher number of unique values compared to the previous loop */ - break; - } - else { - tot_unique_prev = tot_unique; - tot_unique_edges_prev = tot_unique_edges; - } - /* Copy the hash calculated this iter, so we can use them next time */ - memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert); - - topo_pass++; - } - - /* Hash/Index pairs are needed for sorting to find index pairs */ - topo_pairs = MEM_callocN(sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs"); - - /* since we are looping through verts, initialize these values here too */ - index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup"); - - if (em) { - if (skip_em_vert_array_init == false) { - BM_mesh_elem_table_ensure(em->bm, BM_VERT); - } - } - - for (a = 0; a < totvert; a++) { - topo_pairs[a].hash = topo_hash[a]; - topo_pairs[a].v_index = a; - - /* initialize lookup */ - index_lookup[a] = -1; - } - - qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort); - - last = 0; - - /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2, - * but you cant ever access the last 'a' index of MirrTopoPairs */ - if (em) { - BMVert **vtable = em->bm->vtable; - for (a = 1; a <= totvert; a++) { - /* printf("I %d %ld %d\n", (a - last), MirrTopoPairs[a].hash, MirrTopoPairs[a].v_indexs); */ - if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) { - const int match_count = a - last; - if (match_count == 2) { - const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index; - index_lookup[j] = (intptr_t)vtable[k]; - index_lookup[k] = (intptr_t)vtable[j]; - } - else if (match_count == 1) { - /* Center vertex. */ - const int j = topo_pairs[a - 1].v_index; - index_lookup[j] = (intptr_t)vtable[j]; - } - last = a; - } - } - } - else { - /* same as above, for mesh */ - for (a = 1; a <= totvert; a++) { - if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) { - const int match_count = a - last; - if (match_count == 2) { - const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index; - index_lookup[j] = k; - index_lookup[k] = j; - } - else if (match_count == 1) { - /* Center vertex. */ - const int j = topo_pairs[a - 1].v_index; - index_lookup[j] = j; - } - last = a; - } - } - } - - MEM_freeN(topo_pairs); - topo_pairs = NULL; - - MEM_freeN(topo_hash); - MEM_freeN(topo_hash_prev); - - mesh_topo_store->index_lookup = index_lookup; - mesh_topo_store->prev_vert_tot = totvert; - mesh_topo_store->prev_edge_tot = totedge; -} - -void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store) -{ - if (mesh_topo_store->index_lookup) { - MEM_freeN(mesh_topo_store->index_lookup); - } - mesh_topo_store->index_lookup = NULL; - mesh_topo_store->prev_vert_tot = -1; - mesh_topo_store->prev_edge_tot = -1; -} diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 77772cfc8cce68db2319e1ff5c713557ec3965aa..22cb28f0b1b84caa6026814a30972a7778f5f3f6 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -60,9 +60,10 @@ /* ********* add primitive operators ************* */ -static Object *make_prim_init(bContext *C, const char *idname, - float *dia, float mat[4][4], - bool *was_editmode, const float loc[3], const float rot[3], const unsigned int layer) +static Object *make_prim_init( + bContext *C, const char *idname, + float *dia, float mat[4][4], + bool *was_editmode, const float loc[3], const float rot[3], const unsigned int layer) { Object *obedit = CTX_data_edit_object(C); diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 5ac90ec29e68a5eb19224913d0ba8e9d5477f8f6..2c98f05bd27c0b15d4a815fe4a433da3fcca0d9f 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -54,6 +54,10 @@ #include "mesh_intern.h" /* own include */ +/* -------------------------------------------------------------------- */ +/** \name Extrude Internal Utilities + * \{ */ + static void edbm_extrude_edge_exclude_mirror( Object *obedit, BMEditMesh *em, const char hflag, @@ -142,7 +146,7 @@ static bool edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const ch EDBM_flag_disable_all(em, BM_ELEM_SELECT); BMO_op_exec(em->bm, &bmop); - + BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) { BM_face_select_set(em->bm, f, true); @@ -242,7 +246,7 @@ static bool edbm_extrude_ex( BMOIter siter; BMOperator extop; BMElem *ele; - + /* needed to remove the faces left behind */ if (htype & BM_FACE) { htype |= BM_EDGE; @@ -264,7 +268,7 @@ static bool edbm_extrude_ex( BM_SELECT_HISTORY_RESTORE(bm); BMO_op_exec(bm, &extop); - + BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL_NOLOOP) { BM_elem_select_set(bm, ele, true); } @@ -274,14 +278,20 @@ static bool edbm_extrude_ex( return true; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Extrude Repeat Operator + * \{ */ + static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); RegionView3D *rv3d = CTX_wm_region_view3d(C); - + const int steps = RNA_int_get(op->ptr, "steps"); - + const float offs = RNA_float_get(op->ptr, "offset"); float dvec[3], tmat[3][3], bmat[3][3]; short a; @@ -302,7 +312,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) "translate vec=%v verts=%hv", dvec, BM_ELEM_SELECT); } - + EDBM_mesh_normals_update(em); EDBM_update_generic(em, true, true); @@ -316,19 +326,25 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot) ot->name = "Extrude Repeat Mesh"; ot->description = "Extrude selected vertices, edges or faces repeatedly"; ot->idname = "MESH_OT_extrude_repeat"; - + /* api callbacks */ ot->exec = edbm_extrude_repeat_exec; ot->poll = ED_operator_editmesh_view3d; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ RNA_def_float_distance(ot->srna, "offset", 2.0f, 0.0f, 1e12f, "Offset", "", 0.0f, 100.0f); RNA_def_int(ot->srna, "steps", 10, 0, 1000000, "Steps", "", 0, 180); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Extrude Operator + * \{ */ + /* generic extern called extruder */ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) { @@ -365,7 +381,7 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) changed = edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT); break; } - + if (changed) { return true; } @@ -380,7 +396,7 @@ static int edbm_extrude_region_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - + edbm_extrude_mesh(obedit, em, op); /* This normally happens when pushing undo but modal operators @@ -389,7 +405,7 @@ static int edbm_extrude_region_exec(bContext *C, wmOperator *op) EDBM_mesh_normals_update(em); EDBM_update_generic(em, true, true); - + return OPERATOR_FINISHED; } @@ -399,27 +415,33 @@ void MESH_OT_extrude_region(wmOperatorType *ot) ot->name = "Extrude Region"; ot->idname = "MESH_OT_extrude_region"; ot->description = "Extrude region of faces"; - + /* api callbacks */ //ot->invoke = mesh_extrude_region_invoke; ot->exec = edbm_extrude_region_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Extrude Verts Operator + * \{ */ + static int edbm_extrude_verts_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT); - + EDBM_update_generic(em, true, true); - + return OPERATOR_FINISHED; } @@ -429,11 +451,11 @@ void MESH_OT_extrude_verts_indiv(wmOperatorType *ot) ot->name = "Extrude Only Vertices"; ot->idname = "MESH_OT_extrude_verts_indiv"; ot->description = "Extrude individual vertices only"; - + /* api callbacks */ ot->exec = edbm_extrude_verts_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -441,15 +463,21 @@ void MESH_OT_extrude_verts_indiv(wmOperatorType *ot) Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Extrude Edges Operator + * \{ */ + static int edbm_extrude_edges_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT); - + EDBM_update_generic(em, true, true); - + return OPERATOR_FINISHED; } @@ -459,11 +487,11 @@ void MESH_OT_extrude_edges_indiv(wmOperatorType *ot) ot->name = "Extrude Only Edges"; ot->idname = "MESH_OT_extrude_edges_indiv"; ot->description = "Extrude individual edges only"; - + /* api callbacks */ ot->exec = edbm_extrude_edges_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -471,15 +499,21 @@ void MESH_OT_extrude_edges_indiv(wmOperatorType *ot) Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Extrude Faces Operator + * \{ */ + static int edbm_extrude_faces_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT); - + EDBM_update_generic(em, true, true); - + return OPERATOR_FINISHED; } @@ -489,18 +523,25 @@ void MESH_OT_extrude_faces_indiv(wmOperatorType *ot) ot->name = "Extrude Individual Faces"; ot->idname = "MESH_OT_extrude_faces_indiv"; ot->description = "Extrude individual faces only"; - + /* api callbacks */ ot->exec = edbm_extrude_faces_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } -/* *************** add-click-mesh (extrude) operator ************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Dupli-Extrude Operator + * + * Add-click-mesh (extrude) operator. + * \{ */ + static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ViewContext vc; @@ -521,7 +562,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w zero_v3(center); verts_len = 0; - + BM_ITER_MESH (v1, &iter, vc.em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v1, BM_ELEM_SELECT)) { add_v3_v3(center, v1->co); @@ -584,7 +625,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w cross_v3_v3v3(nor, view_vec, cross); normalize_v3(nor); } - + /* center */ copy_v3_v3(ofs, center); @@ -593,7 +634,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w mul_m4_v3(vc.obedit->imat, ofs); // back in object space sub_v3_v3(ofs, center); - + /* calculate rotation */ unit_m3(mat); if (done) { @@ -616,7 +657,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w axis_angle_to_mat3(mat, axis, angle); } } - + if (rot_src) { EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, center, mat); @@ -641,7 +682,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); mul_m4_v3(vc.obedit->imat, center); // back in object space - + EDBM_op_init(vc.em, &bmop, op, "create_vert co=%v", center); BMO_op_exec(vc.em->bm, &bmop); @@ -673,17 +714,22 @@ void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot) ot->name = "Duplicate or Extrude to Cursor"; ot->idname = "MESH_OT_dupli_extrude_cursor"; ot->description = "Duplicate and extrude selected vertices, edges or faces towards the mouse cursor"; - + /* api callbacks */ ot->invoke = edbm_dupli_extrude_cursor_invoke; ot->poll = ED_operator_editmesh_region_view3d; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "rotate_source", true, "Rotate Source", "Rotate initial selection giving better shape"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Spin Operator + * \{ */ static int edbm_spin_exec(bContext *C, wmOperator *op) { @@ -780,6 +826,12 @@ void MESH_OT_spin(wmOperatorType *ot) } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Screw Operator + * \{ */ + static int edbm_screw_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -910,3 +962,5 @@ void MESH_OT_screw(wmOperatorType *ot) RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f); } + +/** \} */ diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 76a0d874a0b3fdb91479fdb61f2b68fbb2622a14..3ce9257de0c69ae625e55de792a24d2758568e93 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1762,7 +1762,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) } kcd->linehits = linehits; - kcd->totlinehit = BLI_array_count(linehits); + kcd->totlinehit = BLI_array_len(linehits); /* find position along screen line, used for sorting */ for (i = 0; i < kcd->totlinehit; i++) { diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index a85d2425b3c9e0d8e4be32fd3def47cd284eb726..bf5a7e3a053c7e79b07ae58c01a2d59fa8e5ab75 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -61,6 +61,10 @@ #include "mesh_intern.h" /* own include */ +/* -------------------------------------------------------------------- */ +/** \name Path Select Struct & Properties + * \{ */ + struct PathSelectParams { bool track_active; /* ensure the active element is the last selected item (handy for picking) */ bool use_topology_distance; @@ -100,8 +104,11 @@ struct UserData { const struct PathSelectParams *op_params; }; +/** \} */ + /* -------------------------------------------------------------------- */ -/* Vert Path */ +/** \name Vert Path + * \{ */ /* callbacks */ static bool verttag_filter_cb(BMVert *v, void *UNUSED(user_data_v)) @@ -204,10 +211,11 @@ static void mouse_mesh_shortest_path_vert( EDBM_update_generic(em, false, false); } - +/** \} */ /* -------------------------------------------------------------------- */ -/* Edge Path */ +/** \name Edge Path + * \{ */ /* callbacks */ static bool edgetag_filter_cb(BMEdge *e, void *UNUSED(user_data_v)) @@ -427,10 +435,11 @@ static void mouse_mesh_shortest_path_edge( EDBM_update_generic(em, false, false); } - +/** \} */ /* -------------------------------------------------------------------- */ -/* Face Path */ +/** \name Face Path + * \{ */ /* callbacks */ static bool facetag_filter_cb(BMFace *f, void *UNUSED(user_data_v)) @@ -478,7 +487,6 @@ static void mouse_mesh_shortest_path_face( facetag_filter_cb, &user_data); } - if (f_act != f_dst) { if (path) { if (op_params->track_active) { @@ -539,10 +547,11 @@ static void mouse_mesh_shortest_path_face( EDBM_update_generic(em, false, false); } - +/** \} */ /* -------------------------------------------------------------------- */ -/* Main Operator for vert/edge/face tag */ +/** \name Main Operator for vert/edge/face tag + * \{ */ static bool edbm_shortest_path_pick_ex( Scene *scene, const struct PathSelectParams *op_params, @@ -709,9 +718,11 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/** \} */ /* -------------------------------------------------------------------- */ -/* Select path between existing selection */ +/** \name Select Path Between Existing Selection + * \{ */ static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op) { @@ -796,3 +807,5 @@ void MESH_OT_shortest_path_select(wmOperatorType *ot) /* properties */ path_select_properties(ot); } + +/** \} */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index f0ad491e148ce92e798e212d49680fa6bea0acd1..181fc4c0c52b9a2383ea28a95830c67c914da498 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -73,7 +73,9 @@ /* use bmesh operator flags for a few operators */ #define BMO_ELE_TAG 1 -/* ****************************** MIRROR **************** */ +/* -------------------------------------------------------------------- */ +/** \name Select Mirror + * \{ */ void EDBM_select_mirrored( BMEditMesh *em, const int axis, const bool extend, @@ -166,21 +168,34 @@ void EDBM_select_mirrored( *r_totfail = totfail; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Auto-Merge + * + * Used after transform operations. + * \{ */ + void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag) { bool ok; BMEditMesh *em = BKE_editmesh_from_object(obedit); - ok = BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, - "automerge verts=%hv dist=%f", - hflag, scene->toolsettings->doublimit); + ok = BMO_op_callf( + em->bm, BMO_FLAG_DEFAULTS, + "automerge verts=%hv dist=%f", + hflag, scene->toolsettings->doublimit); if (LIKELY(ok) && update) { EDBM_update_generic(em, true, true); } } -/* ****************************** SELECTION ROUTINES **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Back-Buffer OpenGL Selection + * \{ */ unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; /* set in drawobject.c ... for colorindices */ @@ -199,21 +214,21 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma struct ImBuf *buf; unsigned int *dr; int a; - + if (vc->obedit == NULL || !V3D_IS_ZBUF(vc->v3d)) { return false; } - + buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } dr = buf->rect; - + /* build selection lookup */ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - + a = (xmax - xmin + 1) * (ymax - ymin + 1); while (a--) { if (*dr > 0 && *dr <= bm_vertoffs) { @@ -263,9 +278,9 @@ static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data) /* mcords is a polygon mask * - grab backbuffer, - * - draw with black in backbuffer, + * - draw with black in backbuffer, * - grab again and compare - * returns 'OK' + * returns 'OK' */ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) { @@ -273,7 +288,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short struct ImBuf *buf; int a; struct LassoMaskData lasso_mask_data; - + /* method in use for face selecting too */ if (vc->obedit == NULL) { if (!BKE_paint_select_elem_test(vc->obact)) { @@ -302,7 +317,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short /* build selection lookup */ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - + a = (xmax - xmin + 1) * (ymax - ymin + 1); while (a--) { if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) { @@ -323,7 +338,7 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) unsigned int *dr; short xmin, ymin, xmax, ymax, xc, yc; int radsq; - + /* method in use for face selecting too */ if (vc->obedit == NULL) { if (!BKE_paint_select_elem_test(vc->obact)) { @@ -342,7 +357,7 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) } dr = buf->rect; - + /* build selection lookup */ selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); radsq = rads * rads; @@ -358,12 +373,12 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) IMB_freeImBuf(buf); return true; - + } +/** \} */ /* -------------------------------------------------------------------- */ - /** \name Find Nearest Vert/Edge/Face * * \note Screen-space manhatten distances are used here, @@ -445,14 +460,14 @@ BMVert *EDBM_vert_find_nearest_ex( float dist_test; unsigned int index; BMVert *eve; - + /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ ED_view3d_backbuf_validate(vc); index = ED_view3d_backbuf_sample_rect( vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; - + if (eve) { if (dist_test < *r_dist) { *r_dist = dist_test; @@ -811,7 +826,7 @@ BMFace *EDBM_face_find_nearest_ex( index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; - + if (r_efa_zbuf) { *r_efa_zbuf = efa; } @@ -889,8 +904,8 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) #undef FIND_NEAR_CYCLE_THRESHOLD_MIN -/* best distance based on screen coords. - * use em->selectmode to define how to use +/* best distance based on screen coords. + * use em->selectmode to define how to use * selected vertices and edges get disadvantage * return 1 if found one */ @@ -906,7 +921,7 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, float dist = dist_init; BMFace *efa_zbuf = NULL; BMEdge *eed_zbuf = NULL; - + BMVert *eve = NULL; BMEdge *eed = NULL; BMFace *efa = NULL; @@ -968,8 +983,10 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Select Similar (Vert/Edge/Face) Operator + * \{ */ -/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */ static const EnumPropertyItem prop_similar_compare_types[] = { {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""}, {SIM_CMP_GT, "GREATER", 0, "Greater", ""}, @@ -1046,7 +1063,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) EDBM_update_generic(em, false, false); return OPERATOR_FINISHED; -} +} /* ***************************************************** */ @@ -1152,8 +1169,9 @@ static int edbm_select_similar_exec(bContext *C, wmOperator *op) else return similar_face_select_exec(C, op); } -static const EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), - bool *r_free) +static const EnumPropertyItem *select_similar_type_itemf( + bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), + bool *r_free) { Object *obedit; @@ -1205,15 +1223,15 @@ void MESH_OT_select_similar(wmOperatorType *ot) ot->name = "Select Similar"; ot->idname = "MESH_OT_select_similar"; ot->description = "Select similar vertices, edges or faces by property types"; - + /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = edbm_select_similar_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ prop = ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", ""); RNA_def_enum_funcs(prop, select_similar_type_itemf); @@ -1223,9 +1241,11 @@ void MESH_OT_select_similar(wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.0f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f); } +/** \} */ /* -------------------------------------------------------------------- */ -/* Select Similar Regions */ +/** \name Select Similar Region Operator + * \{ */ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op) { @@ -1246,9 +1266,10 @@ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op) } groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__); - group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index, - NULL, NULL, - BM_ELEM_SELECT, BM_VERT); + group_tot = BM_mesh_calc_face_groups( + bm, groups_array, &group_index, + NULL, NULL, + BM_ELEM_SELECT, BM_VERT); BM_mesh_elem_table_ensure(bm, BM_FACE); @@ -1313,8 +1334,11 @@ void MESH_OT_select_similar_region(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ -/* **************** Mode Select *************** */ +/* -------------------------------------------------------------------- */ +/** \name Select Mode Vert/Edge/Face Operator + * \{ */ static int edbm_select_mode_exec(bContext *C, wmOperator *op) { @@ -1385,12 +1409,15 @@ void MESH_OT_select_mode(wmOperatorType *ot) RNA_def_enum(ot->srna, "action", actions_items, 2, "Action", "Selection action to execute"); } -/* ***************************************************** */ +/** \} */ -/* **************** LOOP SELECTS *************** */ +/* -------------------------------------------------------------------- */ +/** \name Select Loop (Non Modal) Operator + * \{ */ -static void walker_select_count(BMEditMesh *em, int walkercode, void *start, const bool select, const bool select_mix, - int *r_totsel, int *r_totunsel) +static void walker_select_count( + BMEditMesh *em, int walkercode, void *start, const bool select, const bool select_mix, + int *r_totsel, int *r_totunsel) { BMesh *bm = em->bm; BMElem *ele; @@ -1445,7 +1472,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op) BMEdge **edarray; int edindex; const bool is_ring = RNA_boolean_get(op->ptr, "ring"); - + BMIter iter; int totedgesel = 0; @@ -1454,17 +1481,17 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op) totedgesel++; } } - + edarray = MEM_mallocN(sizeof(BMEdge *) * totedgesel, "edge array"); edindex = 0; - + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { edarray[edindex] = eed; edindex++; } } - + if (is_ring) { for (edindex = 0; edindex < totedgesel; edindex += 1) { eed = edarray[edindex]; @@ -1481,7 +1508,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op) } MEM_freeN(edarray); // if (EM_texFaceCheck()) - + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -1493,23 +1520,23 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot) ot->name = "Multi Select Loops"; ot->idname = "MESH_OT_loop_multi_select"; ot->description = "Select a loop of connected edges by connection type"; - + /* api callbacks */ ot->exec = edbm_loop_multiselect_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ RNA_def_boolean(ot->srna, "ring", 0, "Ring", ""); } - -/* ***************** MAIN MOUSE SELECTION ************** */ - +/** \} */ -/* ***************** loop select (non modal) ************** */ +/* -------------------------------------------------------------------- */ +/** \name Select Loop (Cursor Pick) Operator + * \{ */ static void mouse_mesh_loop_face(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear) { @@ -1564,7 +1591,6 @@ static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool } } - static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring) { ViewContext vc; @@ -1641,11 +1667,15 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de /* We can't be sure this has already been set... */ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); - if (ED_view3d_project_float_object(vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object( + vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) + { length_1 = len_squared_v2v2(mvalf, v1_co); } - if (ED_view3d_project_float_object(vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object( + vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) + { length_2 = len_squared_v2v2(mvalf, v2_co); } #if 0 @@ -1672,7 +1702,9 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de float co[2], tdist; BM_face_calc_center_mean(f, cent); - if (ED_view3d_project_float_object(vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object( + vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) + { tdist = len_squared_v2v2(mvalf, co); if (tdist < best_dist) { /* printf("Best face: %p (%f)\n", f, tdist);*/ @@ -1696,14 +1728,15 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de static int edbm_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - + view3d_operator_needs_opengl(C); - - if (mouse_mesh_loop(C, event->mval, - RNA_boolean_get(op->ptr, "extend"), - RNA_boolean_get(op->ptr, "deselect"), - RNA_boolean_get(op->ptr, "toggle"), - RNA_boolean_get(op->ptr, "ring"))) + + if (mouse_mesh_loop( + C, event->mval, + RNA_boolean_get(op->ptr, "extend"), + RNA_boolean_get(op->ptr, "deselect"), + RNA_boolean_get(op->ptr, "toggle"), + RNA_boolean_get(op->ptr, "ring"))) { return OPERATOR_FINISHED; } @@ -1718,14 +1751,14 @@ void MESH_OT_loop_select(wmOperatorType *ot) ot->name = "Loop Select"; ot->idname = "MESH_OT_loop_select"; ot->description = "Select a loop of connected edges"; - + /* api callbacks */ ot->invoke = edbm_select_loop_invoke; ot->poll = ED_operator_editmesh_region_view3d; - + /* flags */ ot->flag = OPTYPE_UNDO; - + /* properties */ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection"); RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); @@ -1739,11 +1772,11 @@ void MESH_OT_edgering_select(wmOperatorType *ot) ot->name = "Edge Ring Select"; ot->idname = "MESH_OT_edgering_select"; ot->description = "Select an edge ring"; - + /* callbacks */ ot->invoke = edbm_select_loop_invoke; ot->poll = ED_operator_editmesh_region_view3d; - + /* flags */ ot->flag = OPTYPE_UNDO; @@ -1753,7 +1786,12 @@ void MESH_OT_edgering_select(wmOperatorType *ot) RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring"); } -/* ******************** (de)select all operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name (De)Select All Operator + * \{ */ + static int edbm_select_all_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -1798,6 +1836,12 @@ void MESH_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Interior Faces Operator + * \{ */ + static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); @@ -1829,10 +1873,15 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Picking API + * + * Here actual select happens, + * Gets called via generic mouse select operator. + * \{ */ -/* ************************************************** */ -/* here actual select happens */ -/* gets called via generic mouse select operator */ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) { ViewContext vc; @@ -1948,6 +1997,12 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect return false; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Mode Utilities + * \{ */ + static void edbm_strip_selections(BMEditMesh *em) { BMEditSelection *ese, *nextese; @@ -1986,11 +2041,11 @@ void EDBM_selectmode_set(BMEditMesh *em) BMEdge *eed; BMFace *efa; BMIter iter; - + em->bm->selectmode = em->selectmode; edbm_strip_selections(em); /* strip BMEditSelections from em->selected that are not relevant to new mode */ - + if (em->bm->totvertsel == 0 && em->bm->totedgesel == 0 && em->bm->totfacesel == 0) @@ -2153,8 +2208,9 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s } /* user facing function, does notification */ -bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new, - const int action, const bool use_extend, const bool use_expand) +bool EDBM_selectmode_toggle( + bContext *C, const short selectmode_new, + const int action, const bool use_extend, const bool use_expand) { ToolSettings *ts = CTX_data_tool_settings(C); Object *obedit = CTX_data_edit_object(C); @@ -2250,9 +2306,10 @@ bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new, * * \return true if the mode is changed. */ -bool EDBM_selectmode_disable(Scene *scene, BMEditMesh *em, - const short selectmode_disable, - const short selectmode_fallback) +bool EDBM_selectmode_disable( + Scene *scene, BMEditMesh *em, + const short selectmode_disable, + const short selectmode_fallback) { /* note essential, but switch out of vertex mode since the * selected regions wont be nicely isolated after flushing */ @@ -2275,6 +2332,12 @@ bool EDBM_selectmode_disable(Scene *scene, BMEditMesh *em, } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Toggle + * \{ */ + void EDBM_deselect_by_material(BMEditMesh *em, const short index, const bool select) { BMIter iter; @@ -2303,7 +2366,7 @@ void EDBM_select_swap(BMEditMesh *em) /* exported for UV */ BMVert *eve; BMEdge *eed; BMFace *efa; - + if (em->bm->selectmode & SCE_SELECT_VERTEX) { BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) @@ -2326,9 +2389,17 @@ void EDBM_select_swap(BMEditMesh *em) /* exported for UV */ } } -// if (EM_texFaceCheck()) } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Interior Faces + * + * \note This algorithm is limited to single faces and could be improved, see: + * https://blender.stackexchange.com/questions/18916 + * \{ */ + bool EDBM_select_interior_faces(BMEditMesh *em) { BMesh *bm = em->bm; @@ -2361,8 +2432,13 @@ bool EDBM_select_interior_faces(BMEditMesh *em) return changed; } +/** \} */ -/************************ Select Linked Operator *************************/ +/* -------------------------------------------------------------------- */ +/** \name Select Linked Operator + * + * Support delimiting on different edge properties. + * \{ */ /* so we can have last-used default depend on selection mode (rare exception!) */ #define USE_LINKED_SELECT_DEFAULT_HACK @@ -2422,10 +2498,10 @@ static bool select_linked_delimit_test( * Gets the default from the operator fallback to own last-used value * (selected based on mode) */ -static int select_linked_delimit_default_from_op(wmOperator *op, BMEditMesh *em) +static int select_linked_delimit_default_from_op(wmOperator *op, int select_mode) { static char delimit_last_store[2] = {0, BMO_DELIM_SEAM}; - int delimit_last_index = (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0; + int delimit_last_index = (select_mode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0; char *delimit_last = &delimit_last_store[delimit_last_index]; PropertyRNA *prop_delimit = RNA_struct_find_property(op->ptr, "delimit"); int delimit; @@ -2495,7 +2571,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BMWalker walker; #ifdef USE_LINKED_SELECT_DEFAULT_HACK - int delimit = select_linked_delimit_default_from_op(op, em); + int delimit = select_linked_delimit_default_from_op(op, em->selectmode); #else int delimit = RNA_enum_get(op->ptr, "delimit"); #endif @@ -2683,6 +2759,12 @@ void MESH_OT_select_linked(wmOperatorType *ot) #endif } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked (Cursor Pick) Operator + * \{ */ + static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op); static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, int delimit) @@ -2827,7 +2909,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE } #ifdef USE_LINKED_SELECT_DEFAULT_HACK - int delimit = select_linked_delimit_default_from_op(op, em); + int delimit = select_linked_delimit_default_from_op(op, em->selectmode); #else int delimit = RNA_enum_get(op->ptr, "delimit"); #endif @@ -2864,7 +2946,7 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op) BMElem *ele = EDBM_elem_from_index_any(em, index); #ifdef USE_LINKED_SELECT_DEFAULT_HACK - int delimit = select_linked_delimit_default_from_op(op, em); + int delimit = select_linked_delimit_default_from_op(op, em->selectmode); #else int delimit = RNA_enum_get(op->ptr, "delimit"); #endif @@ -2884,15 +2966,15 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot) ot->name = "Select Linked"; ot->idname = "MESH_OT_select_linked_pick"; ot->description = "(De)select all vertices linked to the edge under the mouse cursor"; - + /* api callbacks */ ot->invoke = edbm_select_linked_pick_invoke; ot->exec = edbm_select_linked_pick_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); prop = RNA_def_enum_flag(ot->srna, "delimit", rna_enum_mesh_delimit_mode_items, BMO_DELIM_SEAM, "Delimit", "Delimit selected region"); @@ -2905,6 +2987,11 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Face by Sides Operator + * \{ */ static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op) { @@ -2980,6 +3067,11 @@ void MESH_OT_select_face_by_sides(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Loose Operator + * \{ */ static int edbm_select_loose_exec(bContext *C, wmOperator *op) { @@ -3051,6 +3143,11 @@ void MESH_OT_select_loose(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Mirror Operator + * \{ */ static int edbm_select_mirror_exec(bContext *C, wmOperator *op) { @@ -3099,7 +3196,11 @@ void MESH_OT_select_mirror(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection"); } -/* ******************** **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select More Operator + * \{ */ static int edbm_select_more_exec(bContext *C, wmOperator *op) { @@ -3123,13 +3224,19 @@ void MESH_OT_select_more(wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_select_more_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select More Operator + * \{ */ + static int edbm_select_less_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -3152,13 +3259,19 @@ void MESH_OT_select_less(wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_select_less_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_face_step", true, "Face Step", "Connected faces (instead of edges)"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select N'th Operator + * \{ */ + /** * Check if we're connected to another selected efge. */ @@ -3382,12 +3495,17 @@ void MESH_OT_select_nth(wmOperatorType *ot) void em_setup_viewcontext(bContext *C, ViewContext *vc) { ED_view3d_viewcontext_init(C, vc); - + if (vc->obedit) { vc->em = BKE_editmesh_from_object(vc->obedit); } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Sharp Edges Operator + * \{ */ static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op) { @@ -3428,20 +3546,26 @@ void MESH_OT_edges_select_sharp(wmOperatorType *ot) ot->name = "Select Sharp Edges"; ot->description = "Select all sharp-enough edges"; ot->idname = "MESH_OT_edges_select_sharp"; - + /* api callbacks */ ot->exec = edbm_select_sharp_edges_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ prop = RNA_def_float_rotation(ot->srna, "sharpness", 0, NULL, DEG2RADF(0.01f), DEG2RADF(180.0f), "Sharpness", "", DEG2RADF(1.0f), DEG2RADF(180.0f)); RNA_def_property_float_default(prop, DEG2RADF(30.0f)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked Flat Faces Operator + * \{ */ + static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -3509,20 +3633,26 @@ void MESH_OT_faces_select_linked_flat(wmOperatorType *ot) ot->name = "Select Linked Flat Faces"; ot->description = "Select linked faces by angle"; ot->idname = "MESH_OT_faces_select_linked_flat"; - + /* api callbacks */ ot->exec = edbm_select_linked_flat_faces_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ prop = RNA_def_float_rotation(ot->srna, "sharpness", 0, NULL, DEG2RADF(0.01f), DEG2RADF(180.0f), "Sharpness", "", DEG2RADF(1.0f), DEG2RADF(180.0f)); RNA_def_property_float_default(prop, DEG2RADF(1.0f)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Non-Manifold Operator + * \{ */ + static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -3544,12 +3674,12 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) /* Selects isolated verts, and edges that do not have 2 neighboring * faces */ - + if (em->selectmode == SCE_SELECT_FACE) { BKE_report(op->reports, RPT_ERROR, "Does not work in face selection mode"); return OPERATOR_CANCELLED; } - + if (use_verts) { BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { @@ -3559,7 +3689,7 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) } } } - + if (use_wire || use_boundary || use_multi_face || use_non_contiguous) { BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { @@ -3590,11 +3720,11 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) ot->name = "Select Non Manifold"; ot->description = "Select all non-manifold vertices or edges"; ot->idname = "MESH_OT_select_non_manifold"; - + /* api callbacks */ ot->exec = edbm_select_non_manifold_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3614,6 +3744,12 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) "Vertices connecting multiple face regions"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Random Operator + * \{ */ + static int edbm_select_random_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -3660,9 +3796,9 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) else { EDBM_deselect_flush(em); } - + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - + return OPERATOR_FINISHED; } @@ -3679,11 +3815,17 @@ void MESH_OT_select_random(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ WM_operator_properties_select_random(ot); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Ungrouped Operator + * \{ */ + static int edbm_select_ungrouped_poll(bContext *C) { if (ED_operator_editmesh(C)) { @@ -3750,6 +3892,11 @@ void MESH_OT_select_ungrouped(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Axis Operator + * \{ */ /* BMESH_TODO - some way to select on an arbitrary axis */ static int edbm_select_axis_exec(bContext *C, wmOperator *op) @@ -3836,6 +3983,12 @@ void MESH_OT_select_axis(wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Threshold", "", 0.00001f, 10.0f); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Region to Loop Operator + * \{ */ + static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); @@ -3849,22 +4002,22 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op)) BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { BMLoop *l1, *l2; BMIter liter1, liter2; - + BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) { int tot = 0, totsel = 0; - + BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) { tot++; totsel += BM_elem_flag_test(l2->f, BM_ELEM_SELECT) != 0; } - + if ((tot != totsel && totsel > 0) || (totsel == 1 && tot == 1)) BM_elem_flag_enable(l1->e, BM_ELEM_TAG); } } EDBM_flag_disable_all(em, BM_ELEM_SELECT); - + BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { BM_edge_select_set(em->bm, e, true); @@ -3899,29 +4052,36 @@ void MESH_OT_region_to_loop(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int loop_find_region(BMLoop *l, int flag, - GSet *visit_face_set, BMFace ***region_out) +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Loop to Region Operator + * \{ */ + +static int loop_find_region( + BMLoop *l, int flag, + GSet *visit_face_set, BMFace ***region_out) { BMFace **region = NULL; BMFace **stack = NULL; BLI_array_declare(region); BLI_array_declare(stack); BMFace *f; - + BLI_array_append(stack, l->f); BLI_gset_insert(visit_face_set, l->f); - - while (BLI_array_count(stack) > 0) { + + while (BLI_array_len(stack) > 0) { BMIter liter1, liter2; BMLoop *l1, *l2; - + f = BLI_array_pop(stack); BLI_array_append(region, f); - + BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l1->e, flag)) continue; - + BM_ITER_ELEM (l2, &liter2, l1->e, BM_LOOPS_OF_EDGE) { /* avoids finding same region twice * (otherwise) the logic works fine without */ @@ -3935,11 +4095,11 @@ static int loop_find_region(BMLoop *l, int flag, } } } - + BLI_array_free(stack); - + *region_out = region; - return BLI_array_count(region); + return BLI_array_len(region); } static int verg_radial(const void *va, const void *vb) @@ -3947,10 +4107,9 @@ static int verg_radial(const void *va, const void *vb) const BMEdge *e_a = *((const BMEdge **)va); const BMEdge *e_b = *((const BMEdge **)vb); - int a, b; - a = BM_edge_face_count(e_a); - b = BM_edge_face_count(e_b); - + const int a = BM_edge_face_count(e_a); + const int b = BM_edge_face_count(e_b); + if (a > b) return -1; if (a < b) return 1; return 0; @@ -3969,7 +4128,7 @@ static int loop_find_regions(BMEditMesh *em, const bool selbigger) const int edges_len = em->bm->totedgesel; BMEdge *e, **edges; int count = 0, i; - + visit_face_set = BLI_gset_ptr_new_ex(__func__, edges_len); edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__); @@ -3983,21 +4142,21 @@ static int loop_find_regions(BMEditMesh *em, const bool selbigger) BM_elem_flag_disable(e, BM_ELEM_TAG); } } - + /* sort edges by radial cycle length */ qsort(edges, edges_len, sizeof(*edges), verg_radial); - + for (i = 0; i < edges_len; i++) { BMIter liter; BMLoop *l; BMFace **region = NULL, **region_out; int c, tot = 0; - + e = edges[i]; - + if (!BM_elem_flag_test(e, BM_ELEM_TAG)) continue; - + BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { if (BLI_gset_haskey(visit_face_set, l->f)) continue; @@ -4019,26 +4178,26 @@ static int loop_find_regions(BMEditMesh *em, const bool selbigger) MEM_freeN(region_out); } } - + if (region) { int j; - + for (j = 0; j < tot; j++) { BM_elem_flag_enable(region[j], BM_ELEM_TAG); BM_ITER_ELEM (l, &liter, region[j], BM_LOOPS_OF_FACE) { BM_elem_flag_disable(l->e, BM_ELEM_TAG); } } - + count += tot; - + MEM_freeN(region); } } - + MEM_freeN(edges); BLI_gset_free(visit_face_set, NULL); - + return count; } @@ -4049,25 +4208,23 @@ static int edbm_loop_to_region_exec(bContext *C, wmOperator *op) BMIter iter; BMFace *f; const bool select_bigger = RNA_boolean_get(op->ptr, "select_bigger"); - int a, b; - /* find the set of regions with smallest number of total faces */ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); - a = loop_find_regions(em, select_bigger); - b = loop_find_regions(em, !select_bigger); + const int a = loop_find_regions(em, select_bigger); + const int b = loop_find_regions(em, !select_bigger); BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); loop_find_regions(em, ((a <= b) != select_bigger) ? select_bigger : !select_bigger); - + EDBM_flag_disable_all(em, BM_ELEM_SELECT); - + BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(f, BM_ELEM_TAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { BM_face_select_set(em->bm, f, true); } } - + EDBM_selectmode_flush(em); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -4087,9 +4244,8 @@ void MESH_OT_loop_to_region(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + RNA_def_boolean(ot->srna, "select_bigger", 0, "Select Bigger", "Select bigger regions instead of smaller ones"); } - -/************************ Select Path Operator *************************/ +/** \} */ diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index c979a73e9645b70985d681b26fb1dd0885c5b74c..84299f12cefe62b7e37054ede5fb468773a69fbe 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -84,6 +84,10 @@ #define USE_FACE_CREATE_SEL_EXTEND +/* -------------------------------------------------------------------- */ +/** \name Subdivide Operator + * \{ */ + static int edbm_subdivide_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -93,19 +97,20 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f; const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal"); - if (RNA_boolean_get(op->ptr, "quadtri") && + if (RNA_boolean_get(op->ptr, "quadtri") && RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT) { RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT); } - - BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, - smooth, SUBD_FALLOFF_LIN, false, - fractal, along_normal, - cuts, - SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"), - RNA_boolean_get(op->ptr, "quadtri"), true, false, - RNA_int_get(op->ptr, "seed")); + + BM_mesh_esubdivide( + em->bm, BM_ELEM_SELECT, + smooth, SUBD_FALLOFF_LIN, false, + fractal, along_normal, + cuts, + SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"), + RNA_boolean_get(op->ptr, "quadtri"), true, false, + RNA_int_get(op->ptr, "seed")); EDBM_update_generic(em, true, true); @@ -154,10 +159,14 @@ void MESH_OT_subdivide(wmOperatorType *ot) RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Random Seed", "Seed for the random number generator", 0, 255); } +/** \} */ + /* -------------------------------------------------------------------- */ -/* Edge Ring Subdiv - * (bridge code shares props) - */ +/** \name Edge Ring Subdivide Operator + * + * Bridge code shares props. + * + * \{ */ struct EdgeRingOpSubdProps { int interp_mode; @@ -219,11 +228,12 @@ static int edbm_subdivide_edge_ring_exec(bContext *C, wmOperator *op) mesh_operator_edgering_props_get(op, &op_props); - if (!EDBM_op_callf(em, op, - "subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f " - "profile_shape=%i profile_shape_factor=%f", - BM_ELEM_SELECT, op_props.interp_mode, op_props.cuts, op_props.smooth, - op_props.profile_shape, op_props.profile_shape_factor)) + if (!EDBM_op_callf( + em, op, + "subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f " + "profile_shape=%i profile_shape_factor=%f", + BM_ELEM_SELECT, op_props.interp_mode, op_props.cuts, op_props.smooth, + op_props.profile_shape, op_props.profile_shape_factor)) { return OPERATOR_CANCELLED; } @@ -251,6 +261,11 @@ void MESH_OT_subdivide_edgering(wmOperatorType *ot) mesh_operator_edgering_props(ot, 1, 10); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Un-Subdivide Operator + * \{ */ static int edbm_unsubdivide_exec(bContext *C, wmOperator *op) { @@ -332,6 +347,11 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) ED_transform_snap_object_context_destroy(snap_context); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ /* Note, these values must match delete_mesh() event values */ enum { @@ -386,7 +406,7 @@ static int edbm_delete_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); EDBM_update_generic(em, true, true); - + return OPERATOR_FINISHED; } @@ -405,13 +425,13 @@ void MESH_OT_delete(wmOperatorType *ot) ot->name = "Delete"; ot->description = "Delete selected vertices, edges or faces"; ot->idname = "MESH_OT_delete"; - + /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = edbm_delete_exec; - + ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -420,6 +440,11 @@ void MESH_OT_delete(wmOperatorType *ot) "Type", "Method used for deleting mesh data"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Loose Operator + * \{ */ static bool bm_face_is_loose(BMFace *f) { @@ -518,6 +543,11 @@ void MESH_OT_delete_loose(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_faces", false, "Faces", "Remove loose faces"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Collapse Edge Operator + * \{ */ static int edbm_collapse_edge_exec(bContext *C, wmOperator *op) { @@ -547,6 +577,12 @@ void MESH_OT_edge_collapse(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Create Edge/Face Operator + * \{ */ + static bool edbm_add_edge_face__smooth_get(BMesh *bm) { BMEdge *e; @@ -616,8 +652,9 @@ static BMElem *edbm_add_edge_face_exec__tricky_extend_sel(BMesh *bm) (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false)) ) { - BMEdge *e_other = BM_edge_exists(BM_edge_other_vert(ed_pair[0], v), - BM_edge_other_vert(ed_pair[1], v)); + BMEdge *e_other = BM_edge_exists( + BM_edge_other_vert(ed_pair[0], v), + BM_edge_other_vert(ed_pair[1], v)); BM_edge_select_set(bm, ed_pair[0], true); BM_edge_select_set(bm, ed_pair[1], true); if (e_other) { @@ -740,13 +777,14 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm); #endif - if (!EDBM_op_init(em, &bmop, op, - "contextual_create geom=%hfev mat_nr=%i use_smooth=%b", - BM_ELEM_SELECT, em->mat_nr, use_smooth)) + if (!EDBM_op_init( + em, &bmop, op, + "contextual_create geom=%hfev mat_nr=%i use_smooth=%b", + BM_ELEM_SELECT, em->mat_nr, use_smooth)) { return OPERATOR_CANCELLED; } - + BMO_op_exec(em->bm, &bmop); /* cancel if nothing was done */ @@ -796,16 +834,20 @@ void MESH_OT_edge_face_add(wmOperatorType *ot) ot->name = "Make Edge/Face"; ot->description = "Add an edge or face to selected"; ot->idname = "MESH_OT_edge_face_add"; - + /* api callbacks */ ot->exec = edbm_add_edge_face_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ************************* SEAMS AND EDGES **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mark Edge (Seam) Operator + * \{ */ static int edbm_mark_seam_exec(bContext *C, wmOperator *op) { @@ -817,7 +859,7 @@ static int edbm_mark_seam_exec(bContext *C, wmOperator *op) BMEdge *eed; BMIter iter; const bool clear = RNA_boolean_get(op->ptr, "clear"); - + /* auto-enable seams drawing */ if (clear == 0) { me->drawflag |= ME_DRAWSEAMS; @@ -827,7 +869,7 @@ static int edbm_mark_seam_exec(bContext *C, wmOperator *op) BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_SELECT) || BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) continue; - + BM_elem_flag_disable(eed, BM_ELEM_SEAM); } } @@ -853,18 +895,24 @@ void MESH_OT_mark_seam(wmOperatorType *ot) ot->name = "Mark Seam"; ot->idname = "MESH_OT_mark_seam"; ot->description = "(Un)mark selected edges as a seam"; - + /* api callbacks */ ot->exec = edbm_mark_seam_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mark Edge (Sharp) Operator + * \{ */ + static int edbm_mark_sharp_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -907,14 +955,14 @@ void MESH_OT_mark_sharp(wmOperatorType *ot) ot->name = "Mark Sharp"; ot->idname = "MESH_OT_mark_sharp"; ot->description = "(Un)mark selected edges as sharp"; - + /* api callbacks */ ot->exec = edbm_mark_sharp_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "use_verts", false, "Vertices", @@ -958,17 +1006,19 @@ static int edbm_vert_connect_exec(bContext *C, wmOperator *op) } if (is_pair) { - if (!EDBM_op_init(em, &bmop, op, - "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf", - verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN)) + if (!EDBM_op_init( + em, &bmop, op, + "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf", + verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN)) { goto finally; } } else { - if (!EDBM_op_init(em, &bmop, op, - "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b", - verts, verts_len, BM_ELEM_HIDDEN, check_degenerate)) + if (!EDBM_op_init( + em, &bmop, op, + "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b", + verts, verts_len, BM_ELEM_HIDDEN, check_degenerate)) { goto finally; } @@ -1005,15 +1055,20 @@ void MESH_OT_vert_connect(wmOperatorType *ot) ot->name = "Vertex Connect"; ot->idname = "MESH_OT_vert_connect"; ot->description = "Connect selected vertices of faces, splitting the face"; - + /* api callbacks */ ot->exec = edbm_vert_connect_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Split Concave Faces Operator + * \{ */ /** * check that endpoints are verts and only have a single selected edge connected. @@ -1318,6 +1373,11 @@ void MESH_OT_vert_connect_concave(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Split Non-Planar Faces Operator + * \{ */ static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op) { @@ -1362,6 +1422,12 @@ void MESH_OT_vert_connect_nonplanar(wmOperatorType *ot) RNA_def_property_float_default(prop, DEG2RADF(5.0f)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Make Planar Faces Operator + * \{ */ + static int edbm_face_make_planar_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -1399,6 +1465,11 @@ void MESH_OT_face_make_planar(wmOperatorType *ot) RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Split Edge Operator + * \{ */ static int edbm_edge_split_exec(bContext *C, wmOperator *op) { @@ -1413,7 +1484,7 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op) { return OPERATOR_CANCELLED; } - + if (em->selectmode == SCE_SELECT_FACE) { EDBM_select_flush(em); } @@ -1429,16 +1500,20 @@ void MESH_OT_edge_split(wmOperatorType *ot) ot->name = "Edge Split"; ot->idname = "MESH_OT_edge_split"; ot->description = "Split selected edges so that each neighbor face gets its own copy"; - + /* api callbacks */ ot->exec = edbm_edge_split_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/****************** add duplicate operator ***************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Duplicate Operator + * \{ */ static int edbm_duplicate_exec(bContext *C, wmOperator *op) { @@ -1469,7 +1544,7 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op) } EDBM_update_generic(em, true, true); - + return OPERATOR_FINISHED; } @@ -1478,7 +1553,7 @@ static int edbm_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNU WM_cursor_wait(1); edbm_duplicate_exec(C, op); WM_cursor_wait(0); - + return OPERATOR_FINISHED; } @@ -1488,29 +1563,34 @@ void MESH_OT_duplicate(wmOperatorType *ot) ot->name = "Duplicate"; ot->description = "Duplicate selected vertices, edges or faces"; ot->idname = "MESH_OT_duplicate"; - + /* api callbacks */ ot->invoke = edbm_duplicate_invoke; ot->exec = edbm_duplicate_exec; - + ot->poll = ED_operator_editmesh; - + /* to give to transform */ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Flip Normals Operator + * \{ */ static int edbm_flip_normals_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - + if (!EDBM_op_callf( em, op, "reverse_faces faces=%hf flip_multires=%b", BM_ELEM_SELECT, true)) { return OPERATOR_CANCELLED; } - + EDBM_update_generic(em, true, false); return OPERATOR_FINISHED; @@ -1522,15 +1602,21 @@ void MESH_OT_flip_normals(wmOperatorType *ot) ot->name = "Flip Normals"; ot->description = "Flip the direction of selected faces' normals (and of their vertices)"; ot->idname = "MESH_OT_flip_normals"; - + /* api callbacks */ ot->exec = edbm_flip_normals_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Rotate Edge Operator + * \{ */ + /** * Rotate the edges between selected faces, otherwise rotate the selected edges. */ @@ -1564,7 +1650,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) } } } - + /* ok, we don't have two adjacent faces, but we do have two selected ones. * that's an error condition.*/ if (tot == 0) { @@ -1623,12 +1709,17 @@ void MESH_OT_edge_rotate(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", ""); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Operator + * \{ */ static int edbm_hide_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - + EDBM_mesh_hide(em, RNA_boolean_get(op->ptr, "unselected")); EDBM_update_generic(em, true, false); @@ -1642,18 +1733,24 @@ void MESH_OT_hide(wmOperatorType *ot) ot->name = "Hide Selection"; ot->idname = "MESH_OT_hide"; ot->description = "Hide (un)selected vertices, edges or faces"; - + /* api callbacks */ ot->exec = edbm_hide_exec; ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reveal Operator + * \{ */ + static int edbm_reveal_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -1673,22 +1770,28 @@ void MESH_OT_reveal(wmOperatorType *ot) ot->name = "Reveal Hidden"; ot->idname = "MESH_OT_reveal"; ot->description = "Reveal all hidden vertices, edges and faces"; - + /* api callbacks */ ot->exec = edbm_reveal_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "select", true, "Select", ""); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Recalculate Normals Operator + * \{ */ + static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - + /* doflip has to do with bmesh_rationalize_normals, it's an internal * thing */ if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf", BM_ELEM_SELECT)) @@ -1709,18 +1812,22 @@ void MESH_OT_normals_make_consistent(wmOperatorType *ot) ot->name = "Make Normals Consistent"; ot->description = "Make face and vertex normals point either outside or inside the mesh"; ot->idname = "MESH_OT_normals_make_consistent"; - + /* api callbacks */ ot->exec = edbm_normals_make_consistent_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + RNA_def_boolean(ot->srna, "inside", false, "Inside", ""); } +/** \} */ +/* -------------------------------------------------------------------- */ +/** \name Smooth Vertex Operator + * \{ */ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) { @@ -1744,12 +1851,12 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) } /* if there is a mirror modifier with clipping, flag the verts that - * are within tolerance of the plane(s) of reflection + * are within tolerance of the plane(s) of reflection */ for (md = obedit->modifiers.first; md; md = md->next) { if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) { MirrorModifierData *mmd = (MirrorModifierData *)md; - + if (mmd->flag & MOD_MIR_CLIPPING) { if (mmd->flag & MOD_MIR_AXIS_X) mirrx = true; @@ -1768,10 +1875,11 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) repeat = 1; for (i = 0; i < repeat; i++) { - if (!EDBM_op_callf(em, op, - "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b " - "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b", - BM_ELEM_SELECT, fac, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis)) + if (!EDBM_op_callf( + em, op, + "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b " + "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b", + BM_ELEM_SELECT, fac, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis)) { return OPERATOR_CANCELLED; } @@ -1786,19 +1894,20 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) EDBM_update_generic(em, true, false); return OPERATOR_FINISHED; -} - +} + + void MESH_OT_vertices_smooth(wmOperatorType *ot) { /* identifiers */ ot->name = "Smooth Vertex"; ot->description = "Flatten angles of selected vertices"; ot->idname = "MESH_OT_vertices_smooth"; - + /* api callbacks */ ot->exec = edbm_do_smooth_vertex_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1809,6 +1918,12 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot) RNA_def_boolean(ot->srna, "zaxis", true, "Z-Axis", "Smooth along the Z axis"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Laplacian Vertex Smooth Operator + * \{ */ + static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -1828,7 +1943,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) if (f->len > 4) { BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads"); return OPERATOR_CANCELLED; - } + } } } @@ -1846,11 +1961,12 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) preserve_volume = RNA_boolean_get(op->ptr, "preserve_volume"); if (!repeat) repeat = 1; - + for (i = 0; i < repeat; i++) { - if (!EDBM_op_callf(em, op, - "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b", - BM_ELEM_SELECT, lambda_factor, lambda_border, usex, usey, usez, preserve_volume)) + if (!EDBM_op_callf( + em, op, + "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b", + BM_ELEM_SELECT, lambda_factor, lambda_border, usex, usey, usez, preserve_volume)) { return OPERATOR_CANCELLED; } @@ -1873,11 +1989,11 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot) ot->name = "Laplacian Smooth Vertex"; ot->description = "Laplacian smooth of selected vertices"; ot->idname = "MESH_OT_vertices_smooth_laplacian"; - + /* api callbacks */ ot->exec = edbm_do_smooth_laplacian_vertex_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1893,7 +2009,11 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot) RNA_def_boolean(ot->srna, "preserve_volume", true, "Preserve Volume", "Apply volume preservation after smooth"); } -/********************** Smooth/Solid Operators *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Faces Smooth Shading Operator + * \{ */ static void mesh_set_smooth_faces(BMEditMesh *em, short smooth) { @@ -1901,7 +2021,7 @@ static void mesh_set_smooth_faces(BMEditMesh *em, short smooth) BMFace *efa; if (em == NULL) return; - + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_elem_flag_set(efa, BM_ELEM_SMOOTH, smooth); @@ -1936,6 +2056,12 @@ void MESH_OT_faces_shade_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Faces Flat Shading Operator + * \{ */ + static int edbm_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); @@ -1963,8 +2089,11 @@ void MESH_OT_faces_shade_flat(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ -/********************** UV/Color Operators *************************/ +/* -------------------------------------------------------------------- */ +/** \name UV/Color Rotate/Reverse Operator + * \{ */ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op) { @@ -2134,6 +2263,11 @@ void MESH_OT_colors_reverse(wmOperatorType *ot) //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Merge Vertices Operator + * \{ */ enum { MESH_MERGE_LAST = 1, @@ -2170,7 +2304,7 @@ static bool merge_firstlast(BMEditMesh *em, const bool use_first, const bool use if (!BM_elem_flag_test(mergevert, BM_ELEM_SELECT)) return false; - + if (use_uvmerge) { if (!EDBM_op_callf(em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert)) return false; @@ -2182,8 +2316,9 @@ static bool merge_firstlast(BMEditMesh *em, const bool use_first, const bool use return true; } -static bool merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob, - const bool use_cursor, const bool use_uvmerge, wmOperator *wmop) +static bool merge_target( + BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob, + const bool use_cursor, const bool use_uvmerge, wmOperator *wmop) { BMIter iter; BMVert *v; @@ -2204,7 +2339,7 @@ static bool merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob, add_v3_v3(cent, v->co); i++; } - + if (!i) return false; @@ -2216,7 +2351,7 @@ static bool merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob, if (!vco) return false; - + if (use_uvmerge) { if (!EDBM_op_callf(em, wmop, "average_vert_facedata verts=%hv", BM_ELEM_SELECT)) return false; @@ -2283,14 +2418,14 @@ static const EnumPropertyItem merge_type_items[] = { }; static const EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) -{ +{ Object *obedit; EnumPropertyItem *item = NULL; int totitem = 0; - + if (!C) /* needed for docs */ return merge_type_items; - + obedit = CTX_data_edit_object(C); if (obedit && obedit->type == OB_MESH) { BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2320,7 +2455,7 @@ static const EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *UNUSED( return item; } - + return NULL; } @@ -2345,6 +2480,11 @@ void MESH_OT_merge(wmOperatorType *ot) RNA_def_boolean(ot->srna, "uvs", false, "UVs", "Move UVs according to merge"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Doubles Operator + * \{ */ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) { @@ -2367,9 +2507,10 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) if (use_unselected) { - EDBM_op_init(em, &bmop, op, - "automerge verts=%hv dist=%f", - BM_ELEM_SELECT, threshold); + EDBM_op_init( + em, &bmop, op, + "automerge verts=%hv dist=%f", + BM_ELEM_SELECT, threshold); BMO_op_exec(em->bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, true)) { @@ -2377,9 +2518,10 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) } } else { - EDBM_op_init(em, &bmop, op, - "find_doubles verts=%hv dist=%f", - BM_ELEM_SELECT, threshold); + EDBM_op_init( + em, &bmop, op, + "find_doubles verts=%hv dist=%f", + BM_ELEM_SELECT, threshold); BMO_op_exec(em->bm, &bmop); if (!EDBM_op_callf(em, op, "weld_verts targetmap=%S", &bmop, "targetmap.out")) { @@ -2391,7 +2533,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } } - + count = totvert_orig - em->bm->totvert; BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices", count); @@ -2423,8 +2565,11 @@ void MESH_OT_remove_doubles(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_unselected", false, "Unselected", "Merge selected to other unselected vertices"); } +/** \} */ -/************************ Shape Operators *************************/ +/* -------------------------------------------------------------------- */ +/** \name Shape Key Propagate Operator + * \{ */ /* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/ static void shape_propagate(BMEditMesh *em, wmOperator *op) @@ -2438,7 +2583,7 @@ static void shape_propagate(BMEditMesh *em, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Mesh does not have shape keys"); return; } - + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) continue; @@ -2489,6 +2634,12 @@ void MESH_OT_shape_propagate_to_all(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Blend from Shape Operator + * \{ */ + /* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) { @@ -2515,23 +2666,23 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) if (key) { kb = BLI_findlink(&key->block, shape); } - + /* perform blending on selected vertices*/ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) continue; - + /* get coordinates of shapekey we're blending from */ sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape); copy_v3_v3(co, sco); - + if (use_add) { /* in add mode, we add relative shape key offset */ if (kb) { const float *rco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative); sub_v3_v3v3(co, co, rco); } - + madd_v3_v3fl(eve->co, co, blend); } else { @@ -2546,7 +2697,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) } static const EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) -{ +{ Object *obedit = CTX_data_edit_object(C); BMEditMesh *em; EnumPropertyItem *item = NULL; @@ -2619,6 +2770,12 @@ void MESH_OT_blend_from_shape(wmOperatorType *ot) RNA_def_boolean(ot->srna, "add", true, "Add", "Add rather than blend between shapes"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Solidify Mesh Operator + * \{ */ + static int edbm_solidify_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -2673,6 +2830,12 @@ void MESH_OT_solidify(wmOperatorType *ot) RNA_def_property_ui_range(prop, -10.0, 10.0, 0.1, 4); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Knife Subdivide Operator + * \{ */ + /* ******************************************************************** */ /* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail * drawn by user. @@ -2706,8 +2869,9 @@ static const EnumPropertyItem knife_items[] = { /* bm_edge_seg_isect() Determines if and where a mouse trail intersects an BMEdge */ -static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2], - float (*mouse_path)[2], int len, char mode, int *isected) +static float bm_edge_seg_isect( + const float sco_a[2], const float sco_b[2], + float (*mouse_path)[2], int len, char mode, int *isected) { #define MAXSLOPE 100000 float x11, y11, x12 = 0, y12 = 0, x2max, x2min, y2max; @@ -2716,17 +2880,17 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2], float yi, x1min, x1max, y1max, y1min, perc = 0; float threshold = 0.0; int i; - + //threshold = 0.000001; /* tolerance for vertex intersection */ // XXX threshold = scene->toolsettings->select_thresh / 100; - + /* Get screen coords of verts */ x21 = sco_a[0]; y21 = sco_a[1]; - + x22 = sco_b[0]; y22 = sco_b[1]; - + xdiff2 = (x22 - x21); if (xdiff2) { m2 = (y22 - y21) / xdiff2; @@ -2752,7 +2916,7 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2], } x12 = mouse_path[i][0]; y12 = mouse_path[i][1]; - + /* test e->v1 */ if ((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)) { perc = 0; @@ -2767,7 +2931,7 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2], } } } - + /* now check for edge intersect (may produce vertex intersection as well) */ for (i = 0; i < len; i++) { if (i > 0) { @@ -2780,14 +2944,14 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2], } x12 = mouse_path[i][0]; y12 = mouse_path[i][1]; - + /* Perp. Distance from point to line */ if (m2 != MAXSLOPE) dist = (y12 - m2 * x12 - b2); /* /sqrt(m2 * m2 + 1); Only looking for */ /* change in sign. Skip extra math */ else dist = x22 - x12; - + if (i == 0) lastdist = dist; - + /* if dist changes sign, and intersect point in edge's Bound Box */ if ((lastdist * dist) <= 0) { xdiff1 = (x12 - x11); /* Equation of line between last 2 points */ @@ -2803,14 +2967,14 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2], x2min = min_ff(x21, x22) - 0.001f; /* due to round off error */ y2max = max_ff(y21, y22) + 0.001f; y2min = min_ff(y21, y22) - 0.001f; - + /* Found an intersect, calc intersect point */ if (m1 == m2) { /* co-incident lines */ /* cut at 50% of overlap area */ x1max = max_ff(x11, x12); x1min = min_ff(x11, x12); xi = (min_ff(x2max, x1max) + max_ff(x2min, x1min)) / 2.0f; - + y1max = max_ff(y11, y12); y1min = min_ff(y11, y12); yi = (min_ff(y2max, y1max) + max_ff(y2min, y1min)) / 2.0f; @@ -2827,7 +2991,7 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2], xi = (b1 - b2) / (m2 - m1); yi = (b1 * m2 - m1 * b2) / (m2 - m1); } - + /* Intersect inside bounding box of edge?*/ if ((xi >= x2min) && (xi <= x2max) && (yi <= y2max) && (yi >= y2min)) { /* test for vertex intersect that may be 'close enough'*/ @@ -2850,7 +3014,7 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2], if ((m2 <= 1.0f) && (m2 >= -1.0f)) perc = (xi - x21) / (x22 - x21); else perc = (yi - y21) / (y22 - y21); /* lower slope more accurate */ //isect = 32768.0 * (perc + 0.0000153); /* Percentage in 1 / 32768ths */ - + break; } } @@ -2879,11 +3043,11 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) /* allocd vars */ float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2]; - + /* edit-object needed for matrix, and ar->regiondata for projections to work */ if (ELEM(NULL, obedit, ar, ar->regiondata)) return OPERATOR_CANCELLED; - + if (bm->totvertsel < 2) { BKE_report(op->reports, RPT_ERROR, "No edges are selected to operate on"); return OPERATOR_CANCELLED; @@ -2968,7 +3132,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) BMO_slot_bool_set(bmop.slots_in, "use_grid_fill", false); BMO_slot_float_set(bmop.slots_in, "radius", 0); - + BMO_op_exec(bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, true)) { return OPERATOR_CANCELLED; @@ -2986,13 +3150,13 @@ void MESH_OT_knife_cut(wmOperatorType *ot) ot->name = "Knife Cut"; ot->description = "Cut selected edges and faces into parts"; ot->idname = "MESH_OT_knife_cut"; - + ot->invoke = WM_gesture_lines_invoke; ot->modal = WM_gesture_lines_modal; ot->exec = edbm_knife_cut_exec; - + ot->poll = EDBM_view3d_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3002,13 +3166,16 @@ void MESH_OT_knife_cut(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", ""); - + /* internal */ RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, BC_NUMCURSORS, "Cursor", "", 0, BC_NUMCURSORS); } +/** \} */ -/* *************** Operator: separate parts *************/ +/* -------------------------------------------------------------------- */ +/** \name Separate Parts Operator + * \{ */ enum { MESH_SEPARATE_SELECTED = 0, @@ -3059,7 +3226,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe BM_mesh_free(bm_new); ((Mesh *)base_new->object->data)->edit_btmesh = NULL; - + return base_new; } @@ -3287,7 +3454,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); const int type = RNA_enum_get(op->ptr, "type"); int retval = 0; - + if (ED_operator_editmesh(C)) { Base *base = CTX_data_active_base(C); BMEditMesh *em = BKE_editmesh_from_object(base->object); @@ -3400,18 +3567,23 @@ void MESH_OT_separate(wmOperatorType *ot) ot->name = "Separate"; ot->description = "Separate selected geometry into a new mesh"; ot->idname = "MESH_OT_separate"; - + /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = edbm_separate_exec; ot->poll = ED_operator_scene_editable; /* object and editmode */ - + /* flags */ ot->flag = OPTYPE_UNDO; - + ot->prop = RNA_def_enum(ot->srna, "type", prop_separate_types, MESH_SEPARATE_SELECTED, "Type", ""); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Triangle Fill Operator + * \{ */ static int edbm_fill_exec(bContext *C, wmOperator *op) { @@ -3433,9 +3605,9 @@ static int edbm_fill_exec(bContext *C, wmOperator *op) { return OPERATOR_CANCELLED; } - + BMO_op_exec(em->bm, &bmop); - + if (totface_orig != em->bm->totface) { /* select new geometry */ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, BM_ELEM_SELECT, true); @@ -3473,9 +3645,11 @@ void MESH_OT_fill(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_beauty", true, "Beauty", "Use best triangulation division"); } +/** \} */ /* -------------------------------------------------------------------- */ -/* Grid Fill (and helper functions) */ +/** \name Grid Fill Operator + * \{ */ static bool bm_edge_test_fill_grid_cb(BMEdge *e, void *UNUSED(bm_v)) { @@ -3666,10 +3840,11 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op) /* end tricky prepare code */ - if (!EDBM_op_init(em, &bmop, op, - "grid_fill edges=%he mat_nr=%i use_smooth=%b use_interp_simple=%b", - use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT, - em->mat_nr, use_smooth, use_interp_simple)) + if (!EDBM_op_init( + em, &bmop, op, + "grid_fill edges=%he mat_nr=%i use_smooth=%b use_interp_simple=%b", + use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT, + em->mat_nr, use_smooth, use_interp_simple)) { return OPERATOR_CANCELLED; } @@ -3719,6 +3894,12 @@ void MESH_OT_fill_grid(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_interp_simple", false, "Simple Blending", ""); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hole Fill Operator + * \{ */ + static int edbm_fill_holes_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -3758,6 +3939,12 @@ void MESH_OT_fill_holes(wmOperatorType *ot) "Sides", "Number of sides in hole required to fill (zero fills all holes)", 0, 100); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Beauty Fill Operator + * \{ */ + static int edbm_beautify_fill_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -3775,9 +3962,10 @@ static int edbm_beautify_fill_exec(bContext *C, wmOperator *op) BMEdge *e; BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - BM_elem_flag_set(e, BM_ELEM_TAG, - (BM_elem_flag_test(e, BM_ELEM_SELECT) && - BM_edge_calc_face_angle_ex(e, angle_max) < angle_limit)); + BM_elem_flag_set( + e, BM_ELEM_TAG, + (BM_elem_flag_test(e, BM_ELEM_SELECT) && + BM_edge_calc_face_angle_ex(e, angle_max) < angle_limit)); } @@ -3793,7 +3981,7 @@ static int edbm_beautify_fill_exec(bContext *C, wmOperator *op) } EDBM_update_generic(em, true, true); - + return OPERATOR_FINISHED; } @@ -3819,8 +4007,11 @@ void MESH_OT_beautify_fill(wmOperatorType *ot) RNA_def_property_float_default(prop, DEG2RADF(180.0f)); } +/** \} */ -/********************** Poke Face **********************/ +/* -------------------------------------------------------------------- */ +/** \name Poke Face Operator + * \{ */ static int edbm_poke_face_exec(bContext *C, wmOperator *op) { @@ -3880,7 +4071,11 @@ void MESH_OT_poke(wmOperatorType *ot) "Poke Center", "Poke Face Center Calculation"); } -/********************** Quad/Tri Operators *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Triangulate Face Operator + * \{ */ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op) { @@ -3935,6 +4130,12 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) "Polygon Method", "Method for splitting the polygons into triangles"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert to Quads Operator + * \{ */ + static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -4025,10 +4226,10 @@ void MESH_OT_tris_convert_to_quads(wmOperatorType *ot) join_triangle_props(ot); } +/** \} */ /* -------------------------------------------------------------------- */ - -/** \name Decimate +/** \name Decimate Operator * * \note The function to decimate is intended for use as a modifier, * while its handy allow access as a tool - this does cause access to be a little awkward @@ -4214,9 +4415,9 @@ void MESH_OT_decimate(wmOperatorType *ot) /** \} */ - /* -------------------------------------------------------------------- */ -/* Dissolve */ +/** \name Dissolve Vertices Operator + * \{ */ static void edbm_dissolve_prop__use_verts(wmOperatorType *ot, bool value, int flag) { @@ -4248,9 +4449,10 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op) const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split"); const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear"); - if (!EDBM_op_callf(em, op, - "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b", - BM_ELEM_SELECT, use_face_split, use_boundary_tear)) + if (!EDBM_op_callf( + em, op, + "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b", + BM_ELEM_SELECT, use_face_split, use_boundary_tear)) { return OPERATOR_CANCELLED; } @@ -4278,6 +4480,12 @@ void MESH_OT_dissolve_verts(wmOperatorType *ot) edbm_dissolve_prop__use_boundary_tear(ot); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Dissolve Edges Operator + * \{ */ + static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -4286,9 +4494,10 @@ static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op) const bool use_verts = RNA_boolean_get(op->ptr, "use_verts"); const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split"); - if (!EDBM_op_callf(em, op, - "dissolve_edges edges=%he use_verts=%b use_face_split=%b", - BM_ELEM_SELECT, use_verts, use_face_split)) + if (!EDBM_op_callf( + em, op, + "dissolve_edges edges=%he use_verts=%b use_face_split=%b", + BM_ELEM_SELECT, use_verts, use_face_split)) { return OPERATOR_CANCELLED; } @@ -4316,6 +4525,12 @@ void MESH_OT_dissolve_edges(wmOperatorType *ot) edbm_dissolve_prop__use_face_split(ot); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Dissolve Faces Operator + * \{ */ + static int edbm_dissolve_faces_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -4354,6 +4569,11 @@ void MESH_OT_dissolve_faces(wmOperatorType *ot) edbm_dissolve_prop__use_verts(ot, false, 0); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Dissolve (Context Sensitive) Operator + * \{ */ static int edbm_dissolve_mode_exec(bContext *C, wmOperator *op) { @@ -4399,6 +4619,12 @@ void MESH_OT_dissolve_mode(wmOperatorType *ot) edbm_dissolve_prop__use_boundary_tear(ot); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Limited Dissolve Operator + * \{ */ + static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -4476,6 +4702,12 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot) "Delimit dissolve operation"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Degenerate Dissolve Operator + * \{ */ + static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -4520,6 +4752,11 @@ void MESH_OT_dissolve_degenerate(wmOperatorType *ot) "Minimum distance between elements to merge", 1e-5f, 10.0f); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Edge-Loop Operator + * \{ */ /* internally uses dissolve */ static int edbm_delete_edgeloop_exec(bContext *C, wmOperator *op) @@ -4546,9 +4783,10 @@ static int edbm_delete_edgeloop_exec(bContext *C, wmOperator *op) } } - if (!EDBM_op_callf(em, op, - "dissolve_edges edges=%he use_verts=%b use_face_split=%b", - BM_ELEM_SELECT, true, use_face_split)) + if (!EDBM_op_callf( + em, op, + "dissolve_edges edges=%he use_verts=%b use_face_split=%b", + BM_ELEM_SELECT, true, use_face_split)) { return OPERATOR_CANCELLED; } @@ -4580,6 +4818,12 @@ void MESH_OT_delete_edgeloop(wmOperatorType *ot) "Split off face corners to maintain surrounding geometry"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Split Geometry Operator + * \{ */ + static int edbm_split_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_edit_object(C); @@ -4617,16 +4861,21 @@ void MESH_OT_split(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/****************************************************************************** - * qsort routines. - * Now unified, for vertices/edges/faces. */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sort Geometry Elements Operator + * + * Unified for vertices/edges/faces. + * + * \{ */ enum { SRT_VIEW_ZAXIS = 1, /* Use view Z (deep) axis. */ SRT_VIEW_XAXIS, /* Use view X (left to right) axis. */ SRT_CURSOR_DISTANCE, /* Use distance from element to 3D cursor. */ SRT_MATERIAL, /* Face only: use mat number. */ - SRT_SELECTED, /* Move selected elements in first, without modifying + SRT_SELECTED, /* Move selected elements in first, without modifying * relative order of selected and unselected elements. */ SRT_RANDOMIZE, /* Randomize selected elements. */ SRT_REVERSE, /* Reverse current order of selected elements. */ @@ -4645,10 +4894,11 @@ static int bmelemsort_comp(const void *v1, const void *v2) } /* Reorders vertices/edges/faces using a given methods. Loops are not supported. */ -static void sort_bmelem_flag(Scene *scene, Object *ob, - View3D *v3d, RegionView3D *rv3d, - const int types, const int flag, const int action, - const int reverse, const unsigned int seed) +static void sort_bmelem_flag( + Scene *scene, Object *ob, + View3D *v3d, RegionView3D *rv3d, + const int types, const int flag, const int action, + const int reverse, const unsigned int seed) { BMEditMesh *em = BKE_editmesh_from_object(ob); @@ -5114,8 +5364,9 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op) RNA_enum_set(op->ptr, "elements", elem_types); } - sort_bmelem_flag(scene, ob, v3d, rv3d, - elem_types, BM_ELEM_SELECT, action, use_reverse, seed); + sort_bmelem_flag( + scene, ob, v3d, rv3d, + elem_types, BM_ELEM_SELECT, action, use_reverse, seed); return OPERATOR_FINISHED; } @@ -5204,7 +5455,11 @@ void MESH_OT_sort_elements(wmOperatorType *ot) RNA_def_int(ot->srna, "seed", 0, 0, INT_MAX, "Seed", "Seed for random-based operations", 0, 255); } -/****** end of qsort stuff ****/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Noise (Deform Vertices) Operator + * \{ */ static int edbm_noise_exec(bContext *C, wmOperator *op) { @@ -5237,7 +5492,7 @@ static int edbm_noise_exec(bContext *C, wmOperator *op) vec[0] = fac * (b2 - BLI_hnoise(tex->noisesize, eve->co[0] + ofs, eve->co[1], eve->co[2])); vec[1] = fac * (b2 - BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1] + ofs, eve->co[2])); vec[2] = fac * (b2 - BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2] + ofs)); - + add_v3_v3(eve->co, vec); } } @@ -5278,6 +5533,11 @@ void MESH_OT_noise(wmOperatorType *ot) RNA_def_float(ot->srna, "factor", 0.1f, -1e4f, 1e4f, "Factor", "", 0.0f, 1.0f); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Bridge Operator + * \{ */ enum { MESH_BRIDGELOOP_SINGLE = 0, @@ -5364,9 +5624,10 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op) edge_hflag = BM_ELEM_SELECT; } - EDBM_op_init(em, &bmop, op, - "bridge_loops edges=%he use_pairs=%b use_cyclic=%b use_merge=%b merge_factor=%f twist_offset=%i", - edge_hflag, use_pairs, use_cyclic, use_merge, merge_factor, twist_offset); + EDBM_op_init( + em, &bmop, op, + "bridge_loops edges=%he use_pairs=%b use_cyclic=%b use_merge=%b merge_factor=%f twist_offset=%i", + edge_hflag, use_pairs, use_cyclic, use_merge, merge_factor, twist_offset); if (use_faces && totface_del) { int i; @@ -5374,9 +5635,10 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op) for (i = 0; i < totface_del; i++) { BM_elem_flag_enable(totface_del_arr[i], BM_ELEM_TAG); } - BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, - "delete geom=%hf context=%i", - BM_ELEM_TAG, DEL_FACES_KEEP_BOUNDARY); + BMO_op_callf( + em->bm, BMO_FLAG_DEFAULTS, + "delete geom=%hf context=%i", + BM_ELEM_TAG, DEL_FACES_KEEP_BOUNDARY); } BMO_op_exec(em->bm, &bmop); @@ -5442,11 +5704,11 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot) ot->name = "Bridge Edge Loops"; ot->description = "Make faces between two or more edge loops"; ot->idname = "MESH_OT_bridge_edge_loops"; - + /* api callbacks */ ot->exec = edbm_bridge_edge_loops_exec; ot->poll = ED_operator_editmesh; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -5460,6 +5722,12 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot) mesh_operator_edgering_props(ot, 0, 0); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Wire-Frame Operator + * \{ */ + static int edbm_wireframe_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -5474,11 +5742,12 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op) const float thickness = RNA_float_get(op->ptr, "thickness"); const float offset = RNA_float_get(op->ptr, "offset"); - EDBM_op_init(em, &bmop, op, - "wireframe faces=%hf use_replace=%b use_boundary=%b use_even_offset=%b use_relative_offset=%b " - "use_crease=%b crease_weight=%f thickness=%f offset=%f", - BM_ELEM_SELECT, use_replace, use_boundary, use_even_offset, use_relative_offset, - use_crease, crease_weight, thickness, offset); + EDBM_op_init( + em, &bmop, op, + "wireframe faces=%hf use_replace=%b use_boundary=%b use_even_offset=%b use_relative_offset=%b " + "use_crease=%b crease_weight=%f thickness=%f offset=%f", + BM_ELEM_SELECT, use_replace, use_boundary, use_even_offset, use_relative_offset, + use_crease, crease_weight, thickness, offset); BMO_op_exec(em->bm, &bmop); @@ -5524,6 +5793,12 @@ void MESH_OT_wireframe(wmOperatorType *ot) RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Offset Edge-Loop Operator + * \{ */ + static int edbm_offset_edgeloop_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -5578,6 +5853,12 @@ void MESH_OT_offset_edge_loops(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_cap_endpoint", false, "Cap Endpoint", "Extend loop around end-points"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convex Hull Operator + * \{ */ + #ifdef WITH_BULLET static int edbm_convex_hull_exec(bContext *C, wmOperator *op) { @@ -5585,10 +5866,11 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); BMOperator bmop; - EDBM_op_init(em, &bmop, op, "convex_hull input=%hvef " - "use_existing_faces=%b", - BM_ELEM_SELECT, - RNA_boolean_get(op->ptr, "use_existing_faces")); + EDBM_op_init( + em, &bmop, op, "convex_hull input=%hvef " + "use_existing_faces=%b", + BM_ELEM_SELECT, + RNA_boolean_get(op->ptr, "use_existing_faces")); BMO_op_exec(em->bm, &bmop); /* Hull fails if input is coplanar */ @@ -5601,8 +5883,9 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Delete unused vertices, edges, and faces */ if (RNA_boolean_get(op->ptr, "delete_unused")) { - if (!EDBM_op_callf(em, op, "delete geom=%S context=%i", - &bmop, "geom_unused.out", DEL_ONLYTAGGED)) + if (!EDBM_op_callf( + em, op, "delete geom=%S context=%i", + &bmop, "geom_unused.out", DEL_ONLYTAGGED)) { EDBM_op_finish(em, &bmop, op, true); return OPERATOR_CANCELLED; @@ -5611,8 +5894,9 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Delete hole edges/faces */ if (RNA_boolean_get(op->ptr, "make_holes")) { - if (!EDBM_op_callf(em, op, "delete geom=%S context=%i", - &bmop, "geom_holes.out", DEL_ONLYTAGGED)) + if (!EDBM_op_callf( + em, op, "delete geom=%S context=%i", + &bmop, "geom_holes.out", DEL_ONLYTAGGED)) { EDBM_op_finish(em, &bmop, op, true); return OPERATOR_CANCELLED; @@ -5680,7 +5964,13 @@ void MESH_OT_convex_hull(wmOperatorType *ot) join_triangle_props(ot); } -#endif +#endif /* WITH_BULLET */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Symmetrize Operator + * \{ */ static int mesh_symmetrize_exec(bContext *C, wmOperator *op) { @@ -5690,9 +5980,10 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op) const float thresh = RNA_float_get(op->ptr, "threshold"); - EDBM_op_init(em, &bmop, op, - "symmetrize input=%hvef direction=%i dist=%f", - BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"), thresh); + EDBM_op_init( + em, &bmop, op, + "symmetrize input=%hvef direction=%i dist=%f", + BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"), thresh); BMO_op_exec(em->bm, &bmop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); @@ -5723,12 +6014,19 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ot->prop = RNA_def_enum(ot->srna, "direction", rna_enum_symmetrize_direction_items, - BMO_SYMMETRIZE_NEGATIVE_X, - "Direction", "Which sides to copy from and to"); + ot->prop = RNA_def_enum( + ot->srna, "direction", rna_enum_symmetrize_direction_items, + BMO_SYMMETRIZE_NEGATIVE_X, + "Direction", "Which sides to copy from and to"); RNA_def_float(ot->srna, "threshold", 1e-4f, 0.0f, 10.0f, "Threshold", "", 1e-5f, 0.1f); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snap to Symmetry Operator + * \{ */ + static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op) { const float eps = 0.00001f; @@ -5847,16 +6145,23 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ot->prop = RNA_def_enum(ot->srna, "direction", rna_enum_symmetrize_direction_items, - BMO_SYMMETRIZE_NEGATIVE_X, - "Direction", "Which sides to copy from and to"); + ot->prop = RNA_def_enum( + ot->srna, "direction", rna_enum_symmetrize_direction_items, + BMO_SYMMETRIZE_NEGATIVE_X, + "Direction", "Which sides to copy from and to"); RNA_def_float_distance(ot->srna, "threshold", 0.05f, 0.0f, 10.0f, "Threshold", "", 1e-4f, 1.0f); RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f); RNA_def_boolean(ot->srna, "use_center", true, "Center", "Snap mid verts to the axis center"); } +/** \} */ + #ifdef WITH_FREESTYLE +/* -------------------------------------------------------------------- */ +/** \name Mark Edge (FreeStyle) Operator + * \{ */ + static int edbm_mark_freestyle_edge_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -5922,6 +6227,12 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mark Face (FreeStyle) Operator + * \{ */ + static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -5986,4 +6297,6 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -#endif +/** \} */ + +#endif /* WITH_FREESTYLE */ diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index c4440fa190ad463a6675b6d0e6c1d69227034cf7..d25304cef89580300327141a056a0974bc03c4d0 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -63,8 +63,14 @@ #include "mesh_intern.h" /* own include */ -/* mesh backup implementation. This would greatly benefit from some sort of binary diffing - * just as the undo stack would. So leaving this as an interface for further work */ +/* -------------------------------------------------------------------- */ +/** \name Redo API + * \{ */ + +/* Mesh backup implementation. + * This would greatly benefit from some sort of binary diffing + * just as the undo stack would. + * So leaving this as an interface for further work */ BMBackup EDBM_redo_state_store(BMEditMesh *em) { @@ -76,8 +82,9 @@ BMBackup EDBM_redo_state_store(BMEditMesh *em) void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess) { BMesh *tmpbm; - if (!em || !backup.bmcopy) + if (!em || !backup.bmcopy) { return; + } BM_mesh_data_free(em->bm); tmpbm = BM_mesh_copy(backup.bmcopy); @@ -85,8 +92,9 @@ void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess) MEM_freeN(tmpbm); tmpbm = NULL; - if (recalctess) + if (recalctess) { BKE_editmesh_tessface_calc(em); + } } void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess) @@ -99,68 +107,21 @@ void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess) BM_mesh_data_free(backup->bmcopy); } - if (backup->bmcopy) + if (backup->bmcopy) { MEM_freeN(backup->bmcopy); + } backup->bmcopy = NULL; - if (recalctess && em) + if (recalctess && em) { BKE_editmesh_tessface_calc(em); -} - -void EDBM_mesh_normals_update(BMEditMesh *em) -{ - BM_mesh_normals_update(em->bm); -} - -void EDBM_mesh_clear(BMEditMesh *em) -{ - /* clear bmesh */ - BM_mesh_clear(em->bm); - - /* free derived meshes */ - BKE_editmesh_free_derivedmesh(em); - - /* free tessellation data */ - em->tottri = 0; - if (em->looptris) { - MEM_freeN(em->looptris); - em->looptris = NULL; } } -void EDBM_stats_update(BMEditMesh *em) -{ - const char iter_types[3] = {BM_VERTS_OF_MESH, - BM_EDGES_OF_MESH, - BM_FACES_OF_MESH}; - - BMIter iter; - BMElem *ele; - int *tots[3]; - int i; +/** \} */ - tots[0] = &em->bm->totvertsel; - tots[1] = &em->bm->totedgesel; - tots[2] = &em->bm->totfacesel; - - em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0; - - for (i = 0; i < 3; i++) { - ele = BM_iter_new(&iter, em->bm, iter_types[i], NULL); - for ( ; ele; ele = BM_iter_step(&iter)) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - (*tots[i])++; - } - } - } -} - -DerivedMesh *EDBM_mesh_deform_dm_get(BMEditMesh *em) -{ - return ((em->derivedFinal != NULL) && - (em->derivedFinal->type == DM_TYPE_EDITBMESH) && - (em->derivedFinal->deformedOnly != false)) ? em->derivedFinal : NULL; -} +/* -------------------------------------------------------------------- */ +/** \name BMesh Operator (BMO) API Wrapper + * \{ */ bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt, ...) { @@ -174,9 +135,10 @@ bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char * va_end(list); return false; } - - if (!em->emcopy) + + if (!em->emcopy) { em->emcopy = BKE_editmesh_copy(em); + } em->emcopyusers++; va_end(list); @@ -184,12 +146,11 @@ bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char * return true; } - /* returns 0 on error, 1 on success. executes and finishes a bmesh operator */ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report) { const char *errmsg; - + BMO_op_finish(em->bm, bmop); if (BMO_error_get(em->bm, &errmsg, NULL)) { @@ -244,8 +205,9 @@ bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) return false; } - if (!em->emcopy) + if (!em->emcopy) { em->emcopy = BKE_editmesh_copy(em); + } em->emcopyusers++; BMO_op_exec(bm, &bmop); @@ -254,9 +216,10 @@ bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) return EDBM_op_finish(em, &bmop, op, true); } -bool EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, - const char *select_slot_out, const bool select_extend, - const char *fmt, ...) +bool EDBM_op_call_and_selectf( + BMEditMesh *em, wmOperator *op, + const char *select_slot_out, const bool select_extend, + const char *fmt, ...) { BMOpSlot *slot_select_out; BMesh *bm = em->bm; @@ -272,8 +235,9 @@ bool EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, return false; } - if (!em->emcopy) + if (!em->emcopy) { em->emcopy = BKE_editmesh_copy(em); + } em->emcopyusers++; BMO_op_exec(bm, &bmop); @@ -305,8 +269,9 @@ bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...) return false; } - if (!em->emcopy) + if (!em->emcopy) { em->emcopy = BKE_editmesh_copy(em); + } em->emcopyusers++; BMO_op_exec(bm, &bmop); @@ -315,22 +280,15 @@ bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...) return EDBM_op_finish(em, &bmop, NULL, false); } -void EDBM_selectmode_to_scene(bContext *C) -{ - Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - if (!em) - return; +/** \} */ - scene->toolsettings->selectmode = em->selectmode; - - /* Request redraw of header buttons (to show new select mode) */ - WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene); -} +/* -------------------------------------------------------------------- */ +/** \name Edit BMesh API + * + * Make/Clear/Free functions. + * \{ */ -void EDBM_mesh_make(ToolSettings *ts, Object *ob, const bool add_key_index) +void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) { Mesh *me = ob->data; BMesh *bm; @@ -357,7 +315,7 @@ void EDBM_mesh_make(ToolSettings *ts, Object *ob, const bool add_key_index) me->edit_btmesh = BKE_editmesh_create(bm, false); #endif - me->edit_btmesh->selectmode = me->edit_btmesh->bm->selectmode = ts->selectmode; + me->edit_btmesh->selectmode = me->edit_btmesh->bm->selectmode = select_mode; me->edit_btmesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0; me->edit_btmesh->ob = ob; @@ -412,6 +370,22 @@ void EDBM_mesh_load(Object *ob) #endif } +void EDBM_mesh_clear(BMEditMesh *em) +{ + /* clear bmesh */ + BM_mesh_clear(em->bm); + + /* free derived meshes */ + BKE_editmesh_free_derivedmesh(em); + + /* free tessellation data */ + em->tottri = 0; + if (em->looptris) { + MEM_freeN(em->looptris); + em->looptris = NULL; + } +} + /** * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free */ @@ -426,6 +400,28 @@ void EDBM_mesh_free(BMEditMesh *em) BKE_editmesh_free(em); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Selection Utilities + * \{ */ + +void EDBM_selectmode_to_scene(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + if (!em) { + return; + } + + scene->toolsettings->selectmode = em->selectmode; + + /* Request redraw of header buttons (to show new select mode) */ + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene); +} + void EDBM_selectmode_flush_ex(BMEditMesh *em, const short selectmode) { BM_mesh_select_mode_flush_ex(em->bm, selectmode); @@ -443,7 +439,6 @@ void EDBM_deselect_flush(BMEditMesh *em) BM_mesh_deselect_flush(em->bm); } - void EDBM_select_flush(BMEditMesh *em) { /* function below doesnt use. just do this to keep the values in sync */ @@ -456,9 +451,10 @@ void EDBM_select_more(BMEditMesh *em, const bool use_face_step) BMOperator bmop; const bool use_faces = (em->selectmode == SCE_SELECT_FACE); - BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS, - "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b", - BM_ELEM_SELECT, false, use_faces, use_face_step); + BMO_op_initf( + em->bm, &bmop, BMO_FLAG_DEFAULTS, + "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b", + BM_ELEM_SELECT, false, use_faces, use_face_step); BMO_op_exec(em->bm, &bmop); /* don't flush selection in edge/vertex mode */ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false); @@ -472,9 +468,10 @@ void EDBM_select_less(BMEditMesh *em, const bool use_face_step) BMOperator bmop; const bool use_faces = (em->selectmode == SCE_SELECT_FACE); - BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS, - "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b", - BM_ELEM_SELECT, true, use_faces, use_face_step); + BMO_op_initf( + em->bm, &bmop, BMO_FLAG_DEFAULTS, + "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b", + BM_ELEM_SELECT, true, use_faces, use_face_step); BMO_op_exec(em->bm, &bmop); /* don't flush selection in edge/vertex mode */ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false); @@ -496,6 +493,12 @@ void EDBM_flag_enable_all(BMEditMesh *em, const char hflag) BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, true); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name UV Vertex Map API + * \{ */ + /** * Return a new UVVertMap from the editmesh */ @@ -519,7 +522,7 @@ UvVertMap *BM_uv_vert_map_create( BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); - + totfaces = bm->totface; totverts = bm->totvert; totuv = 0; @@ -549,7 +552,7 @@ UvVertMap *BM_uv_vert_map_create( BKE_mesh_uv_vert_map_free(vmap); return NULL; } - + BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, a) { if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { float (*tf_uv)[2]; @@ -562,7 +565,7 @@ UvVertMap *BM_uv_vert_map_create( buf->tfindex = i; buf->f = a; buf->separate = 0; - + buf->next = vmap->vert[BM_elem_index_get(l->v)]; vmap->vert[BM_elem_index_get(l->v)] = buf; buf++; @@ -578,7 +581,7 @@ UvVertMap *BM_uv_vert_map_create( } } } - + /* sort individual uvs for each vert */ BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, a) { UvMapVert *newvlist = NULL, *vlist = vmap->vert[a]; @@ -593,11 +596,11 @@ UvVertMap *BM_uv_vert_map_create( efa = BM_face_at_index(bm, v->f); /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ - + l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->tfindex); luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv = luv->uv; - + lastv = NULL; iterv = vlist; @@ -605,11 +608,11 @@ UvVertMap *BM_uv_vert_map_create( next = iterv->next; efa = BM_face_at_index(bm, iterv->f); /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ - + l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex); luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv2 = luv->uv; - + sub_v2_v2v2(uvdiff, uv2, uv); if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1] && @@ -642,13 +645,11 @@ UvVertMap *BM_uv_vert_map_create( return vmap; } - UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, unsigned int v) { return vmap->vert[v]; } - /* A specialized vert map used by stitch operator */ UvElementMap *BM_uv_element_map_create( BMesh *bm, @@ -906,42 +907,51 @@ void BM_uv_element_map_free(UvElementMap *element_map) UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l) { - UvElement *element; - - element = map->vert[BM_elem_index_get(l->v)]; - - for (; element; element = element->next) - if (element->l->f == efa) + for (UvElement *element = map->vert[BM_elem_index_get(l->v)]; + element; + element = element->next) + { + if (element->l->f == efa) { return element; + } + } return NULL; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Data Layer Checks + * \{ */ + /* last_sel, use em->act_face otherwise get the last selected face in the editselections * at the moment, last_sel is mainly useful for making sure the space image dosnt flicker */ -MTexPoly *EDBM_mtexpoly_active_get(BMEditMesh *em, BMFace **r_act_efa, const bool sloppy, const bool selected) +BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool selected, MTexPoly **r_tf) { BMFace *efa = NULL; - - if (!EDBM_mtexpoly_check(em)) + + if (!EDBM_uv_check(em)) { return NULL; - + } + efa = BM_mesh_active_face_get(em->bm, sloppy, selected); if (efa) { - if (r_act_efa) *r_act_efa = efa; - return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (r_tf) *r_tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + return efa; } - if (r_act_efa) *r_act_efa = NULL; + if (r_tf) *r_tf = NULL; return NULL; } /* can we edit UV's for this mesh?*/ -bool EDBM_mtexpoly_check(BMEditMesh *em) +bool EDBM_uv_check(BMEditMesh *em) { /* some of these checks could be a touch overkill */ - return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) && + return em && em->bm->totface && + CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) && CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV); } @@ -951,6 +961,12 @@ bool EDBM_vert_color_check(BMEditMesh *em) return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mirror Cache API + * \{ */ + static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index) { intptr_t eve_i = index_lookup[index]; @@ -985,9 +1001,10 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index) * \param maxdist Distance for close point test. * \param r_index Optional array to write into, as an alternative to a customdata layer (length of total verts). */ -void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool use_self, const bool use_select, - /* extra args */ - const bool use_topology, float maxdist, int *r_index) +void EDBM_verts_mirror_cache_begin_ex( + BMEditMesh *em, const int axis, const bool use_self, const bool use_select, + /* extra args */ + const bool use_topology, float maxdist, int *r_index) { Mesh *me = (Mesh *)em->ob->data; BMesh *bm = em->bm; @@ -1011,8 +1028,9 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id); } - cd_vmirr_offset = CustomData_get_n_offset(&bm->vdata, CD_PROP_INT, - em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT)); + cd_vmirr_offset = CustomData_get_n_offset( + &bm->vdata, CD_PROP_INT, + em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT)); bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY; } @@ -1085,14 +1103,16 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool } } -void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const int axis, - const bool use_self, const bool use_select, - const bool use_topology) +void EDBM_verts_mirror_cache_begin( + BMEditMesh *em, const int axis, + const bool use_self, const bool use_select, + const bool use_topology) { - EDBM_verts_mirror_cache_begin_ex(em, axis, - use_self, use_select, - /* extra args */ - use_topology, BM_SEARCH_MAXDIST_MIRR, NULL); + EDBM_verts_mirror_cache_begin_ex( + em, axis, + use_self, use_select, + /* extra args */ + use_topology, BM_SEARCH_MAXDIST_MIRR, NULL); } BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v) @@ -1180,6 +1200,11 @@ void EDBM_verts_mirror_apply(BMEditMesh *em, const int sel_from, const int sel_t } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide/Reveal API + * \{ */ /* swap is 0 or 1, if 1 it hides not selected */ void EDBM_mesh_hide(BMEditMesh *em, bool swap) @@ -1214,17 +1239,18 @@ void EDBM_mesh_hide(BMEditMesh *em, bool swap) */ } - void EDBM_mesh_reveal(BMEditMesh *em, bool select) { - const char iter_types[3] = {BM_VERTS_OF_MESH, - BM_EDGES_OF_MESH, - BM_FACES_OF_MESH}; + const char iter_types[3] = { + BM_VERTS_OF_MESH, + BM_EDGES_OF_MESH, + BM_FACES_OF_MESH, + }; const bool sels[3] = { - (em->selectmode & SCE_SELECT_VERTEX) != 0, - (em->selectmode & SCE_SELECT_EDGE) != 0, - (em->selectmode & SCE_SELECT_FACE) != 0, + (em->selectmode & SCE_SELECT_VERTEX) != 0, + (em->selectmode & SCE_SELECT_EDGE) != 0, + (em->selectmode & SCE_SELECT_FACE) != 0, }; int i; @@ -1264,6 +1290,46 @@ void EDBM_mesh_reveal(BMEditMesh *em, bool select) EDBM_mesh_normals_update(em); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Update API + * \{ */ + +void EDBM_mesh_normals_update(BMEditMesh *em) +{ + BM_mesh_normals_update(em->bm); +} + +void EDBM_stats_update(BMEditMesh *em) +{ + const char iter_types[3] = { + BM_VERTS_OF_MESH, + BM_EDGES_OF_MESH, + BM_FACES_OF_MESH, + }; + + BMIter iter; + BMElem *ele; + int *tots[3]; + int i; + + tots[0] = &em->bm->totvertsel; + tots[1] = &em->bm->totedgesel; + tots[2] = &em->bm->totfacesel; + + em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0; + + for (i = 0; i < 3; i++) { + ele = BM_iter_new(&iter, em->bm, iter_types[i], NULL); + for ( ; ele; ele = BM_iter_step(&iter)) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + (*tots[i])++; + } + } + } +} + /* so many tools call these that we better make it a generic function. */ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive) @@ -1299,15 +1365,41 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d #endif } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Data Access + * \{ */ + +DerivedMesh *EDBM_mesh_deform_dm_get(BMEditMesh *em) +{ + return ((em->derivedFinal != NULL) && + (em->derivedFinal->type == DM_TYPE_EDITBMESH) && + (em->derivedFinal->deformedOnly != false)) ? em->derivedFinal : NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operator Helpers + * \{ */ + /* poll call for mesh operators requiring a view3d context */ int EDBM_view3d_poll(bContext *C) { - if (ED_operator_editmesh(C) && ED_operator_view3d_active(C)) + if (ED_operator_editmesh(C) && ED_operator_view3d_active(C)) { return 1; + } return 0; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name BMesh Element API + * \{ */ + BMElem *EDBM_elem_from_selectmode(BMEditMesh *em, BMVert *eve, BMEdge *eed, BMFace *efa) { BMElem *ele = NULL; @@ -1372,22 +1464,19 @@ BMElem *EDBM_elem_from_index_any(BMEditMesh *em, int index) return NULL; } -/* -------------------------------------------------------------------- */ -/* BMBVH functions */ -// XXX -#if 0 //BMESH_TODO: not implemented yet -int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d) -{ +/** \} */ -} -#endif +/* -------------------------------------------------------------------- */ +/** \name BMesh BVH API + * \{ */ static BMFace *edge_ray_cast(struct BMBVHTree *tree, const float co[3], const float dir[3], float *r_hitout, BMEdge *e) { BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, 0.0f, NULL, r_hitout, NULL); - if (f && BM_edge_in_face(e, f)) + if (f && BM_edge_in_face(e, f)) { return NULL; + } return f; } @@ -1406,8 +1495,10 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v float origin[3], invmat[4][4]; float epsilon = 0.01f; float end[3]; - const float mval_f[2] = {ar->winx / 2.0f, - ar->winy / 2.0f}; + const float mval_f[2] = { + ar->winx / 2.0f, + ar->winy / 2.0f, + }; ED_view3d_win_to_segment(ar, v3d, mval_f, origin, end, false); @@ -1443,12 +1534,17 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v /* do three samplings: left, middle, right */ f = edge_ray_cast(tree, co1, dir1, NULL, e); - if (f && !edge_ray_cast(tree, co2, dir2, NULL, e)) + if (f && !edge_ray_cast(tree, co2, dir2, NULL, e)) { return true; - else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e)) + } + else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e)) { return true; - else if (!f) + } + else if (!f) { return true; + } return false; } + +/** \} */ diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index cfeda36214c2e9e7c593d2402b3c628de18a0f5e..84d2ac3cef1e3fc4e49c8d1359435335eda6bd3d 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -596,7 +596,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e obedit = base->object; me = obedit->data; if (me->edit_btmesh == NULL) { - EDBM_mesh_make(scene->toolsettings, obedit, false); + EDBM_mesh_make(obedit, scene->toolsettings->selectmode, false); exitmode = 1; } if (me->edit_btmesh == NULL) diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c new file mode 100644 index 0000000000000000000000000000000000000000..96b9f054252afc5f6f9fcc2c4f496049782e695c --- /dev/null +++ b/source/blender/editors/mesh/mesh_mirror.c @@ -0,0 +1,374 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation, Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mesh/mesh_mirror.c + * \ingroup edmesh + * + * Mirror calculation for edit-mode and object mode. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_bitmap.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "BKE_DerivedMesh.h" +#include "BLI_kdtree.h" +#include "BKE_editmesh.h" + +#include "ED_mesh.h" + +/* -------------------------------------------------------------------- */ +/** \name Mesh Spatial Mirror API + * \{ */ + +#define KD_THRESH 0.00002f + +static struct { void *tree; } MirrKdStore = {NULL}; + +/* mode is 's' start, or 'e' end, or 'u' use */ +/* if end, ob can be NULL */ +int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, const float co[3], char mode) +{ + if (mode == 'u') { /* use table */ + if (MirrKdStore.tree == NULL) + ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's'); + + if (MirrKdStore.tree) { + KDTreeNearest nearest; + const int i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest); + + if (i != -1) { + if (nearest.dist < KD_THRESH) { + return i; + } + } + } + return -1; + } + else if (mode == 's') { /* start table */ + Mesh *me = ob->data; + const bool use_em = (!dm && em && me->edit_btmesh == em); + const int totvert = use_em ? em->bm->totvert : dm ? dm->getNumVerts(dm) : me->totvert; + + if (MirrKdStore.tree) /* happens when entering this call without ending it */ + ED_mesh_mirror_spatial_table(ob, em, dm, co, 'e'); + + MirrKdStore.tree = BLI_kdtree_new(totvert); + + if (use_em) { + BMVert *eve; + BMIter iter; + int i; + + /* this needs to be valid for index lookups later (callers need) */ + BM_mesh_elem_table_ensure(em->bm, BM_VERT); + + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + BLI_kdtree_insert(MirrKdStore.tree, i, eve->co); + } + } + else { + MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert; + int i; + + for (i = 0; i < totvert; i++, mvert++) { + BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co); + } + } + + BLI_kdtree_balance(MirrKdStore.tree); + } + else if (mode == 'e') { /* end table */ + if (MirrKdStore.tree) { + BLI_kdtree_free(MirrKdStore.tree); + MirrKdStore.tree = NULL; + } + } + else { + BLI_assert(0); + } + + return 0; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mesh Topology Mirror API + * \{ */ + +typedef unsigned int MirrTopoHash_t; + +typedef struct MirrTopoVert_t { + MirrTopoHash_t hash; + int v_index; +} MirrTopoVert_t; + +static int mirrtopo_hash_sort(const void *l1, const void *l2) +{ + if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2) return 1; + else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2) return -1; + return 0; +} + +static int mirrtopo_vert_sort(const void *v1, const void *v2) +{ + if (((MirrTopoVert_t *)v1)->hash > ((MirrTopoVert_t *)v2)->hash) return 1; + else if (((MirrTopoVert_t *)v1)->hash < ((MirrTopoVert_t *)v2)->hash) return -1; + return 0; +} + +bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store) +{ + int totvert; + int totedge; + + if (dm) { + totvert = dm->getNumVerts(dm); + totedge = dm->getNumEdges(dm); + } + else if (me->edit_btmesh) { + totvert = me->edit_btmesh->bm->totvert; + totedge = me->edit_btmesh->bm->totedge; + } + else { + totvert = me->totvert; + totedge = me->totedge; + } + + if ((mesh_topo_store->index_lookup == NULL) || + (mesh_topo_store->prev_ob_mode != ob_mode) || + (totvert != mesh_topo_store->prev_vert_tot) || + (totedge != mesh_topo_store->prev_edge_tot)) + { + return true; + } + else { + return false; + } + +} + +void ED_mesh_mirrtopo_init(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTopoStore_t *mesh_topo_store, + const bool skip_em_vert_array_init) +{ + MEdge *medge = NULL, *med; + BMEditMesh *em = dm ? NULL : me->edit_btmesh; + + /* editmode*/ + BMEdge *eed; + BMIter iter; + + int a, last; + int totvert, totedge; + int tot_unique = -1, tot_unique_prev = -1; + int tot_unique_edges = 0, tot_unique_edges_prev; + + MirrTopoHash_t *topo_hash = NULL; + MirrTopoHash_t *topo_hash_prev = NULL; + MirrTopoVert_t *topo_pairs; + MirrTopoHash_t topo_pass = 1; + + intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */ + + /* reallocate if needed */ + ED_mesh_mirrtopo_free(mesh_topo_store); + + mesh_topo_store->prev_ob_mode = ob_mode; + + if (em) { + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + + totvert = em->bm->totvert; + } + else { + totvert = dm ? dm->getNumVerts(dm) : me->totvert; + } + + topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr"); + + /* Initialize the vert-edge-user counts used to detect unique topology */ + if (em) { + totedge = me->edit_btmesh->bm->totedge; + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2); + topo_hash[i1]++; + topo_hash[i2]++; + } + } + else { + totedge = dm ? dm->getNumEdges(dm) : me->totedge; + medge = dm ? dm->getEdgeArray(dm) : me->medge; + + for (a = 0, med = medge; a < totedge; a++, med++) { + const unsigned int i1 = med->v1, i2 = med->v2; + topo_hash[i1]++; + topo_hash[i2]++; + } + } + + topo_hash_prev = MEM_dupallocN(topo_hash); + + tot_unique_prev = -1; + tot_unique_edges_prev = -1; + while (1) { + /* use the number of edges per vert to give verts unique topology IDs */ + + tot_unique_edges = 0; + + /* This can make really big numbers, wrapping around here is fine */ + if (em) { + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2); + topo_hash[i1] += topo_hash_prev[i2] * topo_pass; + topo_hash[i2] += topo_hash_prev[i1] * topo_pass; + tot_unique_edges += (topo_hash[i1] != topo_hash[i2]); + } + } + else { + for (a = 0, med = medge; a < totedge; a++, med++) { + const unsigned int i1 = med->v1, i2 = med->v2; + topo_hash[i1] += topo_hash_prev[i2] * topo_pass; + topo_hash[i2] += topo_hash_prev[i1] * topo_pass; + tot_unique_edges += (topo_hash[i1] != topo_hash[i2]); + } + } + memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert); + + /* sort so we can count unique values */ + qsort(topo_hash_prev, totvert, sizeof(MirrTopoHash_t), mirrtopo_hash_sort); + + tot_unique = 1; /* account for skiping the first value */ + for (a = 1; a < totvert; a++) { + if (topo_hash_prev[a - 1] != topo_hash_prev[a]) { + tot_unique++; + } + } + + if ((tot_unique <= tot_unique_prev) && (tot_unique_edges <= tot_unique_edges_prev)) { + /* Finish searching for unique values when 1 loop dosnt give a + * higher number of unique values compared to the previous loop */ + break; + } + else { + tot_unique_prev = tot_unique; + tot_unique_edges_prev = tot_unique_edges; + } + /* Copy the hash calculated this iter, so we can use them next time */ + memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert); + + topo_pass++; + } + + /* Hash/Index pairs are needed for sorting to find index pairs */ + topo_pairs = MEM_callocN(sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs"); + + /* since we are looping through verts, initialize these values here too */ + index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup"); + + if (em) { + if (skip_em_vert_array_init == false) { + BM_mesh_elem_table_ensure(em->bm, BM_VERT); + } + } + + for (a = 0; a < totvert; a++) { + topo_pairs[a].hash = topo_hash[a]; + topo_pairs[a].v_index = a; + + /* initialize lookup */ + index_lookup[a] = -1; + } + + qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort); + + last = 0; + + /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2, + * but you cant ever access the last 'a' index of MirrTopoPairs */ + if (em) { + BMVert **vtable = em->bm->vtable; + for (a = 1; a <= totvert; a++) { + /* printf("I %d %ld %d\n", (a - last), MirrTopoPairs[a].hash, MirrTopoPairs[a].v_indexs); */ + if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) { + const int match_count = a - last; + if (match_count == 2) { + const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index; + index_lookup[j] = (intptr_t)vtable[k]; + index_lookup[k] = (intptr_t)vtable[j]; + } + else if (match_count == 1) { + /* Center vertex. */ + const int j = topo_pairs[a - 1].v_index; + index_lookup[j] = (intptr_t)vtable[j]; + } + last = a; + } + } + } + else { + /* same as above, for mesh */ + for (a = 1; a <= totvert; a++) { + if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) { + const int match_count = a - last; + if (match_count == 2) { + const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index; + index_lookup[j] = k; + index_lookup[k] = j; + } + else if (match_count == 1) { + /* Center vertex. */ + const int j = topo_pairs[a - 1].v_index; + index_lookup[j] = j; + } + last = a; + } + } + } + + MEM_freeN(topo_pairs); + topo_pairs = NULL; + + MEM_freeN(topo_hash); + MEM_freeN(topo_hash_prev); + + mesh_topo_store->index_lookup = index_lookup; + mesh_topo_store->prev_vert_tot = totvert; + mesh_topo_store->prev_edge_tot = totedge; +} + +void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store) +{ + if (mesh_topo_store->index_lookup) { + MEM_freeN(mesh_topo_store->index_lookup); + } + mesh_topo_store->index_lookup = NULL; + mesh_topo_store->prev_vert_tot = -1; + mesh_topo_store->prev_edge_tot = -1; +} + +/** \} */ diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index b66821c4e378c254ce4dbe2fb53738b94c45ef9b..d3d29b611821ea67959e69c064d45eb42e258157 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -46,8 +46,6 @@ #include "BLI_math.h" #include "BLI_blenlib.h" - -#include "BLI_kdtree.h" #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_deform.h" @@ -554,12 +552,10 @@ int join_mesh_exec(bContext *C, wmOperator *op) if (ma) id_us_min(&ma->id); } - if (ob->mat) MEM_freeN(ob->mat); - if (ob->matbits) MEM_freeN(ob->matbits); - if (me->mat) MEM_freeN(me->mat); - ob->mat = me->mat = NULL; - ob->matbits = NULL; - + MEM_SAFE_FREE(ob->mat); + MEM_SAFE_FREE(ob->matbits); + MEM_SAFE_FREE(me->mat); + if (totcol) { me->mat = matar; ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar"); @@ -671,84 +667,6 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/* -------------------------------------------------------------------- */ -/* Mesh Mirror (Spatial) */ - -/** \name Mesh Spatial Mirror API - * \{ */ - -#define KD_THRESH 0.00002f - -static struct { void *tree; } MirrKdStore = {NULL}; - -/* mode is 's' start, or 'e' end, or 'u' use */ -/* if end, ob can be NULL */ -int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, const float co[3], char mode) -{ - if (mode == 'u') { /* use table */ - if (MirrKdStore.tree == NULL) - ED_mesh_mirror_spatial_table(ob, em, dm, NULL, 's'); - - if (MirrKdStore.tree) { - KDTreeNearest nearest; - const int i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest); - - if (i != -1) { - if (nearest.dist < KD_THRESH) { - return i; - } - } - } - return -1; - } - else if (mode == 's') { /* start table */ - Mesh *me = ob->data; - const bool use_em = (!dm && em && me->edit_btmesh == em); - const int totvert = use_em ? em->bm->totvert : dm ? dm->getNumVerts(dm) : me->totvert; - - if (MirrKdStore.tree) /* happens when entering this call without ending it */ - ED_mesh_mirror_spatial_table(ob, em, dm, co, 'e'); - - MirrKdStore.tree = BLI_kdtree_new(totvert); - - if (use_em) { - BMVert *eve; - BMIter iter; - int i; - - /* this needs to be valid for index lookups later (callers need) */ - BM_mesh_elem_table_ensure(em->bm, BM_VERT); - - BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { - BLI_kdtree_insert(MirrKdStore.tree, i, eve->co); - } - } - else { - MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert; - int i; - - for (i = 0; i < totvert; i++, mvert++) { - BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co); - } - } - - BLI_kdtree_balance(MirrKdStore.tree); - } - else if (mode == 'e') { /* end table */ - if (MirrKdStore.tree) { - BLI_kdtree_free(MirrKdStore.tree); - MirrKdStore.tree = NULL; - } - } - else { - BLI_assert(0); - } - - return 0; -} - -/** \} */ - /* -------------------------------------------------------------------- */ /* Mesh Mirror (Topology) */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 32f0f1f9bec0ec351982ecb0656bbb623e4a348e..add2ab9865212f7ffa614b7d9ab4ac30cc9f3f47 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -564,7 +564,7 @@ void ED_object_editmode_enter(bContext *C, int flag) const bool use_key_index = mesh_needs_keyindex(ob->data); - EDBM_mesh_make(scene->toolsettings, ob, use_key_index); + EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index); em = BKE_editmesh_from_object(ob); if (LIKELY(em)) { diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 42e3a4a6837aa1024713f293872e08a442cbe9f2..e9203fa1972f1fd87ba417fc27919f93b49a0c19 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -316,7 +316,7 @@ static bool object_hook_index_array(Scene *scene, Object *obedit, BMEditMesh *em; EDBM_mesh_load(obedit); - EDBM_mesh_make(scene->toolsettings, obedit, true); + EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true); DAG_id_tag_update(obedit->data, 0); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index f8c80f2a9333fcf2e7f2504151d180aedf383e65..83d67cea2f09c155b3c64ba1327473c2f8de9d7c 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -140,7 +140,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) BMEditMesh *em; EDBM_mesh_load(obedit); - EDBM_mesh_make(scene->toolsettings, obedit, true); + EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true); DAG_id_tag_update(obedit->data, 0); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index c62ed74eaff160d4ba5a9f38390f77c731ca68ae..c6c20182ac32947ec85ddf70d7e8d0b22301509e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -1187,7 +1187,7 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count) } /* Append a and b verts to array, if not yet present. */ - k = BLI_array_count(verts); + k = BLI_array_len(verts); /* XXX Maybe a == b is enough? */ while (k-- && !(a == b && a == -1)) { if (verts[k] == a) @@ -1209,7 +1209,7 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count) } /* Do not free the array! */ - *count = BLI_array_count(verts); + *count = BLI_array_len(verts); return verts; } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 58b4c0fe2220dc51e4624a59e8b16a5365db9aaa..c27570aabc5c541d468b437071bb92baa37929a6 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -521,10 +521,8 @@ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr, int layer = BLI_findstringindex(&main_rr->layers, (char *)rr->renlay->name, offsetof(RenderLayer, name)); - if (layer != rj->last_layer) { - sima->iuser.layer = layer; - rj->last_layer = layer; - } + sima->iuser.layer = layer; + rj->last_layer = layer; } iuser->pass = sima->iuser.pass; @@ -621,7 +619,21 @@ static void render_image_restore_layer(RenderJob *rj) if (sa == rj->sa) { if (sa->spacetype == SPACE_IMAGE) { SpaceImage *sima = sa->spacedata.first; - sima->iuser.layer = rj->orig_layer; + + if (RE_HasSingleLayer(rj->re)) { + /* For single layer renders keep the active layer + * visible, or show the compositing result. */ + RenderResult *rr = RE_AcquireResultRead(rj->re); + if(RE_HasCombinedLayer(rr)) { + sima->iuser.layer = 0; + } + RE_ReleaseResult(rj->re); + } + else { + /* For multiple layer render, set back the layer + * that was set at the start of rendering. */ + sima->iuser.layer = rj->orig_layer; + } } return; } diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 5ef9d4a64999d6b4fa0ebe7cd4efb4f6a542d1b4..e39750227c065ccea679b0ddc33a14f3de365c67 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -173,7 +173,7 @@ static int uv_sculpt_brush_poll_do(bContext *C, const bool check_region) } em = BKE_editmesh_from_object(obedit); - ret = EDBM_mtexpoly_check(em); + ret = EDBM_uv_check(em); if (ret) { ARegion *ar = CTX_wm_region(C); @@ -650,9 +650,9 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm /* we need to find the active island here */ if (do_island_optimization) { UvElement *element; - NearestHit hit; + UvNearestHit hit = UV_NEAREST_HIT_INIT; Image *ima = CTX_data_edit_image(C); - uv_find_nearest_vert(scene, ima, em, co, NULL, &hit); + uv_find_nearest_vert(scene, ima, em, co, 0.0f, &hit); element = BM_uv_element_get(data->elementMap, hit.efa, hit.l); island_index = element->island; diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 8f2f65954089fc6f5399513cd2a103d5735d014d..9d7944a25d3ac4312c9b7a4ba10cbb0ccd755186 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -365,7 +365,7 @@ bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit) struct BMEditMesh *em = BKE_editmesh_from_object(obedit); bool ret; - ret = EDBM_mtexpoly_check(em); + ret = EDBM_uv_check(em); return ret; } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index ba67eb4683f48a796386312339f2e7d28b62ea7c..bac3b9f8df7000b9662d1db0ab6583fa478e7f53 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -434,12 +434,9 @@ static void image_refresh(const bContext *C, ScrArea *sa) } else { /* old shading system, we set texface */ - MTexPoly *tf; - - if (em && EDBM_mtexpoly_check(em)) { - tf = EDBM_mtexpoly_active_get(em, NULL, sloppy, selected); - - if (tf) { + if (em && EDBM_uv_check(em)) { + MTexPoly *tf; + if (EDBM_uv_active_face_get(em, sloppy, selected, &tf)) { /* don't need to check for pin here, see above */ sima->image = tf->tpage; diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 5d0877a1eff1ed9d6d9845d477449798aca15ab0..508a16926e67de8b86d69c40c19ebf47ba8d2a02 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -482,10 +482,10 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) } NODE_TYPES_END - qsort(sorted_ntypes, BLI_array_count(sorted_ntypes), sizeof(bNodeType *), ui_node_item_name_compare); + qsort(sorted_ntypes, BLI_array_len(sorted_ntypes), sizeof(bNodeType *), ui_node_item_name_compare); /* generate UI */ - for (int j = 0; j < BLI_array_count(sorted_ntypes); j++) { + for (int j = 0; j < BLI_array_len(sorted_ntypes); j++) { bNodeType *ntype = sorted_ntypes[j]; NodeLinkItem *items; int totitems; diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index f717f1c0a4353832b3c8941891d7f91b21790c0c..e27b3fe13f9857e0987d31c6f98037adab419a96 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -31,10 +31,10 @@ * * Typical view-control usage: * - * - acquire a view-control (#ED_view3d_control_acquire). + * - acquire a view-control (#ED_view3d_cameracontrol_acquire). * - modify ``rv3d->ofs``, ``rv3d->viewquat``. - * - update the view data (#ED_view3d_control_acquire) - within a loop which draws the viewport. - * - finish and release the view-control (#ED_view3d_control_release), + * - update the view data (#ED_view3d_cameracontrol_acquire) - within a loop which draws the viewport. + * - finish and release the view-control (#ED_view3d_cameracontrol_release), * either keeping the current view or restoring the initial view. * * Notes: diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 1cdbd4da1c4162a3ea27845589144b82432e7155..1f9f941a507bf609a2fcdcb02bdf47c922b1b499 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -246,9 +246,10 @@ typedef struct LassoSelectUserData { bool is_changed; } LassoSelectUserData; -static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, - ViewContext *vc, const rcti *rect, const int (*mcords)[2], - const int moves, const bool select) +static void view3d_userdata_lassoselect_init( + LassoSelectUserData *r_data, + ViewContext *vc, const rcti *rect, const int (*mcords)[2], + const int moves, const bool select) { r_data->vc = vc; @@ -323,7 +324,8 @@ static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2 return 1; } -static void do_lasso_select_pose__doSelectBone(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) +static void do_lasso_select_pose__doSelectBone( + void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) { LassoSelectUserData *data = userData; bArmature *arm = data->vc->obact->data; @@ -410,8 +412,9 @@ static void object_deselect_all_visible(Scene *scene, View3D *v3d) } } -static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], const short moves, - const bool extend, const bool select) +static void do_lasso_select_objects( + ViewContext *vc, const int mcords[][2], const short moves, + const bool extend, const bool select) { Base *base; @@ -444,7 +447,8 @@ static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, cons BM_vert_select_set(data->vc->em->bm, eve, data->select); } } -static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) +static void do_lasso_select_mesh__doSelectEdge( + void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { LassoSelectUserData *data = userData; @@ -536,7 +540,8 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m EDBM_selectmode_flush(vc->em); } -static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) +static void do_lasso_select_curve__doSelect( + void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) { LassoSelectUserData *data = userData; Object *obedit = data->vc->obedit; @@ -611,7 +616,8 @@ static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], shor lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } -static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) +static void do_lasso_select_armature__doSelectBone( + void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) { LassoSelectUserData *data = userData; bArmature *arm = data->vc->obedit->data; @@ -717,7 +723,8 @@ static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short m mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } -static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index)) +static void do_lasso_select_meshobject__doSelectVert( + void *userData, MVert *mv, const float screen_co[2], int UNUSED(index)) { LassoSelectUserData *data = userData; @@ -822,9 +829,10 @@ static void do_lasso_select_node(int mcords[][2], short moves, const bool select } #endif -static void view3d_lasso_select(bContext *C, ViewContext *vc, - const int mcords[][2], short moves, - bool extend, bool select) +static void view3d_lasso_select( + bContext *C, ViewContext *vc, + const int mcords[][2], short moves, + bool extend, bool select) { Object *ob = CTX_data_active_object(C); @@ -928,7 +936,8 @@ typedef struct SelMenuItemF { static SelMenuItemF object_mouse_select_menu_data[SEL_MENU_SIZE]; /* special (crappy) operator only for menu select */ -static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +static const EnumPropertyItem *object_select_menu_enum_itemf( + bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) { EnumPropertyItem *item = NULL, item_tmp = {0}; int totitem = 0; @@ -1403,8 +1412,9 @@ static bool ed_object_select_pick( while (base) { if (BASE_SELECTABLE(v3d, base)) { float screen_co[2]; - if (ED_view3d_project_float_global(ar, base->object->obmat[3], screen_co, - V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) + if (ED_view3d_project_float_global( + ar, base->object->obmat[3], screen_co, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { float dist_temp = len_manhattan_v2v2(mval_fl, screen_co); if (base == BASACT) dist_temp += 10.0f; @@ -1590,8 +1600,9 @@ typedef struct BoxSelectUserData { bool is_changed; } BoxSelectUserData; -static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data, - ViewContext *vc, const rcti *rect, const bool select) +static void view3d_userdata_boxselect_init( + BoxSelectUserData *r_data, + ViewContext *vc, const rcti *rect, const bool select) { r_data->vc = vc; @@ -1704,7 +1715,8 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo return OPERATOR_FINISHED; } -static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) +static void do_nurbs_box_select__doSelect( + void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) { BoxSelectUserData *data = userData; Object *obedit = data->vc->obedit; @@ -1782,7 +1794,8 @@ static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const BM_vert_select_set(data->vc->em->bm, eve, data->select); } } -static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) +static void do_mesh_box_select__doSelectEdge( + void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { BoxSelectUserData *data = userData; @@ -2338,8 +2351,9 @@ typedef struct CircleSelectUserData { bool is_changed; } CircleSelectUserData; -static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, - ViewContext *vc, const bool select, const int mval[2], const float rad) +static void view3d_userdata_circleselect_init( + CircleSelectUserData *r_data, + ViewContext *vc, const bool select, const int mval[2], const float rad) { r_data->vc = vc; r_data->select = select; @@ -2362,7 +2376,8 @@ static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float sc BM_vert_select_set(data->vc->em->bm, eve, data->select); } } -static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) +static void mesh_circle_doSelectEdge( + void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) { CircleSelectUserData *data = userData; @@ -2439,7 +2454,8 @@ static void paint_facesel_circle_select(ViewContext *vc, const bool select, cons } } -static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index)) +static void paint_vertsel_circle_select_doSelectVert( + void *userData, MVert *mv, const float screen_co[2], int UNUSED(index)) { CircleSelectUserData *data = userData; @@ -2480,7 +2496,8 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons } -static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) +static void nurbscurve_circle_doSelect( + void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) { CircleSelectUserData *data = userData; Object *obedit = data->vc->obedit; @@ -2554,7 +2571,8 @@ static bool pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, cons } return 0; } -static void do_circle_select_pose__doSelectBone(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) +static void do_circle_select_pose__doSelectBone( + void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) { CircleSelectUserData *data = userData; bArmature *arm = data->vc->obact->data; @@ -2640,7 +2658,8 @@ static bool armature_circle_doSelectJoint(void *userData, EditBone *ebone, const } return 0; } -static void do_circle_select_armature__doSelectBone(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) +static void do_circle_select_armature__doSelectBone( + void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) { CircleSelectUserData *data = userData; bArmature *arm = data->vc->obedit->data; @@ -2761,8 +2780,9 @@ static bool object_circle_select(ViewContext *vc, const bool select, const int m for (base = FIRSTBASE; base; base = base->next) { if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag & SELECT) != select_flag)) { float screen_co[2]; - if (ED_view3d_project_float_global(vc->ar, base->object->obmat[3], screen_co, - V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) + if (ED_view3d_project_float_global( + vc->ar, base->object->obmat[3], screen_co, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) { ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 5fd29971fa551ca1f8403b89f076e8b03873aebd..193a29928ef3555ddc53aafabd26b02216b7acec 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -720,7 +720,7 @@ static float screen_aligned(RegionView3D *rv3d, float mat[4][4]) * \param start: Starting segment (based on \a nrings). * \param end: End segment. * \param nsides: Number of points in ring. - * \param nrigns: Number of rings. + * \param nrings: Number of rings. */ static void partial_doughnut(float radring, float radhole, int start, int end, int nsides, int nrings) { diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index eafb3650d3619c0c51a33c693e0eac65f83812e8..d248d0df4e32eff1eb3a3acadcedbf12f9767cb5 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -59,6 +59,10 @@ #include "transform.h" +/* -------------------------------------------------------------------- */ +/** Internal Data Types + * \{ */ + enum eViewProj { VIEW_PROJ_NONE = -1, VIEW_PROJ_ORTHO = 0, @@ -132,10 +136,8 @@ struct SnapObjectContext { /** \} */ - /* -------------------------------------------------------------------- */ - -/** Common utilities +/** Common Utilities * \{ */ @@ -256,9 +258,7 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt); /** \} */ - /* -------------------------------------------------------------------- */ - /** \name Ray Cast Funcs * \{ */ @@ -785,7 +785,6 @@ static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, * Walks through all objects in the scene to find the `hit` on object surface. * * \param sctx: Snap context to store data. - * \param snapdata: struct generated in `set_snapdata`. * \param snap_select : from enum eSnapSelect. * \param use_object_edit_cage : Uses the coordinates of BMesh(if any) to do the snapping. * \param obj_list: List with objects to snap (created in `create_object_list`). @@ -842,9 +841,7 @@ static bool raycastObjects( /** \} */ - /* -------------------------------------------------------------------- */ - /** Snap Nearest utilities * \{ */ @@ -1154,9 +1151,7 @@ static float dist_squared_to_projected_aabb_simple( /** \} */ - /* -------------------------------------------------------------------- */ - /** Walk DFS * \{ */ @@ -1252,7 +1247,6 @@ static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char a /** \} */ /* -------------------------------------------------------------------- */ - /** \name Internal Object Snapping API * \{ */ @@ -2076,9 +2070,7 @@ static bool snapObjectsRay( /** \} */ - /* -------------------------------------------------------------------- */ - /** \name Public Object Snapping API * \{ */ diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c index 2dcfe949f3f27f54f4fd30b0141a8effe24b7196..fa697a0f006dfd73c6d17cebbbf274ea92aeadbd 100644 --- a/source/blender/editors/util/editmode_undo.c +++ b/source/blender/editors/util/editmode_undo.c @@ -181,9 +181,6 @@ void undo_editmode_push( } } -/** \} */ - - /* helper to remove clean other objects from undo stack */ static void undo_clean_stack(bContext *C) { diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index fecacd079970dee2a1a1242c1d6b15ad483a8f51..7b793697077350f6b594e2e621feb32d32942243 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -570,7 +570,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); - activetf = EDBM_mtexpoly_active_get(em, &efa_act, false, false); /* will be set to NULL if hidden */ + efa_act = EDBM_uv_active_face_get(em, false, false, &activetf); /* will be set to NULL if hidden */ #ifndef USE_EDBM_LOOPTRIS activef = BM_mesh_active_face_get(bm, false, false); #endif @@ -967,7 +967,7 @@ static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bo if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) { struct BMEditMesh *em = BKE_editmesh_from_object(obedit); - *show_shadow = EDBM_mtexpoly_check(em); + *show_shadow = EDBM_uv_check(em); } *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT); diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index e028c08091cc366cbbd9059ce9307fee50451955..b5ff46e921997a5e5b39ca314b9ee19a2999b2d7 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -51,18 +51,31 @@ void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_off /* find nearest */ -typedef struct NearestHit { +typedef struct UvNearestHit { + /** Always set if we have a hit. */ struct BMFace *efa; struct MTexPoly *tf; struct BMLoop *l; struct MLoopUV *luv, *luv_next; - int lindex; /* index of loop within face */ -} NearestHit; + /** Index of loop within face. */ + int lindex; + /** Needs to be set before calling nearest functions. */ + float dist_sq; +} UvNearestHit; -void uv_find_nearest_vert(struct Scene *scene, struct Image *ima, struct BMEditMesh *em, - const float co[2], const float penalty[2], struct NearestHit *hit); -void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditMesh *em, - const float co[2], struct NearestHit *hit); +#define UV_NEAREST_HIT_INIT { .dist_sq = FLT_MAX, } + +bool uv_find_nearest_vert( + struct Scene *scene, struct Image *ima, struct BMEditMesh *em, + const float co[2], const float penalty_dist, struct UvNearestHit *hit_final); + +bool uv_find_nearest_edge( + struct Scene *scene, struct Image *ima, struct BMEditMesh *em, + const float co[2], struct UvNearestHit *hit_final); + +bool uv_find_nearest_face( + struct Scene *scene, struct Image *ima, struct BMEditMesh *em, + const float co[2], struct UvNearestHit *hit_final); /* utility tool functions */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index bf5a06f0a1c9d78bc82d5271b46ec933a1d42903..852c4ae5958bee407bfb5c627577ac8ad87fa13c 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -29,7 +29,6 @@ * \ingroup eduv */ - #include <stdlib.h> #include <string.h> #include <math.h> @@ -92,7 +91,9 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object *obedit, const bool select); static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object *obedit, const bool select); -/************************* state testing ************************/ +/* -------------------------------------------------------------------- */ +/** \name State Testing + * \{ */ bool ED_uvedit_test(Object *obedit) { @@ -106,7 +107,7 @@ bool ED_uvedit_test(Object *obedit) return 0; em = BKE_editmesh_from_object(obedit); - ret = EDBM_mtexpoly_check(em); + ret = EDBM_uv_check(em); return ret; } @@ -133,15 +134,21 @@ static int UNUSED_FUNCTION(ED_operator_uvmap_mesh) (bContext *C) return 0; } -/**************************** object active image *****************************/ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Active Image + * \{ */ static bool is_image_texture_node(bNode *node) { return ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT); } -bool ED_object_get_active_image(Object *ob, int mat_nr, - Image **r_ima, ImageUser **r_iuser, bNode **r_node, bNodeTree **r_ntree) +bool ED_object_get_active_image( + Object *ob, int mat_nr, + Image **r_ima, ImageUser **r_iuser, bNode **r_node, bNodeTree **r_ntree) { Material *ma = give_current_material(ob, mat_nr); bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL; @@ -174,7 +181,11 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i } } -/************************* assign image ************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Assign Image + * \{ */ //#define USE_SWITCH_ASPECT @@ -316,7 +327,11 @@ static bool uvedit_set_tile(Object *obedit, Image *ima, int curtile) return true; } -/*********************** space conversion *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Space Conversion + * \{ */ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist) { @@ -334,7 +349,11 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist dist[1] = pixeldist / height; } -/*************** visibility and selection utilities **************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Visibility and Selection Utilities + * \{ */ static void uvedit_vertex_select_tagged(BMEditMesh *em, Scene *scene, bool select, int cd_loop_uv_offset) { @@ -371,8 +390,9 @@ bool uvedit_face_visible_test(Scene *scene, Image *ima, BMFace *efa, MTexPoly *t return uvedit_face_visible_nolocal(scene, efa); } -bool uvedit_face_select_test(Scene *scene, BMFace *efa, - const int cd_loop_uv_offset) +bool uvedit_face_select_test( + Scene *scene, BMFace *efa, + const int cd_loop_uv_offset) { ToolSettings *ts = scene->toolsettings; if (ts->uv_flag & UV_SYNC_SELECTION) { @@ -393,8 +413,9 @@ bool uvedit_face_select_test(Scene *scene, BMFace *efa, } } -bool uvedit_face_select_set(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select, - const bool do_history, const int cd_loop_uv_offset) +bool uvedit_face_select_set( + struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa, const bool select, + const bool do_history, const int cd_loop_uv_offset) { if (select) { return uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset); @@ -404,8 +425,9 @@ bool uvedit_face_select_set(struct Scene *scene, struct BMEditMesh *em, struct B } } -bool uvedit_face_select_enable(Scene *scene, BMEditMesh *em, BMFace *efa, const bool do_history, - const int cd_loop_uv_offset) +bool uvedit_face_select_enable( + Scene *scene, BMEditMesh *em, BMFace *efa, const bool do_history, + const int cd_loop_uv_offset) { ToolSettings *ts = scene->toolsettings; @@ -431,8 +453,9 @@ bool uvedit_face_select_enable(Scene *scene, BMEditMesh *em, BMFace *efa, const return false; } -bool uvedit_face_select_disable(Scene *scene, BMEditMesh *em, BMFace *efa, - const int cd_loop_uv_offset) +bool uvedit_face_select_disable( + Scene *scene, BMEditMesh *em, BMFace *efa, + const int cd_loop_uv_offset) { ToolSettings *ts = scene->toolsettings; @@ -455,8 +478,9 @@ bool uvedit_face_select_disable(Scene *scene, BMEditMesh *em, BMFace *efa, return false; } -bool uvedit_edge_select_test(Scene *scene, BMLoop *l, - const int cd_loop_uv_offset) +bool uvedit_edge_select_test( + Scene *scene, BMLoop *l, + const int cd_loop_uv_offset) { ToolSettings *ts = scene->toolsettings; @@ -482,8 +506,9 @@ bool uvedit_edge_select_test(Scene *scene, BMLoop *l, } } -void uvedit_edge_select_set(BMEditMesh *em, Scene *scene, BMLoop *l, const bool select, - const bool do_history, const int cd_loop_uv_offset) +void uvedit_edge_select_set( + BMEditMesh *em, Scene *scene, BMLoop *l, const bool select, + const bool do_history, const int cd_loop_uv_offset) { if (select) { @@ -494,8 +519,9 @@ void uvedit_edge_select_set(BMEditMesh *em, Scene *scene, BMLoop *l, const bool } } -void uvedit_edge_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const bool do_history, - const int cd_loop_uv_offset) +void uvedit_edge_select_enable( + BMEditMesh *em, Scene *scene, BMLoop *l, const bool do_history, + const int cd_loop_uv_offset) { ToolSettings *ts = scene->toolsettings; @@ -525,8 +551,9 @@ void uvedit_edge_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const bo } } -void uvedit_edge_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l, - const int cd_loop_uv_offset) +void uvedit_edge_select_disable( + BMEditMesh *em, Scene *scene, BMLoop *l, + const int cd_loop_uv_offset) { ToolSettings *ts = scene->toolsettings; @@ -552,8 +579,9 @@ void uvedit_edge_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l, } } -bool uvedit_uv_select_test(Scene *scene, BMLoop *l, - const int cd_loop_uv_offset) +bool uvedit_uv_select_test( + Scene *scene, BMLoop *l, + const int cd_loop_uv_offset) { ToolSettings *ts = scene->toolsettings; @@ -569,8 +597,9 @@ bool uvedit_uv_select_test(Scene *scene, BMLoop *l, } } -void uvedit_uv_select_set(BMEditMesh *em, Scene *scene, BMLoop *l, const bool select, - const bool do_history, const int cd_loop_uv_offset) +void uvedit_uv_select_set( + BMEditMesh *em, Scene *scene, BMLoop *l, const bool select, + const bool do_history, const int cd_loop_uv_offset) { if (select) { uvedit_uv_select_enable(em, scene, l, do_history, cd_loop_uv_offset); @@ -580,8 +609,9 @@ void uvedit_uv_select_set(BMEditMesh *em, Scene *scene, BMLoop *l, const bool se } } -void uvedit_uv_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, - const bool do_history, const int cd_loop_uv_offset) +void uvedit_uv_select_enable( + BMEditMesh *em, Scene *scene, BMLoop *l, + const bool do_history, const int cd_loop_uv_offset) { ToolSettings *ts = scene->toolsettings; @@ -601,8 +631,9 @@ void uvedit_uv_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, } } -void uvedit_uv_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l, - const int cd_loop_uv_offset) +void uvedit_uv_select_disable( + BMEditMesh *em, Scene *scene, BMLoop *l, + const int cd_loop_uv_offset) { ToolSettings *ts = scene->toolsettings; @@ -618,7 +649,11 @@ void uvedit_uv_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l, } } -/*********************** live unwrap utilities ***********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Live Unwrap Utilities + * \{ */ void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit) { @@ -629,7 +664,12 @@ void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit) } } -/*********************** geometric utilities ***********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Geometric Utilities + * \{ */ + void uv_poly_center(BMFace *f, float r_cent[2], const int cd_loop_uv_offset) { BMLoop *l; @@ -758,89 +798,104 @@ static bool uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2 return changed; } -/************************** find nearest ****************************/ +/** \} */ -void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit) +/* -------------------------------------------------------------------- */ +/** \name Find Nearest Elements + * \{ */ + +bool uv_find_nearest_edge( + Scene *scene, Image *ima, BMEditMesh *em, const float co[2], + UvNearestHit *hit) { MTexPoly *tf; BMFace *efa; BMLoop *l; BMIter iter, liter; MLoopUV *luv, *luv_next; - float mindist_squared, dist_squared; int i; + bool found = false; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); - mindist_squared = 1e10f; - memset(hit, 0, sizeof(*hit)); - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa, tf)) { continue; - + } BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); + const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); - if (dist_squared < mindist_squared) { + if (dist_test_sq < hit->dist_sq) { hit->tf = tf; hit->efa = efa; - + hit->l = l; hit->luv = luv; hit->luv_next = luv_next; hit->lindex = i; - mindist_squared = dist_squared; + hit->dist_sq = dist_test_sq; + found = true; } } } + return found; } -static void uv_find_nearest_face(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit) +bool uv_find_nearest_face( + Scene *scene, Image *ima, BMEditMesh *em, const float co[2], + UvNearestHit *hit_final) { - MTexPoly *tf; - BMFace *efa; - BMIter iter; - float mindist, dist, cent[2]; + bool found = false; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); - mindist = 1e10f; - memset(hit, 0, sizeof(*hit)); + /* this will fill in hit.vert1 and hit.vert2 */ + float dist_sq_init = hit_final->dist_sq; + UvNearestHit hit = *hit_final; + if (uv_find_nearest_edge(scene, ima, em, co, &hit)) { + hit.dist_sq = dist_sq_init; + hit.l = NULL; + hit.luv = hit.luv_next = NULL; - /*this will fill in hit.vert1 and hit.vert2*/ - uv_find_nearest_edge(scene, ima, em, co, hit); - hit->l = NULL; - hit->luv = hit->luv_next = NULL; + BMIter iter; + BMFace *efa; - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) - continue; + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); + if (!uvedit_face_visible_test(scene, ima, efa, tf)) { + continue; + } - uv_poly_center(efa, cent, cd_loop_uv_offset); + float cent[2]; + uv_poly_center(efa, cent, cd_loop_uv_offset); - dist = len_manhattan_v2v2(co, cent); + const float dist_test_sq = len_squared_v2v2(co, cent); - if (dist < mindist) { - hit->tf = tf; - hit->efa = efa; - mindist = dist; + if (dist_test_sq < hit.dist_sq) { + hit.efa = efa; + hit.dist_sq = dist_test_sq; + found = true; + } } } + if (found) { + *hit_final = hit; + } + return found; } -static bool uv_nearest_between(const BMLoop *l, const float co[2], - const int cd_loop_uv_offset) +static bool uv_nearest_between( + const BMLoop *l, const float co[2], + const int cd_loop_uv_offset) { const float *uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset))->uv; const float *uv_curr = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv; @@ -850,60 +905,74 @@ static bool uv_nearest_between(const BMLoop *l, const float co[2], (line_point_side_v2(uv_next, uv_curr, co) <= 0.0f)); } -void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, - float const co[2], const float penalty[2], NearestHit *hit) +bool uv_find_nearest_vert( + Scene *scene, Image *ima, BMEditMesh *em, + float const co[2], const float penalty_dist, UvNearestHit *hit_final) { - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MTexPoly *tf; - MLoopUV *luv; - float mindist, dist; - int i; + bool found = false; - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* this will fill in hit.vert1 and hit.vert2 */ + float dist_sq_init = hit_final->dist_sq; + UvNearestHit hit = *hit_final; + if (uv_find_nearest_edge(scene, ima, em, co, &hit)) { + hit.dist_sq = dist_sq_init; - /*this will fill in hit.vert1 and hit.vert2*/ - uv_find_nearest_edge(scene, ima, em, co, hit); - hit->l = NULL; - hit->luv = hit->luv_next = NULL; + hit.l = NULL; + hit.luv = hit.luv_next = NULL; - mindist = 1e10f; - memset(hit, 0, sizeof(*hit)); - - BM_mesh_elem_index_ensure(em->bm, BM_VERT); + BMFace *efa; + BMIter iter; - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) - continue; + BM_mesh_elem_index_ensure(em->bm, BM_VERT); - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (penalty && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) - dist = len_manhattan_v2v2(co, luv->uv) + len_manhattan_v2(penalty); - else - dist = len_manhattan_v2v2(co, luv->uv); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); - if (dist <= mindist) { - if (dist == mindist) { - if (!uv_nearest_between(l, co, cd_loop_uv_offset)) { - continue; - } + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); + if (!uvedit_face_visible_test(scene, ima, efa, tf)) { + continue; + } + + BMIter liter; + BMLoop *l; + int i; + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + float dist_test_sq; + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist; + dist_test_sq = SQUARE(dist_test_sq); + } + else { + dist_test_sq = len_squared_v2v2(co, luv->uv); } - mindist = dist; + if (dist_test_sq <= hit.dist_sq) { + if (dist_test_sq == hit.dist_sq) { + if (!uv_nearest_between(l, co, cd_loop_uv_offset)) { + continue; + } + } - hit->l = l; - hit->luv = luv; - hit->luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - hit->tf = tf; - hit->efa = efa; - hit->lindex = i; + hit.dist_sq = dist_test_sq; + + hit.l = l; + hit.luv = luv; + hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + hit.efa = efa; + hit.lindex = i; + found = true; + } } } } + + if (found) { + *hit_final = hit; + } + + return found; } bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float co[2], float r_uv[2]) @@ -944,7 +1013,11 @@ bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float return found; } -/*********************** loop select ***********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop Select + * \{ */ static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first) { @@ -1029,8 +1102,9 @@ static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, UvMapVert *first1, return true; } -static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit *hit, - const float limit[2], const bool extend) +static int uv_select_edgeloop( + Scene *scene, Image *ima, BMEditMesh *em, UvNearestHit *hit, + const float limit[2], const bool extend) { BMFace *efa; BMIter iter, liter; @@ -1131,14 +1205,19 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH return (select) ? 1 : -1; } -/*********************** linked select ***********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked + * \{ */ -static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], NearestHit *hit, bool extend, bool select_faces) +static void uv_select_linked( + Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], UvNearestHit *hit_final, + bool extend, bool select_faces) { BMFace *efa; BMLoop *l; BMIter iter, liter; - MTexPoly *tf; MLoopUV *luv; UvVertMap *vmap; UvMapVert *vlist, *iterv, *startv; @@ -1165,9 +1244,10 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack"); flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag"); - if (!hit) { + if (hit_final == NULL) { + /* Use existing selection */ BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); + MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { if (select_faces) { @@ -1195,7 +1275,7 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo } else { BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - if (efa == hit->efa) { + if (efa == hit_final->efa) { stack[stacksize] = a; stacksize++; flag[a] = 1; @@ -1350,6 +1430,12 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer return NULL; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select More/Less Operator + * \{ */ + static int uv_select_more_less(bContext *C, const bool select) { Scene *scene = CTX_data_scene(C); @@ -1490,7 +1576,11 @@ static void UV_OT_select_less(wmOperatorType *ot) ot->poll = ED_operator_uvedit_space_image; } -/* ******************** align operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Weld Align Operator + * \{ */ static void uv_weld_align(bContext *C, int tool) { @@ -1602,8 +1692,10 @@ static void uv_weld_align(bContext *C, int tool) /* flush vertex tags to edges */ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - BM_elem_flag_set(eed, BM_ELEM_TAG, (BM_elem_flag_test(eed->v1, BM_ELEM_TAG) && - BM_elem_flag_test(eed->v2, BM_ELEM_TAG))); + BM_elem_flag_set( + eed, BM_ELEM_TAG, + (BM_elem_flag_test(eed->v1, BM_ELEM_TAG) && + BM_elem_flag_test(eed->v2, BM_ELEM_TAG))); } /* find a vertex with only one tagged edge */ @@ -1654,11 +1746,11 @@ static void uv_weld_align(bContext *C, int tool) } /* now we have all verts, make into a line */ - if (BLI_array_count(eve_line) > 2) { + if (BLI_array_len(eve_line) > 2) { /* we know the returns from these must be valid */ const float *uv_start = uv_sel_co_from_eve(scene, ima, em, eve_line[0]); - const float *uv_end = uv_sel_co_from_eve(scene, ima, em, eve_line[BLI_array_count(eve_line) - 1]); + const float *uv_end = uv_sel_co_from_eve(scene, ima, em, eve_line[BLI_array_len(eve_line) - 1]); /* For t & u modes */ float a = 0.0f; @@ -1676,7 +1768,7 @@ static void uv_weld_align(bContext *C, int tool) } /* go over all verts except for endpoints */ - for (i = 0; i < BLI_array_count(eve_line); i++) { + for (i = 0; i < BLI_array_len(eve_line); i++) { BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) { tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); @@ -1749,7 +1841,12 @@ static void UV_OT_align(wmOperatorType *ot) /* properties */ RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on"); } -/* ******************** weld near operator **************** */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Doubles Operator + * \{ */ typedef struct UVvert { MLoopUV *uv_loop; @@ -1789,7 +1886,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) MLoopUV **loop_arr = NULL; BLI_array_declare(loop_arr); - /* TODO, use qsort as with MESH_OT_remove_doubles, this isn't optimal */ + /* TODO, use kd-tree as with MESH_OT_remove_doubles, this isn't optimal */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) @@ -1807,7 +1904,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) } } - for (uv_a_index = 0; uv_a_index < BLI_array_count(vert_arr); uv_a_index++) { + for (uv_a_index = 0; uv_a_index < BLI_array_len(vert_arr); uv_a_index++) { if (vert_arr[uv_a_index].weld == false) { float uv_min[2]; float uv_max[2]; @@ -1821,7 +1918,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) copy_v2_v2(uv_min, uv_a); vert_arr[uv_a_index].weld = true; - for (uv_b_index = uv_a_index + 1; uv_b_index < BLI_array_count(vert_arr); uv_b_index++) { + for (uv_b_index = uv_a_index + 1; uv_b_index < BLI_array_len(vert_arr); uv_b_index++) { uv_b = vert_arr[uv_b_index].uv_loop->uv; if ((vert_arr[uv_b_index].weld == false) && (len_manhattan_v2v2(uv_a, uv_b) < threshold)) @@ -1831,10 +1928,10 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) vert_arr[uv_b_index].weld = true; } } - if (BLI_array_count(loop_arr)) { + if (BLI_array_len(loop_arr)) { float uv_mid[2]; mid_v2_v2v2(uv_mid, uv_min, uv_max); - for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr); uv_b_index++) { + for (uv_b_index = 0; uv_b_index < BLI_array_len(loop_arr); uv_b_index++) { copy_v2_v2(loop_arr[uv_b_index]->uv, uv_mid); } } @@ -1869,12 +1966,12 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op) } } - for (uv_a_index = 0; uv_a_index < BLI_array_count(loop_arr); uv_a_index++) { + for (uv_a_index = 0; uv_a_index < BLI_array_len(loop_arr); uv_a_index++) { float dist_best = FLT_MAX, dist; const float *uv_best = NULL; uv_a = loop_arr[uv_a_index]->uv; - for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr_unselected); uv_b_index++) { + for (uv_b_index = 0; uv_b_index < BLI_array_len(loop_arr_unselected); uv_b_index++) { uv_b = loop_arr_unselected[uv_b_index]->uv; dist = len_manhattan_v2v2(uv_a, uv_b); if ((dist < threshold) && (dist < dist_best)) { @@ -1914,7 +2011,12 @@ static void UV_OT_remove_doubles(wmOperatorType *ot) "Merge Distance", "Maximum distance between welded vertices", 0.0f, 1.0f); RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices"); } -/* ******************** weld operator **************** */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Weld Near Operator + * \{ */ static int uv_weld_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1936,8 +2038,11 @@ static void UV_OT_weld(wmOperatorType *ot) ot->poll = ED_operator_uvedit; } +/** \} */ -/* ******************** (de)select all operator **************** */ +/* -------------------------------------------------------------------- */ +/** \name (De)Select All Operator + * \{ */ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int action) { @@ -2046,9 +2151,13 @@ static void UV_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } -/* ******************** mouse select operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mouse Select Operator + * \{ */ -static bool uv_sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky, int hitlen) +static bool uv_sticky_select(float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen) { int i; @@ -2084,12 +2193,11 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo BMIter iter, liter; MTexPoly *tf; MLoopUV *luv; - NearestHit hit; + UvNearestHit hit = UV_NEAREST_HIT_INIT; int i, selectmode, sticky, sync, *hitv = NULL; bool select = true; int flush = 0, hitlen = 0; /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ float limit[2], **hituv = NULL; - float penalty[2]; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); @@ -2100,8 +2208,13 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo * shift-selecting can consider an adjacent point close enough to add to * the selection rather than de-selecting the closest. */ - uvedit_pixel_to_float(sima, limit, 0.05f); - uvedit_pixel_to_float(sima, penalty, 5.0f / (sima ? sima->zoom : 1.0f)); + float penalty_dist; + { + float penalty[2]; + uvedit_pixel_to_float(sima, limit, 0.05f); + uvedit_pixel_to_float(sima, penalty, 5.0f / (sima ? sima->zoom : 1.0f)); + penalty_dist = len_v2(penalty); + } /* retrieve operation mode */ if (ts->uv_flag & UV_SYNC_SELECTION) { @@ -2125,8 +2238,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo /* find nearest element */ if (loop) { /* find edge */ - uv_find_nearest_edge(scene, ima, em, co, &hit); - if (hit.efa == NULL) { + if (!uv_find_nearest_edge(scene, ima, em, co, &hit)) { return OPERATOR_CANCELLED; } @@ -2134,8 +2246,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo } else if (selectmode == UV_SELECT_VERTEX) { /* find vertex */ - uv_find_nearest_vert(scene, ima, em, co, penalty, &hit); - if (hit.efa == NULL) { + if (!uv_find_nearest_vert(scene, ima, em, co, penalty_dist, &hit)) { return OPERATOR_CANCELLED; } @@ -2151,8 +2262,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo } else if (selectmode == UV_SELECT_EDGE) { /* find edge */ - uv_find_nearest_edge(scene, ima, em, co, &hit); - if (hit.efa == NULL) { + if (!uv_find_nearest_edge(scene, ima, em, co, &hit)) { return OPERATOR_CANCELLED; } @@ -2170,11 +2280,10 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo } else if (selectmode == UV_SELECT_FACE) { /* find face */ - uv_find_nearest_face(scene, ima, em, co, &hit); - if (hit.efa == NULL) { + if (!uv_find_nearest_face(scene, ima, em, co, &hit)) { return OPERATOR_CANCELLED; } - + /* make active */ BM_mesh_active_face_set(em->bm, hit.efa); @@ -2191,9 +2300,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo hitlen = hit.efa->len; } else if (selectmode == UV_SELECT_ISLAND) { - uv_find_nearest_edge(scene, ima, em, co, &hit); - - if (hit.efa == NULL) { + if (!uv_find_nearest_edge(scene, ima, em, co, &hit)) { return OPERATOR_CANCELLED; } @@ -2373,7 +2480,11 @@ static void UV_OT_select(wmOperatorType *ot) "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", -100.0f, 100.0f); } -/* ******************** loop select operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop Select Operator + * \{ */ static int uv_select_loop_exec(bContext *C, wmOperator *op) { @@ -2418,7 +2529,11 @@ static void UV_OT_select_loop(wmOperatorType *ot) "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", -100.0f, 100.0f); } -/* ******************** linked select operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked Operator + * \{ */ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, int pick) { @@ -2432,7 +2547,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent int extend; bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE); - NearestHit hit, *hit_p = NULL; + UvNearestHit hit = UV_NEAREST_HIT_INIT; if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) { BKE_report(op->reports, RPT_ERROR, "Select linked only works in face select mode when sync selection is enabled"); @@ -2457,11 +2572,12 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent RNA_float_get_array(op->ptr, "location", co); } - uv_find_nearest_edge(scene, ima, em, co, &hit); - hit_p = &hit; + if (!uv_find_nearest_edge(scene, ima, em, co, &hit)) { + return OPERATOR_CANCELLED; + } } - uv_select_linked(scene, ima, em, limit, hit_p, extend, select_faces); + uv_select_linked(scene, ima, em, limit, pick ? &hit : NULL, extend, select_faces); DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -2628,17 +2744,21 @@ static void uv_select_sync_flush(ToolSettings *ts, BMEditMesh *em, const short s } } - +/** \} */ /* -------------------------------------------------------------------- */ -/* Utility functions to flush the uv-selection from tags */ +/** \name Select/Tag Flushing Utils + * + * Utility functions to flush the uv-selection from tags. + * \{ */ /** * helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face */ -static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene, BMEditMesh *em, UvVertMap *vmap, - const unsigned int efa_index, BMLoop *l, - const bool select, const int cd_loop_uv_offset) +static void uv_select_flush_from_tag_sticky_loc_internal( + Scene *scene, BMEditMesh *em, UvVertMap *vmap, + const unsigned int efa_index, BMLoop *l, + const bool select, const int cd_loop_uv_offset) { UvMapVert *start_vlist = NULL, *vlist_iter; BMFace *efa_vlist; @@ -2742,8 +2862,9 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - uv_select_flush_from_tag_sticky_loc_internal(scene, em, vmap, efa_index, l, - select, cd_loop_uv_offset); + uv_select_flush_from_tag_sticky_loc_internal( + scene, em, vmap, efa_index, l, + select, cd_loop_uv_offset); } } } @@ -2829,8 +2950,9 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l, BM_ELEM_TAG)) { - uv_select_flush_from_tag_sticky_loc_internal(scene, em, vmap, efa_index, l, - select, cd_loop_uv_offset); + uv_select_flush_from_tag_sticky_loc_internal( + scene, em, vmap, efa_index, l, + select, cd_loop_uv_offset); } } } @@ -2848,7 +2970,11 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object } } -/* ******************** border select operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Border Select Operator + * \{ */ static int uv_border_select_exec(bContext *C, wmOperator *op) { @@ -2866,9 +2992,10 @@ static int uv_border_select_exec(bContext *C, wmOperator *op) MLoopUV *luv; rctf rectf; bool changed, pinned, select, extend; - const bool use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE); + const bool use_face_center = ( + (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); @@ -2981,7 +3108,11 @@ static void UV_OT_select_border(wmOperatorType *ot) WM_operator_properties_gesture_border_select(ot); } -/* ******************** circle select operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Circle Select Operator + * \{ */ static int uv_inside_circle(const float uv[2], const float offset[2], const float ellipse[2]) { @@ -3008,9 +3139,10 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) float zoomx, zoomy, offset[2], ellipse[2]; const bool select = !RNA_boolean_get(op->ptr, "deselect"); bool changed = false; - const bool use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE); + const bool use_face_center = ( + (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); @@ -3099,11 +3231,15 @@ static void UV_OT_circle_select(wmOperatorType *ot) WM_operator_properties_gesture_circle_select(ot); } +/** \} */ -/* ******************** lasso select operator **************** */ +/* -------------------------------------------------------------------- */ +/** \name Lasso Select Operator + * \{ */ -static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short moves, - const bool select, const bool extend) +static bool do_lasso_select_mesh_uv( + bContext *C, const int mcords[][2], short moves, + const bool select, const bool extend) { SpaceImage *sima = CTX_wm_space_image(C); Image *ima = CTX_data_edit_image(C); @@ -3167,9 +3303,10 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (UI_view2d_view_to_region_clip(&ar->v2d, - luv->uv[0], luv->uv[1], - &screen_uv[0], &screen_uv[1]) && + if (UI_view2d_view_to_region_clip( + &ar->v2d, + luv->uv[0], luv->uv[1], + &screen_uv[0], &screen_uv[1]) && BLI_rcti_isect_pt_v(&rect, screen_uv) && BLI_lasso_is_point_inside(mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) { @@ -3238,9 +3375,11 @@ static void UV_OT_select_lasso(wmOperatorType *ot) WM_operator_properties_gesture_lasso_select(ot); } +/** \} */ - -/* ******************** snap cursor operator **************** */ +/* -------------------------------------------------------------------- */ +/** \name Snap Cursor Operator + * \{ */ static void uv_snap_to_pixel(float uvco[2], float w, float h) { @@ -3308,7 +3447,11 @@ static void UV_OT_snap_cursor(wmOperatorType *ot) RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to"); } -/* ******************** snap selection operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snap Selection Operator + * \{ */ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, const float cursor[2]) { @@ -3529,7 +3672,11 @@ static void UV_OT_snap_selected(wmOperatorType *ot) RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to"); } -/* ******************** pin operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Pin UV's Operator + * \{ */ static int uv_pin_exec(bContext *C, wmOperator *op) { @@ -3587,7 +3734,11 @@ static void UV_OT_pin(wmOperatorType *ot) RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear pinning for the selection instead of setting it"); } -/******************* select pinned operator ***************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Pinned UV's Operator + * \{ */ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -3635,15 +3786,20 @@ static void UV_OT_select_pinned(wmOperatorType *ot) ot->poll = ED_operator_uvedit; } -/********************** hide operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Operator + * \{ */ /* check if we are selected or unselected based on 'bool_test' arg, * needed for select swap support */ #define UV_SEL_TEST(luv, bool_test) ((((luv)->flag & MLOOPUV_VERTSEL) == MLOOPUV_VERTSEL) == bool_test) /* is every UV vert selected or unselected depending on bool_test */ -static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test, - const int cd_loop_uv_offset) +static bool bm_face_is_all_uv_sel( + BMFace *f, bool select_test, + const int cd_loop_uv_offset) { BMLoop *l_iter; BMLoop *l_first; @@ -3773,7 +3929,11 @@ static void UV_OT_hide(wmOperatorType *ot) RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected"); } -/****************** reveal operator ******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reveal Operator + * \{ */ static int uv_reveal_exec(bContext *C, wmOperator *op) { @@ -3908,7 +4068,11 @@ static void UV_OT_reveal(wmOperatorType *ot) RNA_def_boolean(ot->srna, "select", true, "Select", ""); } -/******************** set 3d cursor operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set 2D Cursor Operator + * \{ */ static int uv_set_2d_cursor_poll(bContext *C) { @@ -3971,7 +4135,11 @@ static void UV_OT_cursor_set(wmOperatorType *ot) "Cursor location in normalized (0.0-1.0) coordinates", -10.0f, 10.0f); } -/********************** set tile operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Tile Operator + * \{ */ static int set_tile_exec(bContext *C, wmOperator *op) { @@ -4037,6 +4205,11 @@ static void UV_OT_tile_set(wmOperatorType *ot) RNA_def_int_vector(ot->srna, "tile", 2, NULL, 0, INT_MAX, "Tile", "Tile coordinate", 0, 10); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Seam from UV Islands Operator + * \{ */ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) { @@ -4055,7 +4228,7 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) em = me->edit_btmesh; bm = em->bm; - if (!EDBM_mtexpoly_check(em)) { + if (!EDBM_uv_check(em)) { return OPERATOR_CANCELLED; } @@ -4172,6 +4345,12 @@ static void UV_OT_seams_from_islands(wmOperatorType *ot) RNA_def_boolean(ot->srna, "mark_sharp", 0, "Mark Sharp", "Mark boundary edges as sharp"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mark Seam Operator + * \{ */ + static int uv_mark_seam_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_edit_object(C); @@ -4244,8 +4423,11 @@ static void UV_OT_mark_seam(wmOperatorType *ot) RNA_def_boolean(ot->srna, "clear", false, "Clear Seams", "Clear instead of marking seams"); } +/** \} */ -/* ************************** registration **********************************/ +/* -------------------------------------------------------------------- */ +/** \name Operator Registration & Keymap + * \{ */ void ED_operatortypes_uvedit(void) { @@ -4381,3 +4563,4 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf) transform_keymap_for_space(keyconf, keymap, SPACE_IMAGE); } +/** \} */ diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index da36170310a79f145ba73da444015750a5f72537..057417b898f45a73c4e84d797a31bacefd1727e7 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -2058,16 +2058,16 @@ static void stitch_select(bContext *C, Scene *scene, const wmEvent *event, Stitc { /* add uv under mouse to processed uv's */ float co[2]; - NearestHit hit; + UvNearestHit hit = UV_NEAREST_HIT_INIT; ARegion *ar = CTX_wm_region(C); Image *ima = CTX_data_edit_image(C); UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); if (state->mode == STITCH_VERT) { - uv_find_nearest_vert(scene, ima, state->em, co, NULL, &hit); - - if (hit.efa) { + if (uv_find_nearest_vert( + scene, ima, state->em, co, 0.0f, &hit)) + { /* Add vertex to selection, deselect all common uv's of vert other * than selected and update the preview. This behavior was decided so that * you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */ @@ -2079,9 +2079,9 @@ static void stitch_select(bContext *C, Scene *scene, const wmEvent *event, Stitc } } else { - uv_find_nearest_edge(scene, ima, state->em, co, &hit); - - if (hit.efa) { + if (uv_find_nearest_edge( + scene, ima, state->em, co, &hit)) + { UvEdge *edge = uv_edge_get(hit.l, state); stitch_select_edge(edge, state, false); } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 1f5ffbdcc7e25df60f0e3147bd85b02876dc04c5..a0ca719e207d3ba363efb551bb4f7985050fa3f3 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2599,7 +2599,8 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result) vec3 light_specular = gl_LightSource[i].specular.rgb; /* we mix in some diffuse so low roughness still shows up */ - float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / roughness); + float r2 = roughness * roughness; + float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / r2); bsdf += 0.5 * max(dot(N, light_position), 0.0); L += light_specular * bsdf; } diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 5472cae3ef22832adc8fd8372c4e1421dd1c3705..a770b34ecc6ae4d0cb37acd10d54919cd8db3663 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -511,7 +511,7 @@ static int startffmpeg(struct anim *anim) return -1; } - frame_rate = av_get_r_frame_rate_compat(pFormatCtx->streams[videoStream]); + frame_rate = av_get_r_frame_rate_compat(pFormatCtx, pFormatCtx->streams[videoStream]); if (pFormatCtx->streams[videoStream]->nb_frames != 0) { anim->duration = pFormatCtx->streams[videoStream]->nb_frames; } @@ -989,7 +989,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, v_st = anim->pFormatCtx->streams[anim->videoStream]; - frame_rate = av_q2d(av_get_r_frame_rate_compat(v_st)); + frame_rate = av_q2d(av_get_r_frame_rate_compat(anim->pFormatCtx, v_st)); st_time = anim->pFormatCtx->start_time; pts_time_base = av_q2d(v_st->time_base); diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 009258079ee7aa3a9f0ff57b580a43eb21e00a0f..eaf4dfd84b4ca58cc6ff8df9e5ece26e0f0b9942 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -909,7 +909,7 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, stream_size = avio_size(context->iFormatCtx->pb); - context->frame_rate = av_q2d(av_get_r_frame_rate_compat(context->iStream)); + context->frame_rate = av_q2d(av_get_r_frame_rate_compat(context->iFormatCtx, context->iStream)); context->pts_time_base = av_q2d(context->iStream->time_base); while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) { diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 4cb1c13a44a98b1c3319f359337f916d65d39250..4e85d70d3829a56dac489ccd6d3a73725c4bd49d 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1621,14 +1621,13 @@ static bool exr_has_alpha(MultiPartInputFile& file) static bool imb_exr_is_multilayer_file(MultiPartInputFile& file) { - const StringAttribute *comments = file.header(0).findTypedAttribute<StringAttribute>("BlenderMultiChannel"); const ChannelList& channels = file.header(0).channels(); std::set <std::string> layerNames; /* will not include empty layer names */ channels.layers(layerNames); - if (comments || layerNames.size() > 1) + if (layerNames.size() > 1) return true; if (layerNames.size()) { @@ -1667,7 +1666,7 @@ static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views, } else { *r_singlelayer = false; - *r_multilayer = true; + *r_multilayer = (layerNames.size() > 1); *r_multiview = false; return; } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 1cc5cbf8c423f5fdca76bdfb0a31f5fca29f6838..b41e649b628bd76090dfaa6e3d45d07da6212d26 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -251,6 +251,7 @@ typedef enum eScenePassType { SCE_PASS_SUBSURFACE_DIRECT = (1 << 28), SCE_PASS_SUBSURFACE_INDIRECT = (1 << 29), SCE_PASS_SUBSURFACE_COLOR = (1 << 30), + SCE_PASS_ROUGHNESS = (1 << 31), } eScenePassType; #define RE_PASSNAME_COMBINED "Combined" diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index dec93f97c6c54f73768d2cf4bdb1408654bdd10a..2e21223d042dfca04f90ae2f821a461375925261 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -57,7 +57,7 @@ * \section dna_genfile Overview * * - please note: no builtin security to detect input of double structs - * - if you want a struct not to be in DNA file: add two hash marks above it (#<enter>#<enter>) + * - if you want a struct not to be in DNA file: add two hash marks above it `(#<enter>#<enter>)`. * * Structure DNA data is added to each blender file and to each executable, this to detect * in .blend files new variables in structs, changed array sizes, etc. It's also used for diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 6a67e036c5d3ca78b4cab635f4cc753038b98cb7..1fd17afdc6008851a80c00f79158523042bd6697 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -430,7 +430,6 @@ static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi br->id.icon_id = 0; if (br->flag & BRUSH_CUSTOM_ICON) { - BKE_previewimg_id_ensure(&br->id); BKE_icon_changed(BKE_icon_id_ensure(&br->id)); } diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index 6d93c56885e9cd12e35340a9e1962528c5c88534..94fda7097ee4c3487a83a7341d1302ddd61b5c5b 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -722,11 +722,11 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_WAVE_OPEN_BORDERS); RNA_def_property_ui_text(prop, "Open Borders", "Pass waves through mesh edges"); - /* cache */ prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "pointcache"); + RNA_def_property_struct_type(prop, "PointCache"); RNA_def_property_ui_text(prop, "Point Cache", ""); /* is cache used */ diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index e6e7069488575e099a400b13057f886f981f0dae..1d77030fe00d841de93d4a77f5659b11657ae554 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -273,7 +273,7 @@ static void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA switch (ob->type) { case OB_MESH: EDBM_mesh_load(ob); - EDBM_mesh_make(scene->toolsettings, ob, true); + EDBM_mesh_make(ob, scene->toolsettings->selectmode, true); DAG_id_tag_update(ob->data, 0); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index b3808e4dde0390ca237e625663ccf0bd96eb97a6..c9c3372000f2fe7cc439d0a0d0feca23b6f0933d 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -768,31 +768,8 @@ static const EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), Poi #else -/* ptcache.point_caches */ -static void rna_def_ptcache_point_caches(BlenderRNA *brna, PropertyRNA *cprop) +static void rna_def_pointcache_common(StructRNA *srna) { - StructRNA *srna; - PropertyRNA *prop; - - /* FunctionRNA *func; */ - /* PropertyRNA *parm; */ - - RNA_def_property_srna(cprop, "PointCaches"); - srna = RNA_def_struct(brna, "PointCaches", NULL); - RNA_def_struct_sdna(srna, "PointCache"); - RNA_def_struct_ui_text(srna, "Point Caches", "Collection of point caches"); - - prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_funcs(prop, "rna_Cache_active_point_cache_index_get", - "rna_Cache_active_point_cache_index_set", - "rna_Cache_active_point_cache_index_range"); - RNA_def_property_ui_text(prop, "Active Point Cache Index", ""); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change"); -} - -static void rna_def_pointcache(BlenderRNA *brna) -{ - StructRNA *srna; PropertyRNA *prop; static const EnumPropertyItem point_cache_compress_items[] = { @@ -802,16 +779,12 @@ static void rna_def_pointcache(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - srna = RNA_def_struct(brna, "PointCache", NULL); - RNA_def_struct_ui_text(srna, "Point Cache", "Point cache for physics simulations"); - RNA_def_struct_ui_icon(srna, ICON_PHYSICS); - prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "startframe"); RNA_def_property_range(prop, -MAXFRAME, MAXFRAME); RNA_def_property_ui_range(prop, 1, MAXFRAME, 1, 1); RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts"); - + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "endframe"); RNA_def_property_range(prop, 1, MAXFRAME); @@ -892,13 +865,59 @@ static void rna_def_pointcache(BlenderRNA *brna) "Use this file's path for the disk cache when library linked into another file " "(for local bakes per scene file, disable this option)"); RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); +} + +static void rna_def_ptcache_point_caches(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* FunctionRNA *func; */ + /* PropertyRNA *parm; */ + + RNA_def_property_srna(cprop, "PointCaches"); + srna = RNA_def_struct(brna, "PointCaches", NULL); + RNA_def_struct_sdna(srna, "PointCache"); + RNA_def_struct_ui_text(srna, "Point Caches", "Collection of point caches"); + + prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, "rna_Cache_active_point_cache_index_get", + "rna_Cache_active_point_cache_index_set", + "rna_Cache_active_point_cache_index_range"); + RNA_def_property_ui_text(prop, "Active Point Cache Index", ""); + RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change"); + + /* And define another RNA type for those collection items. */ + srna = RNA_def_struct(brna, "PointCacheItem", NULL); + RNA_def_struct_sdna(srna, "PointCache"); + RNA_def_struct_ui_text(srna, "Point Cache", "point cache for physics simulations"); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); + + rna_def_pointcache_common(srna); +} + +static void rna_def_pointcache_active(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "PointCache", NULL); + RNA_def_struct_ui_text(srna, "Active Point Cache", "Active point cache for physics simulations"); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); + + rna_def_pointcache_common(srna); + /* This first-level RNA pointer also has list of all caches from owning ID. + * Those caches items have exact same content as 'active' one, except for that collection, + * to prevent ugly recursive layout pattern. + * Note: This shall probably be redone from scratch in a proper way at some poitn, but for now that will do, + * and shall not break anything in the API. */ prop = RNA_def_property(srna, "point_caches", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, "rna_Cache_list_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", NULL, NULL, NULL, NULL); - RNA_def_property_struct_type(prop, "PointCache"); - RNA_def_property_ui_text(prop, "Point Cache List", "Point cache list"); + RNA_def_property_struct_type(prop, "PointCacheItem"); + RNA_def_property_ui_text(prop, "Point Cache List", ""); rna_def_ptcache_point_caches(brna, prop); } @@ -1878,7 +1897,7 @@ static void rna_def_softbody(BlenderRNA *brna) void RNA_def_object_force(BlenderRNA *brna) { - rna_def_pointcache(brna); + rna_def_pointcache_active(brna); rna_def_collision(brna); rna_def_effector_weight(brna); rna_def_field(brna); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index d3b3ed51981c929b8006303b91f3f8c91f03ff76..98ae6eb048083087ee61f3b9e555c502e054a7a2 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -89,6 +89,7 @@ const EnumPropertyItem rna_enum_bake_pass_type_items[] = { {SCE_PASS_SHADOW, "SHADOW", 0, "Shadow", ""}, {SCE_PASS_NORMAL, "NORMAL", 0, "Normal", ""}, {SCE_PASS_UV, "UV", 0, "UV", ""}, + {SCE_PASS_ROUGHNESS, "ROUGHNESS", 0, "ROUGHNESS", ""}, {SCE_PASS_EMIT, "EMIT", 0, "Emit", ""}, {SCE_PASS_ENVIRONMENT, "ENVIRONMENT", 0, "Environment", ""}, {SCE_PASS_DIFFUSE_COLOR, "DIFFUSE", 0, "Diffuse", ""}, diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c index 335b7d31acf396302fccc3c977e0ab9508351d42..188200eaff9334ca45c2a191a78ac0503800a6bd 100644 --- a/source/blender/makesrna/intern/rna_rigidbody.c +++ b/source/blender/makesrna/intern/rna_rigidbody.c @@ -803,6 +803,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "pointcache"); + RNA_def_property_struct_type(prop, "PointCache"); RNA_def_property_ui_text(prop, "Point Cache", ""); /* effector weights */ diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 3043e636b318b72be47638dee2bc741f966758f7..2a63f465dc26b2d830ba48e4de1a6132df542b22 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -112,7 +112,7 @@ static void rna_Scene_uvedit_aspect(Scene *scene, Object *ob, float *aspect) if ((ob->type == OB_MESH) && (ob->mode == OB_MODE_EDIT)) { BMEditMesh *em; em = BKE_editmesh_from_object(ob); - if (EDBM_mtexpoly_check(em)) { + if (EDBM_uv_check(em)) { ED_uvedit_get_aspect(scene, ob, em->bm, aspect, aspect + 1); return; } diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 54daba706c783ac5957771642cad923f570c792c..3bfe1fbcb83c3596f29e227f1f10f165f04356f0 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -622,6 +622,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "point_cache[0]"); + RNA_def_property_struct_type(prop, "PointCache"); RNA_def_property_ui_text(prop, "Point Cache", ""); prop = RNA_def_property(srna, "point_cache_compress_type", PROP_ENUM, PROP_NONE); diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 5a13f92f237b134765f89d4a9604a57e40d9fc0e..dda0c413f57d8c5c63e02aca765ef5631db5131b 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1304,9 +1304,9 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f else if (split_face->len > 4) { /* Maintain a dynamic vert array containing the split_face's * vertices, avoids frequent allocs in collapse_face_corners() */ - if (BLI_array_count(vert_buf) < split_face->len) { + if (BLI_array_len(vert_buf) < split_face->len) { BLI_array_grow_items(vert_buf, (split_face->len - - BLI_array_count(vert_buf))); + BLI_array_len(vert_buf))); } /* Get split face's verts */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c index 01ca0bd6512bb9a1ae55164572cec4745d75f6b7..6410441797a60b34badd82b7797c8d0d8fb4887b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c @@ -31,7 +31,7 @@ static bNodeSocketTemplate sh_node_bsdf_anisotropic_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_FLOAT, 1, N_("Anisotropy"), 0.5f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Rotation"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c index 7e1bc971c7353919641d6aec7f0a275b93e37cea..c13fd89d6e5096f5fc00448ba0062c5dbc4e7805 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c @@ -31,7 +31,7 @@ static bNodeSocketTemplate sh_node_bsdf_glossy_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index c5ff2592746daa41f118d3ec791f6e66a679b860..1e2ce3727272f68561781e45d3567466982d6aba 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -360,6 +360,8 @@ static PyGetSetDef bpy_app_getsets[] = { {(char *)"debug_depsgraph_build", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_BUILD}, {(char *)"debug_depsgraph_eval", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_EVAL}, {(char *)"debug_depsgraph_tag", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TAG}, + {(char *)"debug_depsgraph_time", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TIME}, + {(char *)"debug_depsgraph_pretty", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_PRETTY}, {(char *)"debug_simdata", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA}, {(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM}, diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 924e46a8c000410bbc5a377cc0906b3924f83c1c..cc6a536789569d1aabadeedb8a87561ad040c9f8 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -1710,10 +1710,18 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) /* TODO, different sized matrix */ if (self->num_col == 4 && self->num_row == 4) { +#ifdef MATH_STANDALONE + blend_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac); +#else interp_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac); +#endif } else if (self->num_col == 3 && self->num_row == 3) { +#ifdef MATH_STANDALONE + blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac); +#else interp_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac); +#endif } else { PyErr_SetString(PyExc_ValueError, diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index fa0d271f7d327c304f7aedd616c18a6e5fa9f540..d935949fd8c40f3802d630b394115494f0e7c87e 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -742,7 +742,7 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec float lambda; PyObject *ret; int size = 2; - + if (!PyArg_ParseTuple( args, "OOO:intersect_point_line", &py_pt, &py_line_a, &py_line_b)) @@ -760,7 +760,7 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec /* do the calculation */ lambda = closest_to_line_v3(pt_out, pt, line_a, line_b); - + ret = PyTuple_New(2); PyTuple_SET_ITEMS(ret, Vector_CreatePyObject(pt_out, size, NULL), @@ -882,7 +882,7 @@ static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyOb PyObject *py_pt, *py_quad[4]; float pt[2], quad[4][2]; int i; - + if (!PyArg_ParseTuple( args, "OOOOO:intersect_point_quad_2d", &py_pt, UNPACK4_EX(&, py_quad, ))) @@ -954,12 +954,12 @@ PyDoc_STRVAR(M_Geometry_barycentric_transform_doc, " :type tri_a2: :class:`mathutils.Vector`\n" " :arg tri_a3: source triangle vertex.\n" " :type tri_a3: :class:`mathutils.Vector`\n" -" :arg tri_a1: target triangle vertex.\n" -" :type tri_a1: :class:`mathutils.Vector`\n" -" :arg tri_a2: target triangle vertex.\n" -" :type tri_a2: :class:`mathutils.Vector`\n" -" :arg tri_a3: target triangle vertex.\n" -" :type tri_a3: :class:`mathutils.Vector`\n" +" :arg tri_b1: target triangle vertex.\n" +" :type tri_b1: :class:`mathutils.Vector`\n" +" :arg tri_b2: target triangle vertex.\n" +" :type tri_b2: :class:`mathutils.Vector`\n" +" :arg tri_b3: target triangle vertex.\n" +" :type tri_b3: :class:`mathutils.Vector`\n" " :return: The transformed point\n" " :rtype: :class:`mathutils.Vector`'s\n" ); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index bb056675887fd5ec5db0ea8cdb8d3abeedf9d1de..de71b8d10236f17e3c685ccc2dd9b9e0b43343f0 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -236,6 +236,8 @@ void RE_render_result_rect_from_ibuf( struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name); float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname); +bool RE_HasSingleLayer(struct Render *re); + /* add passes for grease pencil */ struct RenderPass *RE_create_gp_pass(struct RenderResult *rr, const char *layername, const char *viewname); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7cab5f43acac3ff983c0fa53f592770add700e42..e17a503cd4ec4b1324a59779b62ccb9cfff86558 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -257,6 +257,11 @@ RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name) } } +bool RE_HasSingleLayer(Render *re) +{ + return (re->r.scemode & R_SINGLE_LAYER); +} + RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty) { return render_result_new_from_exr(exrhandle, colorspace, predivide, rectx, recty); @@ -264,12 +269,19 @@ RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool RenderLayer *render_get_active_layer(Render *re, RenderResult *rr) { - RenderLayer *rl = BLI_findlink(&rr->layers, re->r.actlay); - - if (rl) - return rl; - else - return rr->layers.first; + SceneRenderLayer *srl = BLI_findlink(&re->r.layers, re->r.actlay); + + if (srl) { + RenderLayer *rl = BLI_findstring(&rr->layers, + srl->name, + offsetof(RenderLayer, name)); + + if (rl) { + return rl; + } + } + + return rr->layers.first; } static int render_scene_needs_vector(Render *re) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 8079cd0c2a9ff8a6157cf6a2b38c8eecb2276480..2a50de62ddadfabbfc4d335ffddf36973e1e89e3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3885,6 +3885,7 @@ static const EnumPropertyItem *rna_id_itemf( for (; id; id = id->next) { if ((filter_ids != NULL) && filter_ids(user_data, id) == false) { + i++; continue; } if (local == false || !ID_IS_LINKED(id)) { diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index bf3d28e39e0e1db27f9e5dd595761300cb9642ae..cbf06e8c6e9dec9e4548406bfe7308b1391691e6 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -448,12 +448,7 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm ghostwin = GHOST_CreateWindow(g_system, title, win->posx, posy, win->sizex, win->sizey, -#ifdef __APPLE__ - /* we agreed to not set any fullscreen or iconized state on startup */ - GHOST_kWindowStateNormal, -#else (GHOST_TWindowState)win->windowstate, -#endif GHOST_kDrawingContextTypeOpenGL, glSettings); @@ -510,7 +505,7 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm } /** - * Initialize #wmWindows without ghostwin, open these and clear. + * Initialize #wmWindow without ghostwin, open these and clear. * * window size is read from window, if 0 it uses prefsize * called in #WM_check, also inits stuff after file read. diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 880c866085d571dfb53cde08f32be83cf52039a4..9486546b92338ea0b746e72ccde5e0c5c5bf327a 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -224,10 +224,10 @@ bool BPY_string_is_keyword(const char *str) { return false; } /*new render funcs */ void EDBM_selectmode_set(struct BMEditMesh *em) RET_NONE void EDBM_mesh_load(struct Object *ob) RET_NONE -void EDBM_mesh_make(struct ToolSettings *ts, struct Object *ob, const bool use_key_index) RET_NONE +void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool use_key_index) RET_NONE void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE void *g_system; -bool EDBM_mtexpoly_check(struct BMEditMesh *em) RET_ZERO +bool EDBM_uv_check(struct BMEditMesh *em) RET_ZERO float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL float RE_filter_value(int type, float x) RET_ZERO diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 45af15817404b4d2ef70d39ad0d1da9a614d88c0..25f8d732c5828ef1e62b176e534b2313d0162c11 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -505,7 +505,7 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo printf("\n"); printf("Window Options:\n"); BLI_argsPrintArgDoc(ba, "--window-border"); - BLI_argsPrintArgDoc(ba, "--window-borderless"); + BLI_argsPrintArgDoc(ba, "--window-fullscreen"); BLI_argsPrintArgDoc(ba, "--window-geometry"); BLI_argsPrintArgDoc(ba, "--start-console"); BLI_argsPrintArgDoc(ba, "--no-native-pixels"); @@ -755,10 +755,14 @@ static const char arg_handle_debug_mode_generic_set_doc_depsgraph_build[] = "\n\tEnable debug messages from dependency graph related on graph construction."; static const char arg_handle_debug_mode_generic_set_doc_depsgraph_tag[] = "\n\tEnable debug messages from dependency graph related on tagging."; +static const char arg_handle_debug_mode_generic_set_doc_depsgraph_time[] = +"\n\tEnable debug messages from dependency graph related on timing."; static const char arg_handle_debug_mode_generic_set_doc_depsgraph_eval[] = "\n\tEnable debug messages from dependency graph related on evaluation."; static const char arg_handle_debug_mode_generic_set_doc_depsgraph_no_threads[] = "\n\tSwitch dependency graph to a single threaded evaluation."; +static const char arg_handle_debug_mode_generic_set_doc_depsgraph_pretty[] = +"\n\tEnable colors for dependency graph debug messages."; static const char arg_handle_debug_mode_generic_set_doc_gpumem[] = "\n\tEnable GPU memory stats in status bar."; @@ -972,7 +976,7 @@ static int arg_handle_with_borders(int UNUSED(argc), const char **UNUSED(argv), } static const char arg_handle_without_borders_doc[] = -"\n\tForce opening without borders." +"\n\tForce opening in fullscreen mode." ; static int arg_handle_without_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data)) { @@ -1872,8 +1876,12 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) CB_EX(arg_handle_debug_mode_generic_set, depsgraph_eval), (void *)G_DEBUG_DEPSGRAPH_EVAL); BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-tag", CB_EX(arg_handle_debug_mode_generic_set, depsgraph_tag), (void *)G_DEBUG_DEPSGRAPH_TAG); + BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-time", + CB_EX(arg_handle_debug_mode_generic_set, depsgraph_time), (void *)G_DEBUG_DEPSGRAPH_TIME); BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-no-threads", CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads), (void *)G_DEBUG_DEPSGRAPH_NO_THREADS); + BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-pretty", + CB_EX(arg_handle_debug_mode_generic_set, depsgraph_pretty), (void *)G_DEBUG_DEPSGRAPH_PRETTY); BLI_argsAdd(ba, 1, NULL, "--debug-gpumem", CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM); @@ -1892,7 +1900,7 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) /* second pass: custom window stuff */ BLI_argsAdd(ba, 2, "-p", "--window-geometry", CB(arg_handle_window_geometry), NULL); BLI_argsAdd(ba, 2, "-w", "--window-border", CB(arg_handle_with_borders), NULL); - BLI_argsAdd(ba, 2, "-W", "--window-borderless", CB(arg_handle_without_borders), NULL); + BLI_argsAdd(ba, 2, "-W", "--window-fullscreen", CB(arg_handle_without_borders), NULL); BLI_argsAdd(ba, 2, "-con", "--start-console", CB(arg_handle_start_with_console), NULL); BLI_argsAdd(ba, 2, "-R", NULL, CB(arg_handle_register_extension), NULL); BLI_argsAdd(ba, 2, "-r", NULL, CB_EX(arg_handle_register_extension, silent), ba); diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 10196804656c4cae3e7434b7113aa009df2ba391..11ec97ca5f8e59831132869f0be6f1403433520c 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -228,7 +228,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV codecCtx->frame_rate_base=1000; m_baseFrameRate = (double)codecCtx->frame_rate / (double)codecCtx->frame_rate_base; #else - m_baseFrameRate = av_q2d(av_get_r_frame_rate_compat(formatCtx->streams[videoStream])); + m_baseFrameRate = av_q2d(av_get_r_frame_rate_compat(formatCtx, formatCtx->streams[videoStream])); #endif if (m_baseFrameRate <= 0.0) m_baseFrameRate = defFrameRate; diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 6419c3f36e2aa70bca608044ef33c82dce6e06ef..9b1807b796b3018d75e903bf9599dca9536f4b35 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -27,6 +27,7 @@ set(USE_EXPERIMENTAL_TESTS FALSE) set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/../lib/tests) +set(TEST_DATA_SRC_DIR ${CMAKE_SOURCE_DIR}/../lib/tests_data) set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests) # ugh, any better way to do this on testing only? @@ -546,20 +547,22 @@ if(WITH_CYCLES) add_cycles_render_test(opengl) endif() add_cycles_render_test(bake) + add_cycles_render_test(bsdf) add_cycles_render_test(denoise) add_cycles_render_test(displacement) + add_cycles_render_test(hair) add_cycles_render_test(image_data_types) add_cycles_render_test(image_mapping) add_cycles_render_test(image_texture_limit) + add_cycles_render_test(integrator) add_cycles_render_test(light) - add_cycles_render_test(mblur) + add_cycles_render_test(mesh) + add_cycles_render_test(motion_blur) + add_cycles_render_test(render_layer) add_cycles_render_test(reports) - add_cycles_render_test(render) add_cycles_render_test(shader) - add_cycles_render_test(shader_tangent) add_cycles_render_test(shadow_catcher) add_cycles_render_test(sss) - add_cycles_render_test(texture_space) add_cycles_render_test(volume) else() MESSAGE(STATUS "Disabling Cycles tests because tests folder does not exist") @@ -617,4 +620,13 @@ if(WITH_ALEMBIC) ) endif() +if(WITH_CODEC_FFMPEG) + add_python_test( + ffmpeg_tests + ${CMAKE_CURRENT_LIST_DIR}/ffmpeg_tests.py + --blender "$<TARGET_FILE:blender>" + --testdir "${TEST_DATA_SRC_DIR}/ffmpeg" + ) +endif() + add_subdirectory(collada) diff --git a/tests/python/ffmpeg_tests.py b/tests/python/ffmpeg_tests.py new file mode 100755 index 0000000000000000000000000000000000000000..9493d6f7a17777bc4a2fc02f94e65f9e777476cb --- /dev/null +++ b/tests/python/ffmpeg_tests.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> + +import argparse +import functools +import shutil +import pathlib +import subprocess +import sys +import tempfile +import unittest + +from modules.test_utils import AbstractBlenderRunnerTest + + +class AbstractFFmpegTest(AbstractBlenderRunnerTest): + @classmethod + def setUpClass(cls): + cls.blender = args.blender + cls.testdir = pathlib.Path(args.testdir) + + +class AbstractFFmpegSequencerTest(AbstractFFmpegTest): + def get_script_for_file(self, filename: pathlib.Path) -> str: + movie = self.testdir / filename + return \ + "import bpy; " \ + "bpy.context.scene.sequence_editor_create(); " \ + "strip = bpy.context.scene.sequence_editor.sequences.new_movie(" \ + "'test_movie', %r, channel=1, frame_start=1); " \ + "print(f'fps:{strip.fps}')" % movie.as_posix() + + def get_movie_file_fps(self, filename: pathlib.Path) -> float: + script = self.get_script_for_file(filename) + output = self.run_blender('', script) + for line in output.splitlines(): + if line.startswith('fps:'): + return float(line.split(':')[1]) + return 0.0 + + +class FPSDetectionTest(AbstractFFmpegSequencerTest): + def test_T51153(self): + self.assertAlmostEqual( + self.get_movie_file_fps('T51153_bad_clip_2.mts'), + 29.97, + places=2) + + def test_T53857(self): + self.assertAlmostEqual( + self.get_movie_file_fps('T53857_2018-01-22_15-30-49.mkv'), + 30.0, + places=2) + + def test_T54148(self): + self.assertAlmostEqual( + self.get_movie_file_fps('T54148_magn_0.mkv'), + 1.0, + places=2) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--blender', required=True) + parser.add_argument('--testdir', required=True) + args, remaining = parser.parse_known_args() + + unittest.main(argv=sys.argv[0:1] + remaining) diff --git a/tests/python/modules/test_utils.py b/tests/python/modules/test_utils.py index 6ca498d8cdf6f9ef2b076cc2fd2b490895cb2735..55ef882c49cf013f251debcd0d8fd6310e286bd4 100755 --- a/tests/python/modules/test_utils.py +++ b/tests/python/modules/test_utils.py @@ -75,18 +75,24 @@ class AbstractBlenderRunnerTest(unittest.TestCase): assert self.blender, "Path to Blender binary is to be set in setUpClass()" assert self.testdir, "Path to tests binary is to be set in setUpClass()" - blendfile = self.testdir / filepath + blendfile = self.testdir / filepath if filepath else "" - command = ( + command = [ self.blender, '--background', '-noaudio', '--factory-startup', '--enable-autoexec', - str(blendfile), + ] + + if blendfile: + command.append(str(blendfile)) + + command.extend([ '-E', 'CYCLES', '--python-exit-code', '47', '--python-expr', python_script, + ] ) proc = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,