Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt20
-rw-r--r--build_files/build_environment/CMakeLists.txt1
-rw-r--r--build_files/build_environment/cmake/python.cmake4
-rw-r--r--build_files/cmake/macros.cmake12
-rw-r--r--build_files/cmake/platform/platform_apple.cmake2
-rw-r--r--build_files/cmake/platform/platform_unix.cmake2
-rw-r--r--doc/python_api/sphinx_doc_gen.py10
-rw-r--r--intern/clog/clog.c38
-rw-r--r--intern/cycles/bvh/bvh_binning.cpp8
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h12
-rw-r--r--intern/cycles/util/util_logging.cpp10
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm2
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm7
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h6
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm5
-rw-r--r--intern/ghost/intern/GHOST_WindowViewCocoa.h4
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp11
-rw-r--r--intern/libmv/.clang-format36
-rw-r--r--intern/libmv/intern/autotrack.cc35
-rw-r--r--intern/libmv/intern/autotrack.h10
-rw-r--r--intern/libmv/intern/camera_intrinsics.cc436
-rw-r--r--intern/libmv/intern/camera_intrinsics.h12
-rw-r--r--intern/libmv/intern/detector.cc16
-rw-r--r--intern/libmv/intern/detector.h2
-rw-r--r--intern/libmv/intern/frame_accessor.cc101
-rw-r--r--intern/libmv/intern/frame_accessor.h19
-rw-r--r--intern/libmv/intern/homography.cc6
-rw-r--r--intern/libmv/intern/image.cc64
-rw-r--r--intern/libmv/intern/image.h30
-rw-r--r--intern/libmv/intern/logging.cc11
-rw-r--r--intern/libmv/intern/reconstruction.cc229
-rw-r--r--intern/libmv/intern/reconstruction.h46
-rw-r--r--intern/libmv/intern/stub.cc214
-rw-r--r--intern/libmv/intern/track_region.cc43
-rw-r--r--intern/libmv/intern/track_region.h8
-rw-r--r--intern/libmv/intern/tracks.cc6
-rw-r--r--intern/libmv/intern/tracksN.cc39
-rw-r--r--intern/libmv/intern/tracksN.h10
-rw-r--r--intern/libmv/intern/utildefines.h36
-rw-r--r--intern/libmv/libmv/autotrack/autotrack.cc68
-rw-r--r--intern/libmv/libmv/autotrack/autotrack.h58
-rw-r--r--intern/libmv/libmv/autotrack/frame_accessor.h9
-rw-r--r--intern/libmv/libmv/autotrack/marker.h39
-rw-r--r--intern/libmv/libmv/autotrack/model.h9
-rw-r--r--intern/libmv/libmv/autotrack/predict_tracks.cc60
-rw-r--r--intern/libmv/libmv/autotrack/predict_tracks_test.cc44
-rw-r--r--intern/libmv/libmv/autotrack/quad.h6
-rw-r--r--intern/libmv/libmv/autotrack/reconstruction.h12
-rw-r--r--intern/libmv/libmv/autotrack/region.h2
-rw-r--r--intern/libmv/libmv/autotrack/tracks.cc43
-rw-r--r--intern/libmv/libmv/autotrack/tracks.h12
-rw-r--r--intern/libmv/libmv/autotrack/tracks_test.cc2
-rw-r--r--intern/libmv/libmv/base/aligned_malloc.cc6
-rw-r--r--intern/libmv/libmv/base/aligned_malloc.h4
-rw-r--r--intern/libmv/libmv/base/id_generator.h1
-rw-r--r--intern/libmv/libmv/base/map.h2
-rw-r--r--intern/libmv/libmv/base/scoped_ptr.h38
-rw-r--r--intern/libmv/libmv/base/scoped_ptr_test.cc8
-rw-r--r--intern/libmv/libmv/base/vector_test.cc8
-rw-r--r--intern/libmv/libmv/base/vector_utils.h5
-rw-r--r--intern/libmv/libmv/image/array_nd.cc27
-rw-r--r--intern/libmv/libmv/image/array_nd.h188
-rw-r--r--intern/libmv/libmv/image/array_nd_test.cc10
-rw-r--r--intern/libmv/libmv/image/convolve.cc170
-rw-r--r--intern/libmv/libmv/image/convolve.h62
-rw-r--r--intern/libmv/libmv/image/convolve_test.cc12
-rw-r--r--intern/libmv/libmv/image/correlation.h11
-rw-r--r--intern/libmv/libmv/image/image.h93
-rw-r--r--intern/libmv/libmv/image/image_converter.h21
-rw-r--r--intern/libmv/libmv/image/image_drawing.h112
-rw-r--r--intern/libmv/libmv/image/image_test.cc6
-rw-r--r--intern/libmv/libmv/image/sample.h40
-rw-r--r--intern/libmv/libmv/image/sample_test.cc14
-rw-r--r--intern/libmv/libmv/image/tuple.h32
-rw-r--r--intern/libmv/libmv/multiview/conditioning.cc28
-rw-r--r--intern/libmv/libmv/multiview/conditioning.h24
-rw-r--r--intern/libmv/libmv/multiview/euclidean_resection.cc200
-rw-r--r--intern/libmv/libmv/multiview/euclidean_resection.h47
-rw-r--r--intern/libmv/libmv/multiview/euclidean_resection_test.cc74
-rw-r--r--intern/libmv/libmv/multiview/fundamental.cc227
-rw-r--r--intern/libmv/libmv/multiview/fundamental.h115
-rw-r--r--intern/libmv/libmv/multiview/fundamental_test.cc8
-rw-r--r--intern/libmv/libmv/multiview/homography.cc249
-rw-r--r--intern/libmv/libmv/multiview/homography.h34
-rw-r--r--intern/libmv/libmv/multiview/homography_error.h120
-rw-r--r--intern/libmv/libmv/multiview/homography_parameterization.h36
-rw-r--r--intern/libmv/libmv/multiview/homography_test.cc40
-rw-r--r--intern/libmv/libmv/multiview/nviewtriangulation.h32
-rw-r--r--intern/libmv/libmv/multiview/nviewtriangulation_test.cc4
-rw-r--r--intern/libmv/libmv/multiview/panography.cc47
-rw-r--r--intern/libmv/libmv/multiview/panography.h12
-rw-r--r--intern/libmv/libmv/multiview/panography_kernel.cc4
-rw-r--r--intern/libmv/libmv/multiview/panography_kernel.h18
-rw-r--r--intern/libmv/libmv/multiview/panography_test.cc26
-rw-r--r--intern/libmv/libmv/multiview/projection.cc58
-rw-r--r--intern/libmv/libmv/multiview/projection.h124
-rw-r--r--intern/libmv/libmv/multiview/projection_test.cc18
-rw-r--r--intern/libmv/libmv/multiview/resection.h18
-rw-r--r--intern/libmv/libmv/multiview/resection_test.cc8
-rw-r--r--intern/libmv/libmv/multiview/test_data_sets.cc33
-rw-r--r--intern/libmv/libmv/multiview/test_data_sets.h42
-rw-r--r--intern/libmv/libmv/multiview/triangulation.cc18
-rw-r--r--intern/libmv/libmv/multiview/triangulation.h16
-rw-r--r--intern/libmv/libmv/multiview/triangulation_test.cc2
-rw-r--r--intern/libmv/libmv/multiview/two_view_kernel.h31
-rw-r--r--intern/libmv/libmv/numeric/dogleg.h119
-rw-r--r--intern/libmv/libmv/numeric/dogleg_test.cc31
-rw-r--r--intern/libmv/libmv/numeric/function_derivative.h17
-rw-r--r--intern/libmv/libmv/numeric/function_derivative_test.cc18
-rw-r--r--intern/libmv/libmv/numeric/levenberg_marquardt.h70
-rw-r--r--intern/libmv/libmv/numeric/levenberg_marquardt_test.cc10
-rw-r--r--intern/libmv/libmv/numeric/numeric.cc36
-rw-r--r--intern/libmv/libmv/numeric/numeric.h393
-rw-r--r--intern/libmv/libmv/numeric/numeric_test.cc92
-rw-r--r--intern/libmv/libmv/numeric/poly.h29
-rw-r--r--intern/libmv/libmv/numeric/poly_test.cc26
-rw-r--r--intern/libmv/libmv/simple_pipeline/bundle.cc464
-rw-r--r--intern/libmv/libmv/simple_pipeline/bundle.h35
-rw-r--r--intern/libmv/libmv/simple_pipeline/callbacks.h2
-rw-r--r--intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc279
-rw-r--r--intern/libmv/libmv/simple_pipeline/camera_intrinsics.h104
-rw-r--r--intern/libmv/libmv/simple_pipeline/camera_intrinsics_impl.h143
-rw-r--r--intern/libmv/libmv/simple_pipeline/camera_intrinsics_test.cc129
-rw-r--r--intern/libmv/libmv/simple_pipeline/detect.cc172
-rw-r--r--intern/libmv/libmv/simple_pipeline/detect.h17
-rw-r--r--intern/libmv/libmv/simple_pipeline/detect_test.cc19
-rw-r--r--intern/libmv/libmv/simple_pipeline/distortion_models.cc193
-rw-r--r--intern/libmv/libmv/simple_pipeline/distortion_models.h129
-rw-r--r--intern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc42
-rw-r--r--intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h29
-rw-r--r--intern/libmv/libmv/simple_pipeline/intersect.cc82
-rw-r--r--intern/libmv/libmv/simple_pipeline/intersect.h16
-rw-r--r--intern/libmv/libmv/simple_pipeline/intersect_test.cc18
-rw-r--r--intern/libmv/libmv/simple_pipeline/keyframe_selection.cc107
-rw-r--r--intern/libmv/libmv/simple_pipeline/keyframe_selection.h9
-rw-r--r--intern/libmv/libmv/simple_pipeline/keyframe_selection_test.cc478
-rw-r--r--intern/libmv/libmv/simple_pipeline/modal_solver.cc59
-rw-r--r--intern/libmv/libmv/simple_pipeline/modal_solver.h10
-rw-r--r--intern/libmv/libmv/simple_pipeline/modal_solver_test.cc31
-rw-r--r--intern/libmv/libmv/simple_pipeline/packed_intrinsics.h18
-rw-r--r--intern/libmv/libmv/simple_pipeline/pipeline.cc192
-rw-r--r--intern/libmv/libmv/simple_pipeline/pipeline.h31
-rw-r--r--intern/libmv/libmv/simple_pipeline/reconstruction.cc67
-rw-r--r--intern/libmv/libmv/simple_pipeline/reconstruction.h41
-rw-r--r--intern/libmv/libmv/simple_pipeline/reconstruction_scale.cc6
-rw-r--r--intern/libmv/libmv/simple_pipeline/reconstruction_scale.h2
-rw-r--r--intern/libmv/libmv/simple_pipeline/resect.cc80
-rw-r--r--intern/libmv/libmv/simple_pipeline/resect.h11
-rw-r--r--intern/libmv/libmv/simple_pipeline/resect_test.cc4
-rw-r--r--intern/libmv/libmv/simple_pipeline/tracks.cc30
-rw-r--r--intern/libmv/libmv/simple_pipeline/tracks.h16
-rw-r--r--intern/libmv/libmv/threading/threading.h2
-rw-r--r--intern/libmv/libmv/tracking/brute_region_tracker.cc195
-rw-r--r--intern/libmv/libmv/tracking/brute_region_tracker.h14
-rw-r--r--intern/libmv/libmv/tracking/hybrid_region_tracker.cc12
-rw-r--r--intern/libmv/libmv/tracking/hybrid_region_tracker.h19
-rw-r--r--intern/libmv/libmv/tracking/kalman_filter.h68
-rw-r--r--intern/libmv/libmv/tracking/klt_region_tracker.cc63
-rw-r--r--intern/libmv/libmv/tracking/klt_region_tracker.h10
-rw-r--r--intern/libmv/libmv/tracking/pyramid_region_tracker.cc19
-rw-r--r--intern/libmv/libmv/tracking/pyramid_region_tracker.h15
-rw-r--r--intern/libmv/libmv/tracking/pyramid_region_tracker_test.cc10
-rw-r--r--intern/libmv/libmv/tracking/region_tracker.h10
-rw-r--r--intern/libmv/libmv/tracking/retrack_region_tracker.cc10
-rw-r--r--intern/libmv/libmv/tracking/retrack_region_tracker.h15
-rw-r--r--intern/libmv/libmv/tracking/track_region.cc620
-rw-r--r--intern/libmv/libmv/tracking/track_region.h34
-rw-r--r--intern/libmv/libmv/tracking/trklt_region_tracker.cc63
-rw-r--r--intern/libmv/libmv/tracking/trklt_region_tracker.h10
-rw-r--r--release/scripts/modules/bl_i18n_utils/bl_extract_messages.py2
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils.py3
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/utils_rtl.py3
-rw-r--r--release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py1
-rw-r--r--release/scripts/modules/bl_previews_utils/bl_previews_render.py3
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py4
-rw-r--r--release/scripts/modules/bpy_types.py8
-rw-r--r--release/scripts/modules/console/complete_calltip.py16
-rw-r--r--release/scripts/modules/console_python.py13
-rw-r--r--release/scripts/modules/rna_info.py4
-rw-r--r--release/scripts/presets/framerate/120.py3
-rw-r--r--release/scripts/presets/framerate/240.py3
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py49
-rw-r--r--release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py1
-rw-r--r--release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py1
-rw-r--r--release/scripts/startup/bl_operators/console.py1
-rw-r--r--release/scripts/startup/bl_operators/geometry_nodes.py4
-rw-r--r--release/scripts/startup/bl_operators/object_align.py1
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py1
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_follow_active.py1
-rw-r--r--release/scripts/startup/bl_operators/view3d.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_data_gpencil.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_data_hair.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_data_pointcloud.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_shaderfx.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_volume.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_output.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_view_layer.py6
-rw-r--r--release/scripts/startup/bl_ui/space_image.py2
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py7
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py10
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py2
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py19
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py4
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py12
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py13
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py9
-rw-r--r--source/blender/blenkernel/BKE_animsys.h12
-rw-r--r--source/blender/blenkernel/BKE_armature.h8
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_colortools.h1
-rw-r--r--source/blender/blenkernel/BKE_cryptomatte.h14
-rw-r--r--source/blender/blenkernel/BKE_cryptomatte.hh19
-rw-r--r--source/blender/blenkernel/BKE_main.h16
-rw-r--r--source/blender/blenkernel/BKE_mesh_mirror.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h16
-rw-r--r--source/blender/blenkernel/BKE_node_ui_storage.hh3
-rw-r--r--source/blender/blenkernel/BKE_paint.h12
-rw-r--r--source/blender/blenkernel/BKE_volume_to_mesh.hh1
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/action.c2
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c129
-rw-r--r--source/blender/blenkernel/intern/armature_pose.cc133
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc68
-rw-r--r--source/blender/blenkernel/intern/blendfile.c2
-rw-r--r--source/blender/blenkernel/intern/bpath.c2
-rw-r--r--source/blender/blenkernel/intern/colortools.c6
-rw-r--r--source/blender/blenkernel/intern/cryptomatte.cc219
-rw-r--r--source/blender/blenkernel/intern/cryptomatte_test.cc113
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc3
-rw-r--r--source/blender/blenkernel/intern/idtype.c2
-rw-r--r--source/blender/blenkernel/intern/lib_id.c6
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c2
-rw-r--r--source/blender/blenkernel/intern/lib_query.c20
-rw-r--r--source/blender/blenkernel/intern/main.c23
-rw-r--r--source/blender/blenkernel/intern/main_idmap.c10
-rw-r--r--source/blender/blenkernel/intern/mesh_boolean_convert.cc74
-rw-r--r--source/blender/blenkernel/intern/node.cc25
-rw-r--r--source/blender/blenkernel/intern/node_ui_storage.cc32
-rw-r--r--source/blender/blenkernel/intern/outliner_treehash.c4
-rw-r--r--source/blender/blenkernel/intern/paint.c13
-rw-r--r--source/blender/blenkernel/intern/screen.c1
-rw-r--r--source/blender/blenkernel/intern/studiolight.c2
-rw-r--r--source/blender/blenlib/BLI_multi_value_map.hh16
-rw-r--r--source/blender/blenlib/intern/storage.c2
-rw-r--r--source/blender/blenlib/intern/string_search.cc17
-rw-r--r--source/blender/blenlib/intern/string_utils.c9
-rw-r--r--source/blender/blenlib/tests/BLI_multi_value_map_test.cc21
-rw-r--r--source/blender/blenloader/intern/blend_validate.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c22
-rw-r--r--source/blender/blenloader/intern/versioning_270.c2
-rw-r--r--source/blender/blenloader/intern/versioning_280.c2
-rw-r--r--source/blender/blenloader/intern/versioning_290.c55
-rw-r--r--source/blender/blenloader/intern/writefile.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c2
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c4
-rw-r--r--source/blender/compositor/COM_compositor.h6
-rw-r--r--source/blender/compositor/intern/COM_CPUDevice.cpp4
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp31
-rw-r--r--source/blender/compositor/intern/COM_Converter.h79
-rw-r--r--source/blender/compositor/intern/COM_Device.h2
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.cpp229
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.h55
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cpp48
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.h27
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp11
-rw-r--r--source/blender/compositor/intern/COM_MetaData.cpp37
-rw-r--r--source/blender/compositor/intern/COM_MetaData.h17
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.cpp6
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.h26
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.cpp8
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h8
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.cpp65
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.h8
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cpp10
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.h8
-rw-r--r--source/blender/compositor/intern/COM_WorkPackage.cpp6
-rw-r--r--source/blender/compositor/intern/COM_WorkPackage.h30
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp18
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.h5
-rw-r--r--source/blender/compositor/nodes/COM_SwitchViewNode.cpp2
-rw-r--r--source/blender/compositor/operations/COM_BokehBlurOperation.cpp22
-rw-r--r--source/blender/compositor/operations/COM_BokehBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_BoxMaskOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ChannelMatteOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_ChannelMatteOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ColorSpillOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp8
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp8
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.cpp8
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.cpp96
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_DirectionalBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_EllipseMaskOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_GlareThresholdOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_KeyingBlurOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_KeyingDespillOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_KeyingOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.cpp34
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.h19
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cpp1
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp63
-rw-r--r--source/blender/compositor/operations/COM_RotateOperation.cpp8
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_TonemapOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp22
-rw-r--r--source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_ZCombineOperation.cpp4
-rw-r--r--source/blender/datatoc/datatoc_icon.c108
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h8
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc4
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc12
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc14
-rw-r--r--source/blender/draw/engines/eevee/eevee_cryptomatte.c51
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c7
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c11
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c12
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl54
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl5
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl17
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl18
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl8
-rw-r--r--source/blender/draw/intern/draw_cache.c9
-rw-r--r--source/blender/draw/intern/draw_manager.h4
-rw-r--r--source/blender/draw/intern/draw_manager_profiling.c1
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c4
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c5
-rw-r--r--source/blender/editors/armature/armature_relations.c13
-rw-r--r--source/blender/editors/armature/pose_edit.c4
-rw-r--r--source/blender/editors/armature/pose_lib.c4
-rw-r--r--source/blender/editors/curve/editcurve.c4
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_edit_curve.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c43
-rw-r--r--source/blender/editors/gpencil/gpencil_mesh.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c33
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c21
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c13
-rw-r--r--source/blender/editors/gpencil/gpencil_uv.c1
-rw-r--r--source/blender/editors/include/ED_anim_api.h1
-rw-r--r--source/blender/editors/include/ED_fileselect.h7
-rw-r--r--source/blender/editors/include/ED_object.h4
-rw-r--r--source/blender/editors/include/ED_screen.h3
-rw-r--r--source/blender/editors/include/ED_space_api.h5
-rw-r--r--source/blender/editors/include/ED_util.h8
-rw-r--r--source/blender/editors/include/UI_interface.h7
-rw-r--r--source/blender/editors/interface/interface.c11
-rw-r--r--source/blender/editors/interface/interface_draw.c4
-rw-r--r--source/blender/editors/interface/interface_handlers.c24
-rw-r--r--source/blender/editors/interface/interface_intern.h21
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c14
-rw-r--r--source/blender/editors/interface/interface_region_search.c17
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.c3
-rw-r--r--source/blender/editors/interface/interface_template_search_operator.c3
-rw-r--r--source/blender/editors/interface/interface_templates.c10
-rw-r--r--source/blender/editors/interface/interface_utils.c5
-rw-r--r--source/blender/editors/interface/interface_widgets.c2
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c1
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c1
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c2
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c14
-rw-r--r--source/blender/editors/object/object_bake.c2
-rw-r--r--source/blender/editors/object/object_bake_api.c2
-rw-r--r--source/blender/editors/object/object_edit.c4
-rw-r--r--source/blender/editors/object/object_relations.c8
-rw-r--r--source/blender/editors/render/render_internal.c4
-rw-r--r--source/blender/editors/render/render_shading.c2
-rw-r--r--source/blender/editors/screen/area.c291
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt2
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c10
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c3
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c20
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_boundary.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_expand.c2291
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_geodesic.c360
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h185
-rw-r--r--source/blender/editors/space_action/action_data.c4
-rw-r--r--source/blender/editors/space_api/spacetypes.c5
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c251
-rw-r--r--source/blender/editors/space_clip/clip_draw.c1
-rw-r--r--source/blender/editors/space_clip/tracking_ops_solve.c2
-rw-r--r--source/blender/editors/space_clip/tracking_ops_track.c2
-rw-r--r--source/blender/editors/space_file/file_intern.h15
-rw-r--r--source/blender/editors/space_file/filelist.c61
-rw-r--r--source/blender/editors/space_file/filelist.h2
-rw-r--r--source/blender/editors/space_file/filesel.c60
-rw-r--r--source/blender/editors/space_file/space_file.c51
-rw-r--r--source/blender/editors/space_image/image_draw.c1
-rw-r--r--source/blender/editors/space_image/image_ops.c4
-rw-r--r--source/blender/editors/space_image/space_image.c1
-rw-r--r--source/blender/editors/space_nla/nla_channels.c4
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_node/drawnode.c10
-rw-r--r--source/blender/editors/space_node/node_draw.cc9
-rw-r--r--source/blender/editors/space_node/node_edit.c5
-rw-r--r--source/blender/editors/space_node/node_geometry_attribute_search.cc151
-rw-r--r--source/blender/editors/space_node/node_intern.h9
-rw-r--r--source/blender/editors/space_node/node_relationships.c22
-rw-r--r--source/blender/editors/space_node/node_select.c3
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c14
-rw-r--r--source/blender/editors/space_outliner/outliner_context.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c8
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c35
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c13
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c16
-rw-r--r--source/blender/editors/space_outliner/outliner_sync.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c12
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c80
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c8
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_libraries.cc6
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_orphaned.cc5
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_scenes.cc3
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_view_layer.cc14
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element.cc12
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element.h1
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element.hh9
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element_anim_data.cc3
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element_gpencil_layer.cc40
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element_gpencil_layer.hh34
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element_id.cc100
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element_id.hh48
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c579
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c209
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c25
-rw-r--r--source/blender/editors/transform/transform_constraints.c7
-rw-r--r--source/blender/editors/transform/transform_convert_gpencil.c11
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c52
-rw-r--r--source/blender/editors/undo/memfile_undo.c2
-rw-r--r--source/blender/editors/util/CMakeLists.txt2
-rw-r--r--source/blender/editors/util/ed_draw.c385
-rw-r--r--source/blender/editors/util/ed_util.c38
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c5
-rw-r--r--source/blender/gpu/intern/gpu_immediate.cc2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl7
-rw-r--r--source/blender/imbuf/intern/IMB_colormanagement_intern.h1
-rw-r--r--source/blender/imbuf/intern/anim_movie.c2
-rw-r--r--source/blender/makesdna/DNA_ID.h50
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h10
-rw-r--r--source/blender/makesdna/DNA_space_types.h5
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h27
-rw-r--r--source/blender/makesrna/RNA_define.h2
-rw-r--r--source/blender/makesrna/intern/makesrna.c6
-rw-r--r--source/blender/makesrna/intern/rna_ID.c3
-rw-r--r--source/blender/makesrna/intern/rna_access.c20
-rw-r--r--source/blender/makesrna/intern/rna_animviz.c4
-rw-r--r--source/blender/makesrna/intern/rna_armature.c9
-rw-r--r--source/blender/makesrna/intern/rna_brush.c3
-rw-r--r--source/blender/makesrna/intern/rna_color.c5
-rw-r--r--source/blender/makesrna/intern/rna_define.c12
-rw-r--r--source/blender/makesrna/intern/rna_fluid.c2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c6
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_lattice.c2
-rw-r--r--source/blender/makesrna/intern/rna_light.c2
-rw-r--r--source/blender/makesrna/intern/rna_material.c2
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c3
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c2
-rw-r--r--source/blender/makesrna/intern/rna_object.c5
-rw-r--r--source/blender/makesrna/intern/rna_particle.c16
-rw-r--r--source/blender/makesrna/intern/rna_pose.c23
-rw-r--r--source/blender/makesrna/intern/rna_pose_api.c52
-rw-r--r--source/blender/makesrna/intern/rna_rna.c4
-rw-r--r--source/blender/makesrna/intern/rna_scene.c6
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c198
-rw-r--r--source/blender/makesrna/intern/rna_space.c46
-rw-r--r--source/blender/makesrna/intern/rna_space_api.c21
-rw-r--r--source/blender/makesrna/intern/rna_ui.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c30
-rw-r--r--source/blender/makesrna/intern/rna_volume.c2
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c8
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc268
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c7
-rw-r--r--source/blender/nodes/CMakeLists.txt4
-rw-r--r--source/blender/nodes/NOD_derived_node_tree.hh556
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh6
-rw-r--r--source/blender/nodes/NOD_node_tree_multi_function.hh107
-rw-r--r--source/blender/nodes/NOD_node_tree_ref.hh134
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc (renamed from source/blender/nodes/composite/nodes/node_composite_cryptomatte.c)59
-rw-r--r--source/blender/nodes/function/nodes/node_fn_group_instance_id.cc7
-rw-r--r--source/blender/nodes/function/nodes/node_fn_random_float.cc11
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc5
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_instance.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_scale.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc2
-rw-r--r--source/blender/nodes/intern/derived_node_tree.cc639
-rw-r--r--source/blender/nodes/intern/node_exec.c14
-rw-r--r--source/blender/nodes/intern/node_exec.h2
-rw-r--r--source/blender/nodes/intern/node_geometry_exec.cc17
-rw-r--r--source/blender/nodes/intern/node_tree_multi_function.cc263
-rw-r--r--source/blender/nodes/intern/node_tree_ref.cc37
-rw-r--r--source/blender/nodes/shader/node_shader_util.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.cc8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_value.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc (renamed from source/blender/nodes/shader/nodes/node_shader_vector_rotate.c)36
-rw-r--r--source/blender/python/gpu/gpu_py_api.c3
-rw-r--r--source/blender/python/gpu/gpu_py_batch.c2
-rw-r--r--source/blender/python/gpu/gpu_py_buffer.c3
-rw-r--r--source/blender/python/gpu/gpu_py_offscreen.c4
-rw-r--r--source/blender/python/gpu/gpu_py_texture.c59
-rw-r--r--source/blender/python/gpu/gpu_py_texture.h2
-rw-r--r--source/blender/python/intern/bpy_app.c2
-rw-r--r--source/blender/python/intern/bpy_app_alembic.c4
-rw-r--r--source/blender/python/intern/bpy_app_ffmpeg.c4
-rw-r--r--source/blender/python/intern/bpy_app_ocio.c4
-rw-r--r--source/blender/python/intern/bpy_app_oiio.c4
-rw-r--r--source/blender/python/intern/bpy_app_opensubdiv.c4
-rw-r--r--source/blender/python/intern/bpy_app_openvdb.c4
-rw-r--r--source/blender/python/intern/bpy_app_sdl.c4
-rw-r--r--source/blender/python/intern/bpy_app_usd.c4
-rw-r--r--source/blender/python/intern/bpy_library_load.c19
-rw-r--r--source/blender/python/intern/bpy_library_write.c6
-rw-r--r--source/blender/python/intern/bpy_props.c6
-rw-r--r--source/blender/python/intern/bpy_rna.c135
-rw-r--r--source/blender/sequencer/SEQ_add.h96
-rw-r--r--source/blender/sequencer/SEQ_sequencer.h4
-rw-r--r--source/blender/sequencer/intern/render.c29
-rw-r--r--source/blender/sequencer/intern/sequencer.c52
-rw-r--r--source/blender/sequencer/intern/strip_add.c498
-rw-r--r--source/blender/sequencer/intern/strip_time.c22
-rw-r--r--source/blender/windowmanager/WM_types.h54
-rw-r--r--source/blender/windowmanager/intern/wm.c8
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c2
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c2
-rw-r--r--source/blender/windowmanager/intern/wm_event_query.c4
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c385
-rw-r--r--source/blender/windowmanager/intern/wm_files.c15
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c17
-rw-r--r--source/blender/windowmanager/intern/wm_platform_support.c10
-rw-r--r--source/blender/windowmanager/intern/wm_window.c14
-rw-r--r--source/blender/windowmanager/wm_window.h4
-rw-r--r--source/creator/creator.c12
-rw-r--r--source/creator/creator_args.c22
-rw-r--r--tests/gtests/runner/CMakeLists.txt1
-rw-r--r--tests/python/bl_blendfile_io.py6
-rw-r--r--tests/python/bl_blendfile_liblink.py9
574 files changed, 13892 insertions, 8989 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 24201ae6869..ddfce0a48d9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -901,6 +901,18 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Release")
endif()
endif()
+# Test SIMD support, before platform includes to determine if sse2neon is needed.
+if(WITH_CPU_SIMD)
+ set(COMPILER_SSE_FLAG)
+ set(COMPILER_SSE2_FLAG)
+
+ # Test Neon first since macOS Arm can compile and run x86-64 SSE binaries.
+ TEST_NEON_SUPPORT()
+ if(NOT SUPPORT_NEON_BUILD)
+ TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
+ endif()
+endif()
+
# ----------------------------------------------------------------------------
# Main Platform Checks
#
@@ -956,16 +968,11 @@ if(WITH_INTERNATIONAL)
endif()
endif()
-# See TEST_SSE_SUPPORT() and TEST_NEON_SUPPORT() for how these are defined.
+# Enable SIMD support if detected by TEST_SSE_SUPPORT() or TEST_NEON_SUPPORT().
#
# This is done globally, so that all modules can use it if available, and
# because these are used in headers used by many modules.
if(WITH_CPU_SIMD)
- set(COMPILER_SSE_FLAG)
- set(COMPILER_SSE2_FLAG)
-
- # Test Neon first since macOS Arm can compile and run x86-64 SSE binaries.
- TEST_NEON_SUPPORT()
if(SUPPORT_NEON_BUILD)
# Neon
if(SSE2NEON_FOUND)
@@ -974,7 +981,6 @@ if(WITH_CPU_SIMD)
endif()
else()
# SSE
- TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
if(SUPPORT_SSE_BUILD)
string(PREPEND PLATFORM_CFLAGS "${COMPILER_SSE_FLAG} ")
add_definitions(-D__SSE__ -D__MMX__)
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
index aa6b1cbe539..09dcc91ce08 100644
--- a/build_files/build_environment/CMakeLists.txt
+++ b/build_files/build_environment/CMakeLists.txt
@@ -31,6 +31,7 @@
#
# MAC OS X USAGE:
# Install with homebrew: brew install autoconf automake bison cmake libtool pkg-config yasm
+# Additional requirements for macOS arm64: brew install flex
# Run "make deps" from main Blender directory
#
# LINUX USAGE:
diff --git a/build_files/build_environment/cmake/python.cmake b/build_files/build_environment/cmake/python.cmake
index fa1498dda82..7e718d22805 100644
--- a/build_files/build_environment/cmake/python.cmake
+++ b/build_files/build_environment/cmake/python.cmake
@@ -81,8 +81,8 @@ else()
# Link against zlib statically (Unix). Avoid rpath issues (macOS).
set(PYTHON_PATCH ${PATCH_CMD} --verbose -p1 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_unix.diff)
set(PYTHON_CONFIGURE_EXTRA_ARGS "--with-openssl=${LIBDIR}/ssl")
- set(PYTHON_CFLAGS "-I${LIBDIR}/sqlite/include -I${LIBDIR}/bzip2/include -I${LIBDIR}/lzma/include -I${LIBDIR}/zlib/include")
- set(PYTHON_LDFLAGS "-L${LIBDIR}/ffi/lib -L${LIBDIR}/sqlite/lib -L${LIBDIR}/bzip2/lib -L${LIBDIR}/lzma/lib -L${LIBDIR}/zlib/lib")
+ set(PYTHON_CFLAGS "-I${LIBDIR}/sqlite/include -I${LIBDIR}/bzip2/include -I${LIBDIR}/lzma/include -I${LIBDIR}/zlib/include ${PLATFORM_CFLAGS}")
+ set(PYTHON_LDFLAGS "-L${LIBDIR}/ffi/lib -L${LIBDIR}/sqlite/lib -L${LIBDIR}/bzip2/lib -L${LIBDIR}/lzma/lib -L${LIBDIR}/zlib/lib ${PLATFORM_LDFLAGS}")
set(PYTHON_CONFIGURE_EXTRA_ENV
export CFLAGS=${PYTHON_CFLAGS} &&
export CPPFLAGS=${PYTHON_CFLAGS} &&
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index b8f92a10761..cad1d86b75a 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -682,11 +682,13 @@ macro(TEST_SSE_SUPPORT
endmacro()
macro(TEST_NEON_SUPPORT)
- include(CheckCXXSourceCompiles)
- check_cxx_source_compiles(
- "#include <arm_neon.h>
- int main() {return vaddvq_s32(vdupq_n_s32(1));}"
- SUPPORT_NEON_BUILD)
+ if(NOT DEFINED SUPPORT_NEON_BUILD)
+ include(CheckCXXSourceCompiles)
+ check_cxx_source_compiles(
+ "#include <arm_neon.h>
+ int main() {return vaddvq_s32(vdupq_n_s32(1));}"
+ SUPPORT_NEON_BUILD)
+ endif()
endmacro()
# Only print message if running CMake first time
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 12a7a6c504f..be9261798f4 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -324,7 +324,7 @@ if(WITH_NANOVDB)
find_package(NanoVDB)
endif()
-if(WITH_CPU_SIMD)
+if(WITH_CPU_SIMD AND SUPPORT_NEON_BUILD)
find_package(sse2neon)
endif()
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index ef73ef40ac3..47c788c7eb6 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -285,7 +285,7 @@ if(WITH_NANOVDB)
endif()
endif()
-if(WITH_CPU_SIMD)
+if(WITH_CPU_SIMD AND SUPPORT_NEON_BUILD)
find_package_wrapper(sse2neon)
endif()
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 2b659de1cf8..5c6cf24a178 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -253,6 +253,7 @@ else:
"gpu.select",
"gpu.shader",
"gpu.state",
+ "gpu.texture",
"gpu_extras",
"idprop.types",
"mathutils",
@@ -1981,10 +1982,11 @@ def write_rst_importable_modules(basepath):
"imbuf.types": "Image Buffer Types",
"gpu": "GPU Shader Module",
"gpu.types": "GPU Types",
- "gpu.matrix": "GPU Matrix",
- "gpu.select": "GPU Select",
- "gpu.shader": "GPU Shader",
- "gpu.state": "GPU State",
+ "gpu.matrix": "GPU Matrix Utilities",
+ "gpu.select": "GPU Select Utilities",
+ "gpu.shader": "GPU Shader Utilities",
+ "gpu.state": "GPU State Utilities",
+ "gpu.texture": "GPU Texture Utilities",
"bmesh": "BMesh Module",
"bmesh.ops": "BMesh Operators",
"bmesh.types": "BMesh Types",
diff --git a/intern/clog/clog.c b/intern/clog/clog.c
index 2bc3985c71f..a26ac10a61f 100644
--- a/intern/clog/clog.c
+++ b/intern/clog/clog.c
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -38,8 +38,13 @@
#endif
#if defined(_MSC_VER)
+# include <Windows.h>
+
+# include <VersionHelpers.h> /* This needs to be included after Windows.h. */
# include <io.h>
-# include <windows.h>
+# if !defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+# endif
#endif
/* For printing timestamp. */
@@ -228,6 +233,9 @@ enum eCLogColor {
#define COLOR_LEN (COLOR_RESET + 1)
static const char *clg_color_table[COLOR_LEN] = {NULL};
+#ifdef _WIN32
+static DWORD clg_previous_console_mode = 0;
+#endif
static void clg_color_table_init(bool use_color)
{
@@ -548,13 +556,22 @@ static void CLG_ctx_output_set(CLogContext *ctx, void *file_handle)
#if defined(__unix__) || defined(__APPLE__)
ctx->use_color = isatty(ctx->output);
#elif defined(WIN32)
- /* Windows Terminal supports color like the Linux terminals do while the standard console does
- * not, the way to tell the two apart is to look at the `WT_SESSION` environment variable which
- * will only be defined for Windows Terminal. */
-
- /* #getenv is used here rather than #BLI_getenv since it would be a bad level call
- * and there are no benefits for using it in this context. */
- ctx->use_color = isatty(ctx->output) && getenv("WT_SESSION");
+ /* As of Windows 10 build 18298 all the standard consoles supports color
+ * like the Linux Terminal do, but it needs to be turned on.
+ * To turn on colors we need to enable virtual terminal processing by passing the flag
+ * ENABLE_VIRTUAL_TERMINAL_PROCESSING into SetConsoleMode.
+ * If the system doesn't support virtual terminal processing it will fail silently and the flag
+ * will not be set. */
+
+ GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &clg_previous_console_mode);
+
+ ctx->use_color = 0;
+ if (IsWindows10OrGreater() && isatty(ctx->output)) {
+ DWORD mode = clg_previous_console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+ if (SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), mode)) {
+ ctx->use_color = 1;
+ }
+ }
#endif
}
@@ -638,6 +655,9 @@ static CLogContext *CLG_ctx_init(void)
static void CLG_ctx_free(CLogContext *ctx)
{
+#if defined(WIN32)
+ SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), clg_previous_console_mode);
+#endif
while (ctx->types != NULL) {
CLG_LogType *item = ctx->types;
ctx->types = item->next;
diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp
index d51143c578e..1cc38275d11 100644
--- a/intern/cycles/bvh/bvh_binning.cpp
+++ b/intern/cycles/bvh/bvh_binning.cpp
@@ -107,9 +107,9 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange &job,
/* map geometry to bins, unrolled once */
{
- ssize_t i;
+ int64_t i;
- for (i = 0; i < ssize_t(size()) - 1; i += 2) {
+ for (i = 0; i < int64_t(size()) - 1; i += 2) {
prefetch_L2(&prims[start() + i + 8]);
/* map even and odd primitive to bin */
@@ -146,7 +146,7 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange &job,
}
/* for uneven number of primitives */
- if (i < ssize_t(size())) {
+ if (i < int64_t(size())) {
/* map primitive to bin */
const BVHReference &prim0 = prims[start() + i];
BoundBox bounds0 = get_prim_bounds(prim0);
@@ -237,7 +237,7 @@ void BVHObjectBinning::split(BVHReference *prims,
BoundBox lcent_bounds = BoundBox::empty;
BoundBox rcent_bounds = BoundBox::empty;
- ssize_t l = 0, r = N - 1;
+ int64_t l = 0, r = N - 1;
while (l <= r) {
prefetch_L2(&prims[start() + l + 8]);
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index ea3b78b7cef..da74d6aafac 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -41,6 +41,18 @@ typedef unsigned long long uint64_t;
typedef unsigned short half;
typedef unsigned long long CUtexObject;
+//XXX fix compiler error on windows
+#ifdef __CUDA_ARCH__
+static __device__ float myfloor(float f) {
+ float f2 = (float)((int)f);
+ f2 += (float)(f < 0.0f);
+
+ return f2;
+}
+
+#define floor myfloor
+#endif
+
#ifdef CYCLES_CUBIN_CC
# define FLT_MIN 1.175494350822287507969e-38f
# define FLT_MAX 340282346638528859811704183484516925440.0f
diff --git a/intern/cycles/util/util_logging.cpp b/intern/cycles/util/util_logging.cpp
index e41250ab1b9..3782187d78c 100644
--- a/intern/cycles/util/util_logging.cpp
+++ b/intern/cycles/util/util_logging.cpp
@@ -46,17 +46,13 @@ void util_logging_init(const char *argv0)
#ifdef WITH_CYCLES_LOGGING
using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
- /* Make it so ERROR messages are always print into console. */
- char severity_fatal[32];
- snprintf(severity_fatal, sizeof(severity_fatal), "%d", google::GLOG_ERROR);
-
google::InitGoogleLogging(argv0);
SetCommandLineOption("logtostderr", "1");
if (!is_verbosity_set()) {
SetCommandLineOption("v", "0");
}
- SetCommandLineOption("stderrthreshold", severity_fatal);
- SetCommandLineOption("minloglevel", severity_fatal);
+ SetCommandLineOption("stderrthreshold", "0");
+ SetCommandLineOption("minloglevel", "0");
#else
(void)argv0;
#endif
@@ -70,7 +66,7 @@ void util_logging_start()
if (!is_verbosity_set()) {
SetCommandLineOption("v", "2");
}
- SetCommandLineOption("stderrthreshold", "1");
+ SetCommandLineOption("stderrthreshold", "0");
SetCommandLineOption("minloglevel", "0");
#endif
}
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index ab76b78e6df..687173ded09 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -278,7 +278,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
#ifdef GHOST_WAIT_FOR_VSYNC
{
GLint swapInt = 1;
- /* wait for vsync, to avoid tearing artifacts */
+ /* Wait for vertical-sync, to avoid tearing artifacts. */
[m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
}
#endif
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
index cd13ee1a8ae..0c851e067e8 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.h
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -296,7 +296,7 @@ class GHOST_ImeWin32 {
* Disable the IME attached to the given window, i.e. prohibits any user-input
* events from being dispatched to the IME.
* In Chrome, this function is used when:
- * * a rendeder process sets its input focus to a password input.
+ * * a renderer process sets its input focus to a password input.
* Parameters
* * window_handle [in] (HWND)
* Represents the window handle of the caller.
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index f42d4af109a..4a23b30e078 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -80,7 +80,7 @@ static GHOST_TButtonMask convertButton(int button)
}
/**
- * Converts Mac rawkey codes (same for Cocoa & Carbon)
+ * Converts Mac raw-key codes (same for Cocoa & Carbon)
* into GHOST key codes
* \param rawCode: The raw physical key code
* \param recvChar: the character ignoring modifiers (except for shift)
@@ -646,6 +646,11 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
[NSApp setDelegate:appDelegate];
}
+ // AppKit provides automatic window tabbing. Blender is a single-tabbed application without a
+ // macOS tab bar, and should explicitly opt-out of this. This is also controlled by the macOS
+ // user default #NSWindowTabbingEnabled.
+ NSWindow.allowsAutomaticWindowTabbing = NO;
+
[NSApp finishLaunching];
[pool drain];
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index a7e325bc9e1..ed5e945f69e 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -34,9 +34,9 @@
#ifdef WITH_X11_XINPUT
# include <X11/extensions/XInput.h>
-/* Disable xinput warp, currently not implemented by Xorg for multi-head display.
- * (see comment in xserver "Xi/xiwarppointer.c" -> "FIXME: panoramix stuff is missing" ~ v1.13.4)
- * If this is supported we can add back xinput for warping (fixing T48901).
+/* Disable XINPUT warp, currently not implemented by Xorg for multi-head display.
+ * (see comment in XSERVER `Xi/xiwarppointer.c` -> `FIXME: panoramix stuff is missing` ~ v1.13.4)
+ * If this is supported we can add back XINPUT for warping (fixing T48901).
* For now disable (see T50383). */
// # define USE_X11_XINPUT_WARP
#endif
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 73927317b24..add7962d924 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -336,11 +336,6 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
backing:NSBackingStoreBuffered
defer:NO];
- if (m_window == nil) {
- [pool drain];
- return;
- }
-
[m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
// Forbid to resize the window below the blender defined minimum one
diff --git a/intern/ghost/intern/GHOST_WindowViewCocoa.h b/intern/ghost/intern/GHOST_WindowViewCocoa.h
index 14c70382916..f47e02704b2 100644
--- a/intern/ghost/intern/GHOST_WindowViewCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowViewCocoa.h
@@ -253,7 +253,7 @@
- (NSAttributedString *)attributedSubstringFromRange:(NSRange)range
{
- return [NSAttributedString new]; // XXX does this leak?
+ return [[[NSAttributedString alloc] init] autorelease];
}
- (NSRange)markedRange
@@ -284,7 +284,7 @@
- (NSArray *)validAttributesForMarkedText
{
- return [NSArray array]; // XXX does this leak?
+ return [NSArray array];
}
@end
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 32672461873..eaa708f52b9 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -124,16 +124,11 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
{
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
RECT win_rect = {left, top, (long)(left + width), (long)(top + height)};
- RECT parent_rect = {0, 0, 0, 0};
// Initialize tablet variables
memset(&m_wintab, 0, sizeof(m_wintab));
m_tabletData = GHOST_TABLET_DATA_NONE;
- if (parentwindow) {
- GetWindowRect(m_parentWindowHwnd, &parent_rect);
- }
-
DWORD style = parentwindow ?
WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX :
WS_OVERLAPPEDWINDOW;
@@ -156,9 +151,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
MONITORINFOEX monitor;
monitor.cbSize = sizeof(MONITORINFOEX);
monitor.dwFlags = 0;
- GetMonitorInfo(
- MonitorFromRect(parentwindow ? &parent_rect : &win_rect, MONITOR_DEFAULTTONEAREST),
- &monitor);
+ GetMonitorInfo(MonitorFromRect(&win_rect, MONITOR_DEFAULTTONEAREST), &monitor);
/* Adjust our requested size to allow for caption and borders and constrain to monitor. */
AdjustWindowRectEx(&win_rect, WS_CAPTION, FALSE, 0);
@@ -1232,7 +1225,7 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
GHOST_TUns32 fullBitRow, fullMaskRow;
int x, y, cols;
- cols = sizeX / 8; /* Number of whole bytes per row (width of bm/mask). */
+ cols = sizeX / 8; /* Number of whole bytes per row (width of bitmap/mask). */
if (sizeX % 8)
cols++;
diff --git a/intern/libmv/.clang-format b/intern/libmv/.clang-format
index 9d159247d51..fae0530c572 100644
--- a/intern/libmv/.clang-format
+++ b/intern/libmv/.clang-format
@@ -1,2 +1,34 @@
-DisableFormat: true
-SortIncludes: false
+BasedOnStyle: Google
+
+ColumnLimit: 80
+
+Standard: Cpp11
+
+# Indent nested preprocessor.
+# #ifdef Foo
+# # include <nested>
+# #endif
+IndentPPDirectives: AfterHash
+
+# For the cases when namespace is closing with a wrong comment
+FixNamespaceComments: true
+
+AllowShortFunctionsOnASingleLine: InlineOnly
+AllowShortBlocksOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: true
+
+# No bin packing, every argument is on its own line.
+BinPackArguments: false
+BinPackParameters: false
+
+# Ensure pointer alignment.
+# ObjectType* object;
+PointerAlignment: Left
+DerivePointerAlignment: false
+
+AlignEscapedNewlines: Right
+
+IncludeBlocks: Preserve
+SortIncludes: true
diff --git a/intern/libmv/intern/autotrack.cc b/intern/libmv/intern/autotrack.cc
index 7000a422de8..b7110957b15 100644
--- a/intern/libmv/intern/autotrack.cc
+++ b/intern/libmv/intern/autotrack.cc
@@ -22,15 +22,15 @@
#include "intern/utildefines.h"
#include "libmv/autotrack/autotrack.h"
+using libmv::TrackRegionOptions;
+using libmv::TrackRegionResult;
using mv::AutoTrack;
using mv::FrameAccessor;
using mv::Marker;
-using libmv::TrackRegionOptions;
-using libmv::TrackRegionResult;
-libmv_AutoTrack* libmv_autoTrackNew(libmv_FrameAccessor *frame_accessor) {
- return (libmv_AutoTrack*) LIBMV_OBJECT_NEW(AutoTrack,
- (FrameAccessor*) frame_accessor);
+libmv_AutoTrack* libmv_autoTrackNew(libmv_FrameAccessor* frame_accessor) {
+ return (libmv_AutoTrack*)LIBMV_OBJECT_NEW(AutoTrack,
+ (FrameAccessor*)frame_accessor);
}
void libmv_autoTrackDestroy(libmv_AutoTrack* libmv_autotrack) {
@@ -39,7 +39,7 @@ void libmv_autoTrackDestroy(libmv_AutoTrack* libmv_autotrack) {
void libmv_autoTrackSetOptions(libmv_AutoTrack* libmv_autotrack,
const libmv_AutoTrackOptions* options) {
- AutoTrack *autotrack = ((AutoTrack*) libmv_autotrack);
+ AutoTrack* autotrack = ((AutoTrack*)libmv_autotrack);
libmv_configureTrackRegionOptions(options->track_region,
&autotrack->options.track_region);
@@ -51,18 +51,15 @@ void libmv_autoTrackSetOptions(libmv_AutoTrack* libmv_autotrack,
int libmv_autoTrackMarker(libmv_AutoTrack* libmv_autotrack,
const libmv_TrackRegionOptions* libmv_options,
- libmv_Marker *libmv_tracked_marker,
+ libmv_Marker* libmv_tracked_marker,
libmv_TrackRegionResult* libmv_result) {
-
Marker tracked_marker;
TrackRegionOptions options;
TrackRegionResult result;
libmv_apiMarkerToMarker(*libmv_tracked_marker, &tracked_marker);
- libmv_configureTrackRegionOptions(*libmv_options,
- &options);
- bool ok = (((AutoTrack*) libmv_autotrack)->TrackMarker(&tracked_marker,
- &result,
- &options));
+ libmv_configureTrackRegionOptions(*libmv_options, &options);
+ bool ok = (((AutoTrack*)libmv_autotrack)
+ ->TrackMarker(&tracked_marker, &result, &options));
libmv_markerToApiMarker(tracked_marker, libmv_tracked_marker);
libmv_regionTrackergetResult(result, libmv_result);
return ok && result.is_usable();
@@ -72,7 +69,7 @@ void libmv_autoTrackAddMarker(libmv_AutoTrack* libmv_autotrack,
const libmv_Marker* libmv_marker) {
Marker marker;
libmv_apiMarkerToMarker(*libmv_marker, &marker);
- ((AutoTrack*) libmv_autotrack)->AddMarker(marker);
+ ((AutoTrack*)libmv_autotrack)->AddMarker(marker);
}
void libmv_autoTrackSetMarkers(libmv_AutoTrack* libmv_autotrack,
@@ -87,19 +84,17 @@ void libmv_autoTrackSetMarkers(libmv_AutoTrack* libmv_autotrack,
for (size_t i = 0; i < num_markers; ++i) {
libmv_apiMarkerToMarker(libmv_marker[i], &markers[i]);
}
- ((AutoTrack*) libmv_autotrack)->SetMarkers(&markers);
+ ((AutoTrack*)libmv_autotrack)->SetMarkers(&markers);
}
int libmv_autoTrackGetMarker(libmv_AutoTrack* libmv_autotrack,
int clip,
int frame,
int track,
- libmv_Marker *libmv_marker) {
+ libmv_Marker* libmv_marker) {
Marker marker;
- int ok = ((AutoTrack*) libmv_autotrack)->GetMarker(clip,
- frame,
- track,
- &marker);
+ int ok =
+ ((AutoTrack*)libmv_autotrack)->GetMarker(clip, frame, track, &marker);
if (ok) {
libmv_markerToApiMarker(marker, libmv_marker);
}
diff --git a/intern/libmv/intern/autotrack.h b/intern/libmv/intern/autotrack.h
index 6b49a6908e1..3887983814b 100644
--- a/intern/libmv/intern/autotrack.h
+++ b/intern/libmv/intern/autotrack.h
@@ -21,9 +21,9 @@
#define LIBMV_C_API_AUTOTRACK_H_
#include "intern/frame_accessor.h"
-#include "intern/tracksN.h"
-#include "intern/track_region.h"
#include "intern/region.h"
+#include "intern/track_region.h"
+#include "intern/tracksN.h"
#ifdef __cplusplus
extern "C" {
@@ -36,7 +36,7 @@ typedef struct libmv_AutoTrackOptions {
libmv_Region search_region;
} libmv_AutoTrackOptions;
-libmv_AutoTrack* libmv_autoTrackNew(libmv_FrameAccessor *frame_accessor);
+libmv_AutoTrack* libmv_autoTrackNew(libmv_FrameAccessor* frame_accessor);
void libmv_autoTrackDestroy(libmv_AutoTrack* libmv_autotrack);
@@ -45,7 +45,7 @@ void libmv_autoTrackSetOptions(libmv_AutoTrack* libmv_autotrack,
int libmv_autoTrackMarker(libmv_AutoTrack* libmv_autotrack,
const libmv_TrackRegionOptions* libmv_options,
- libmv_Marker *libmv_tracker_marker,
+ libmv_Marker* libmv_tracker_marker,
libmv_TrackRegionResult* libmv_result);
void libmv_autoTrackAddMarker(libmv_AutoTrack* libmv_autotrack,
@@ -59,7 +59,7 @@ int libmv_autoTrackGetMarker(libmv_AutoTrack* libmv_autotrack,
int clip,
int frame,
int track,
- libmv_Marker *libmv_marker);
+ libmv_Marker* libmv_marker);
#ifdef __cplusplus
}
diff --git a/intern/libmv/intern/camera_intrinsics.cc b/intern/libmv/intern/camera_intrinsics.cc
index 628637e12cc..243b26d9fb3 100644
--- a/intern/libmv/intern/camera_intrinsics.cc
+++ b/intern/libmv/intern/camera_intrinsics.cc
@@ -21,62 +21,56 @@
#include "intern/utildefines.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
+using libmv::BrownCameraIntrinsics;
using libmv::CameraIntrinsics;
using libmv::DivisionCameraIntrinsics;
-using libmv::PolynomialCameraIntrinsics;
using libmv::NukeCameraIntrinsics;
-using libmv::BrownCameraIntrinsics;
+using libmv::PolynomialCameraIntrinsics;
-libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
+libmv_CameraIntrinsics* libmv_cameraIntrinsicsNew(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options) {
- CameraIntrinsics *camera_intrinsics =
- libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
- return (libmv_CameraIntrinsics *) camera_intrinsics;
+ CameraIntrinsics* camera_intrinsics =
+ libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
+ return (libmv_CameraIntrinsics*)camera_intrinsics;
}
-libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
+libmv_CameraIntrinsics* libmv_cameraIntrinsicsCopy(
const libmv_CameraIntrinsics* libmv_intrinsics) {
- const CameraIntrinsics *orig_intrinsics =
- (const CameraIntrinsics *) libmv_intrinsics;
+ const CameraIntrinsics* orig_intrinsics =
+ (const CameraIntrinsics*)libmv_intrinsics;
- CameraIntrinsics *new_intrinsics = NULL;
+ CameraIntrinsics* new_intrinsics = NULL;
switch (orig_intrinsics->GetDistortionModelType()) {
- case libmv::DISTORTION_MODEL_POLYNOMIAL:
- {
- const PolynomialCameraIntrinsics *polynomial_intrinsics =
+ case libmv::DISTORTION_MODEL_POLYNOMIAL: {
+ const PolynomialCameraIntrinsics* polynomial_intrinsics =
static_cast<const PolynomialCameraIntrinsics*>(orig_intrinsics);
- new_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics,
- *polynomial_intrinsics);
- break;
- }
- case libmv::DISTORTION_MODEL_DIVISION:
- {
- const DivisionCameraIntrinsics *division_intrinsics =
+ new_intrinsics =
+ LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics, *polynomial_intrinsics);
+ break;
+ }
+ case libmv::DISTORTION_MODEL_DIVISION: {
+ const DivisionCameraIntrinsics* division_intrinsics =
static_cast<const DivisionCameraIntrinsics*>(orig_intrinsics);
- new_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics,
- *division_intrinsics);
- break;
- }
- case libmv::DISTORTION_MODEL_NUKE:
- {
- const NukeCameraIntrinsics *nuke_intrinsics =
+ new_intrinsics =
+ LIBMV_OBJECT_NEW(DivisionCameraIntrinsics, *division_intrinsics);
+ break;
+ }
+ case libmv::DISTORTION_MODEL_NUKE: {
+ const NukeCameraIntrinsics* nuke_intrinsics =
static_cast<const NukeCameraIntrinsics*>(orig_intrinsics);
- new_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics,
- *nuke_intrinsics);
- break;
- }
- case libmv::DISTORTION_MODEL_BROWN:
- {
- const BrownCameraIntrinsics *brown_intrinsics =
+ new_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics, *nuke_intrinsics);
+ break;
+ }
+ case libmv::DISTORTION_MODEL_BROWN: {
+ const BrownCameraIntrinsics* brown_intrinsics =
static_cast<const BrownCameraIntrinsics*>(orig_intrinsics);
- new_intrinsics = LIBMV_OBJECT_NEW(BrownCameraIntrinsics,
- *brown_intrinsics);
- break;
- }
- default:
- assert(!"Unknown distortion model");
+ new_intrinsics =
+ LIBMV_OBJECT_NEW(BrownCameraIntrinsics, *brown_intrinsics);
+ break;
+ }
+ default: assert(!"Unknown distortion model");
}
- return (libmv_CameraIntrinsics *) new_intrinsics;
+ return (libmv_CameraIntrinsics*)new_intrinsics;
}
void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics* libmv_intrinsics) {
@@ -86,7 +80,7 @@ void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics* libmv_intrinsics) {
void libmv_cameraIntrinsicsUpdate(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
libmv_CameraIntrinsics* libmv_intrinsics) {
- CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+ CameraIntrinsics* camera_intrinsics = (CameraIntrinsics*)libmv_intrinsics;
double focal_length = libmv_camera_intrinsics_options->focal_length;
double principal_x = libmv_camera_intrinsics_options->principal_point_x;
@@ -115,191 +109,173 @@ void libmv_cameraIntrinsicsUpdate(
}
switch (libmv_camera_intrinsics_options->distortion_model) {
- case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
- {
- assert(camera_intrinsics->GetDistortionModelType() ==
- libmv::DISTORTION_MODEL_POLYNOMIAL);
-
- PolynomialCameraIntrinsics *polynomial_intrinsics =
- (PolynomialCameraIntrinsics *) camera_intrinsics;
-
- double k1 = libmv_camera_intrinsics_options->polynomial_k1;
- double k2 = libmv_camera_intrinsics_options->polynomial_k2;
- double k3 = libmv_camera_intrinsics_options->polynomial_k3;
-
- if (polynomial_intrinsics->k1() != k1 ||
- polynomial_intrinsics->k2() != k2 ||
- polynomial_intrinsics->k3() != k3) {
- polynomial_intrinsics->SetRadialDistortion(k1, k2, k3);
- }
- break;
+ case LIBMV_DISTORTION_MODEL_POLYNOMIAL: {
+ assert(camera_intrinsics->GetDistortionModelType() ==
+ libmv::DISTORTION_MODEL_POLYNOMIAL);
+
+ PolynomialCameraIntrinsics* polynomial_intrinsics =
+ (PolynomialCameraIntrinsics*)camera_intrinsics;
+
+ double k1 = libmv_camera_intrinsics_options->polynomial_k1;
+ double k2 = libmv_camera_intrinsics_options->polynomial_k2;
+ double k3 = libmv_camera_intrinsics_options->polynomial_k3;
+
+ if (polynomial_intrinsics->k1() != k1 ||
+ polynomial_intrinsics->k2() != k2 ||
+ polynomial_intrinsics->k3() != k3) {
+ polynomial_intrinsics->SetRadialDistortion(k1, k2, k3);
}
+ break;
+ }
- case LIBMV_DISTORTION_MODEL_DIVISION:
- {
- assert(camera_intrinsics->GetDistortionModelType() ==
- libmv::DISTORTION_MODEL_DIVISION);
+ case LIBMV_DISTORTION_MODEL_DIVISION: {
+ assert(camera_intrinsics->GetDistortionModelType() ==
+ libmv::DISTORTION_MODEL_DIVISION);
- DivisionCameraIntrinsics *division_intrinsics =
- (DivisionCameraIntrinsics *) camera_intrinsics;
+ DivisionCameraIntrinsics* division_intrinsics =
+ (DivisionCameraIntrinsics*)camera_intrinsics;
- double k1 = libmv_camera_intrinsics_options->division_k1;
- double k2 = libmv_camera_intrinsics_options->division_k2;
+ double k1 = libmv_camera_intrinsics_options->division_k1;
+ double k2 = libmv_camera_intrinsics_options->division_k2;
- if (division_intrinsics->k1() != k1 ||
- division_intrinsics->k2() != k2) {
- division_intrinsics->SetDistortion(k1, k2);
- }
+ if (division_intrinsics->k1() != k1 || division_intrinsics->k2() != k2) {
+ division_intrinsics->SetDistortion(k1, k2);
+ }
- break;
+ break;
+ }
+
+ case LIBMV_DISTORTION_MODEL_NUKE: {
+ assert(camera_intrinsics->GetDistortionModelType() ==
+ libmv::DISTORTION_MODEL_NUKE);
+
+ NukeCameraIntrinsics* nuke_intrinsics =
+ (NukeCameraIntrinsics*)camera_intrinsics;
+
+ double k1 = libmv_camera_intrinsics_options->nuke_k1;
+ double k2 = libmv_camera_intrinsics_options->nuke_k2;
+
+ if (nuke_intrinsics->k1() != k1 || nuke_intrinsics->k2() != k2) {
+ nuke_intrinsics->SetDistortion(k1, k2);
}
- case LIBMV_DISTORTION_MODEL_NUKE:
- {
- assert(camera_intrinsics->GetDistortionModelType() ==
- libmv::DISTORTION_MODEL_NUKE);
+ break;
+ }
- NukeCameraIntrinsics *nuke_intrinsics =
- (NukeCameraIntrinsics *) camera_intrinsics;
+ case LIBMV_DISTORTION_MODEL_BROWN: {
+ assert(camera_intrinsics->GetDistortionModelType() ==
+ libmv::DISTORTION_MODEL_BROWN);
- double k1 = libmv_camera_intrinsics_options->nuke_k1;
- double k2 = libmv_camera_intrinsics_options->nuke_k2;
+ BrownCameraIntrinsics* brown_intrinsics =
+ (BrownCameraIntrinsics*)camera_intrinsics;
- if (nuke_intrinsics->k1() != k1 ||
- nuke_intrinsics->k2() != k2) {
- nuke_intrinsics->SetDistortion(k1, k2);
- }
+ double k1 = libmv_camera_intrinsics_options->brown_k1;
+ double k2 = libmv_camera_intrinsics_options->brown_k2;
+ double k3 = libmv_camera_intrinsics_options->brown_k3;
+ double k4 = libmv_camera_intrinsics_options->brown_k4;
- break;
+ if (brown_intrinsics->k1() != k1 || brown_intrinsics->k2() != k2 ||
+ brown_intrinsics->k3() != k3 || brown_intrinsics->k4() != k4) {
+ brown_intrinsics->SetRadialDistortion(k1, k2, k3, k4);
}
- case LIBMV_DISTORTION_MODEL_BROWN:
- {
- assert(camera_intrinsics->GetDistortionModelType() ==
- libmv::DISTORTION_MODEL_BROWN);
-
- BrownCameraIntrinsics *brown_intrinsics =
- (BrownCameraIntrinsics *) camera_intrinsics;
-
- double k1 = libmv_camera_intrinsics_options->brown_k1;
- double k2 = libmv_camera_intrinsics_options->brown_k2;
- double k3 = libmv_camera_intrinsics_options->brown_k3;
- double k4 = libmv_camera_intrinsics_options->brown_k4;
-
- if (brown_intrinsics->k1() != k1 ||
- brown_intrinsics->k2() != k2 ||
- brown_intrinsics->k3() != k3 ||
- brown_intrinsics->k4() != k4) {
- brown_intrinsics->SetRadialDistortion(k1, k2, k3, k4);
- }
-
- double p1 = libmv_camera_intrinsics_options->brown_p1;
- double p2 = libmv_camera_intrinsics_options->brown_p2;
-
- if (brown_intrinsics->p1() != p1 || brown_intrinsics->p2() != p2) {
- brown_intrinsics->SetTangentialDistortion(p1, p2);
- }
- break;
+ double p1 = libmv_camera_intrinsics_options->brown_p1;
+ double p2 = libmv_camera_intrinsics_options->brown_p2;
+
+ if (brown_intrinsics->p1() != p1 || brown_intrinsics->p2() != p2) {
+ brown_intrinsics->SetTangentialDistortion(p1, p2);
}
+ break;
+ }
- default:
- assert(!"Unknown distortion model");
+ default: assert(!"Unknown distortion model");
}
}
void libmv_cameraIntrinsicsSetThreads(libmv_CameraIntrinsics* libmv_intrinsics,
int threads) {
- CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+ CameraIntrinsics* camera_intrinsics = (CameraIntrinsics*)libmv_intrinsics;
camera_intrinsics->SetThreads(threads);
}
void libmv_cameraIntrinsicsExtractOptions(
const libmv_CameraIntrinsics* libmv_intrinsics,
libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
- const CameraIntrinsics *camera_intrinsics =
- (const CameraIntrinsics *) libmv_intrinsics;
+ const CameraIntrinsics* camera_intrinsics =
+ (const CameraIntrinsics*)libmv_intrinsics;
// Fill in options which are common for all distortion models.
camera_intrinsics_options->focal_length = camera_intrinsics->focal_length();
camera_intrinsics_options->principal_point_x =
- camera_intrinsics->principal_point_x();
+ camera_intrinsics->principal_point_x();
camera_intrinsics_options->principal_point_y =
- camera_intrinsics->principal_point_y();
+ camera_intrinsics->principal_point_y();
camera_intrinsics_options->image_width = camera_intrinsics->image_width();
camera_intrinsics_options->image_height = camera_intrinsics->image_height();
switch (camera_intrinsics->GetDistortionModelType()) {
- case libmv::DISTORTION_MODEL_POLYNOMIAL:
- {
- const PolynomialCameraIntrinsics *polynomial_intrinsics =
- static_cast<const PolynomialCameraIntrinsics *>(camera_intrinsics);
- camera_intrinsics_options->distortion_model =
+ case libmv::DISTORTION_MODEL_POLYNOMIAL: {
+ const PolynomialCameraIntrinsics* polynomial_intrinsics =
+ static_cast<const PolynomialCameraIntrinsics*>(camera_intrinsics);
+ camera_intrinsics_options->distortion_model =
LIBMV_DISTORTION_MODEL_POLYNOMIAL;
- camera_intrinsics_options->polynomial_k1 = polynomial_intrinsics->k1();
- camera_intrinsics_options->polynomial_k2 = polynomial_intrinsics->k2();
- camera_intrinsics_options->polynomial_k3 = polynomial_intrinsics->k3();
- camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p1();
- camera_intrinsics_options->polynomial_p2 = polynomial_intrinsics->p2();
- break;
- }
+ camera_intrinsics_options->polynomial_k1 = polynomial_intrinsics->k1();
+ camera_intrinsics_options->polynomial_k2 = polynomial_intrinsics->k2();
+ camera_intrinsics_options->polynomial_k3 = polynomial_intrinsics->k3();
+ camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p1();
+ camera_intrinsics_options->polynomial_p2 = polynomial_intrinsics->p2();
+ break;
+ }
- case libmv::DISTORTION_MODEL_DIVISION:
- {
- const DivisionCameraIntrinsics *division_intrinsics =
- static_cast<const DivisionCameraIntrinsics *>(camera_intrinsics);
- camera_intrinsics_options->distortion_model =
+ case libmv::DISTORTION_MODEL_DIVISION: {
+ const DivisionCameraIntrinsics* division_intrinsics =
+ static_cast<const DivisionCameraIntrinsics*>(camera_intrinsics);
+ camera_intrinsics_options->distortion_model =
LIBMV_DISTORTION_MODEL_DIVISION;
- camera_intrinsics_options->division_k1 = division_intrinsics->k1();
- camera_intrinsics_options->division_k2 = division_intrinsics->k2();
- break;
- }
-
- case libmv::DISTORTION_MODEL_NUKE:
- {
- const NukeCameraIntrinsics *nuke_intrinsics =
- static_cast<const NukeCameraIntrinsics *>(camera_intrinsics);
- camera_intrinsics_options->distortion_model =
- LIBMV_DISTORTION_MODEL_NUKE;
- camera_intrinsics_options->nuke_k1 = nuke_intrinsics->k1();
- camera_intrinsics_options->nuke_k2 = nuke_intrinsics->k2();
- break;
- }
+ camera_intrinsics_options->division_k1 = division_intrinsics->k1();
+ camera_intrinsics_options->division_k2 = division_intrinsics->k2();
+ break;
+ }
+
+ case libmv::DISTORTION_MODEL_NUKE: {
+ const NukeCameraIntrinsics* nuke_intrinsics =
+ static_cast<const NukeCameraIntrinsics*>(camera_intrinsics);
+ camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_NUKE;
+ camera_intrinsics_options->nuke_k1 = nuke_intrinsics->k1();
+ camera_intrinsics_options->nuke_k2 = nuke_intrinsics->k2();
+ break;
+ }
- case libmv::DISTORTION_MODEL_BROWN:
- {
- const BrownCameraIntrinsics *brown_intrinsics =
- static_cast<const BrownCameraIntrinsics *>(camera_intrinsics);
- camera_intrinsics_options->distortion_model =
+ case libmv::DISTORTION_MODEL_BROWN: {
+ const BrownCameraIntrinsics* brown_intrinsics =
+ static_cast<const BrownCameraIntrinsics*>(camera_intrinsics);
+ camera_intrinsics_options->distortion_model =
LIBMV_DISTORTION_MODEL_BROWN;
- camera_intrinsics_options->brown_k1 = brown_intrinsics->k1();
- camera_intrinsics_options->brown_k2 = brown_intrinsics->k2();
- camera_intrinsics_options->brown_k3 = brown_intrinsics->k3();
- camera_intrinsics_options->brown_k4 = brown_intrinsics->k4();
- camera_intrinsics_options->brown_p1 = brown_intrinsics->p1();
- camera_intrinsics_options->brown_p2 = brown_intrinsics->p2();
- break;
- }
+ camera_intrinsics_options->brown_k1 = brown_intrinsics->k1();
+ camera_intrinsics_options->brown_k2 = brown_intrinsics->k2();
+ camera_intrinsics_options->brown_k3 = brown_intrinsics->k3();
+ camera_intrinsics_options->brown_k4 = brown_intrinsics->k4();
+ camera_intrinsics_options->brown_p1 = brown_intrinsics->p1();
+ camera_intrinsics_options->brown_p2 = brown_intrinsics->p2();
+ break;
+ }
- default:
- assert(!"Unknown distortion model");
+ default: assert(!"Unknown distortion model");
}
}
void libmv_cameraIntrinsicsUndistortByte(
const libmv_CameraIntrinsics* libmv_intrinsics,
- const unsigned char *source_image,
+ const unsigned char* source_image,
int width,
int height,
float overscan,
int channels,
unsigned char* destination_image) {
- CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
- camera_intrinsics->UndistortBuffer(source_image,
- width, height,
- overscan,
- channels,
- destination_image);
+ CameraIntrinsics* camera_intrinsics = (CameraIntrinsics*)libmv_intrinsics;
+ camera_intrinsics->UndistortBuffer(
+ source_image, width, height, overscan, channels, destination_image);
}
void libmv_cameraIntrinsicsUndistortFloat(
@@ -310,28 +286,22 @@ void libmv_cameraIntrinsicsUndistortFloat(
float overscan,
int channels,
float* destination_image) {
- CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
- intrinsics->UndistortBuffer(source_image,
- width, height,
- overscan,
- channels,
- destination_image);
+ CameraIntrinsics* intrinsics = (CameraIntrinsics*)libmv_intrinsics;
+ intrinsics->UndistortBuffer(
+ source_image, width, height, overscan, channels, destination_image);
}
void libmv_cameraIntrinsicsDistortByte(
const struct libmv_CameraIntrinsics* libmv_intrinsics,
- const unsigned char *source_image,
+ const unsigned char* source_image,
int width,
int height,
float overscan,
int channels,
- unsigned char *destination_image) {
- CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
- intrinsics->DistortBuffer(source_image,
- width, height,
- overscan,
- channels,
- destination_image);
+ unsigned char* destination_image) {
+ CameraIntrinsics* intrinsics = (CameraIntrinsics*)libmv_intrinsics;
+ intrinsics->DistortBuffer(
+ source_image, width, height, overscan, channels, destination_image);
}
void libmv_cameraIntrinsicsDistortFloat(
@@ -342,12 +312,9 @@ void libmv_cameraIntrinsicsDistortFloat(
float overscan,
int channels,
float* destination_image) {
- CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
- intrinsics->DistortBuffer(source_image,
- width, height,
- overscan,
- channels,
- destination_image);
+ CameraIntrinsics* intrinsics = (CameraIntrinsics*)libmv_intrinsics;
+ intrinsics->DistortBuffer(
+ source_image, width, height, overscan, channels, destination_image);
}
void libmv_cameraIntrinsicsApply(
@@ -356,7 +323,7 @@ void libmv_cameraIntrinsicsApply(
double y,
double* x1,
double* y1) {
- CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+ CameraIntrinsics* intrinsics = (CameraIntrinsics*)libmv_intrinsics;
intrinsics->ApplyIntrinsics(x, y, x1, y1);
}
@@ -366,7 +333,7 @@ void libmv_cameraIntrinsicsInvert(
double y,
double* x1,
double* y1) {
- CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+ CameraIntrinsics* intrinsics = (CameraIntrinsics*)libmv_intrinsics;
intrinsics->InvertIntrinsics(x, y, x1, y1);
}
@@ -381,69 +348,63 @@ static void libmv_cameraIntrinsicsFillFromOptions(
camera_intrinsics_options->principal_point_y);
camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width,
- camera_intrinsics_options->image_height);
+ camera_intrinsics_options->image_height);
switch (camera_intrinsics_options->distortion_model) {
- case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
- {
- PolynomialCameraIntrinsics *polynomial_intrinsics =
+ case LIBMV_DISTORTION_MODEL_POLYNOMIAL: {
+ PolynomialCameraIntrinsics* polynomial_intrinsics =
static_cast<PolynomialCameraIntrinsics*>(camera_intrinsics);
- polynomial_intrinsics->SetRadialDistortion(
- camera_intrinsics_options->polynomial_k1,
- camera_intrinsics_options->polynomial_k2,
- camera_intrinsics_options->polynomial_k3);
+ polynomial_intrinsics->SetRadialDistortion(
+ camera_intrinsics_options->polynomial_k1,
+ camera_intrinsics_options->polynomial_k2,
+ camera_intrinsics_options->polynomial_k3);
- break;
- }
+ break;
+ }
- case LIBMV_DISTORTION_MODEL_DIVISION:
- {
- DivisionCameraIntrinsics *division_intrinsics =
+ case LIBMV_DISTORTION_MODEL_DIVISION: {
+ DivisionCameraIntrinsics* division_intrinsics =
static_cast<DivisionCameraIntrinsics*>(camera_intrinsics);
- division_intrinsics->SetDistortion(
- camera_intrinsics_options->division_k1,
- camera_intrinsics_options->division_k2);
- break;
- }
+ division_intrinsics->SetDistortion(
+ camera_intrinsics_options->division_k1,
+ camera_intrinsics_options->division_k2);
+ break;
+ }
- case LIBMV_DISTORTION_MODEL_NUKE:
- {
- NukeCameraIntrinsics *nuke_intrinsics =
+ case LIBMV_DISTORTION_MODEL_NUKE: {
+ NukeCameraIntrinsics* nuke_intrinsics =
static_cast<NukeCameraIntrinsics*>(camera_intrinsics);
- nuke_intrinsics->SetDistortion(
- camera_intrinsics_options->nuke_k1,
- camera_intrinsics_options->nuke_k2);
- break;
- }
+ nuke_intrinsics->SetDistortion(camera_intrinsics_options->nuke_k1,
+ camera_intrinsics_options->nuke_k2);
+ break;
+ }
- case LIBMV_DISTORTION_MODEL_BROWN:
- {
- BrownCameraIntrinsics *brown_intrinsics =
+ case LIBMV_DISTORTION_MODEL_BROWN: {
+ BrownCameraIntrinsics* brown_intrinsics =
static_cast<BrownCameraIntrinsics*>(camera_intrinsics);
- brown_intrinsics->SetRadialDistortion(
- camera_intrinsics_options->brown_k1,
- camera_intrinsics_options->brown_k2,
- camera_intrinsics_options->brown_k3,
- camera_intrinsics_options->brown_k4);
- brown_intrinsics->SetTangentialDistortion(
+ brown_intrinsics->SetRadialDistortion(
+ camera_intrinsics_options->brown_k1,
+ camera_intrinsics_options->brown_k2,
+ camera_intrinsics_options->brown_k3,
+ camera_intrinsics_options->brown_k4);
+ brown_intrinsics->SetTangentialDistortion(
camera_intrinsics_options->brown_p1,
camera_intrinsics_options->brown_p2);
- break;
- }
+ break;
+ }
- default:
- assert(!"Unknown distortion model");
+ default: assert(!"Unknown distortion model");
}
}
CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
const libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
- CameraIntrinsics *camera_intrinsics = NULL;
+ CameraIntrinsics* camera_intrinsics = NULL;
switch (camera_intrinsics_options->distortion_model) {
case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
camera_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics);
@@ -457,8 +418,7 @@ CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
case LIBMV_DISTORTION_MODEL_BROWN:
camera_intrinsics = LIBMV_OBJECT_NEW(BrownCameraIntrinsics);
break;
- default:
- assert(!"Unknown distortion model");
+ default: assert(!"Unknown distortion model");
}
libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options,
camera_intrinsics);
diff --git a/intern/libmv/intern/camera_intrinsics.h b/intern/libmv/intern/camera_intrinsics.h
index eb6176770ec..8a65c93e6a4 100644
--- a/intern/libmv/intern/camera_intrinsics.h
+++ b/intern/libmv/intern/camera_intrinsics.h
@@ -56,10 +56,10 @@ typedef struct libmv_CameraIntrinsicsOptions {
double brown_p1, brown_p2;
} libmv_CameraIntrinsicsOptions;
-libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
+libmv_CameraIntrinsics* libmv_cameraIntrinsicsNew(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options);
-libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
+libmv_CameraIntrinsics* libmv_cameraIntrinsicsCopy(
const libmv_CameraIntrinsics* libmv_intrinsics);
void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics* libmv_intrinsics);
@@ -76,7 +76,7 @@ void libmv_cameraIntrinsicsExtractOptions(
void libmv_cameraIntrinsicsUndistortByte(
const libmv_CameraIntrinsics* libmv_intrinsics,
- const unsigned char *source_image,
+ const unsigned char* source_image,
int width,
int height,
float overscan,
@@ -94,12 +94,12 @@ void libmv_cameraIntrinsicsUndistortFloat(
void libmv_cameraIntrinsicsDistortByte(
const struct libmv_CameraIntrinsics* libmv_intrinsics,
- const unsigned char *source_image,
+ const unsigned char* source_image,
int width,
int height,
float overscan,
int channels,
- unsigned char *destination_image);
+ unsigned char* destination_image);
void libmv_cameraIntrinsicsDistortFloat(
const libmv_CameraIntrinsics* libmv_intrinsics,
@@ -131,7 +131,7 @@ void libmv_cameraIntrinsicsInvert(
#ifdef __cplusplus
namespace libmv {
- class CameraIntrinsics;
+class CameraIntrinsics;
}
libmv::CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
diff --git a/intern/libmv/intern/detector.cc b/intern/libmv/intern/detector.cc
index 455e431f6f4..21f5b46595c 100644
--- a/intern/libmv/intern/detector.cc
+++ b/intern/libmv/intern/detector.cc
@@ -34,7 +34,7 @@ struct libmv_Features {
namespace {
-libmv_Features *libmv_featuresFromVector(
+libmv_Features* libmv_featuresFromVector(
const libmv::vector<Feature>& features) {
libmv_Features* libmv_features = LIBMV_STRUCT_NEW(libmv_Features, 1);
int count = features.size();
@@ -50,12 +50,12 @@ libmv_Features *libmv_featuresFromVector(
return libmv_features;
}
-void libmv_convertDetectorOptions(libmv_DetectOptions *options,
- DetectOptions *detector_options) {
+void libmv_convertDetectorOptions(libmv_DetectOptions* options,
+ DetectOptions* detector_options) {
switch (options->detector) {
-#define LIBMV_CONVERT(the_detector) \
- case LIBMV_DETECTOR_ ## the_detector: \
- detector_options->type = DetectOptions::the_detector; \
+#define LIBMV_CONVERT(the_detector) \
+ case LIBMV_DETECTOR_##the_detector: \
+ detector_options->type = DetectOptions::the_detector; \
break;
LIBMV_CONVERT(FAST)
LIBMV_CONVERT(MORAVEC)
@@ -72,7 +72,7 @@ void libmv_convertDetectorOptions(libmv_DetectOptions *options,
} // namespace
-libmv_Features *libmv_detectFeaturesByte(const unsigned char* image_buffer,
+libmv_Features* libmv_detectFeaturesByte(const unsigned char* image_buffer,
int width,
int height,
int channels,
@@ -133,7 +133,7 @@ void libmv_getFeature(const libmv_Features* libmv_features,
double* y,
double* score,
double* size) {
- Feature &feature = libmv_features->features[number];
+ Feature& feature = libmv_features->features[number];
*x = feature.x;
*y = feature.y;
*score = feature.score;
diff --git a/intern/libmv/intern/detector.h b/intern/libmv/intern/detector.h
index b36935fc67f..f21e78d7f2b 100644
--- a/intern/libmv/intern/detector.h
+++ b/intern/libmv/intern/detector.h
@@ -38,7 +38,7 @@ typedef struct libmv_DetectOptions {
int min_distance;
int fast_min_trackness;
int moravec_max_count;
- unsigned char *moravec_pattern;
+ unsigned char* moravec_pattern;
double harris_threshold;
} libmv_DetectOptions;
diff --git a/intern/libmv/intern/frame_accessor.cc b/intern/libmv/intern/frame_accessor.cc
index 9fde73f0d71..3a6c753cc8d 100644
--- a/intern/libmv/intern/frame_accessor.cc
+++ b/intern/libmv/intern/frame_accessor.cc
@@ -36,20 +36,18 @@ struct LibmvFrameAccessor : public FrameAccessor {
libmv_ReleaseImageCallback release_image_callback,
libmv_GetMaskForTrackCallback get_mask_for_track_callback,
libmv_ReleaseMaskCallback release_mask_callback)
- : user_data_(user_data),
- get_image_callback_(get_image_callback),
- release_image_callback_(release_image_callback),
- get_mask_for_track_callback_(get_mask_for_track_callback),
- release_mask_callback_(release_mask_callback) { }
+ : user_data_(user_data),
+ get_image_callback_(get_image_callback),
+ release_image_callback_(release_image_callback),
+ get_mask_for_track_callback_(get_mask_for_track_callback),
+ release_mask_callback_(release_mask_callback) {}
- virtual ~LibmvFrameAccessor() {
- }
+ virtual ~LibmvFrameAccessor() {}
libmv_InputMode get_libmv_input_mode(InputMode input_mode) {
switch (input_mode) {
-#define CHECK_INPUT_MODE(mode) \
- case mode: \
- return LIBMV_IMAGE_MODE_ ## mode;
+#define CHECK_INPUT_MODE(mode) \
+ case mode: return LIBMV_IMAGE_MODE_##mode;
CHECK_INPUT_MODE(MONO)
CHECK_INPUT_MODE(RGBA)
#undef CHECK_INPUT_MODE
@@ -59,8 +57,7 @@ struct LibmvFrameAccessor : public FrameAccessor {
return LIBMV_IMAGE_MODE_MONO;
}
- void get_libmv_region(const Region& region,
- libmv_Region* libmv_region) {
+ void get_libmv_region(const Region& region, libmv_Region* libmv_region) {
libmv_region->min[0] = region.min(0);
libmv_region->min[1] = region.min(1);
libmv_region->max[0] = region.max(0);
@@ -74,7 +71,7 @@ struct LibmvFrameAccessor : public FrameAccessor {
const Region* region,
const Transform* transform,
FloatImage* destination) {
- float *float_buffer;
+ float* float_buffer;
int width, height, channels;
libmv_Region libmv_region;
if (region) {
@@ -86,46 +83,41 @@ struct LibmvFrameAccessor : public FrameAccessor {
get_libmv_input_mode(input_mode),
downscale,
region != NULL ? &libmv_region : NULL,
- (libmv_FrameTransform*) transform,
+ (libmv_FrameTransform*)transform,
&float_buffer,
&width,
&height,
&channels);
// TODO(sergey): Dumb code for until we can set data directly.
- FloatImage temp_image(float_buffer,
- height,
- width,
- channels);
+ FloatImage temp_image(float_buffer, height, width, channels);
destination->CopyFrom(temp_image);
return cache_key;
}
- void ReleaseImage(Key cache_key) {
- release_image_callback_(cache_key);
- }
+ void ReleaseImage(Key cache_key) { release_image_callback_(cache_key); }
Key GetMaskForTrack(int clip,
int frame,
int track,
const Region* region,
FloatImage* destination) {
- float *float_buffer;
+ float* float_buffer;
int width, height;
libmv_Region libmv_region;
if (region) {
get_libmv_region(*region, &libmv_region);
}
- Key cache_key = get_mask_for_track_callback_(
- user_data_,
- clip,
- frame,
- track,
- region != NULL ? &libmv_region : NULL,
- &float_buffer,
- &width,
- &height);
+ Key cache_key =
+ get_mask_for_track_callback_(user_data_,
+ clip,
+ frame,
+ track,
+ region != NULL ? &libmv_region : NULL,
+ &float_buffer,
+ &width,
+ &height);
if (cache_key == NULL) {
// No mask for the given track.
@@ -133,30 +125,21 @@ struct LibmvFrameAccessor : public FrameAccessor {
}
// TODO(sergey): Dumb code for until we can set data directly.
- FloatImage temp_image(float_buffer,
- height,
- width,
- 1);
+ FloatImage temp_image(float_buffer, height, width, 1);
destination->CopyFrom(temp_image);
return cache_key;
}
- void ReleaseMask(Key key) {
- release_mask_callback_(key);
- }
+ void ReleaseMask(Key key) { release_mask_callback_(key); }
- bool GetClipDimensions(int /*clip*/, int * /*width*/, int * /*height*/) {
+ bool GetClipDimensions(int /*clip*/, int* /*width*/, int* /*height*/) {
return false;
}
- int NumClips() {
- return 1;
- }
+ int NumClips() { return 1; }
- int NumFrames(int /*clip*/) {
- return 0;
- }
+ int NumFrames(int /*clip*/) { return 0; }
libmv_FrameAccessorUserData* user_data_;
libmv_GetImageCallback get_image_callback_;
@@ -173,35 +156,35 @@ libmv_FrameAccessor* libmv_FrameAccessorNew(
libmv_ReleaseImageCallback release_image_callback,
libmv_GetMaskForTrackCallback get_mask_for_track_callback,
libmv_ReleaseMaskCallback release_mask_callback) {
- return (libmv_FrameAccessor*) LIBMV_OBJECT_NEW(LibmvFrameAccessor,
- user_data,
- get_image_callback,
- release_image_callback,
- get_mask_for_track_callback,
- release_mask_callback);
+ return (libmv_FrameAccessor*)LIBMV_OBJECT_NEW(LibmvFrameAccessor,
+ user_data,
+ get_image_callback,
+ release_image_callback,
+ get_mask_for_track_callback,
+ release_mask_callback);
}
void libmv_FrameAccessorDestroy(libmv_FrameAccessor* frame_accessor) {
LIBMV_OBJECT_DELETE(frame_accessor, LibmvFrameAccessor);
}
-int64_t libmv_frameAccessorgetTransformKey(const libmv_FrameTransform *transform) {
- return ((FrameAccessor::Transform*) transform)->key();
+int64_t libmv_frameAccessorgetTransformKey(
+ const libmv_FrameTransform* transform) {
+ return ((FrameAccessor::Transform*)transform)->key();
}
-void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform,
- const libmv_FloatImage *input_image,
- libmv_FloatImage *output_image) {
+void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform* transform,
+ const libmv_FloatImage* input_image,
+ libmv_FloatImage* output_image) {
const FloatImage input(input_image->buffer,
input_image->height,
input_image->width,
input_image->channels);
FloatImage output;
- ((FrameAccessor::Transform*) transform)->run(input,
- &output);
+ ((FrameAccessor::Transform*)transform)->run(input, &output);
- int num_pixels = output.Width() *output.Height() * output.Depth();
+ int num_pixels = output.Width() * output.Height() * output.Depth();
output_image->buffer = new float[num_pixels];
memcpy(output_image->buffer, output.Data(), num_pixels * sizeof(float));
output_image->width = output.Width();
diff --git a/intern/libmv/intern/frame_accessor.h b/intern/libmv/intern/frame_accessor.h
index 6bccb305282..39a3bc5eb1d 100644
--- a/intern/libmv/intern/frame_accessor.h
+++ b/intern/libmv/intern/frame_accessor.h
@@ -32,14 +32,14 @@ extern "C" {
typedef struct libmv_FrameAccessor libmv_FrameAccessor;
typedef struct libmv_FrameTransform libmv_FrameTransform;
typedef struct libmv_FrameAccessorUserData libmv_FrameAccessorUserData;
-typedef void *libmv_CacheKey;
+typedef void* libmv_CacheKey;
typedef enum {
LIBMV_IMAGE_MODE_MONO,
LIBMV_IMAGE_MODE_RGBA,
} libmv_InputMode;
-typedef libmv_CacheKey (*libmv_GetImageCallback) (
+typedef libmv_CacheKey (*libmv_GetImageCallback)(
libmv_FrameAccessorUserData* user_data,
int clip,
int frame,
@@ -52,9 +52,9 @@ typedef libmv_CacheKey (*libmv_GetImageCallback) (
int* height,
int* channels);
-typedef void (*libmv_ReleaseImageCallback) (libmv_CacheKey cache_key);
+typedef void (*libmv_ReleaseImageCallback)(libmv_CacheKey cache_key);
-typedef libmv_CacheKey (*libmv_GetMaskForTrackCallback) (
+typedef libmv_CacheKey (*libmv_GetMaskForTrackCallback)(
libmv_FrameAccessorUserData* user_data,
int clip,
int frame,
@@ -63,7 +63,7 @@ typedef libmv_CacheKey (*libmv_GetMaskForTrackCallback) (
float** destination,
int* width,
int* height);
-typedef void (*libmv_ReleaseMaskCallback) (libmv_CacheKey cache_key);
+typedef void (*libmv_ReleaseMaskCallback)(libmv_CacheKey cache_key);
libmv_FrameAccessor* libmv_FrameAccessorNew(
libmv_FrameAccessorUserData* user_data,
@@ -73,11 +73,12 @@ libmv_FrameAccessor* libmv_FrameAccessorNew(
libmv_ReleaseMaskCallback release_mask_callback);
void libmv_FrameAccessorDestroy(libmv_FrameAccessor* frame_accessor);
-int64_t libmv_frameAccessorgetTransformKey(const libmv_FrameTransform *transform);
+int64_t libmv_frameAccessorgetTransformKey(
+ const libmv_FrameTransform* transform);
-void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform,
- const libmv_FloatImage *input_image,
- libmv_FloatImage *output_image);
+void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform* transform,
+ const libmv_FloatImage* input_image,
+ libmv_FloatImage* output_image);
#ifdef __cplusplus
}
#endif
diff --git a/intern/libmv/intern/homography.cc b/intern/libmv/intern/homography.cc
index 179aeaa08aa..dc1009b5636 100644
--- a/intern/libmv/intern/homography.cc
+++ b/intern/libmv/intern/homography.cc
@@ -41,10 +41,8 @@ void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*x1)[2],
LG << "x2: " << x2_mat;
libmv::EstimateHomographyOptions options;
- libmv::EstimateHomography2DFromCorrespondences(x1_mat,
- x2_mat,
- options,
- &H_mat);
+ libmv::EstimateHomography2DFromCorrespondences(
+ x1_mat, x2_mat, options, &H_mat);
LG << "H: " << H_mat;
diff --git a/intern/libmv/intern/image.cc b/intern/libmv/intern/image.cc
index a6e09277680..564e4762448 100644
--- a/intern/libmv/intern/image.cc
+++ b/intern/libmv/intern/image.cc
@@ -21,14 +21,14 @@
#include "intern/utildefines.h"
#include "libmv/tracking/track_region.h"
-#include <cassert>
#include <png.h>
+#include <cassert>
using libmv::FloatImage;
using libmv::SamplePlanarPatch;
-void libmv_floatImageDestroy(libmv_FloatImage *image) {
- delete [] image->buffer;
+void libmv_floatImageDestroy(libmv_FloatImage* image) {
+ delete[] image->buffer;
}
/* Image <-> buffers conversion */
@@ -63,8 +63,7 @@ void libmv_floatBufferToFloatImage(const float* buffer,
}
}
-void libmv_floatImageToFloatBuffer(const FloatImage &image,
- float* buffer) {
+void libmv_floatImageToFloatBuffer(const FloatImage& image, float* buffer) {
for (int y = 0, a = 0; y < image.Height(); y++) {
for (int x = 0; x < image.Width(); x++) {
for (int k = 0; k < image.Depth(); k++) {
@@ -74,9 +73,9 @@ void libmv_floatImageToFloatBuffer(const FloatImage &image,
}
}
-void libmv_floatImageToByteBuffer(const libmv::FloatImage &image,
+void libmv_floatImageToByteBuffer(const libmv::FloatImage& image,
unsigned char* buffer) {
- for (int y = 0, a= 0; y < image.Height(); y++) {
+ for (int y = 0, a = 0; y < image.Height(); y++) {
for (int x = 0; x < image.Width(); x++) {
for (int k = 0; k < image.Depth(); k++) {
buffer[a++] = image(y, x, k) * 255.0f;
@@ -93,7 +92,7 @@ static bool savePNGImage(png_bytep* row_pointers,
const char* file_name) {
png_infop info_ptr;
png_structp png_ptr;
- FILE *fp = fopen(file_name, "wb");
+ FILE* fp = fopen(file_name, "wb");
if (fp == NULL) {
return false;
@@ -153,7 +152,7 @@ bool libmv_saveImage(const FloatImage& image,
int x0,
int y0) {
int x, y;
- png_bytep *row_pointers;
+ png_bytep* row_pointers;
assert(image.Depth() == 1);
@@ -180,9 +179,8 @@ bool libmv_saveImage(const FloatImage& image,
static int image_counter = 0;
char file_name[128];
- snprintf(file_name, sizeof(file_name),
- "%s_%02d.png",
- prefix, ++image_counter);
+ snprintf(
+ file_name, sizeof(file_name), "%s_%02d.png", prefix, ++image_counter);
bool result = savePNGImage(row_pointers,
image.Width(),
image.Height(),
@@ -191,9 +189,9 @@ bool libmv_saveImage(const FloatImage& image,
file_name);
for (y = 0; y < image.Height(); y++) {
- delete [] row_pointers[y];
+ delete[] row_pointers[y];
}
- delete [] row_pointers;
+ delete[] row_pointers;
return result;
}
@@ -211,7 +209,7 @@ void libmv_samplePlanarPatchFloat(const float* image,
double* warped_position_x,
double* warped_position_y) {
FloatImage libmv_image, libmv_patch, libmv_mask;
- FloatImage *libmv_mask_for_sample = NULL;
+ FloatImage* libmv_mask_for_sample = NULL;
libmv_floatBufferToFloatImage(image, width, height, channels, &libmv_image);
@@ -221,8 +219,10 @@ void libmv_samplePlanarPatchFloat(const float* image,
}
SamplePlanarPatch(libmv_image,
- xs, ys,
- num_samples_x, num_samples_y,
+ xs,
+ ys,
+ num_samples_x,
+ num_samples_y,
libmv_mask_for_sample,
&libmv_patch,
warped_position_x,
@@ -232,19 +232,19 @@ void libmv_samplePlanarPatchFloat(const float* image,
}
void libmv_samplePlanarPatchByte(const unsigned char* image,
- int width,
- int height,
- int channels,
- const double* xs,
- const double* ys,
- int num_samples_x,
- int num_samples_y,
- const float* mask,
- unsigned char* patch,
- double* warped_position_x,
- double* warped_position_y) {
+ int width,
+ int height,
+ int channels,
+ const double* xs,
+ const double* ys,
+ int num_samples_x,
+ int num_samples_y,
+ const float* mask,
+ unsigned char* patch,
+ double* warped_position_x,
+ double* warped_position_y) {
libmv::FloatImage libmv_image, libmv_patch, libmv_mask;
- libmv::FloatImage *libmv_mask_for_sample = NULL;
+ libmv::FloatImage* libmv_mask_for_sample = NULL;
libmv_byteBufferToFloatImage(image, width, height, channels, &libmv_image);
@@ -254,8 +254,10 @@ void libmv_samplePlanarPatchByte(const unsigned char* image,
}
libmv::SamplePlanarPatch(libmv_image,
- xs, ys,
- num_samples_x, num_samples_y,
+ xs,
+ ys,
+ num_samples_x,
+ num_samples_y,
libmv_mask_for_sample,
&libmv_patch,
warped_position_x,
diff --git a/intern/libmv/intern/image.h b/intern/libmv/intern/image.h
index a1381a4c216..02cef86a127 100644
--- a/intern/libmv/intern/image.h
+++ b/intern/libmv/intern/image.h
@@ -35,7 +35,7 @@ void libmv_floatBufferToFloatImage(const float* buffer,
libmv::FloatImage* image);
void libmv_floatImageToFloatBuffer(const libmv::FloatImage& image,
- float *buffer);
+ float* buffer);
void libmv_floatImageToByteBuffer(const libmv::FloatImage& image,
unsigned char* buffer);
@@ -51,13 +51,13 @@ extern "C" {
#endif
typedef struct libmv_FloatImage {
- float *buffer;
+ float* buffer;
int width;
int height;
int channels;
} libmv_FloatImage;
-void libmv_floatImageDestroy(libmv_FloatImage *image);
+void libmv_floatImageDestroy(libmv_FloatImage* image);
void libmv_samplePlanarPatchFloat(const float* image,
int width,
@@ -72,18 +72,18 @@ void libmv_samplePlanarPatchFloat(const float* image,
double* warped_position_x,
double* warped_position_y);
- void libmv_samplePlanarPatchByte(const unsigned char* image,
- int width,
- int height,
- int channels,
- const double* xs,
- const double* ys,
- int num_samples_x,
- int num_samples_y,
- const float* mask,
- unsigned char* patch,
- double* warped_position_x,
- double* warped_position_y);
+void libmv_samplePlanarPatchByte(const unsigned char* image,
+ int width,
+ int height,
+ int channels,
+ const double* xs,
+ const double* ys,
+ int num_samples_x,
+ int num_samples_y,
+ const float* mask,
+ unsigned char* patch,
+ double* warped_position_x,
+ double* warped_position_y);
#ifdef __cplusplus
}
diff --git a/intern/libmv/intern/logging.cc b/intern/libmv/intern/logging.cc
index 350be29d4db..a8c7e93880d 100644
--- a/intern/libmv/intern/logging.cc
+++ b/intern/libmv/intern/logging.cc
@@ -35,16 +35,13 @@ static bool is_verbosity_set() {
void libmv_initLogging(const char* argv0) {
using LIBMV_GFLAGS_NAMESPACE::SetCommandLineOption;
- // Make it so ERROR messages are always print into console.
- char severity_fatal[32];
- snprintf(severity_fatal, sizeof(severity_fatal), "%d",
- google::GLOG_ERROR);
google::InitGoogleLogging(argv0);
+ SetCommandLineOption("logtostderr", "1");
if (!is_verbosity_set()) {
SetCommandLineOption("v", "0");
}
- SetCommandLineOption("stderrthreshold", severity_fatal);
- SetCommandLineOption("minloglevel", severity_fatal);
+ SetCommandLineOption("stderrthreshold", "0");
+ SetCommandLineOption("minloglevel", "0");
}
void libmv_startDebugLogging(void) {
@@ -53,7 +50,7 @@ void libmv_startDebugLogging(void) {
if (!is_verbosity_set()) {
SetCommandLineOption("v", "2");
}
- SetCommandLineOption("stderrthreshold", "1");
+ SetCommandLineOption("stderrthreshold", "0");
SetCommandLineOption("minloglevel", "0");
}
diff --git a/intern/libmv/intern/reconstruction.cc b/intern/libmv/intern/reconstruction.cc
index 0f4e890d4ca..430607461da 100644
--- a/intern/libmv/intern/reconstruction.cc
+++ b/intern/libmv/intern/reconstruction.cc
@@ -24,8 +24,8 @@
#include "libmv/logging/logging.h"
#include "libmv/simple_pipeline/bundle.h"
-#include "libmv/simple_pipeline/keyframe_selection.h"
#include "libmv/simple_pipeline/initialize_reconstruction.h"
+#include "libmv/simple_pipeline/keyframe_selection.h"
#include "libmv/simple_pipeline/modal_solver.h"
#include "libmv/simple_pipeline/pipeline.h"
#include "libmv/simple_pipeline/reconstruction_scale.h"
@@ -39,19 +39,19 @@ using libmv::EuclideanScaleToUnity;
using libmv::Marker;
using libmv::ProgressUpdateCallback;
-using libmv::PolynomialCameraIntrinsics;
-using libmv::Tracks;
using libmv::EuclideanBundle;
using libmv::EuclideanCompleteReconstruction;
using libmv::EuclideanReconstructTwoFrames;
using libmv::EuclideanReprojectionError;
+using libmv::PolynomialCameraIntrinsics;
+using libmv::Tracks;
struct libmv_Reconstruction {
EuclideanReconstruction reconstruction;
/* Used for per-track average error calculation after reconstruction */
Tracks tracks;
- CameraIntrinsics *intrinsics;
+ CameraIntrinsics* intrinsics;
double error;
bool is_valid;
@@ -63,7 +63,7 @@ class ReconstructUpdateCallback : public ProgressUpdateCallback {
public:
ReconstructUpdateCallback(
reconstruct_progress_update_cb progress_update_callback,
- void *callback_customdata) {
+ void* callback_customdata) {
progress_update_callback_ = progress_update_callback;
callback_customdata_ = callback_customdata;
}
@@ -73,13 +73,14 @@ class ReconstructUpdateCallback : public ProgressUpdateCallback {
progress_update_callback_(callback_customdata_, progress, message);
}
}
+
protected:
reconstruct_progress_update_cb progress_update_callback_;
void* callback_customdata_;
};
void libmv_solveRefineIntrinsics(
- const Tracks &tracks,
+ const Tracks& tracks,
const int refine_intrinsics,
const int bundle_constraints,
reconstruct_progress_update_cb progress_update_callback,
@@ -96,11 +97,11 @@ void libmv_solveRefineIntrinsics(
bundle_intrinsics |= libmv::BUNDLE_PRINCIPAL_POINT;
}
-#define SET_DISTORTION_FLAG_CHECKED(type, coefficient) \
- do { \
- if (refine_intrinsics & LIBMV_REFINE_ ## type ##_DISTORTION_ ## coefficient) { \
- bundle_intrinsics |= libmv::BUNDLE_ ## type ## _ ## coefficient; \
- } \
+#define SET_DISTORTION_FLAG_CHECKED(type, coefficient) \
+ do { \
+ if (refine_intrinsics & LIBMV_REFINE_##type##_DISTORTION_##coefficient) { \
+ bundle_intrinsics |= libmv::BUNDLE_##type##_##coefficient; \
+ } \
} while (0)
SET_DISTORTION_FLAG_CHECKED(RADIAL, K1);
@@ -123,20 +124,19 @@ void libmv_solveRefineIntrinsics(
}
void finishReconstruction(
- const Tracks &tracks,
- const CameraIntrinsics &camera_intrinsics,
- libmv_Reconstruction *libmv_reconstruction,
+ const Tracks& tracks,
+ const CameraIntrinsics& camera_intrinsics,
+ libmv_Reconstruction* libmv_reconstruction,
reconstruct_progress_update_cb progress_update_callback,
- void *callback_customdata) {
- EuclideanReconstruction &reconstruction =
- libmv_reconstruction->reconstruction;
+ void* callback_customdata) {
+ EuclideanReconstruction& reconstruction =
+ libmv_reconstruction->reconstruction;
/* Reprojection error calculation. */
progress_update_callback(callback_customdata, 1.0, "Finishing solution");
libmv_reconstruction->tracks = tracks;
- libmv_reconstruction->error = EuclideanReprojectionError(tracks,
- reconstruction,
- camera_intrinsics);
+ libmv_reconstruction->error =
+ EuclideanReprojectionError(tracks, reconstruction, camera_intrinsics);
}
bool selectTwoKeyframesBasedOnGRICAndVariance(
@@ -148,9 +148,8 @@ bool selectTwoKeyframesBasedOnGRICAndVariance(
libmv::vector<int> keyframes;
/* Get list of all keyframe candidates first. */
- SelectKeyframesBasedOnGRICAndVariance(normalized_tracks,
- camera_intrinsics,
- keyframes);
+ SelectKeyframesBasedOnGRICAndVariance(
+ normalized_tracks, camera_intrinsics, keyframes);
if (keyframes.size() < 2) {
LG << "Not enough keyframes detected by GRIC";
@@ -175,24 +174,20 @@ bool selectTwoKeyframesBasedOnGRICAndVariance(
EuclideanReconstruction reconstruction;
int current_keyframe = keyframes[i];
libmv::vector<Marker> keyframe_markers =
- normalized_tracks.MarkersForTracksInBothImages(previous_keyframe,
- current_keyframe);
+ normalized_tracks.MarkersForTracksInBothImages(previous_keyframe,
+ current_keyframe);
Tracks keyframe_tracks(keyframe_markers);
/* get a solution from two keyframes only */
EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction);
EuclideanBundle(keyframe_tracks, &reconstruction);
- EuclideanCompleteReconstruction(keyframe_tracks,
- &reconstruction,
- NULL);
+ EuclideanCompleteReconstruction(keyframe_tracks, &reconstruction, NULL);
- double current_error = EuclideanReprojectionError(tracks,
- reconstruction,
- camera_intrinsics);
+ double current_error =
+ EuclideanReprojectionError(tracks, reconstruction, camera_intrinsics);
- LG << "Error between " << previous_keyframe
- << " and " << current_keyframe
+ LG << "Error between " << previous_keyframe << " and " << current_keyframe
<< ": " << current_error;
if (current_error < best_error) {
@@ -214,53 +209,49 @@ Marker libmv_projectMarker(const EuclideanPoint& point,
projected /= projected(2);
libmv::Marker reprojected_marker;
- intrinsics.ApplyIntrinsics(projected(0), projected(1),
- &reprojected_marker.x,
- &reprojected_marker.y);
+ intrinsics.ApplyIntrinsics(
+ projected(0), projected(1), &reprojected_marker.x, &reprojected_marker.y);
reprojected_marker.image = camera.image;
reprojected_marker.track = point.track;
return reprojected_marker;
}
-void libmv_getNormalizedTracks(const Tracks &tracks,
- const CameraIntrinsics &camera_intrinsics,
- Tracks *normalized_tracks) {
+void libmv_getNormalizedTracks(const Tracks& tracks,
+ const CameraIntrinsics& camera_intrinsics,
+ Tracks* normalized_tracks) {
libmv::vector<Marker> markers = tracks.AllMarkers();
for (int i = 0; i < markers.size(); ++i) {
- Marker &marker = markers[i];
- camera_intrinsics.InvertIntrinsics(marker.x, marker.y,
- &marker.x, &marker.y);
- normalized_tracks->Insert(marker.image,
- marker.track,
- marker.x, marker.y,
- marker.weight);
+ Marker& marker = markers[i];
+ camera_intrinsics.InvertIntrinsics(
+ marker.x, marker.y, &marker.x, &marker.y);
+ normalized_tracks->Insert(
+ marker.image, marker.track, marker.x, marker.y, marker.weight);
}
}
} // namespace
-libmv_Reconstruction *libmv_solveReconstruction(
+libmv_Reconstruction* libmv_solveReconstruction(
const libmv_Tracks* libmv_tracks,
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
libmv_ReconstructionOptions* libmv_reconstruction_options,
reconstruct_progress_update_cb progress_update_callback,
void* callback_customdata) {
- libmv_Reconstruction *libmv_reconstruction =
- LIBMV_OBJECT_NEW(libmv_Reconstruction);
+ libmv_Reconstruction* libmv_reconstruction =
+ LIBMV_OBJECT_NEW(libmv_Reconstruction);
- Tracks &tracks = *((Tracks *) libmv_tracks);
- EuclideanReconstruction &reconstruction =
- libmv_reconstruction->reconstruction;
+ Tracks& tracks = *((Tracks*)libmv_tracks);
+ EuclideanReconstruction& reconstruction =
+ libmv_reconstruction->reconstruction;
ReconstructUpdateCallback update_callback =
- ReconstructUpdateCallback(progress_update_callback,
- callback_customdata);
+ ReconstructUpdateCallback(progress_update_callback, callback_customdata);
/* Retrieve reconstruction options from C-API to libmv API. */
- CameraIntrinsics *camera_intrinsics;
+ CameraIntrinsics* camera_intrinsics;
camera_intrinsics = libmv_reconstruction->intrinsics =
- libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
+ libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
/* Invert the camera intrinsics/ */
Tracks normalized_tracks;
@@ -276,10 +267,10 @@ libmv_Reconstruction *libmv_solveReconstruction(
update_callback.invoke(0, "Selecting keyframes");
if (selectTwoKeyframesBasedOnGRICAndVariance(tracks,
- normalized_tracks,
- *camera_intrinsics,
- keyframe1,
- keyframe2)) {
+ normalized_tracks,
+ *camera_intrinsics,
+ keyframe1,
+ keyframe2)) {
/* so keyframes in the interface would be updated */
libmv_reconstruction_options->keyframe1 = keyframe1;
libmv_reconstruction_options->keyframe2 = keyframe2;
@@ -290,7 +281,7 @@ libmv_Reconstruction *libmv_solveReconstruction(
LG << "frames to init from: " << keyframe1 << " " << keyframe2;
libmv::vector<Marker> keyframe_markers =
- normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2);
+ normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2);
LG << "number of markers for init: " << keyframe_markers.size();
@@ -309,14 +300,12 @@ libmv_Reconstruction *libmv_solveReconstruction(
}
EuclideanBundle(normalized_tracks, &reconstruction);
- EuclideanCompleteReconstruction(normalized_tracks,
- &reconstruction,
- &update_callback);
+ EuclideanCompleteReconstruction(
+ normalized_tracks, &reconstruction, &update_callback);
/* Refinement. */
if (libmv_reconstruction_options->refine_intrinsics) {
- libmv_solveRefineIntrinsics(
- tracks,
+ libmv_solveRefineIntrinsics(tracks,
libmv_reconstruction_options->refine_intrinsics,
libmv::BUNDLE_NO_CONSTRAINTS,
progress_update_callback,
@@ -336,31 +325,29 @@ libmv_Reconstruction *libmv_solveReconstruction(
callback_customdata);
libmv_reconstruction->is_valid = true;
- return (libmv_Reconstruction *) libmv_reconstruction;
+ return (libmv_Reconstruction*)libmv_reconstruction;
}
-libmv_Reconstruction *libmv_solveModal(
- const libmv_Tracks *libmv_tracks,
- const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
- const libmv_ReconstructionOptions *libmv_reconstruction_options,
+libmv_Reconstruction* libmv_solveModal(
+ const libmv_Tracks* libmv_tracks,
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ const libmv_ReconstructionOptions* libmv_reconstruction_options,
reconstruct_progress_update_cb progress_update_callback,
- void *callback_customdata) {
- libmv_Reconstruction *libmv_reconstruction =
- LIBMV_OBJECT_NEW(libmv_Reconstruction);
+ void* callback_customdata) {
+ libmv_Reconstruction* libmv_reconstruction =
+ LIBMV_OBJECT_NEW(libmv_Reconstruction);
- Tracks &tracks = *((Tracks *) libmv_tracks);
- EuclideanReconstruction &reconstruction =
- libmv_reconstruction->reconstruction;
+ Tracks& tracks = *((Tracks*)libmv_tracks);
+ EuclideanReconstruction& reconstruction =
+ libmv_reconstruction->reconstruction;
ReconstructUpdateCallback update_callback =
- ReconstructUpdateCallback(progress_update_callback,
- callback_customdata);
+ ReconstructUpdateCallback(progress_update_callback, callback_customdata);
/* Retrieve reconstruction options from C-API to libmv API. */
- CameraIntrinsics *camera_intrinsics;
+ CameraIntrinsics* camera_intrinsics;
camera_intrinsics = libmv_reconstruction->intrinsics =
- libmv_cameraIntrinsicsCreateFromOptions(
- libmv_camera_intrinsics_options);
+ libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
/* Invert the camera intrinsics. */
Tracks normalized_tracks;
@@ -378,11 +365,11 @@ libmv_Reconstruction *libmv_solveModal(
/* Refinement. */
if (libmv_reconstruction_options->refine_intrinsics) {
- libmv_solveRefineIntrinsics(
- tracks,
+ libmv_solveRefineIntrinsics(tracks,
libmv_reconstruction_options->refine_intrinsics,
libmv::BUNDLE_NO_TRANSLATION,
- progress_update_callback, callback_customdata,
+ progress_update_callback,
+ callback_customdata,
&reconstruction,
camera_intrinsics);
}
@@ -395,26 +382,25 @@ libmv_Reconstruction *libmv_solveModal(
callback_customdata);
libmv_reconstruction->is_valid = true;
- return (libmv_Reconstruction *) libmv_reconstruction;
+ return (libmv_Reconstruction*)libmv_reconstruction;
}
-int libmv_reconstructionIsValid(libmv_Reconstruction *libmv_reconstruction) {
+int libmv_reconstructionIsValid(libmv_Reconstruction* libmv_reconstruction) {
return libmv_reconstruction->is_valid;
}
-void libmv_reconstructionDestroy(libmv_Reconstruction *libmv_reconstruction) {
+void libmv_reconstructionDestroy(libmv_Reconstruction* libmv_reconstruction) {
LIBMV_OBJECT_DELETE(libmv_reconstruction->intrinsics, CameraIntrinsics);
LIBMV_OBJECT_DELETE(libmv_reconstruction, libmv_Reconstruction);
}
int libmv_reprojectionPointForTrack(
- const libmv_Reconstruction *libmv_reconstruction,
+ const libmv_Reconstruction* libmv_reconstruction,
int track,
double pos[3]) {
- const EuclideanReconstruction *reconstruction =
- &libmv_reconstruction->reconstruction;
- const EuclideanPoint *point =
- reconstruction->PointForTrack(track);
+ const EuclideanReconstruction* reconstruction =
+ &libmv_reconstruction->reconstruction;
+ const EuclideanPoint* point = reconstruction->PointForTrack(track);
if (point) {
pos[0] = point->X[0];
pos[1] = point->X[2];
@@ -425,23 +411,22 @@ int libmv_reprojectionPointForTrack(
}
double libmv_reprojectionErrorForTrack(
- const libmv_Reconstruction *libmv_reconstruction,
- int track) {
- const EuclideanReconstruction *reconstruction =
- &libmv_reconstruction->reconstruction;
- const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics;
+ const libmv_Reconstruction* libmv_reconstruction, int track) {
+ const EuclideanReconstruction* reconstruction =
+ &libmv_reconstruction->reconstruction;
+ const CameraIntrinsics* intrinsics = libmv_reconstruction->intrinsics;
libmv::vector<Marker> markers =
- libmv_reconstruction->tracks.MarkersForTrack(track);
+ libmv_reconstruction->tracks.MarkersForTrack(track);
int num_reprojected = 0;
double total_error = 0.0;
for (int i = 0; i < markers.size(); ++i) {
double weight = markers[i].weight;
- const EuclideanCamera *camera =
- reconstruction->CameraForImage(markers[i].image);
- const EuclideanPoint *point =
- reconstruction->PointForTrack(markers[i].track);
+ const EuclideanCamera* camera =
+ reconstruction->CameraForImage(markers[i].image);
+ const EuclideanPoint* point =
+ reconstruction->PointForTrack(markers[i].track);
if (!camera || !point || weight == 0.0) {
continue;
@@ -450,7 +435,7 @@ double libmv_reprojectionErrorForTrack(
num_reprojected++;
Marker reprojected_marker =
- libmv_projectMarker(*point, *camera, *intrinsics);
+ libmv_projectMarker(*point, *camera, *intrinsics);
double ex = (reprojected_marker.x - markers[i].x) * weight;
double ey = (reprojected_marker.y - markers[i].y) * weight;
@@ -461,14 +446,13 @@ double libmv_reprojectionErrorForTrack(
}
double libmv_reprojectionErrorForImage(
- const libmv_Reconstruction *libmv_reconstruction,
- int image) {
- const EuclideanReconstruction *reconstruction =
- &libmv_reconstruction->reconstruction;
- const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics;
+ const libmv_Reconstruction* libmv_reconstruction, int image) {
+ const EuclideanReconstruction* reconstruction =
+ &libmv_reconstruction->reconstruction;
+ const CameraIntrinsics* intrinsics = libmv_reconstruction->intrinsics;
libmv::vector<Marker> markers =
- libmv_reconstruction->tracks.MarkersInImage(image);
- const EuclideanCamera *camera = reconstruction->CameraForImage(image);
+ libmv_reconstruction->tracks.MarkersInImage(image);
+ const EuclideanCamera* camera = reconstruction->CameraForImage(image);
int num_reprojected = 0;
double total_error = 0.0;
@@ -477,8 +461,8 @@ double libmv_reprojectionErrorForImage(
}
for (int i = 0; i < markers.size(); ++i) {
- const EuclideanPoint *point =
- reconstruction->PointForTrack(markers[i].track);
+ const EuclideanPoint* point =
+ reconstruction->PointForTrack(markers[i].track);
if (!point) {
continue;
@@ -487,7 +471,7 @@ double libmv_reprojectionErrorForImage(
num_reprojected++;
Marker reprojected_marker =
- libmv_projectMarker(*point, *camera, *intrinsics);
+ libmv_projectMarker(*point, *camera, *intrinsics);
double ex = (reprojected_marker.x - markers[i].x) * markers[i].weight;
double ey = (reprojected_marker.y - markers[i].y) * markers[i].weight;
@@ -498,13 +482,12 @@ double libmv_reprojectionErrorForImage(
}
int libmv_reprojectionCameraForImage(
- const libmv_Reconstruction *libmv_reconstruction,
+ const libmv_Reconstruction* libmv_reconstruction,
int image,
double mat[4][4]) {
- const EuclideanReconstruction *reconstruction =
- &libmv_reconstruction->reconstruction;
- const EuclideanCamera *camera =
- reconstruction->CameraForImage(image);
+ const EuclideanReconstruction* reconstruction =
+ &libmv_reconstruction->reconstruction;
+ const EuclideanCamera* camera = reconstruction->CameraForImage(image);
if (camera) {
for (int j = 0; j < 3; ++j) {
@@ -541,11 +524,11 @@ int libmv_reprojectionCameraForImage(
}
double libmv_reprojectionError(
- const libmv_Reconstruction *libmv_reconstruction) {
+ const libmv_Reconstruction* libmv_reconstruction) {
return libmv_reconstruction->error;
}
-libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics(
- libmv_Reconstruction *libmv_reconstruction) {
- return (libmv_CameraIntrinsics *) libmv_reconstruction->intrinsics;
+libmv_CameraIntrinsics* libmv_reconstructionExtractIntrinsics(
+ libmv_Reconstruction* libmv_reconstruction) {
+ return (libmv_CameraIntrinsics*)libmv_reconstruction->intrinsics;
}
diff --git a/intern/libmv/intern/reconstruction.h b/intern/libmv/intern/reconstruction.h
index 408ac884684..600bc92ccfc 100644
--- a/intern/libmv/intern/reconstruction.h
+++ b/intern/libmv/intern/reconstruction.h
@@ -31,17 +31,16 @@ struct libmv_CameraIntrinsicsOptions;
typedef struct libmv_Reconstruction libmv_Reconstruction;
enum {
- LIBMV_REFINE_FOCAL_LENGTH = (1 << 0),
- LIBMV_REFINE_PRINCIPAL_POINT = (1 << 1),
-
- LIBMV_REFINE_RADIAL_DISTORTION_K1 = (1 << 2),
- LIBMV_REFINE_RADIAL_DISTORTION_K2 = (1 << 3),
- LIBMV_REFINE_RADIAL_DISTORTION_K3 = (1 << 4),
- LIBMV_REFINE_RADIAL_DISTORTION_K4 = (1 << 5),
- LIBMV_REFINE_RADIAL_DISTORTION = (LIBMV_REFINE_RADIAL_DISTORTION_K1 |
- LIBMV_REFINE_RADIAL_DISTORTION_K2 |
- LIBMV_REFINE_RADIAL_DISTORTION_K3 |
- LIBMV_REFINE_RADIAL_DISTORTION_K4),
+ LIBMV_REFINE_FOCAL_LENGTH = (1 << 0),
+ LIBMV_REFINE_PRINCIPAL_POINT = (1 << 1),
+
+ LIBMV_REFINE_RADIAL_DISTORTION_K1 = (1 << 2),
+ LIBMV_REFINE_RADIAL_DISTORTION_K2 = (1 << 3),
+ LIBMV_REFINE_RADIAL_DISTORTION_K3 = (1 << 4),
+ LIBMV_REFINE_RADIAL_DISTORTION_K4 = (1 << 5),
+ LIBMV_REFINE_RADIAL_DISTORTION =
+ (LIBMV_REFINE_RADIAL_DISTORTION_K1 | LIBMV_REFINE_RADIAL_DISTORTION_K2 |
+ LIBMV_REFINE_RADIAL_DISTORTION_K3 | LIBMV_REFINE_RADIAL_DISTORTION_K4),
LIBMV_REFINE_TANGENTIAL_DISTORTION_P1 = (1 << 6),
LIBMV_REFINE_TANGENTIAL_DISTORTION_P2 = (1 << 7),
@@ -55,9 +54,9 @@ typedef struct libmv_ReconstructionOptions {
int refine_intrinsics;
} libmv_ReconstructionOptions;
-typedef void (*reconstruct_progress_update_cb) (void* customdata,
- double progress,
- const char* message);
+typedef void (*reconstruct_progress_update_cb)(void* customdata,
+ double progress,
+ const char* message);
libmv_Reconstruction* libmv_solveReconstruction(
const struct libmv_Tracks* libmv_tracks,
@@ -73,35 +72,32 @@ libmv_Reconstruction* libmv_solveModal(
reconstruct_progress_update_cb progress_update_callback,
void* callback_customdata);
-int libmv_reconstructionIsValid(libmv_Reconstruction *libmv_reconstruction);
+int libmv_reconstructionIsValid(libmv_Reconstruction* libmv_reconstruction);
void libmv_reconstructionDestroy(libmv_Reconstruction* libmv_reconstruction);
int libmv_reprojectionPointForTrack(
- const libmv_Reconstruction* libmv_reconstruction,
- int track,
- double pos[3]);
+ const libmv_Reconstruction* libmv_reconstruction, int track, double pos[3]);
double libmv_reprojectionErrorForTrack(
- const libmv_Reconstruction* libmv_reconstruction,
- int track);
+ const libmv_Reconstruction* libmv_reconstruction, int track);
double libmv_reprojectionErrorForImage(
- const libmv_Reconstruction* libmv_reconstruction,
- int image);
+ const libmv_Reconstruction* libmv_reconstruction, int image);
int libmv_reprojectionCameraForImage(
const libmv_Reconstruction* libmv_reconstruction,
int image,
double mat[4][4]);
-double libmv_reprojectionError(const libmv_Reconstruction* libmv_reconstruction);
+double libmv_reprojectionError(
+ const libmv_Reconstruction* libmv_reconstruction);
struct libmv_CameraIntrinsics* libmv_reconstructionExtractIntrinsics(
- libmv_Reconstruction *libmv_Reconstruction);
+ libmv_Reconstruction* libmv_Reconstruction);
#ifdef __cplusplus
}
#endif
-#endif // LIBMV_C_API_RECONSTRUCTION_H_
+#endif // LIBMV_C_API_RECONSTRUCTION_H_
diff --git a/intern/libmv/intern/stub.cc b/intern/libmv/intern/stub.cc
index 47e1896b4cf..1920042b4ec 100644
--- a/intern/libmv/intern/stub.cc
+++ b/intern/libmv/intern/stub.cc
@@ -24,7 +24,7 @@
/* ************ Logging ************ */
-void libmv_initLogging(const char * /*argv0*/) {
+void libmv_initLogging(const char* /*argv0*/) {
}
void libmv_startDebugLogging(void) {
@@ -36,18 +36,18 @@ void libmv_setLoggingVerbosity(int /*verbosity*/) {
/* ************ Planar tracker ************ */
/* TrackRegion (new planar tracker) */
-int libmv_trackRegion(const libmv_TrackRegionOptions * /*options*/,
- const float * /*image1*/,
+int libmv_trackRegion(const libmv_TrackRegionOptions* /*options*/,
+ const float* /*image1*/,
int /*image1_width*/,
int /*image1_height*/,
- const float * /*image2*/,
+ const float* /*image2*/,
int /*image2_width*/,
int /*image2_height*/,
- const double *x1,
- const double *y1,
- libmv_TrackRegionResult *result,
- double *x2,
- double *y2) {
+ const double* x1,
+ const double* y1,
+ libmv_TrackRegionResult* result,
+ double* x2,
+ double* y2) {
/* Convert to doubles for the libmv api. The four corners and the center. */
for (int i = 0; i < 5; ++i) {
x2[i] = x1[i];
@@ -61,46 +61,46 @@ int libmv_trackRegion(const libmv_TrackRegionOptions * /*options*/,
return false;
}
-void libmv_samplePlanarPatchFloat(const float * /*image*/,
+void libmv_samplePlanarPatchFloat(const float* /*image*/,
int /*width*/,
int /*height*/,
int /*channels*/,
- const double * /*xs*/,
- const double * /*ys*/,
+ const double* /*xs*/,
+ const double* /*ys*/,
int /*num_samples_x*/,
int /*num_samples_y*/,
- const float * /*mask*/,
- float * /*patch*/,
- double * /*warped_position_x*/,
- double * /*warped_position_y*/) {
+ const float* /*mask*/,
+ float* /*patch*/,
+ double* /*warped_position_x*/,
+ double* /*warped_position_y*/) {
/* TODO(sergey): implement */
}
-void libmv_samplePlanarPatchByte(const unsigned char * /*image*/,
+void libmv_samplePlanarPatchByte(const unsigned char* /*image*/,
int /*width*/,
int /*height*/,
int /*channels*/,
- const double * /*xs*/,
- const double * /*ys*/,
- int /*num_samples_x*/, int /*num_samples_y*/,
- const float * /*mask*/,
- unsigned char * /*patch*/,
- double * /*warped_position_x*/,
- double * /*warped_position_y*/) {
+ const double* /*xs*/,
+ const double* /*ys*/,
+ int /*num_samples_x*/,
+ int /*num_samples_y*/,
+ const float* /*mask*/,
+ unsigned char* /*patch*/,
+ double* /*warped_position_x*/,
+ double* /*warped_position_y*/) {
/* TODO(sergey): implement */
}
-void libmv_floatImageDestroy(libmv_FloatImage* /*image*/)
-{
+void libmv_floatImageDestroy(libmv_FloatImage* /*image*/) {
}
/* ************ Tracks ************ */
-libmv_Tracks *libmv_tracksNew(void) {
+libmv_Tracks* libmv_tracksNew(void) {
return NULL;
}
-void libmv_tracksInsert(libmv_Tracks * /*libmv_tracks*/,
+void libmv_tracksInsert(libmv_Tracks* /*libmv_tracks*/,
int /*image*/,
int /*track*/,
double /*x*/,
@@ -108,152 +108,152 @@ void libmv_tracksInsert(libmv_Tracks * /*libmv_tracks*/,
double /*weight*/) {
}
-void libmv_tracksDestroy(libmv_Tracks * /*libmv_tracks*/) {
+void libmv_tracksDestroy(libmv_Tracks* /*libmv_tracks*/) {
}
/* ************ Reconstruction solver ************ */
-libmv_Reconstruction *libmv_solveReconstruction(
- const libmv_Tracks * /*libmv_tracks*/,
- const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/,
- libmv_ReconstructionOptions * /*libmv_reconstruction_options*/,
+libmv_Reconstruction* libmv_solveReconstruction(
+ const libmv_Tracks* /*libmv_tracks*/,
+ const libmv_CameraIntrinsicsOptions* /*libmv_camera_intrinsics_options*/,
+ libmv_ReconstructionOptions* /*libmv_reconstruction_options*/,
reconstruct_progress_update_cb /*progress_update_callback*/,
- void * /*callback_customdata*/) {
+ void* /*callback_customdata*/) {
return NULL;
}
-libmv_Reconstruction *libmv_solveModal(
- const libmv_Tracks * /*libmv_tracks*/,
- const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/,
- const libmv_ReconstructionOptions * /*libmv_reconstruction_options*/,
+libmv_Reconstruction* libmv_solveModal(
+ const libmv_Tracks* /*libmv_tracks*/,
+ const libmv_CameraIntrinsicsOptions* /*libmv_camera_intrinsics_options*/,
+ const libmv_ReconstructionOptions* /*libmv_reconstruction_options*/,
reconstruct_progress_update_cb /*progress_update_callback*/,
- void * /*callback_customdata*/) {
+ void* /*callback_customdata*/) {
return NULL;
}
-int libmv_reconstructionIsValid(libmv_Reconstruction * /*libmv_reconstruction*/) {
+int libmv_reconstructionIsValid(
+ libmv_Reconstruction* /*libmv_reconstruction*/) {
return 0;
}
int libmv_reprojectionPointForTrack(
- const libmv_Reconstruction * /*libmv_reconstruction*/,
+ const libmv_Reconstruction* /*libmv_reconstruction*/,
int /*track*/,
double /*pos*/[3]) {
return 0;
}
double libmv_reprojectionErrorForTrack(
- const libmv_Reconstruction * /*libmv_reconstruction*/,
- int /*track*/) {
+ const libmv_Reconstruction* /*libmv_reconstruction*/, int /*track*/) {
return 0.0;
}
double libmv_reprojectionErrorForImage(
- const libmv_Reconstruction * /*libmv_reconstruction*/,
- int /*image*/) {
+ const libmv_Reconstruction* /*libmv_reconstruction*/, int /*image*/) {
return 0.0;
}
int libmv_reprojectionCameraForImage(
- const libmv_Reconstruction * /*libmv_reconstruction*/,
+ const libmv_Reconstruction* /*libmv_reconstruction*/,
int /*image*/,
double /*mat*/[4][4]) {
return 0;
}
double libmv_reprojectionError(
- const libmv_Reconstruction * /*libmv_reconstruction*/) {
+ const libmv_Reconstruction* /*libmv_reconstruction*/) {
return 0.0;
}
void libmv_reconstructionDestroy(
- struct libmv_Reconstruction * /*libmv_reconstruction*/) {
+ struct libmv_Reconstruction* /*libmv_reconstruction*/) {
}
/* ************ Feature detector ************ */
-libmv_Features *libmv_detectFeaturesByte(const unsigned char * /*image_buffer*/,
+libmv_Features* libmv_detectFeaturesByte(const unsigned char* /*image_buffer*/,
int /*width*/,
int /*height*/,
int /*channels*/,
- libmv_DetectOptions * /*options*/) {
+ libmv_DetectOptions* /*options*/) {
return NULL;
}
-struct libmv_Features *libmv_detectFeaturesFloat(
- const float * /*image_buffer*/,
+struct libmv_Features* libmv_detectFeaturesFloat(
+ const float* /*image_buffer*/,
int /*width*/,
int /*height*/,
int /*channels*/,
- libmv_DetectOptions * /*options*/) {
+ libmv_DetectOptions* /*options*/) {
return NULL;
}
-int libmv_countFeatures(const libmv_Features * /*libmv_features*/) {
+int libmv_countFeatures(const libmv_Features* /*libmv_features*/) {
return 0;
}
-void libmv_getFeature(const libmv_Features * /*libmv_features*/,
+void libmv_getFeature(const libmv_Features* /*libmv_features*/,
int /*number*/,
- double *x,
- double *y,
- double *score,
- double *size) {
+ double* x,
+ double* y,
+ double* score,
+ double* size) {
*x = 0.0;
*y = 0.0;
*score = 0.0;
*size = 0.0;
}
-void libmv_featuresDestroy(struct libmv_Features * /*libmv_features*/) {
+void libmv_featuresDestroy(struct libmv_Features* /*libmv_features*/) {
}
/* ************ Camera intrinsics ************ */
-libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics(
- libmv_Reconstruction * /*libmv_reconstruction*/) {
+libmv_CameraIntrinsics* libmv_reconstructionExtractIntrinsics(
+ libmv_Reconstruction* /*libmv_reconstruction*/) {
return NULL;
}
-libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
- const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/) {
+libmv_CameraIntrinsics* libmv_cameraIntrinsicsNew(
+ const libmv_CameraIntrinsicsOptions* /*libmv_camera_intrinsics_options*/) {
return NULL;
}
-libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
- const libmv_CameraIntrinsics * /*libmvIntrinsics*/) {
+libmv_CameraIntrinsics* libmv_cameraIntrinsicsCopy(
+ const libmv_CameraIntrinsics* /*libmvIntrinsics*/) {
return NULL;
}
void libmv_cameraIntrinsicsDestroy(
- libmv_CameraIntrinsics * /*libmvIntrinsics*/) {
+ libmv_CameraIntrinsics* /*libmvIntrinsics*/) {
}
void libmv_cameraIntrinsicsUpdate(
- const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/,
- libmv_CameraIntrinsics * /*libmv_intrinsics*/) {
+ const libmv_CameraIntrinsicsOptions* /*libmv_camera_intrinsics_options*/,
+ libmv_CameraIntrinsics* /*libmv_intrinsics*/) {
}
void libmv_cameraIntrinsicsSetThreads(
- libmv_CameraIntrinsics * /*libmv_intrinsics*/,
- int /*threads*/) {
+ libmv_CameraIntrinsics* /*libmv_intrinsics*/, int /*threads*/) {
}
void libmv_cameraIntrinsicsExtractOptions(
- const libmv_CameraIntrinsics * /*libmv_intrinsics*/,
- libmv_CameraIntrinsicsOptions *camera_intrinsics_options) {
+ const libmv_CameraIntrinsics* /*libmv_intrinsics*/,
+ libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
memset(camera_intrinsics_options, 0, sizeof(libmv_CameraIntrinsicsOptions));
camera_intrinsics_options->focal_length = 1.0;
}
void libmv_cameraIntrinsicsUndistortByte(
- const libmv_CameraIntrinsics * /*libmv_intrinsics*/,
- const unsigned char *source_image,
- int width, int height,
+ const libmv_CameraIntrinsics* /*libmv_intrinsics*/,
+ const unsigned char* source_image,
+ int width,
+ int height,
float /*overscan*/,
int channels,
- unsigned char *destination_image) {
- memcpy(destination_image, source_image,
+ unsigned char* destination_image) {
+ memcpy(destination_image,
+ source_image,
channels * width * height * sizeof(unsigned char));
}
@@ -265,19 +265,21 @@ void libmv_cameraIntrinsicsUndistortFloat(
float /*overscan*/,
int channels,
float* destination_image) {
- memcpy(destination_image, source_image,
+ memcpy(destination_image,
+ source_image,
channels * width * height * sizeof(float));
}
void libmv_cameraIntrinsicsDistortByte(
const struct libmv_CameraIntrinsics* /*libmv_intrinsics*/,
- const unsigned char *source_image,
+ const unsigned char* source_image,
int width,
int height,
float /*overscan*/,
int channels,
- unsigned char *destination_image) {
- memcpy(destination_image, source_image,
+ unsigned char* destination_image) {
+ memcpy(destination_image,
+ source_image,
channels * width * height * sizeof(unsigned char));
}
@@ -289,7 +291,8 @@ void libmv_cameraIntrinsicsDistortFloat(
float /*overscan*/,
int channels,
float* destination_image) {
- memcpy(destination_image, source_image,
+ memcpy(destination_image,
+ source_image,
channels * width * height * sizeof(float));
}
@@ -315,8 +318,8 @@ void libmv_cameraIntrinsicsInvert(
*y1 = 0.0;
}
-void libmv_homography2DFromCorrespondencesEuc(/* const */ double (* /*x1*/)[2],
- /* const */ double (* /*x2*/)[2],
+void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*/*x1*/)[2],
+ /* const */ double (*/*x2*/)[2],
int /*num_points*/,
double H[3][3]) {
memset(H, 0, sizeof(double[3][3]));
@@ -327,45 +330,38 @@ void libmv_homography2DFromCorrespondencesEuc(/* const */ double (* /*x1*/)[2],
/* ************ autotrack ************ */
-libmv_AutoTrack* libmv_autoTrackNew(libmv_FrameAccessor* /*frame_accessor*/)
-{
+libmv_AutoTrack* libmv_autoTrackNew(libmv_FrameAccessor* /*frame_accessor*/) {
return NULL;
}
-void libmv_autoTrackDestroy(libmv_AutoTrack* /*libmv_autotrack*/)
-{
+void libmv_autoTrackDestroy(libmv_AutoTrack* /*libmv_autotrack*/) {
}
void libmv_autoTrackSetOptions(libmv_AutoTrack* /*libmv_autotrack*/,
- const libmv_AutoTrackOptions* /*options*/)
-{
+ const libmv_AutoTrackOptions* /*options*/) {
}
int libmv_autoTrackMarker(libmv_AutoTrack* /*libmv_autotrack*/,
const libmv_TrackRegionOptions* /*libmv_options*/,
- libmv_Marker * /*libmv_tracker_marker*/,
- libmv_TrackRegionResult* /*libmv_result*/)
-{
+ libmv_Marker* /*libmv_tracker_marker*/,
+ libmv_TrackRegionResult* /*libmv_result*/) {
return 0;
}
void libmv_autoTrackAddMarker(libmv_AutoTrack* /*libmv_autotrack*/,
- const libmv_Marker* /*libmv_marker*/)
-{
+ const libmv_Marker* /*libmv_marker*/) {
}
void libmv_autoTrackSetMarkers(libmv_AutoTrack* /*libmv_autotrack*/,
const libmv_Marker* /*libmv_marker-*/,
- size_t /*num_markers*/)
-{
+ size_t /*num_markers*/) {
}
int libmv_autoTrackGetMarker(libmv_AutoTrack* /*libmv_autotrack*/,
int /*clip*/,
int /*frame*/,
int /*track*/,
- libmv_Marker* /*libmv_marker*/)
-{
+ libmv_Marker* /*libmv_marker*/) {
return 0;
}
@@ -376,24 +372,20 @@ libmv_FrameAccessor* libmv_FrameAccessorNew(
libmv_GetImageCallback /*get_image_callback*/,
libmv_ReleaseImageCallback /*release_image_callback*/,
libmv_GetMaskForTrackCallback /*get_mask_for_track_callback*/,
- libmv_ReleaseMaskCallback /*release_mask_callback*/)
-{
+ libmv_ReleaseMaskCallback /*release_mask_callback*/) {
return NULL;
}
-void libmv_FrameAccessorDestroy(libmv_FrameAccessor* /*frame_accessor*/)
-{
+void libmv_FrameAccessorDestroy(libmv_FrameAccessor* /*frame_accessor*/) {
}
int64_t libmv_frameAccessorgetTransformKey(
- const libmv_FrameTransform * /*transform*/)
-{
+ const libmv_FrameTransform* /*transform*/) {
return 0;
}
-void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform* /*transform*/,
- const libmv_FloatImage* /*input_image*/,
- libmv_FloatImage* /*output_image*/)
-{
+void libmv_frameAccessorgetTransformRun(
+ const libmv_FrameTransform* /*transform*/,
+ const libmv_FloatImage* /*input_image*/,
+ libmv_FloatImage* /*output_image*/) {
}
-
diff --git a/intern/libmv/intern/track_region.cc b/intern/libmv/intern/track_region.cc
index 2a3909c0ced..af88afd7ac2 100644
--- a/intern/libmv/intern/track_region.cc
+++ b/intern/libmv/intern/track_region.cc
@@ -32,17 +32,17 @@
#undef DUMP_ALWAYS
using libmv::FloatImage;
+using libmv::TrackRegion;
using libmv::TrackRegionOptions;
using libmv::TrackRegionResult;
-using libmv::TrackRegion;
void libmv_configureTrackRegionOptions(
const libmv_TrackRegionOptions& options,
TrackRegionOptions* track_region_options) {
switch (options.motion_model) {
-#define LIBMV_CONVERT(the_model) \
- case TrackRegionOptions::the_model: \
- track_region_options->mode = TrackRegionOptions::the_model; \
+#define LIBMV_CONVERT(the_model) \
+ case TrackRegionOptions::the_model: \
+ track_region_options->mode = TrackRegionOptions::the_model; \
break;
LIBMV_CONVERT(TRANSLATION)
LIBMV_CONVERT(TRANSLATION_ROTATION)
@@ -66,7 +66,8 @@ void libmv_configureTrackRegionOptions(
* so disabling for now for until proper prediction model is landed.
*
* The thing is, currently blender sends input coordinates as the guess to
- * region tracker and in case of fast motion such an early out ruins the track.
+ * region tracker and in case of fast motion such an early out ruins the
+ * track.
*/
track_region_options->attempt_refine_before_brute = false;
track_region_options->use_normalized_intensities = options.use_normalization;
@@ -74,7 +75,7 @@ void libmv_configureTrackRegionOptions(
void libmv_regionTrackergetResult(const TrackRegionResult& track_region_result,
libmv_TrackRegionResult* result) {
- result->termination = (int) track_region_result.termination;
+ result->termination = (int)track_region_result.termination;
result->termination_reason = "";
result->correlation = track_region_result.correlation;
}
@@ -108,33 +109,27 @@ int libmv_trackRegion(const libmv_TrackRegionOptions* options,
libmv_configureTrackRegionOptions(*options, &track_region_options);
if (options->image1_mask) {
- libmv_floatBufferToFloatImage(options->image1_mask,
- image1_width,
- image1_height,
- 1,
- &image1_mask);
+ libmv_floatBufferToFloatImage(
+ options->image1_mask, image1_width, image1_height, 1, &image1_mask);
track_region_options.image1_mask = &image1_mask;
}
// Convert from raw float buffers to libmv's FloatImage.
FloatImage old_patch, new_patch;
- libmv_floatBufferToFloatImage(image1,
- image1_width,
- image1_height,
- 1,
- &old_patch);
- libmv_floatBufferToFloatImage(image2,
- image2_width,
- image2_height,
- 1,
- &new_patch);
+ libmv_floatBufferToFloatImage(
+ image1, image1_width, image1_height, 1, &old_patch);
+ libmv_floatBufferToFloatImage(
+ image2, image2_width, image2_height, 1, &new_patch);
TrackRegionResult track_region_result;
- TrackRegion(old_patch, new_patch,
- xx1, yy1,
+ TrackRegion(old_patch,
+ new_patch,
+ xx1,
+ yy1,
track_region_options,
- xx2, yy2,
+ xx2,
+ yy2,
&track_region_result);
// Convert to floats for the blender api.
diff --git a/intern/libmv/intern/track_region.h b/intern/libmv/intern/track_region.h
index 48ae97a1c1a..4566fe9bf0f 100644
--- a/intern/libmv/intern/track_region.h
+++ b/intern/libmv/intern/track_region.h
@@ -31,7 +31,7 @@ typedef struct libmv_TrackRegionOptions {
int use_normalization;
double minimum_correlation;
double sigma;
- float *image1_mask;
+ float* image1_mask;
} libmv_TrackRegionOptions;
typedef struct libmv_TrackRegionResult {
@@ -42,9 +42,9 @@ typedef struct libmv_TrackRegionResult {
#ifdef __cplusplus
namespace libmv {
- struct TrackRegionOptions;
- struct TrackRegionResult;
-}
+struct TrackRegionOptions;
+struct TrackRegionResult;
+} // namespace libmv
void libmv_configureTrackRegionOptions(
const libmv_TrackRegionOptions& options,
libmv::TrackRegionOptions* track_region_options);
diff --git a/intern/libmv/intern/tracks.cc b/intern/libmv/intern/tracks.cc
index 0ca5a31796b..146908d6db5 100644
--- a/intern/libmv/intern/tracks.cc
+++ b/intern/libmv/intern/tracks.cc
@@ -28,18 +28,18 @@ using libmv::Tracks;
libmv_Tracks* libmv_tracksNew(void) {
Tracks* tracks = LIBMV_OBJECT_NEW(Tracks);
- return (libmv_Tracks*) tracks;
+ return (libmv_Tracks*)tracks;
}
void libmv_tracksDestroy(libmv_Tracks* libmv_tracks) {
LIBMV_OBJECT_DELETE(libmv_tracks, Tracks);
}
-void libmv_tracksInsert(libmv_Tracks *libmv_tracks,
+void libmv_tracksInsert(libmv_Tracks* libmv_tracks,
int image,
int track,
double x,
double y,
double weight) {
- ((Tracks *) libmv_tracks)->Insert(image, track, x, y, weight);
+ ((Tracks*)libmv_tracks)->Insert(image, track, x, y, weight);
}
diff --git a/intern/libmv/intern/tracksN.cc b/intern/libmv/intern/tracksN.cc
index 1441d8a2066..c7ffb13a386 100644
--- a/intern/libmv/intern/tracksN.cc
+++ b/intern/libmv/intern/tracksN.cc
@@ -25,8 +25,7 @@
using mv::Marker;
using mv::Tracks;
-void libmv_apiMarkerToMarker(const libmv_Marker& libmv_marker,
- Marker *marker) {
+void libmv_apiMarkerToMarker(const libmv_Marker& libmv_marker, Marker* marker) {
marker->clip = libmv_marker.clip;
marker->frame = libmv_marker.frame;
marker->track = libmv_marker.track;
@@ -41,17 +40,16 @@ void libmv_apiMarkerToMarker(const libmv_Marker& libmv_marker,
marker->search_region.max(0) = libmv_marker.search_region_max[0];
marker->search_region.max(1) = libmv_marker.search_region_max[1];
marker->weight = libmv_marker.weight;
- marker->source = (Marker::Source) libmv_marker.source;
- marker->status = (Marker::Status) libmv_marker.status;
+ marker->source = (Marker::Source)libmv_marker.source;
+ marker->status = (Marker::Status)libmv_marker.status;
marker->reference_clip = libmv_marker.reference_clip;
marker->reference_frame = libmv_marker.reference_frame;
- marker->model_type = (Marker::ModelType) libmv_marker.model_type;
+ marker->model_type = (Marker::ModelType)libmv_marker.model_type;
marker->model_id = libmv_marker.model_id;
marker->disabled_channels = libmv_marker.disabled_channels;
}
-void libmv_markerToApiMarker(const Marker& marker,
- libmv_Marker *libmv_marker) {
+void libmv_markerToApiMarker(const Marker& marker, libmv_Marker* libmv_marker) {
libmv_marker->clip = marker.clip;
libmv_marker->frame = marker.frame;
libmv_marker->track = marker.track;
@@ -66,11 +64,11 @@ void libmv_markerToApiMarker(const Marker& marker,
libmv_marker->search_region_max[0] = marker.search_region.max(0);
libmv_marker->search_region_max[1] = marker.search_region.max(1);
libmv_marker->weight = marker.weight;
- libmv_marker->source = (libmv_MarkerSource) marker.source;
- libmv_marker->status = (libmv_MarkerStatus) marker.status;
+ libmv_marker->source = (libmv_MarkerSource)marker.source;
+ libmv_marker->status = (libmv_MarkerStatus)marker.status;
libmv_marker->reference_clip = marker.reference_clip;
libmv_marker->reference_frame = marker.reference_frame;
- libmv_marker->model_type = (libmv_MarkerModelType) marker.model_type;
+ libmv_marker->model_type = (libmv_MarkerModelType)marker.model_type;
libmv_marker->model_id = marker.model_id;
libmv_marker->disabled_channels = marker.disabled_channels;
}
@@ -78,7 +76,7 @@ void libmv_markerToApiMarker(const Marker& marker,
libmv_TracksN* libmv_tracksNewN(void) {
Tracks* tracks = LIBMV_OBJECT_NEW(Tracks);
- return (libmv_TracksN*) tracks;
+ return (libmv_TracksN*)tracks;
}
void libmv_tracksDestroyN(libmv_TracksN* libmv_tracks) {
@@ -89,7 +87,7 @@ void libmv_tracksAddMarkerN(libmv_TracksN* libmv_tracks,
const libmv_Marker* libmv_marker) {
Marker marker;
libmv_apiMarkerToMarker(*libmv_marker, &marker);
- ((Tracks*) libmv_tracks)->AddMarker(marker);
+ ((Tracks*)libmv_tracks)->AddMarker(marker);
}
void libmv_tracksGetMarkerN(libmv_TracksN* libmv_tracks,
@@ -98,7 +96,7 @@ void libmv_tracksGetMarkerN(libmv_TracksN* libmv_tracks,
int track,
libmv_Marker* libmv_marker) {
Marker marker;
- ((Tracks*) libmv_tracks)->GetMarker(clip, frame, track, &marker);
+ ((Tracks*)libmv_tracks)->GetMarker(clip, frame, track, &marker);
libmv_markerToApiMarker(marker, libmv_marker);
}
@@ -106,26 +104,25 @@ void libmv_tracksRemoveMarkerN(libmv_TracksN* libmv_tracks,
int clip,
int frame,
int track) {
- ((Tracks *) libmv_tracks)->RemoveMarker(clip, frame, track);
+ ((Tracks*)libmv_tracks)->RemoveMarker(clip, frame, track);
}
-void libmv_tracksRemoveMarkersForTrack(libmv_TracksN* libmv_tracks,
- int track) {
- ((Tracks *) libmv_tracks)->RemoveMarkersForTrack(track);
+void libmv_tracksRemoveMarkersForTrack(libmv_TracksN* libmv_tracks, int track) {
+ ((Tracks*)libmv_tracks)->RemoveMarkersForTrack(track);
}
int libmv_tracksMaxClipN(libmv_TracksN* libmv_tracks) {
- return ((Tracks*) libmv_tracks)->MaxClip();
+ return ((Tracks*)libmv_tracks)->MaxClip();
}
int libmv_tracksMaxFrameN(libmv_TracksN* libmv_tracks, int clip) {
- return ((Tracks*) libmv_tracks)->MaxFrame(clip);
+ return ((Tracks*)libmv_tracks)->MaxFrame(clip);
}
int libmv_tracksMaxTrackN(libmv_TracksN* libmv_tracks) {
- return ((Tracks*) libmv_tracks)->MaxTrack();
+ return ((Tracks*)libmv_tracks)->MaxTrack();
}
int libmv_tracksNumMarkersN(libmv_TracksN* libmv_tracks) {
- return ((Tracks*) libmv_tracks)->NumMarkers();
+ return ((Tracks*)libmv_tracks)->NumMarkers();
}
diff --git a/intern/libmv/intern/tracksN.h b/intern/libmv/intern/tracksN.h
index 9363d34bed7..b5d1f9753e0 100644
--- a/intern/libmv/intern/tracksN.h
+++ b/intern/libmv/intern/tracksN.h
@@ -79,20 +79,19 @@ typedef struct libmv_Marker {
#ifdef __cplusplus
namespace mv {
- struct Marker;
+struct Marker;
}
void libmv_apiMarkerToMarker(const libmv_Marker& libmv_marker,
- mv::Marker *marker);
+ mv::Marker* marker);
void libmv_markerToApiMarker(const mv::Marker& marker,
- libmv_Marker *libmv_marker);
+ libmv_Marker* libmv_marker);
#endif
libmv_TracksN* libmv_tracksNewN(void);
void libmv_tracksDestroyN(libmv_TracksN* libmv_tracks);
-
void libmv_tracksAddMarkerN(libmv_TracksN* libmv_tracks,
const libmv_Marker* libmv_marker);
@@ -107,8 +106,7 @@ void libmv_tracksRemoveMarkerN(libmv_TracksN* libmv_tracks,
int frame,
int track);
-void libmv_tracksRemoveMarkersForTrack(libmv_TracksN* libmv_tracks,
- int track);
+void libmv_tracksRemoveMarkersForTrack(libmv_TracksN* libmv_tracks, int track);
int libmv_tracksMaxClipN(libmv_TracksN* libmv_tracks);
int libmv_tracksMaxFrameN(libmv_TracksN* libmv_tracks, int clip);
diff --git a/intern/libmv/intern/utildefines.h b/intern/libmv/intern/utildefines.h
index d76d32f9c4d..052052a1d76 100644
--- a/intern/libmv/intern/utildefines.h
+++ b/intern/libmv/intern/utildefines.h
@@ -30,27 +30,33 @@
# define LIBMV_OBJECT_NEW OBJECT_GUARDED_NEW
# define LIBMV_OBJECT_DELETE OBJECT_GUARDED_DELETE
# define LIBMV_OBJECT_DELETE OBJECT_GUARDED_DELETE
-# define LIBMV_STRUCT_NEW(type, count) \
- (type*)MEM_mallocN(sizeof(type) * count, __func__)
+# define LIBMV_STRUCT_NEW(type, count) \
+ (type*)MEM_mallocN(sizeof(type) * count, __func__)
# define LIBMV_STRUCT_DELETE(what) MEM_freeN(what)
#else
// Need this to keep libmv-capi potentially standalone.
# if defined __GNUC__ || defined __sun
-# define LIBMV_OBJECT_NEW(type, args ...) \
- new(malloc(sizeof(type))) type(args)
+# define LIBMV_OBJECT_NEW(type, args...) \
+ new (malloc(sizeof(type))) type(args)
# else
-# define LIBMV_OBJECT_NEW(type, ...) \
- new(malloc(sizeof(type))) type(__VA_ARGS__)
-#endif
-# define LIBMV_OBJECT_DELETE(what, type) \
- { \
- if (what) { \
- ((type*)(what))->~type(); \
- free(what); \
- } \
- } (void)0
+# define LIBMV_OBJECT_NEW(type, ...) \
+ new (malloc(sizeof(type))) type(__VA_ARGS__)
+# endif
+# define LIBMV_OBJECT_DELETE(what, type) \
+ { \
+ if (what) { \
+ ((type*)(what))->~type(); \
+ free(what); \
+ } \
+ } \
+ (void)0
# define LIBMV_STRUCT_NEW(type, count) (type*)malloc(sizeof(type) * count)
-# define LIBMV_STRUCT_DELETE(what) { if (what) free(what); } (void)0
+# define LIBMV_STRUCT_DELETE(what) \
+ { \
+ if (what) \
+ free(what); \
+ } \
+ (void)0
#endif
#endif // LIBMV_C_API_UTILDEFINES_H_
diff --git a/intern/libmv/libmv/autotrack/autotrack.cc b/intern/libmv/libmv/autotrack/autotrack.cc
index 3b0a762178a..c18567a5f28 100644
--- a/intern/libmv/libmv/autotrack/autotrack.cc
+++ b/intern/libmv/libmv/autotrack/autotrack.cc
@@ -21,9 +21,9 @@
// Author: mierle@gmail.com (Keir Mierle)
#include "libmv/autotrack/autotrack.h"
-#include "libmv/autotrack/quad.h"
#include "libmv/autotrack/frame_accessor.h"
#include "libmv/autotrack/predict_tracks.h"
+#include "libmv/autotrack/quad.h"
#include "libmv/base/scoped_ptr.h"
#include "libmv/logging/logging.h"
#include "libmv/numeric/numeric.h"
@@ -35,34 +35,30 @@ namespace {
class DisableChannelsTransform : public FrameAccessor::Transform {
public:
DisableChannelsTransform(int disabled_channels)
- : disabled_channels_(disabled_channels) { }
+ : disabled_channels_(disabled_channels) {}
- int64_t key() const {
- return disabled_channels_;
- }
+ int64_t key() const { return disabled_channels_; }
void run(const FloatImage& input, FloatImage* output) const {
- bool disable_red = (disabled_channels_ & Marker::CHANNEL_R) != 0,
+ bool disable_red = (disabled_channels_ & Marker::CHANNEL_R) != 0,
disable_green = (disabled_channels_ & Marker::CHANNEL_G) != 0,
- disable_blue = (disabled_channels_ & Marker::CHANNEL_B) != 0;
+ disable_blue = (disabled_channels_ & Marker::CHANNEL_B) != 0;
- LG << "Disabling channels: "
- << (disable_red ? "R " : "")
- << (disable_green ? "G " : "")
- << (disable_blue ? "B" : "");
+ LG << "Disabling channels: " << (disable_red ? "R " : "")
+ << (disable_green ? "G " : "") << (disable_blue ? "B" : "");
// It's important to rescale the resultappropriately so that e.g. if only
// blue is selected, it's not zeroed out.
- float scale = (disable_red ? 0.0f : 0.2126f) +
+ float scale = (disable_red ? 0.0f : 0.2126f) +
(disable_green ? 0.0f : 0.7152f) +
- (disable_blue ? 0.0f : 0.0722f);
+ (disable_blue ? 0.0f : 0.0722f);
output->Resize(input.Height(), input.Width(), 1);
for (int y = 0; y < input.Height(); y++) {
for (int x = 0; x < input.Width(); x++) {
- float r = disable_red ? 0.0f : input(y, x, 0);
+ float r = disable_red ? 0.0f : input(y, x, 0);
float g = disable_green ? 0.0f : input(y, x, 1);
- float b = disable_blue ? 0.0f : input(y, x, 2);
+ float b = disable_blue ? 0.0f : input(y, x, 2);
(*output)(y, x, 0) = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
}
}
@@ -73,7 +69,7 @@ class DisableChannelsTransform : public FrameAccessor::Transform {
int disabled_channels_;
};
-template<typename QuadT, typename ArrayT>
+template <typename QuadT, typename ArrayT>
void QuadToArrays(const QuadT& quad, ArrayT* x, ArrayT* y) {
for (int i = 0; i < 4; ++i) {
x[i] = quad.coordinates(i, 0);
@@ -115,11 +111,8 @@ FrameAccessor::Key GetMaskForMarker(const Marker& marker,
FrameAccessor* frame_accessor,
FloatImage* mask) {
Region region = marker.search_region.Rounded();
- return frame_accessor->GetMaskForTrack(marker.clip,
- marker.frame,
- marker.track,
- &region,
- mask);
+ return frame_accessor->GetMaskForTrack(
+ marker.clip, marker.frame, marker.track, &region, mask);
}
} // namespace
@@ -152,23 +145,20 @@ bool AutoTrack::TrackMarker(Marker* tracked_marker,
// TODO(keir): Technically this could take a smaller slice from the source
// image instead of taking one the size of the search window.
FloatImage reference_image;
- FrameAccessor::Key reference_key = GetImageForMarker(reference_marker,
- frame_accessor_,
- &reference_image);
+ FrameAccessor::Key reference_key =
+ GetImageForMarker(reference_marker, frame_accessor_, &reference_image);
if (!reference_key) {
LG << "Couldn't get frame for reference marker: " << reference_marker;
return false;
}
FloatImage reference_mask;
- FrameAccessor::Key reference_mask_key = GetMaskForMarker(reference_marker,
- frame_accessor_,
- &reference_mask);
+ FrameAccessor::Key reference_mask_key =
+ GetMaskForMarker(reference_marker, frame_accessor_, &reference_mask);
FloatImage tracked_image;
- FrameAccessor::Key tracked_key = GetImageForMarker(*tracked_marker,
- frame_accessor_,
- &tracked_image);
+ FrameAccessor::Key tracked_key =
+ GetImageForMarker(*tracked_marker, frame_accessor_, &tracked_image);
if (!tracked_key) {
frame_accessor_->ReleaseImage(reference_key);
LG << "Couldn't get frame for tracked marker: " << tracked_marker;
@@ -191,9 +181,11 @@ bool AutoTrack::TrackMarker(Marker* tracked_marker,
local_track_region_options.attempt_refine_before_brute = predicted_position;
TrackRegion(reference_image,
tracked_image,
- x1, y1,
+ x1,
+ y1,
local_track_region_options,
- x2, y2,
+ x2,
+ y2,
result);
// Copy results over the tracked marker.
@@ -208,7 +200,7 @@ bool AutoTrack::TrackMarker(Marker* tracked_marker,
tracked_marker->search_region.Offset(delta);
tracked_marker->source = Marker::TRACKED;
tracked_marker->status = Marker::UNKNOWN;
- tracked_marker->reference_clip = reference_marker.clip;
+ tracked_marker->reference_clip = reference_marker.clip;
tracked_marker->reference_frame = reference_marker.frame;
// Release the images and masks from the accessor cache.
@@ -230,7 +222,9 @@ void AutoTrack::SetMarkers(vector<Marker>* markers) {
tracks_.SetMarkers(markers);
}
-bool AutoTrack::GetMarker(int clip, int frame, int track,
+bool AutoTrack::GetMarker(int clip,
+ int frame,
+ int track,
Marker* markers) const {
return tracks_.GetMarker(clip, frame, track, markers);
}
@@ -242,7 +236,8 @@ void AutoTrack::DetectAndTrack(const DetectAndTrackOptions& options) {
vector<Marker> previous_frame_markers;
// Q: How to decide track #s when detecting?
// Q: How to match markers from previous frame? set of prev frame tracks?
- // Q: How to decide what markers should get tracked and which ones should not?
+ // Q: How to decide what markers should get tracked and which ones should
+ // not?
for (int frame = 0; frame < num_frames; ++frame) {
if (Cancelled()) {
LG << "Got cancel message while detecting and tracking...";
@@ -271,8 +266,7 @@ void AutoTrack::DetectAndTrack(const DetectAndTrackOptions& options) {
for (int i = 0; i < this_frame_markers.size(); ++i) {
tracks_in_this_frame.push_back(this_frame_markers[i].track);
}
- std::sort(tracks_in_this_frame.begin(),
- tracks_in_this_frame.end());
+ std::sort(tracks_in_this_frame.begin(), tracks_in_this_frame.end());
// Find tracks in the previous frame that are not in this one.
vector<Marker*> previous_frame_markers_to_track;
diff --git a/intern/libmv/libmv/autotrack/autotrack.h b/intern/libmv/libmv/autotrack/autotrack.h
index 1d7422f54e7..281766f600f 100644
--- a/intern/libmv/libmv/autotrack/autotrack.h
+++ b/intern/libmv/libmv/autotrack/autotrack.h
@@ -23,8 +23,8 @@
#ifndef LIBMV_AUTOTRACK_AUTOTRACK_H_
#define LIBMV_AUTOTRACK_AUTOTRACK_H_
-#include "libmv/autotrack/tracks.h"
#include "libmv/autotrack/region.h"
+#include "libmv/autotrack/tracks.h"
#include "libmv/tracking/track_region.h"
namespace libmv {
@@ -74,15 +74,14 @@ class AutoTrack {
Region search_region;
};
- AutoTrack(FrameAccessor* frame_accessor)
- : frame_accessor_(frame_accessor) {}
+ AutoTrack(FrameAccessor* frame_accessor) : frame_accessor_(frame_accessor) {}
// Marker manipulation.
// Clip manipulation.
// Set the number of clips. These clips will get accessed from the frame
// accessor, matches between frames found, and a reconstruction created.
- //void SetNumFrames(int clip, int num_frames);
+ // void SetNumFrames(int clip, int num_frames);
// Tracking & Matching
@@ -90,7 +89,7 @@ class AutoTrack {
// Caller maintains ownership of *result and *tracked_marker.
bool TrackMarker(Marker* tracked_marker,
TrackRegionResult* result,
- const TrackRegionOptions* track_options=NULL);
+ const TrackRegionOptions* track_options = NULL);
// Wrapper around Tracks API; however these may add additional processing.
void AddMarker(const Marker& tracked_marker);
@@ -99,36 +98,36 @@ class AutoTrack {
// TODO(keir): Implement frame matching! This could be very cool for loop
// closing and connecting across clips.
- //void MatchFrames(int clip1, int frame1, int clip2, int frame2) {}
+ // void MatchFrames(int clip1, int frame1, int clip2, int frame2) {}
// Wrapper around the Reconstruction API.
// Returns the new ID.
int AddCameraIntrinsics(CameraIntrinsics* intrinsics) {
- (void) intrinsics;
+ (void)intrinsics;
return 0;
} // XXX
int SetClipIntrinsics(int clip, int intrinsics) {
- (void) clip;
- (void) intrinsics;
+ (void)clip;
+ (void)intrinsics;
return 0;
- } // XXX
+ } // XXX
enum Motion {
GENERAL_CAMERA_MOTION,
TRIPOD_CAMERA_MOTION,
};
int SetClipMotion(int clip, Motion motion) {
- (void) clip;
- (void) motion;
+ (void)clip;
+ (void)motion;
return 0;
- } // XXX
+ } // XXX
// Decide what to refine for the given intrinsics. bundle_options is from
// bundle.h (e.g. BUNDLE_FOCAL_LENGTH | BUNDLE_RADIAL_K1).
void SetIntrinsicsRefine(int intrinsics, int bundle_options) {
- (void) intrinsics;
- (void) bundle_options;
- } // XXX
+ (void)intrinsics;
+ (void)bundle_options;
+ } // XXX
// Keyframe read/write.
struct ClipFrame {
@@ -150,20 +149,19 @@ class AutoTrack {
};
void DetectAndTrack(const DetectAndTrackOptions& options);
- struct DetectFeaturesInFrameOptions {
- };
- void DetectFeaturesInFrame(int clip, int frame,
- const DetectFeaturesInFrameOptions* options=NULL) {
- (void) clip;
- (void) frame;
- (void) options;
- } // XXX
+ struct DetectFeaturesInFrameOptions {};
+ void DetectFeaturesInFrame(
+ int clip, int frame, const DetectFeaturesInFrameOptions* options = NULL) {
+ (void)clip;
+ (void)frame;
+ (void)options;
+ } // XXX
// Does not take ownership of the given listener, but keeps a reference to it.
- void AddListener(OperationListener* listener) {(void) listener;} // XXX
+ void AddListener(OperationListener* listener) { (void)listener; } // XXX
// Create the initial reconstruction,
- //void FindInitialReconstruction();
+ // void FindInitialReconstruction();
// State machine
//
@@ -202,17 +200,17 @@ class AutoTrack {
bool Cancelled() { return false; }
Tracks tracks_; // May be normalized camera coordinates or raw pixels.
- //Reconstruction reconstruction_;
+ // Reconstruction reconstruction_;
// TODO(keir): Add the motion models here.
- //vector<MotionModel> motion_models_;
+ // vector<MotionModel> motion_models_;
// TODO(keir): Should num_clips and num_frames get moved to FrameAccessor?
// TODO(keir): What about masking for clips and frames to prevent various
// things like reconstruction or tracking from happening on certain frames?
FrameAccessor* frame_accessor_;
- //int num_clips_;
- //vector<int> num_frames_; // Indexed by clip.
+ // int num_clips_;
+ // vector<int> num_frames_; // Indexed by clip.
// The intrinsics for each clip, assuming each clip has fixed intrinsics.
// TODO(keir): Decide what the semantics should be for varying focal length.
diff --git a/intern/libmv/libmv/autotrack/frame_accessor.h b/intern/libmv/libmv/autotrack/frame_accessor.h
index cfad9ca71ff..e9308dc400a 100644
--- a/intern/libmv/libmv/autotrack/frame_accessor.h
+++ b/intern/libmv/libmv/autotrack/frame_accessor.h
@@ -41,7 +41,7 @@ using libmv::FloatImage;
// implementations to cache filtered image pieces).
struct FrameAccessor {
struct Transform {
- virtual ~Transform() { }
+ virtual ~Transform() {}
// The key should depend on the transform arguments. Must be non-zero.
virtual int64_t key() const = 0;
@@ -50,10 +50,7 @@ struct FrameAccessor {
virtual void run(const FloatImage& input, FloatImage* output) const = 0;
};
- enum InputMode {
- MONO,
- RGBA
- };
+ enum InputMode { MONO, RGBA };
typedef void* Key;
@@ -100,6 +97,6 @@ struct FrameAccessor {
virtual int NumFrames(int clip) = 0;
};
-} // namespace libmv
+} // namespace mv
#endif // LIBMV_AUTOTRACK_FRAME_ACCESSOR_H_
diff --git a/intern/libmv/libmv/autotrack/marker.h b/intern/libmv/libmv/autotrack/marker.h
index bb803313af8..29e163c0446 100644
--- a/intern/libmv/libmv/autotrack/marker.h
+++ b/intern/libmv/libmv/autotrack/marker.h
@@ -57,23 +57,19 @@ struct Marker {
float weight;
enum Source {
- MANUAL, // The user placed this marker manually.
- DETECTED, // A keypoint detector found this point.
- TRACKED, // The tracking algorithm placed this marker.
- MATCHED, // A matching algorithm (e.g. SIFT or SURF or ORB) found this.
- PREDICTED, // A motion model predicted this marker. This is needed for
- // handling occlusions in some cases where an imaginary marker
- // is placed to keep camera motion smooth.
+ MANUAL, // The user placed this marker manually.
+ DETECTED, // A keypoint detector found this point.
+ TRACKED, // The tracking algorithm placed this marker.
+ MATCHED, // A matching algorithm (e.g. SIFT or SURF or ORB) found this.
+ PREDICTED, // A motion model predicted this marker. This is needed for
+ // handling occlusions in some cases where an imaginary marker
+ // is placed to keep camera motion smooth.
};
Source source;
// Markers may be inliers or outliers if the tracking fails; this allows
// visualizing the markers in the image.
- enum Status {
- UNKNOWN,
- INLIER,
- OUTLIER
- };
+ enum Status { UNKNOWN, INLIER, OUTLIER };
Status status;
// When doing correlation tracking, where to search in the current frame for
@@ -90,12 +86,7 @@ struct Marker {
// another primitive (a rectangular prisim). This captures the information
// needed to say that for example a collection of markers belongs to model #2
// (and model #2 is a plane).
- enum ModelType {
- POINT,
- PLANE,
- LINE,
- CUBE
- };
+ enum ModelType { POINT, PLANE, LINE, CUBE };
ModelType model_type;
// The model ID this track (e.g. the second model, which is a plane).
@@ -114,7 +105,7 @@ struct Marker {
int disabled_channels;
// Offset everything (center, patch, search) by the given delta.
- template<typename T>
+ template <typename T>
void Offset(const T& offset) {
center += offset.template cast<float>();
patch.coordinates.rowwise() += offset.template cast<int>();
@@ -122,19 +113,15 @@ struct Marker {
}
// Shift the center to the given new position (and patch, search).
- template<typename T>
+ template <typename T>
void SetPosition(const T& new_center) {
Offset(new_center - center);
}
};
inline std::ostream& operator<<(std::ostream& out, const Marker& marker) {
- out << "{"
- << marker.clip << ", "
- << marker.frame << ", "
- << marker.track << ", ("
- << marker.center.x() << ", "
- << marker.center.y() << ")"
+ out << "{" << marker.clip << ", " << marker.frame << ", " << marker.track
+ << ", (" << marker.center.x() << ", " << marker.center.y() << ")"
<< "}";
return out;
}
diff --git a/intern/libmv/libmv/autotrack/model.h b/intern/libmv/libmv/autotrack/model.h
index 1165281cdac..e79d38b742b 100644
--- a/intern/libmv/libmv/autotrack/model.h
+++ b/intern/libmv/libmv/autotrack/model.h
@@ -23,18 +23,13 @@
#ifndef LIBMV_AUTOTRACK_MODEL_H_
#define LIBMV_AUTOTRACK_MODEL_H_
-#include "libmv/numeric/numeric.h"
#include "libmv/autotrack/quad.h"
+#include "libmv/numeric/numeric.h"
namespace mv {
struct Model {
- enum ModelType {
- POINT,
- PLANE,
- LINE,
- CUBE
- };
+ enum ModelType { POINT, PLANE, LINE, CUBE };
// ???
};
diff --git a/intern/libmv/libmv/autotrack/predict_tracks.cc b/intern/libmv/libmv/autotrack/predict_tracks.cc
index 3786c1b9a3b..d78b5b340f9 100644
--- a/intern/libmv/libmv/autotrack/predict_tracks.cc
+++ b/intern/libmv/libmv/autotrack/predict_tracks.cc
@@ -20,8 +20,8 @@
//
// Author: mierle@gmail.com (Keir Mierle)
-#include "libmv/autotrack/marker.h"
#include "libmv/autotrack/predict_tracks.h"
+#include "libmv/autotrack/marker.h"
#include "libmv/autotrack/tracks.h"
#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
@@ -31,8 +31,8 @@ namespace mv {
namespace {
-using libmv::vector;
using libmv::Vec2;
+using libmv::vector;
// Implied time delta between steps. Set empirically by tweaking and seeing
// what numbers did best at prediction.
@@ -57,6 +57,8 @@ const double dt = 3.8;
// For a typical system having constant velocity. This gives smooth-appearing
// predictions, but they are not always as accurate.
+//
+// clang-format off
const double velocity_state_transition_data[] = {
1, dt, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0,
@@ -65,10 +67,13 @@ const double velocity_state_transition_data[] = {
0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 1
};
+// clang-format on
#if 0
// This 3rd-order system also models acceleration. This makes for "jerky"
// predictions, but that tend to be more accurate.
+//
+// clang-format off
const double acceleration_state_transition_data[] = {
1, dt, dt*dt/2, 0, 0, 0,
0, 1, dt, 0, 0, 0,
@@ -77,9 +82,12 @@ const double acceleration_state_transition_data[] = {
0, 0, 0, 0, 1, dt,
0, 0, 0, 0, 0, 1
};
+// clang-format on
// This system (attempts) to add an angular velocity component. However, it's
// total junk.
+//
+// clang-format off
const double angular_state_transition_data[] = {
1, dt, -dt, 0, 0, 0, // Position x
0, 1, 0, 0, 0, 0, // Velocity x
@@ -88,17 +96,22 @@ const double angular_state_transition_data[] = {
0, 0, 0, 0, 1, 0, // Velocity y
0, 0, 0, 0, 0, 1 // Ignored
};
+// clang-format on
#endif
const double* state_transition_data = velocity_state_transition_data;
// Observation matrix.
+// clang-format off
const double observation_data[] = {
1., 0., 0., 0., 0., 0.,
0., 0., 0., 1., 0., 0.
};
+// clang-format on
// Process covariance.
+//
+// clang-format off
const double process_covariance_data[] = {
35, 0, 0, 0, 0, 0,
0, 5, 0, 0, 0, 0,
@@ -107,14 +120,19 @@ const double process_covariance_data[] = {
0, 0, 0, 0, 5, 0,
0, 0, 0, 0, 0, 5
};
+// clang-format on
// Process covariance.
const double measurement_covariance_data[] = {
- 0.01, 0.00,
- 0.00, 0.01,
+ 0.01,
+ 0.00,
+ 0.00,
+ 0.01,
};
// Initial covariance.
+//
+// clang-format off
const double initial_covariance_data[] = {
10, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0,
@@ -123,6 +141,7 @@ const double initial_covariance_data[] = {
0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 1
};
+// clang-format on
typedef mv::KalmanFilter<double, 6, 2> TrackerKalman;
@@ -138,7 +157,7 @@ bool OrderByFrameLessThan(const Marker* a, const Marker* b) {
}
return a->clip < b->clip;
}
- return a->frame < b-> frame;
+ return a->frame < b->frame;
}
// Predicted must be after the previous markers (in the frame numbering sense).
@@ -146,9 +165,9 @@ void RunPrediction(const vector<Marker*> previous_markers,
Marker* predicted_marker) {
TrackerKalman::State state;
state.mean << previous_markers[0]->center.x(), 0, 0,
- previous_markers[0]->center.y(), 0, 0;
- state.covariance = Eigen::Matrix<double, 6, 6, Eigen::RowMajor>(
- initial_covariance_data);
+ previous_markers[0]->center.y(), 0, 0;
+ state.covariance =
+ Eigen::Matrix<double, 6, 6, Eigen::RowMajor>(initial_covariance_data);
int current_frame = previous_markers[0]->frame;
int target_frame = predicted_marker->frame;
@@ -159,19 +178,18 @@ void RunPrediction(const vector<Marker*> previous_markers,
for (int i = 1; i < previous_markers.size(); ++i) {
// Step forward predicting the state until it is on the current marker.
int predictions = 0;
- for (;
- current_frame != previous_markers[i]->frame;
+ for (; current_frame != previous_markers[i]->frame;
current_frame += frame_delta) {
filter.Step(&state);
predictions++;
- LG << "Predicted point (frame " << current_frame << "): "
- << state.mean(0) << ", " << state.mean(3);
+ LG << "Predicted point (frame " << current_frame << "): " << state.mean(0)
+ << ", " << state.mean(3);
}
// Log the error -- not actually used, but interesting.
Vec2 error = previous_markers[i]->center.cast<double>() -
Vec2(state.mean(0), state.mean(3));
- LG << "Prediction error for " << predictions << " steps: ("
- << error.x() << ", " << error.y() << "); norm: " << error.norm();
+ LG << "Prediction error for " << predictions << " steps: (" << error.x()
+ << ", " << error.y() << "); norm: " << error.norm();
// Now that the state is predicted in the current frame, update the state
// based on the measurement from the current frame.
filter.Update(previous_markers[i]->center.cast<double>(),
@@ -184,8 +202,8 @@ void RunPrediction(const vector<Marker*> previous_markers,
// predict until the target frame.
for (; current_frame != target_frame; current_frame += frame_delta) {
filter.Step(&state);
- LG << "Final predicted point (frame " << current_frame << "): "
- << state.mean(0) << ", " << state.mean(3);
+ LG << "Final predicted point (frame " << current_frame
+ << "): " << state.mean(0) << ", " << state.mean(3);
}
// The x and y positions are at 0 and 3; ignore acceleration and velocity.
@@ -253,13 +271,13 @@ bool PredictMarkerPosition(const Tracks& tracks, Marker* marker) {
} else if (insert_at != -1) {
// Found existing marker; scan before and after it.
forward_scan_begin = insert_at + 1;
- forward_scan_end = markers.size() - 1;;
+ forward_scan_end = markers.size() - 1;
backward_scan_begin = insert_at - 1;
backward_scan_end = 0;
} else {
// Didn't find existing marker but found an insertion point.
forward_scan_begin = insert_before;
- forward_scan_end = markers.size() - 1;;
+ forward_scan_end = markers.size() - 1;
backward_scan_begin = insert_before - 1;
backward_scan_end = 0;
}
@@ -301,9 +319,8 @@ bool PredictMarkerPosition(const Tracks& tracks, Marker* marker) {
return false;
}
LG << "Predicting backward";
- int predict_begin =
- std::min(forward_scan_begin + max_frames_to_predict_from,
- forward_scan_end);
+ int predict_begin = std::min(
+ forward_scan_begin + max_frames_to_predict_from, forward_scan_end);
int predict_end = forward_scan_begin;
vector<Marker*> previous_markers;
for (int i = predict_begin; i >= predict_end; --i) {
@@ -312,7 +329,6 @@ bool PredictMarkerPosition(const Tracks& tracks, Marker* marker) {
RunPrediction(previous_markers, marker);
return false;
}
-
}
} // namespace mv
diff --git a/intern/libmv/libmv/autotrack/predict_tracks_test.cc b/intern/libmv/libmv/autotrack/predict_tracks_test.cc
index f7c2c68d750..fea93b91bce 100644
--- a/intern/libmv/libmv/autotrack/predict_tracks_test.cc
+++ b/intern/libmv/libmv/autotrack/predict_tracks_test.cc
@@ -35,17 +35,15 @@ static void AddMarker(int frame, float x, float y, Tracks* tracks) {
marker.frame = frame;
marker.center.x() = x;
marker.center.y() = y;
- marker.patch.coordinates << x - 1, y - 1,
- x + 1, y - 1,
- x + 1, y + 1,
- x - 1, y + 1;
+ marker.patch.coordinates << x - 1, y - 1, x + 1, y - 1, x + 1, y + 1, x - 1,
+ y + 1;
tracks->AddMarker(marker);
}
TEST(PredictMarkerPosition, EasyLinearMotion) {
Tracks tracks;
- AddMarker(0, 1.0, 0.0, &tracks);
- AddMarker(1, 2.0, 5.0, &tracks);
+ AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
AddMarker(2, 3.0, 10.0, &tracks);
AddMarker(3, 4.0, 15.0, &tracks);
AddMarker(4, 5.0, 20.0, &tracks);
@@ -66,10 +64,8 @@ TEST(PredictMarkerPosition, EasyLinearMotion) {
// Check the patch coordinates as well.
double x = 9, y = 40.0;
Quad2Df expected_patch;
- expected_patch.coordinates << x - 1, y - 1,
- x + 1, y - 1,
- x + 1, y + 1,
- x - 1, y + 1;
+ expected_patch.coordinates << x - 1, y - 1, x + 1, y - 1, x + 1, y + 1, x - 1,
+ y + 1;
error = (expected_patch.coordinates - predicted.patch.coordinates).norm();
LG << "Patch error: " << error;
@@ -78,8 +74,8 @@ TEST(PredictMarkerPosition, EasyLinearMotion) {
TEST(PredictMarkerPosition, EasyBackwardLinearMotion) {
Tracks tracks;
- AddMarker(8, 1.0, 0.0, &tracks);
- AddMarker(7, 2.0, 5.0, &tracks);
+ AddMarker(8, 1.0, 0.0, &tracks);
+ AddMarker(7, 2.0, 5.0, &tracks);
AddMarker(6, 3.0, 10.0, &tracks);
AddMarker(5, 4.0, 15.0, &tracks);
AddMarker(4, 5.0, 20.0, &tracks);
@@ -101,10 +97,8 @@ TEST(PredictMarkerPosition, EasyBackwardLinearMotion) {
// Check the patch coordinates as well.
double x = 9.0, y = 40.0;
Quad2Df expected_patch;
- expected_patch.coordinates << x - 1, y - 1,
- x + 1, y - 1,
- x + 1, y + 1,
- x - 1, y + 1;
+ expected_patch.coordinates << x - 1, y - 1, x + 1, y - 1, x + 1, y + 1, x - 1,
+ y + 1;
error = (expected_patch.coordinates - predicted.patch.coordinates).norm();
LG << "Patch error: " << error;
@@ -113,8 +107,8 @@ TEST(PredictMarkerPosition, EasyBackwardLinearMotion) {
TEST(PredictMarkerPosition, TwoFrameGap) {
Tracks tracks;
- AddMarker(0, 1.0, 0.0, &tracks);
- AddMarker(1, 2.0, 5.0, &tracks);
+ AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
AddMarker(2, 3.0, 10.0, &tracks);
AddMarker(3, 4.0, 15.0, &tracks);
AddMarker(4, 5.0, 20.0, &tracks);
@@ -135,8 +129,8 @@ TEST(PredictMarkerPosition, TwoFrameGap) {
TEST(PredictMarkerPosition, FourFrameGap) {
Tracks tracks;
- AddMarker(0, 1.0, 0.0, &tracks);
- AddMarker(1, 2.0, 5.0, &tracks);
+ AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
AddMarker(2, 3.0, 10.0, &tracks);
AddMarker(3, 4.0, 15.0, &tracks);
// Missing frames 4, 5, 6, 7.
@@ -154,13 +148,13 @@ TEST(PredictMarkerPosition, FourFrameGap) {
TEST(PredictMarkerPosition, MultipleGaps) {
Tracks tracks;
- AddMarker(0, 1.0, 0.0, &tracks);
- AddMarker(1, 2.0, 5.0, &tracks);
+ AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
AddMarker(2, 3.0, 10.0, &tracks);
// AddMarker(3, 4.0, 15.0, &tracks); // Note the 3-frame gap.
// AddMarker(4, 5.0, 20.0, &tracks);
// AddMarker(5, 6.0, 25.0, &tracks);
- AddMarker(6, 7.0, 30.0, &tracks); // Intermediate measurement.
+ AddMarker(6, 7.0, 30.0, &tracks); // Intermediate measurement.
// AddMarker(7, 8.0, 35.0, &tracks);
Marker predicted;
@@ -178,14 +172,14 @@ TEST(PredictMarkerPosition, MarkersInRandomOrder) {
Tracks tracks;
// This is the same as the easy, except that the tracks are randomly ordered.
- AddMarker(0, 1.0, 0.0, &tracks);
+ AddMarker(0, 1.0, 0.0, &tracks);
AddMarker(2, 3.0, 10.0, &tracks);
AddMarker(7, 8.0, 35.0, &tracks);
AddMarker(5, 6.0, 25.0, &tracks);
AddMarker(4, 5.0, 20.0, &tracks);
AddMarker(3, 4.0, 15.0, &tracks);
AddMarker(6, 7.0, 30.0, &tracks);
- AddMarker(1, 2.0, 5.0, &tracks);
+ AddMarker(1, 2.0, 5.0, &tracks);
Marker predicted;
predicted.clip = 0;
diff --git a/intern/libmv/libmv/autotrack/quad.h b/intern/libmv/libmv/autotrack/quad.h
index 0c70f9882da..4aeb66f20f7 100644
--- a/intern/libmv/libmv/autotrack/quad.h
+++ b/intern/libmv/libmv/autotrack/quad.h
@@ -27,7 +27,7 @@
namespace mv {
-template<typename T, int D>
+template <typename T, int D>
struct Quad {
// A quad is 4 points; generally in 2D or 3D.
//
@@ -35,7 +35,7 @@ struct Quad {
// |\.
// | \.
// | z (z goes into screen)
- // |
+ // |
// | r0----->r1
// | ^ |
// | | . |
@@ -44,7 +44,7 @@ struct Quad {
// | \.
// | \.
// v normal goes away (right handed).
- // y
+ // y
//
// Each row is one of the corners coordinates; either (x, y) or (x, y, z).
Eigen::Matrix<T, 4, D> coordinates;
diff --git a/intern/libmv/libmv/autotrack/reconstruction.h b/intern/libmv/libmv/autotrack/reconstruction.h
index 732e74063f1..f993b39f79e 100644
--- a/intern/libmv/libmv/autotrack/reconstruction.h
+++ b/intern/libmv/libmv/autotrack/reconstruction.h
@@ -57,17 +57,17 @@ class Reconstruction {
public:
// All methods copy their input reference or take ownership of the pointer.
void AddCameraPose(const CameraPose& pose);
- int AddCameraIntrinsics(CameraIntrinsics* intrinsics);
- int AddPoint(const Point& point);
- int AddModel(Model* model);
+ int AddCameraIntrinsics(CameraIntrinsics* intrinsics);
+ int AddPoint(const Point& point);
+ int AddModel(Model* model);
// Returns the corresponding pose or point or NULL if missing.
- CameraPose* CameraPoseForFrame(int clip, int frame);
+ CameraPose* CameraPoseForFrame(int clip, int frame);
const CameraPose* CameraPoseForFrame(int clip, int frame) const;
- Point* PointForTrack(int track);
+ Point* PointForTrack(int track);
const Point* PointForTrack(int track) const;
- const vector<vector<CameraPose> >& camera_poses() const {
+ const vector<vector<CameraPose>>& camera_poses() const {
return camera_poses_;
}
diff --git a/intern/libmv/libmv/autotrack/region.h b/intern/libmv/libmv/autotrack/region.h
index b35d99eb60d..687a217ab2a 100644
--- a/intern/libmv/libmv/autotrack/region.h
+++ b/intern/libmv/libmv/autotrack/region.h
@@ -46,7 +46,7 @@ struct Region {
Vec2f min;
Vec2f max;
- template<typename T>
+ template <typename T>
void Offset(const T& offset) {
min += offset.template cast<float>();
max += offset.template cast<float>();
diff --git a/intern/libmv/libmv/autotrack/tracks.cc b/intern/libmv/libmv/autotrack/tracks.cc
index 174f264f3f2..8044bb28bb4 100644
--- a/intern/libmv/libmv/autotrack/tracks.cc
+++ b/intern/libmv/libmv/autotrack/tracks.cc
@@ -23,8 +23,8 @@
#include "libmv/autotrack/tracks.h"
#include <algorithm>
-#include <vector>
#include <iterator>
+#include <vector>
#include "libmv/numeric/numeric.h"
@@ -34,12 +34,12 @@ Tracks::Tracks(const Tracks& other) {
markers_ = other.markers_;
}
-Tracks::Tracks(const vector<Marker>& markers) : markers_(markers) {}
+Tracks::Tracks(const vector<Marker>& markers) : markers_(markers) {
+}
bool Tracks::GetMarker(int clip, int frame, int track, Marker* marker) const {
for (int i = 0; i < markers_.size(); ++i) {
- if (markers_[i].clip == clip &&
- markers_[i].frame == frame &&
+ if (markers_[i].clip == clip && markers_[i].frame == frame &&
markers_[i].track == track) {
*marker = markers_[i];
return true;
@@ -60,8 +60,7 @@ void Tracks::GetMarkersForTrackInClip(int clip,
int track,
vector<Marker>* markers) const {
for (int i = 0; i < markers_.size(); ++i) {
- if (clip == markers_[i].clip &&
- track == markers_[i].track) {
+ if (clip == markers_[i].clip && track == markers_[i].track) {
markers->push_back(markers_[i]);
}
}
@@ -71,15 +70,16 @@ void Tracks::GetMarkersInFrame(int clip,
int frame,
vector<Marker>* markers) const {
for (int i = 0; i < markers_.size(); ++i) {
- if (markers_[i].clip == clip &&
- markers_[i].frame == frame) {
+ if (markers_[i].clip == clip && markers_[i].frame == frame) {
markers->push_back(markers_[i]);
}
}
}
-void Tracks::GetMarkersForTracksInBothImages(int clip1, int frame1,
- int clip2, int frame2,
+void Tracks::GetMarkersForTracksInBothImages(int clip1,
+ int frame1,
+ int clip2,
+ int frame2,
vector<Marker>* markers) const {
std::vector<int> image1_tracks;
std::vector<int> image2_tracks;
@@ -99,20 +99,19 @@ void Tracks::GetMarkersForTracksInBothImages(int clip1, int frame1,
std::sort(image1_tracks.begin(), image1_tracks.end());
std::sort(image2_tracks.begin(), image2_tracks.end());
std::vector<int> intersection;
- std::set_intersection(image1_tracks.begin(), image1_tracks.end(),
- image2_tracks.begin(), image2_tracks.end(),
+ std::set_intersection(image1_tracks.begin(),
+ image1_tracks.end(),
+ image2_tracks.begin(),
+ image2_tracks.end(),
std::back_inserter(intersection));
// Scan through and get the relevant tracks from the two images.
for (int i = 0; i < markers_.size(); ++i) {
// Save markers that are in either frame and are in our candidate set.
- if (((markers_[i].clip == clip1 &&
- markers_[i].frame == frame1) ||
- (markers_[i].clip == clip2 &&
- markers_[i].frame == frame2)) &&
- std::binary_search(intersection.begin(),
- intersection.end(),
- markers_[i].track)) {
+ if (((markers_[i].clip == clip1 && markers_[i].frame == frame1) ||
+ (markers_[i].clip == clip2 && markers_[i].frame == frame2)) &&
+ std::binary_search(
+ intersection.begin(), intersection.end(), markers_[i].track)) {
markers->push_back(markers_[i]);
}
}
@@ -122,8 +121,7 @@ void Tracks::AddMarker(const Marker& marker) {
// TODO(keir): This is quadratic for repeated insertions. Fix this by adding
// a smarter data structure like a set<>.
for (int i = 0; i < markers_.size(); ++i) {
- if (markers_[i].clip == marker.clip &&
- markers_[i].frame == marker.frame &&
+ if (markers_[i].clip == marker.clip && markers_[i].frame == marker.frame &&
markers_[i].track == marker.track) {
markers_[i] = marker;
return;
@@ -139,8 +137,7 @@ void Tracks::SetMarkers(vector<Marker>* markers) {
bool Tracks::RemoveMarker(int clip, int frame, int track) {
int size = markers_.size();
for (int i = 0; i < markers_.size(); ++i) {
- if (markers_[i].clip == clip &&
- markers_[i].frame == frame &&
+ if (markers_[i].clip == clip && markers_[i].frame == frame &&
markers_[i].track == track) {
markers_[i] = markers_[size - 1];
markers_.resize(size - 1);
diff --git a/intern/libmv/libmv/autotrack/tracks.h b/intern/libmv/libmv/autotrack/tracks.h
index 0b7de91d211..dd11a2d6fbd 100644
--- a/intern/libmv/libmv/autotrack/tracks.h
+++ b/intern/libmv/libmv/autotrack/tracks.h
@@ -23,8 +23,8 @@
#ifndef LIBMV_AUTOTRACK_TRACKS_H_
#define LIBMV_AUTOTRACK_TRACKS_H_
-#include "libmv/base/vector.h"
#include "libmv/autotrack/marker.h"
+#include "libmv/base/vector.h"
namespace mv {
@@ -33,8 +33,8 @@ using libmv::vector;
// The Tracks container stores correspondences between frames.
class Tracks {
public:
- Tracks() { }
- Tracks(const Tracks &other);
+ Tracks() {}
+ Tracks(const Tracks& other);
// Create a tracks object with markers already initialized. Copies markers.
explicit Tracks(const vector<Marker>& markers);
@@ -51,8 +51,10 @@ class Tracks {
//
// This is not the same as the union of the markers in frame1 and
// frame2; each marker is for a track that appears in both images.
- void GetMarkersForTracksInBothImages(int clip1, int frame1,
- int clip2, int frame2,
+ void GetMarkersForTracksInBothImages(int clip1,
+ int frame1,
+ int clip2,
+ int frame2,
vector<Marker>* markers) const;
void AddMarker(const Marker& marker);
diff --git a/intern/libmv/libmv/autotrack/tracks_test.cc b/intern/libmv/libmv/autotrack/tracks_test.cc
index 028b4a10913..eeefd3714b0 100644
--- a/intern/libmv/libmv/autotrack/tracks_test.cc
+++ b/intern/libmv/libmv/autotrack/tracks_test.cc
@@ -22,8 +22,8 @@
#include "libmv/autotrack/tracks.h"
-#include "testing/testing.h"
#include "libmv/logging/logging.h"
+#include "testing/testing.h"
namespace mv {
diff --git a/intern/libmv/libmv/base/aligned_malloc.cc b/intern/libmv/libmv/base/aligned_malloc.cc
index 5d3e05e9df9..6e327acf928 100644
--- a/intern/libmv/libmv/base/aligned_malloc.cc
+++ b/intern/libmv/libmv/base/aligned_malloc.cc
@@ -41,11 +41,11 @@
namespace libmv {
-void *aligned_malloc(int size, int alignment) {
+void* aligned_malloc(int size, int alignment) {
#ifdef _WIN32
return _aligned_malloc(size, alignment);
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__)
- void *result;
+ void* result;
if (posix_memalign(&result, alignment, size)) {
// non-zero means allocation error
@@ -58,7 +58,7 @@ void *aligned_malloc(int size, int alignment) {
#endif
}
-void aligned_free(void *ptr) {
+void aligned_free(void* ptr) {
#ifdef _WIN32
_aligned_free(ptr);
#else
diff --git a/intern/libmv/libmv/base/aligned_malloc.h b/intern/libmv/libmv/base/aligned_malloc.h
index 096ff6e2d7c..25583bb6be4 100644
--- a/intern/libmv/libmv/base/aligned_malloc.h
+++ b/intern/libmv/libmv/base/aligned_malloc.h
@@ -24,10 +24,10 @@
namespace libmv {
// Allocate block of size bytes at least aligned to a given value.
-void *aligned_malloc(int size, int alignment);
+void* aligned_malloc(int size, int alignment);
// Free memory allocated by aligned_malloc.
-void aligned_free(void *ptr);
+void aligned_free(void* ptr);
} // namespace libmv
diff --git a/intern/libmv/libmv/base/id_generator.h b/intern/libmv/libmv/base/id_generator.h
index bf1eafd218e..535c9bd7b38 100644
--- a/intern/libmv/libmv/base/id_generator.h
+++ b/intern/libmv/libmv/base/id_generator.h
@@ -28,6 +28,7 @@ class IdGenerator {
public:
IdGenerator() : next_(0) {}
ID Generate() { return next_++; }
+
private:
ID next_;
};
diff --git a/intern/libmv/libmv/base/map.h b/intern/libmv/libmv/base/map.h
index 88b720f17fe..a91e3561791 100644
--- a/intern/libmv/libmv/base/map.h
+++ b/intern/libmv/libmv/base/map.h
@@ -26,8 +26,8 @@
namespace libmv {
-using std::map;
using std::make_pair;
+using std::map;
} // namespace libmv
diff --git a/intern/libmv/libmv/base/scoped_ptr.h b/intern/libmv/libmv/base/scoped_ptr.h
index b9cd4854213..9bfcfe1d615 100644
--- a/intern/libmv/libmv/base/scoped_ptr.h
+++ b/intern/libmv/libmv/base/scoped_ptr.h
@@ -30,44 +30,44 @@ namespace libmv {
* A handle for a heap-allocated resource that should be freed when it goes out
* of scope. This looks similar to the one found in TR1.
*/
-template<typename T>
+template <typename T>
class scoped_ptr {
public:
- scoped_ptr(T *resource) : resource_(resource) {}
+ scoped_ptr(T* resource) : resource_(resource) {}
~scoped_ptr() { reset(0); }
- T *get() const { return resource_; }
- T *operator->() const { return resource_; }
- T &operator*() const { return *resource_; }
+ T* get() const { return resource_; }
+ T* operator->() const { return resource_; }
+ T& operator*() const { return *resource_; }
- void reset(T *new_resource) {
+ void reset(T* new_resource) {
if (sizeof(T)) {
delete resource_;
}
resource_ = new_resource;
}
- T *release() {
- T *released_resource = resource_;
+ T* release() {
+ T* released_resource = resource_;
resource_ = 0;
return released_resource;
}
private:
// No copying allowed.
- T *resource_;
+ T* resource_;
};
// Same as scoped_ptr but caller must allocate the data
// with new[] and the destructor will free the memory
// using delete[].
-template<typename T>
+template <typename T>
class scoped_array {
public:
- scoped_array(T *array) : array_(array) {}
+ scoped_array(T* array) : array_(array) {}
~scoped_array() { reset(NULL); }
- T *get() const { return array_; }
+ T* get() const { return array_; }
T& operator[](std::ptrdiff_t i) const {
assert(i >= 0);
@@ -75,25 +75,27 @@ class scoped_array {
return array_[i];
}
- void reset(T *new_array) {
+ void reset(T* new_array) {
if (sizeof(T)) {
delete array_;
}
array_ = new_array;
}
- T *release() {
- T *released_array = array_;
+ T* release() {
+ T* released_array = array_;
array_ = NULL;
return released_array;
}
private:
- T *array_;
+ T* array_;
// Forbid comparison of different scoped_array types.
- template <typename T2> bool operator==(scoped_array<T2> const& p2) const;
- template <typename T2> bool operator!=(scoped_array<T2> const& p2) const;
+ template <typename T2>
+ bool operator==(scoped_array<T2> const& p2) const;
+ template <typename T2>
+ bool operator!=(scoped_array<T2> const& p2) const;
// Disallow evil constructors
scoped_array(const scoped_array&);
diff --git a/intern/libmv/libmv/base/scoped_ptr_test.cc b/intern/libmv/libmv/base/scoped_ptr_test.cc
index ce1d56b500a..e86af6d4516 100644
--- a/intern/libmv/libmv/base/scoped_ptr_test.cc
+++ b/intern/libmv/libmv/base/scoped_ptr_test.cc
@@ -25,9 +25,9 @@ namespace libmv {
namespace {
struct FreeMe {
- FreeMe(int *freed) : freed(freed) {}
+ FreeMe(int* freed) : freed(freed) {}
~FreeMe() { (*freed)++; }
- int *freed;
+ int* freed;
};
TEST(ScopedPtr, NullDoesNothing) {
@@ -61,8 +61,8 @@ TEST(ScopedPtr, Reset) {
TEST(ScopedPtr, ReleaseAndGet) {
int frees = 0;
- FreeMe *allocated = new FreeMe(&frees);
- FreeMe *released = NULL;
+ FreeMe* allocated = new FreeMe(&frees);
+ FreeMe* released = NULL;
{
scoped_ptr<FreeMe> scoped(allocated);
EXPECT_EQ(0, frees);
diff --git a/intern/libmv/libmv/base/vector_test.cc b/intern/libmv/libmv/base/vector_test.cc
index f171e3a18b5..d31bee751cd 100644
--- a/intern/libmv/libmv/base/vector_test.cc
+++ b/intern/libmv/libmv/base/vector_test.cc
@@ -19,9 +19,9 @@
// IN THE SOFTWARE.
#include "libmv/base/vector.h"
+#include <algorithm>
#include "libmv/numeric/numeric.h"
#include "testing/testing.h"
-#include <algorithm>
namespace {
using namespace libmv;
@@ -62,7 +62,7 @@ int foo_destruct_calls = 0;
struct Foo {
public:
Foo() : value(5) { foo_construct_calls++; }
- ~Foo() { foo_destruct_calls++; }
+ ~Foo() { foo_destruct_calls++; }
int value;
};
@@ -150,7 +150,7 @@ TEST_F(VectorTest, CopyConstructor) {
a.push_back(3);
vector<int> b(a);
- EXPECT_EQ(a.size(), b.size());
+ EXPECT_EQ(a.size(), b.size());
for (int i = 0; i < a.size(); ++i) {
EXPECT_EQ(a[i], b[i]);
}
@@ -164,7 +164,7 @@ TEST_F(VectorTest, OperatorEquals) {
b = a;
- EXPECT_EQ(a.size(), b.size());
+ EXPECT_EQ(a.size(), b.size());
for (int i = 0; i < a.size(); ++i) {
EXPECT_EQ(a[i], b[i]);
}
diff --git a/intern/libmv/libmv/base/vector_utils.h b/intern/libmv/libmv/base/vector_utils.h
index c71e1bea951..5f69c03d937 100644
--- a/intern/libmv/libmv/base/vector_utils.h
+++ b/intern/libmv/libmv/base/vector_utils.h
@@ -18,14 +18,13 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-
#ifndef LIBMV_BASE_VECTOR_UTILS_H_
#define LIBMV_BASE_VECTOR_UTILS_H_
/// Delete the contents of a container.
template <class Array>
-void DeleteElements(Array *array) {
- for (int i = 0; i < array->size(); ++i) {
+void DeleteElements(Array* array) {
+ for (int i = 0; i < array->size(); ++i) {
delete (*array)[i];
}
array->clear();
diff --git a/intern/libmv/libmv/image/array_nd.cc b/intern/libmv/libmv/image/array_nd.cc
index 469a19aabf1..07feda33e66 100644
--- a/intern/libmv/libmv/image/array_nd.cc
+++ b/intern/libmv/libmv/image/array_nd.cc
@@ -18,18 +18,17 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-#include "libmv/image/image.h"
-#include <iostream>
#include <cmath>
+#include <iostream>
+#include "libmv/image/image.h"
namespace libmv {
-void FloatArrayToScaledByteArray(const Array3Df &float_array,
- Array3Du *byte_array,
- bool automatic_range_detection
- ) {
+void FloatArrayToScaledByteArray(const Array3Df& float_array,
+ Array3Du* byte_array,
+ bool automatic_range_detection) {
byte_array->ResizeLike(float_array);
- float minval = HUGE_VAL;
+ float minval = HUGE_VAL;
float maxval = -HUGE_VAL;
if (automatic_range_detection) {
for (int i = 0; i < float_array.Height(); ++i) {
@@ -54,8 +53,8 @@ void FloatArrayToScaledByteArray(const Array3Df &float_array,
}
}
-void ByteArrayToScaledFloatArray(const Array3Du &byte_array,
- Array3Df *float_array) {
+void ByteArrayToScaledFloatArray(const Array3Du& byte_array,
+ Array3Df* float_array) {
float_array->ResizeLike(byte_array);
for (int i = 0; i < byte_array.Height(); ++i) {
for (int j = 0; j < byte_array.Width(); ++j) {
@@ -66,10 +65,10 @@ void ByteArrayToScaledFloatArray(const Array3Du &byte_array,
}
}
-void SplitChannels(const Array3Df &input,
- Array3Df *channel0,
- Array3Df *channel1,
- Array3Df *channel2) {
+void SplitChannels(const Array3Df& input,
+ Array3Df* channel0,
+ Array3Df* channel1,
+ Array3Df* channel2) {
assert(input.Depth() >= 3);
channel0->Resize(input.Height(), input.Width());
channel1->Resize(input.Height(), input.Width());
@@ -83,7 +82,7 @@ void SplitChannels(const Array3Df &input,
}
}
-void PrintArray(const Array3Df &array) {
+void PrintArray(const Array3Df& array) {
using namespace std;
printf("[\n");
diff --git a/intern/libmv/libmv/image/array_nd.h b/intern/libmv/libmv/image/array_nd.h
index e95e66aa2b3..1a3c39d0461 100644
--- a/intern/libmv/libmv/image/array_nd.h
+++ b/intern/libmv/libmv/image/array_nd.h
@@ -44,13 +44,13 @@ class ArrayND : public BaseArray {
ArrayND() : data_(NULL), own_data_(true) { Resize(Index(0)); }
/// Create an array with the specified shape.
- ArrayND(const Index &shape) : data_(NULL), own_data_(true) { Resize(shape); }
+ ArrayND(const Index& shape) : data_(NULL), own_data_(true) { Resize(shape); }
/// Create an array with the specified shape.
- ArrayND(int *shape) : data_(NULL), own_data_(true) { Resize(shape); }
+ ArrayND(int* shape) : data_(NULL), own_data_(true) { Resize(shape); }
/// Copy constructor.
- ArrayND(const ArrayND<T, N> &b) : data_(NULL), own_data_(true) {
+ ArrayND(const ArrayND<T, N>& b) : data_(NULL), own_data_(true) {
ResizeLike(b);
std::memcpy(Data(), b.Data(), sizeof(T) * Size());
}
@@ -58,7 +58,7 @@ class ArrayND : public BaseArray {
ArrayND(int s0) : data_(NULL), own_data_(true) { Resize(s0); }
ArrayND(int s0, int s1) : data_(NULL), own_data_(true) { Resize(s0, s1); }
ArrayND(int s0, int s1, int s2) : data_(NULL), own_data_(true) {
- Resize(s0, s1, s2);
+ Resize(s0, s1, s2);
}
ArrayND(T* data, int s0, int s1, int s2)
@@ -69,28 +69,24 @@ class ArrayND : public BaseArray {
/// Destructor deletes pixel data.
~ArrayND() {
if (own_data_) {
- delete [] data_;
+ delete[] data_;
}
}
/// Assignation copies pixel data.
- ArrayND &operator=(const ArrayND<T, N> &b) {
+ ArrayND& operator=(const ArrayND<T, N>& b) {
assert(this != &b);
ResizeLike(b);
std::memcpy(Data(), b.Data(), sizeof(T) * Size());
return *this;
}
- const Index &Shapes() const {
- return shape_;
- }
+ const Index& Shapes() const { return shape_; }
- const Index &Strides() const {
- return strides_;
- }
+ const Index& Strides() const { return strides_; }
/// Create an array of shape s.
- void Resize(const Index &new_shape) {
+ void Resize(const Index& new_shape) {
if (data_ != NULL && shape_ == new_shape) {
// Don't bother realloacting if the shapes match.
return;
@@ -101,7 +97,7 @@ class ArrayND : public BaseArray {
strides_(i - 1) = strides_(i) * shape_(i);
}
if (own_data_) {
- delete [] data_;
+ delete[] data_;
data_ = NULL;
if (Size() > 0) {
data_ = new T[Size()];
@@ -109,15 +105,13 @@ class ArrayND : public BaseArray {
}
}
- template<typename D>
- void ResizeLike(const ArrayND<D, N> &other) {
+ template <typename D>
+ void ResizeLike(const ArrayND<D, N>& other) {
Resize(other.Shape());
}
/// Resizes the array to shape s. All data is lost.
- void Resize(const int *new_shape_array) {
- Resize(Index(new_shape_array));
- }
+ void Resize(const int* new_shape_array) { Resize(Index(new_shape_array)); }
/// Resize a 1D array to length s0.
void Resize(int s0) {
@@ -136,9 +130,7 @@ class ArrayND : public BaseArray {
}
// Match Eigen2's API.
- void resize(int rows, int cols) {
- Resize(rows, cols);
- }
+ void resize(int rows, int cols) { Resize(rows, cols); }
/// Resize a 3D array to shape (s0,s1,s2).
void Resize(int s0, int s1, int s2) {
@@ -147,11 +139,11 @@ class ArrayND : public BaseArray {
Resize(shape);
}
- template<typename D>
- void CopyFrom(const ArrayND<D, N> &other) {
+ template <typename D>
+ void CopyFrom(const ArrayND<D, N>& other) {
ResizeLike(other);
- T *data = Data();
- const D *other_data = other.Data();
+ T* data = Data();
+ const D* other_data = other.Data();
for (int i = 0; i < Size(); ++i) {
data[i] = T(other_data[i]);
}
@@ -171,19 +163,13 @@ class ArrayND : public BaseArray {
}
/// Return a tuple containing the length of each axis.
- const Index &Shape() const {
- return shape_;
- }
+ const Index& Shape() const { return shape_; }
/// Return the length of an axis.
- int Shape(int axis) const {
- return shape_(axis);
- }
+ int Shape(int axis) const { return shape_(axis); }
/// Return the distance between neighboring elements along axis.
- int Stride(int axis) const {
- return strides_(axis);
- }
+ int Stride(int axis) const { return strides_(axis); }
/// Return the number of elements of the array.
int Size() const {
@@ -194,18 +180,16 @@ class ArrayND : public BaseArray {
}
/// Return the total amount of memory used by the array.
- int MemorySizeInBytes() const {
- return sizeof(*this) + Size() * sizeof(T);
- }
+ int MemorySizeInBytes() const { return sizeof(*this) + Size() * sizeof(T); }
/// Pointer to the first element of the array.
- T *Data() { return data_; }
+ T* Data() { return data_; }
/// Constant pointer to the first element of the array.
- const T *Data() const { return data_; }
+ const T* Data() const { return data_; }
/// Distance between the first element and the element at position index.
- int Offset(const Index &index) const {
+ int Offset(const Index& index) const {
int offset = 0;
for (int i = 0; i < N; ++i)
offset += index(i) * Stride(i);
@@ -231,25 +215,23 @@ class ArrayND : public BaseArray {
}
/// Return a reference to the element at position index.
- T &operator()(const Index &index) {
+ T& operator()(const Index& index) {
// TODO(pau) Boundary checking in debug mode.
- return *( Data() + Offset(index) );
+ return *(Data() + Offset(index));
}
/// 1D specialization.
- T &operator()(int i0) {
- return *( Data() + Offset(i0) );
- }
+ T& operator()(int i0) { return *(Data() + Offset(i0)); }
/// 2D specialization.
- T &operator()(int i0, int i1) {
+ T& operator()(int i0, int i1) {
assert(0 <= i0 && i0 < Shape(0));
assert(0 <= i1 && i1 < Shape(1));
return *(Data() + Offset(i0, i1));
}
/// 3D specialization.
- T &operator()(int i0, int i1, int i2) {
+ T& operator()(int i0, int i1, int i2) {
assert(0 <= i0 && i0 < Shape(0));
assert(0 <= i1 && i1 < Shape(1));
assert(0 <= i2 && i2 < Shape(2));
@@ -257,29 +239,27 @@ class ArrayND : public BaseArray {
}
/// Return a constant reference to the element at position index.
- const T &operator()(const Index &index) const {
+ const T& operator()(const Index& index) const {
return *(Data() + Offset(index));
}
/// 1D specialization.
- const T &operator()(int i0) const {
- return *(Data() + Offset(i0));
- }
+ const T& operator()(int i0) const { return *(Data() + Offset(i0)); }
/// 2D specialization.
- const T &operator()(int i0, int i1) const {
+ const T& operator()(int i0, int i1) const {
assert(0 <= i0 && i0 < Shape(0));
assert(0 <= i1 && i1 < Shape(1));
return *(Data() + Offset(i0, i1));
}
/// 3D specialization.
- const T &operator()(int i0, int i1, int i2) const {
+ const T& operator()(int i0, int i1, int i2) const {
return *(Data() + Offset(i0, i1, i2));
}
/// True if index is inside array.
- bool Contains(const Index &index) const {
+ bool Contains(const Index& index) const {
for (int i = 0; i < N; ++i)
if (index(i) < 0 || index(i) >= Shape(i))
return false;
@@ -287,26 +267,24 @@ class ArrayND : public BaseArray {
}
/// 1D specialization.
- bool Contains(int i0) const {
- return 0 <= i0 && i0 < Shape(0);
- }
+ bool Contains(int i0) const { return 0 <= i0 && i0 < Shape(0); }
/// 2D specialization.
bool Contains(int i0, int i1) const {
- return 0 <= i0 && i0 < Shape(0)
- && 0 <= i1 && i1 < Shape(1);
+ return 0 <= i0 && i0 < Shape(0) && 0 <= i1 && i1 < Shape(1);
}
/// 3D specialization.
bool Contains(int i0, int i1, int i2) const {
- return 0 <= i0 && i0 < Shape(0)
- && 0 <= i1 && i1 < Shape(1)
- && 0 <= i2 && i2 < Shape(2);
+ return 0 <= i0 && i0 < Shape(0) && 0 <= i1 && i1 < Shape(1) && 0 <= i2 &&
+ i2 < Shape(2);
}
- bool operator==(const ArrayND<T, N> &other) const {
- if (shape_ != other.shape_) return false;
- if (strides_ != other.strides_) return false;
+ bool operator==(const ArrayND<T, N>& other) const {
+ if (shape_ != other.shape_)
+ return false;
+ if (strides_ != other.strides_)
+ return false;
for (int i = 0; i < Size(); ++i) {
if (this->Data()[i] != other.Data()[i])
return false;
@@ -314,11 +292,11 @@ class ArrayND : public BaseArray {
return true;
}
- bool operator!=(const ArrayND<T, N> &other) const {
+ bool operator!=(const ArrayND<T, N>& other) const {
return !(*this == other);
}
- ArrayND<T, N> operator*(const ArrayND<T, N> &other) const {
+ ArrayND<T, N> operator*(const ArrayND<T, N>& other) const {
assert(Shape() = other.Shape());
ArrayND<T, N> res;
res.ResizeLike(*this);
@@ -336,7 +314,7 @@ class ArrayND : public BaseArray {
Index strides_;
/// Pointer to the first element of the array.
- T *data_;
+ T* data_;
/// Flag if this Array either own or reference the data
bool own_data_;
@@ -346,30 +324,20 @@ class ArrayND : public BaseArray {
template <typename T>
class Array3D : public ArrayND<T, 3> {
typedef ArrayND<T, 3> Base;
+
public:
- Array3D()
- : Base() {
- }
- Array3D(int height, int width, int depth = 1)
- : Base(height, width, depth) {
- }
+ Array3D() : Base() {}
+ Array3D(int height, int width, int depth = 1) : Base(height, width, depth) {}
Array3D(T* data, int height, int width, int depth = 1)
- : Base(data, height, width, depth) {
- }
+ : Base(data, height, width, depth) {}
void Resize(int height, int width, int depth = 1) {
Base::Resize(height, width, depth);
}
- int Height() const {
- return Base::Shape(0);
- }
- int Width() const {
- return Base::Shape(1);
- }
- int Depth() const {
- return Base::Shape(2);
- }
+ int Height() const { return Base::Shape(0); }
+ int Width() const { return Base::Shape(1); }
+ int Depth() const { return Base::Shape(2); }
// Match Eigen2's API so that Array3D's and Mat*'s can work together via
// template magic.
@@ -377,15 +345,15 @@ class Array3D : public ArrayND<T, 3> {
int cols() const { return Width(); }
int depth() const { return Depth(); }
- int Get_Step() const { return Width()*Depth(); }
+ int Get_Step() const { return Width() * Depth(); }
/// Enable accessing with 2 indices for grayscale images.
- T &operator()(int i0, int i1, int i2 = 0) {
+ T& operator()(int i0, int i1, int i2 = 0) {
assert(0 <= i0 && i0 < Height());
assert(0 <= i1 && i1 < Width());
return Base::operator()(i0, i1, i2);
}
- const T &operator()(int i0, int i1, int i2 = 0) const {
+ const T& operator()(int i0, int i1, int i2 = 0) const {
assert(0 <= i0 && i0 < Height());
assert(0 <= i1 && i1 < Width());
return Base::operator()(i0, i1, i2);
@@ -398,31 +366,29 @@ typedef Array3D<int> Array3Di;
typedef Array3D<float> Array3Df;
typedef Array3D<short> Array3Ds;
-void SplitChannels(const Array3Df &input,
- Array3Df *channel0,
- Array3Df *channel1,
- Array3Df *channel2);
+void SplitChannels(const Array3Df& input,
+ Array3Df* channel0,
+ Array3Df* channel1,
+ Array3Df* channel2);
-void PrintArray(const Array3Df &array);
+void PrintArray(const Array3Df& array);
/** Convert a float array into a byte array by scaling values by 255* (max-min).
- * where max and min are automatically detected
+ * where max and min are automatically detected
* (if automatic_range_detection = true)
* \note and TODO this automatic detection only works when the image contains
* at least one pixel of both bounds.
**/
-void FloatArrayToScaledByteArray(const Array3Df &float_array,
- Array3Du *byte_array,
+void FloatArrayToScaledByteArray(const Array3Df& float_array,
+ Array3Du* byte_array,
bool automatic_range_detection = false);
//! Convert a byte array into a float array by dividing values by 255.
-void ByteArrayToScaledFloatArray(const Array3Du &byte_array,
- Array3Df *float_array);
+void ByteArrayToScaledFloatArray(const Array3Du& byte_array,
+ Array3Df* float_array);
template <typename AArrayType, typename BArrayType, typename CArrayType>
-void MultiplyElements(const AArrayType &a,
- const BArrayType &b,
- CArrayType *c) {
+void MultiplyElements(const AArrayType& a, const BArrayType& b, CArrayType* c) {
// This function does an element-wise multiply between
// the two Arrays A and B, and stores the result in C.
// A and B must have the same dimensions.
@@ -435,7 +401,7 @@ void MultiplyElements(const AArrayType &a,
// The index starts at the maximum value for each dimension
const typename CArrayType::Index& cShape = c->Shape();
- for ( int i = 0; i < CArrayType::Index::SIZE; ++i )
+ for (int i = 0; i < CArrayType::Index::SIZE; ++i)
index(i) = cShape(i) - 1;
// After each multiplication, the highest-dimensional index is reduced.
@@ -443,12 +409,12 @@ void MultiplyElements(const AArrayType &a,
// and decrements the index of the next lower dimension.
// This ripple-action continues until the entire new array has been
// calculated, indicated by dimension zero having a negative index.
- while ( index(0) >= 0 ) {
+ while (index(0) >= 0) {
(*c)(index) = a(index) * b(index);
int dimension = CArrayType::Index::SIZE - 1;
index(dimension) = index(dimension) - 1;
- while ( dimension > 0 && index(dimension) < 0 ) {
+ while (dimension > 0 && index(dimension) < 0) {
index(dimension) = cShape(dimension) - 1;
index(dimension - 1) = index(dimension - 1) - 1;
--dimension;
@@ -457,9 +423,9 @@ void MultiplyElements(const AArrayType &a,
}
template <typename TA, typename TB, typename TC>
-void MultiplyElements(const ArrayND<TA, 3> &a,
- const ArrayND<TB, 3> &b,
- ArrayND<TC, 3> *c) {
+void MultiplyElements(const ArrayND<TA, 3>& a,
+ const ArrayND<TB, 3>& b,
+ ArrayND<TC, 3>* c) {
// Specialization for N==3
c->ResizeLike(a);
assert(a.Shape(0) == b.Shape(0));
@@ -475,9 +441,9 @@ void MultiplyElements(const ArrayND<TA, 3> &a,
}
template <typename TA, typename TB, typename TC>
-void MultiplyElements(const Array3D<TA> &a,
- const Array3D<TB> &b,
- Array3D<TC> *c) {
+void MultiplyElements(const Array3D<TA>& a,
+ const Array3D<TB>& b,
+ Array3D<TC>* c) {
// Specialization for N==3
c->ResizeLike(a);
assert(a.Shape(0) == b.Shape(0));
diff --git a/intern/libmv/libmv/image/array_nd_test.cc b/intern/libmv/libmv/image/array_nd_test.cc
index dc7cfacf90d..67838d34051 100644
--- a/intern/libmv/libmv/image/array_nd_test.cc
+++ b/intern/libmv/libmv/image/array_nd_test.cc
@@ -21,9 +21,9 @@
#include "libmv/image/array_nd.h"
#include "testing/testing.h"
-using libmv::ArrayND;
using libmv::Array3D;
using libmv::Array3Df;
+using libmv::ArrayND;
namespace {
@@ -100,7 +100,7 @@ TEST(ArrayND, Size) {
int l[] = {0, 1, 2};
ArrayND<int, 3>::Index last(l);
- EXPECT_EQ(a.Size(), a.Offset(last)+1);
+ EXPECT_EQ(a.Size(), a.Offset(last) + 1);
EXPECT_TRUE(a.Contains(last));
EXPECT_FALSE(a.Contains(shape));
}
@@ -120,8 +120,8 @@ TEST(ArrayND, Parenthesis) {
int s[] = {3, 3};
ArrayND<int, 2> a(s);
- *(a.Data()+0) = 0;
- *(a.Data()+5) = 5;
+ *(a.Data() + 0) = 0;
+ *(a.Data() + 5) = 5;
int i1[] = {0, 0};
EXPECT_EQ(0, a(Index(i1)));
@@ -210,7 +210,7 @@ TEST(ArrayND, MultiplyElements) {
b(1, 1, 0) = 3;
ArrayND<int, 3> c;
MultiplyElements(a, b, &c);
- EXPECT_FLOAT_EQ(6, c(0, 0, 0));
+ EXPECT_FLOAT_EQ(6, c(0, 0, 0));
EXPECT_FLOAT_EQ(10, c(0, 1, 0));
EXPECT_FLOAT_EQ(12, c(1, 0, 0));
EXPECT_FLOAT_EQ(12, c(1, 1, 0));
diff --git a/intern/libmv/libmv/image/convolve.cc b/intern/libmv/libmv/image/convolve.cc
index 464043581d2..478e320377d 100644
--- a/intern/libmv/libmv/image/convolve.cc
+++ b/intern/libmv/libmv/image/convolve.cc
@@ -29,7 +29,7 @@ namespace libmv {
// Compute a Gaussian kernel and derivative, such that you can take the
// derivative of an image by convolving with the kernel horizontally then the
// derivative vertically to get (eg) the y derivative.
-void ComputeGaussianKernel(double sigma, Vec *kernel, Vec *derivative) {
+void ComputeGaussianKernel(double sigma, Vec* kernel, Vec* derivative) {
assert(sigma >= 0.0);
// 0.004 implies a 3 pixel kernel with 1 pixel sigma.
@@ -37,7 +37,7 @@ void ComputeGaussianKernel(double sigma, Vec *kernel, Vec *derivative) {
// Calculate the kernel size based on sigma such that it is odd.
float precisehalfwidth = GaussianInversePositive(truncation_factor, sigma);
- int width = lround(2*precisehalfwidth);
+ int width = lround(2 * precisehalfwidth);
if (width % 2 == 0) {
width++;
}
@@ -47,7 +47,7 @@ void ComputeGaussianKernel(double sigma, Vec *kernel, Vec *derivative) {
kernel->setZero();
derivative->setZero();
int halfwidth = width / 2;
- for (int i = -halfwidth; i <= halfwidth; ++i) {
+ for (int i = -halfwidth; i <= halfwidth; ++i) {
(*kernel)(i + halfwidth) = Gaussian(i, sigma);
(*derivative)(i + halfwidth) = GaussianDerivative(i, sigma);
}
@@ -57,16 +57,21 @@ void ComputeGaussianKernel(double sigma, Vec *kernel, Vec *derivative) {
// Normalize the derivative differently. See
// www.cs.duke.edu/courses/spring03/cps296.1/handouts/Image%20Processing.pdf
double factor = 0.;
- for (int i = -halfwidth; i <= halfwidth; ++i) {
- factor -= i*(*derivative)(i+halfwidth);
+ for (int i = -halfwidth; i <= halfwidth; ++i) {
+ factor -= i * (*derivative)(i + halfwidth);
}
*derivative /= factor;
}
template <int size, bool vertical>
-void FastConvolve(const Vec &kernel, int width, int height,
- const float* src, int src_stride, int src_line_stride,
- float* dst, int dst_stride) {
+void FastConvolve(const Vec& kernel,
+ int width,
+ int height,
+ const float* src,
+ int src_stride,
+ int src_line_stride,
+ float* dst,
+ int dst_stride) {
double coefficients[2 * size + 1];
for (int k = 0; k < 2 * size + 1; ++k) {
coefficients[k] = kernel(2 * size - k);
@@ -93,14 +98,14 @@ void FastConvolve(const Vec &kernel, int width, int height,
}
}
-template<bool vertical>
-void Convolve(const Array3Df &in,
- const Vec &kernel,
- Array3Df *out_pointer,
+template <bool vertical>
+void Convolve(const Array3Df& in,
+ const Vec& kernel,
+ Array3Df* out_pointer,
int plane) {
int width = in.Width();
int height = in.Height();
- Array3Df &out = *out_pointer;
+ Array3Df& out = *out_pointer;
if (plane == -1) {
out.ResizeLike(in);
plane = 0;
@@ -119,61 +124,62 @@ void Convolve(const Array3Df &in,
// fast path.
int half_width = kernel.size() / 2;
switch (half_width) {
-#define static_convolution(size) case size: \
- FastConvolve<size, vertical>(kernel, width, height, src, src_stride, \
- src_line_stride, dst, dst_stride); break;
- static_convolution(1)
- static_convolution(2)
- static_convolution(3)
- static_convolution(4)
- static_convolution(5)
- static_convolution(6)
- static_convolution(7)
+#define static_convolution(size) \
+ case size: \
+ FastConvolve<size, vertical>(kernel, \
+ width, \
+ height, \
+ src, \
+ src_stride, \
+ src_line_stride, \
+ dst, \
+ dst_stride); \
+ break;
+ static_convolution(1) static_convolution(2) static_convolution(3)
+ static_convolution(4) static_convolution(5) static_convolution(6)
+ static_convolution(7)
#undef static_convolution
- default:
- int dynamic_size = kernel.size() / 2;
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- double sum = 0;
- // Slow path: this loop cannot be unrolled.
- for (int k = -dynamic_size; k <= dynamic_size; ++k) {
- if (vertical) {
- if (y + k >= 0 && y + k < height) {
- sum += src[k * src_line_stride] *
- kernel(2 * dynamic_size - (k + dynamic_size));
- }
- } else {
- if (x + k >= 0 && x + k < width) {
- sum += src[k * src_stride] *
- kernel(2 * dynamic_size - (k + dynamic_size));
- }
+ default : int dynamic_size = kernel.size() / 2;
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ double sum = 0;
+ // Slow path: this loop cannot be unrolled.
+ for (int k = -dynamic_size; k <= dynamic_size; ++k) {
+ if (vertical) {
+ if (y + k >= 0 && y + k < height) {
+ sum += src[k * src_line_stride] *
+ kernel(2 * dynamic_size - (k + dynamic_size));
+ }
+ } else {
+ if (x + k >= 0 && x + k < width) {
+ sum += src[k * src_stride] *
+ kernel(2 * dynamic_size - (k + dynamic_size));
}
}
- dst[0] = static_cast<float>(sum);
- src += src_stride;
- dst += dst_stride;
}
+ dst[0] = static_cast<float>(sum);
+ src += src_stride;
+ dst += dst_stride;
}
+ }
}
}
-void ConvolveHorizontal(const Array3Df &in,
- const Vec &kernel,
- Array3Df *out_pointer,
+void ConvolveHorizontal(const Array3Df& in,
+ const Vec& kernel,
+ Array3Df* out_pointer,
int plane) {
Convolve<false>(in, kernel, out_pointer, plane);
}
-void ConvolveVertical(const Array3Df &in,
- const Vec &kernel,
- Array3Df *out_pointer,
+void ConvolveVertical(const Array3Df& in,
+ const Vec& kernel,
+ Array3Df* out_pointer,
int plane) {
Convolve<true>(in, kernel, out_pointer, plane);
}
-void ConvolveGaussian(const Array3Df &in,
- double sigma,
- Array3Df *out_pointer) {
+void ConvolveGaussian(const Array3Df& in, double sigma, Array3Df* out_pointer) {
Vec kernel, derivative;
ComputeGaussianKernel(sigma, &kernel, &derivative);
@@ -182,10 +188,10 @@ void ConvolveGaussian(const Array3Df &in,
ConvolveHorizontal(tmp, kernel, out_pointer);
}
-void ImageDerivatives(const Array3Df &in,
+void ImageDerivatives(const Array3Df& in,
double sigma,
- Array3Df *gradient_x,
- Array3Df *gradient_y) {
+ Array3Df* gradient_x,
+ Array3Df* gradient_y) {
Vec kernel, derivative;
ComputeGaussianKernel(sigma, &kernel, &derivative);
Array3Df tmp;
@@ -199,11 +205,11 @@ void ImageDerivatives(const Array3Df &in,
ConvolveVertical(tmp, derivative, gradient_y);
}
-void BlurredImageAndDerivatives(const Array3Df &in,
+void BlurredImageAndDerivatives(const Array3Df& in,
double sigma,
- Array3Df *blurred_image,
- Array3Df *gradient_x,
- Array3Df *gradient_y) {
+ Array3Df* blurred_image,
+ Array3Df* gradient_x,
+ Array3Df* gradient_y) {
Vec kernel, derivative;
ComputeGaussianKernel(sigma, &kernel, &derivative);
Array3Df tmp;
@@ -224,9 +230,9 @@ void BlurredImageAndDerivatives(const Array3Df &in,
// image, and store the results in three channels. Since the blurred value and
// gradients are closer in memory, this leads to better performance if all
// three values are needed at the same time.
-void BlurredImageAndDerivativesChannels(const Array3Df &in,
+void BlurredImageAndDerivativesChannels(const Array3Df& in,
double sigma,
- Array3Df *blurred_and_gradxy) {
+ Array3Df* blurred_and_gradxy) {
assert(in.Depth() == 1);
Vec kernel, derivative;
@@ -246,10 +252,10 @@ void BlurredImageAndDerivativesChannels(const Array3Df &in,
ConvolveVertical(tmp, derivative, blurred_and_gradxy, 2);
}
-void BoxFilterHorizontal(const Array3Df &in,
+void BoxFilterHorizontal(const Array3Df& in,
int window_size,
- Array3Df *out_pointer) {
- Array3Df &out = *out_pointer;
+ Array3Df* out_pointer) {
+ Array3Df& out = *out_pointer;
out.ResizeLike(in);
int half_width = (window_size - 1) / 2;
@@ -266,7 +272,7 @@ void BoxFilterHorizontal(const Array3Df &in,
out(i, j, k) = sum;
}
// Fill interior.
- for (int j = half_width + 1; j < in.Width()-half_width; ++j) {
+ for (int j = half_width + 1; j < in.Width() - half_width; ++j) {
sum -= in(i, j - half_width - 1, k);
sum += in(i, j + half_width, k);
out(i, j, k) = sum;
@@ -280,10 +286,10 @@ void BoxFilterHorizontal(const Array3Df &in,
}
}
-void BoxFilterVertical(const Array3Df &in,
+void BoxFilterVertical(const Array3Df& in,
int window_size,
- Array3Df *out_pointer) {
- Array3Df &out = *out_pointer;
+ Array3Df* out_pointer) {
+ Array3Df& out = *out_pointer;
out.ResizeLike(in);
int half_width = (window_size - 1) / 2;
@@ -300,7 +306,7 @@ void BoxFilterVertical(const Array3Df &in,
out(i, j, k) = sum;
}
// Fill interior.
- for (int i = half_width + 1; i < in.Height()-half_width; ++i) {
+ for (int i = half_width + 1; i < in.Height() - half_width; ++i) {
sum -= in(i - half_width - 1, j, k);
sum += in(i + half_width, j, k);
out(i, j, k) = sum;
@@ -314,9 +320,7 @@ void BoxFilterVertical(const Array3Df &in,
}
}
-void BoxFilter(const Array3Df &in,
- int box_width,
- Array3Df *out) {
+void BoxFilter(const Array3Df& in, int box_width, Array3Df* out) {
Array3Df tmp;
BoxFilterHorizontal(in, box_width, &tmp);
BoxFilterVertical(tmp, box_width, out);
@@ -327,17 +331,17 @@ void LaplaceFilter(unsigned char* src,
int width,
int height,
int strength) {
- for (int y = 1; y < height-1; y++)
- for (int x = 1; x < width-1; x++) {
- const unsigned char* s = &src[y*width+x];
- int l = 128 +
- s[-width-1] + s[-width] + s[-width+1] +
- s[1] - 8*s[0] + s[1] +
- s[ width-1] + s[ width] + s[ width+1];
- int d = ((256-strength)*s[0] + strength*l) / 256;
- if (d < 0) d=0;
- if (d > 255) d=255;
- dst[y*width+x] = d;
+ for (int y = 1; y < height - 1; y++)
+ for (int x = 1; x < width - 1; x++) {
+ const unsigned char* s = &src[y * width + x];
+ int l = 128 + s[-width - 1] + s[-width] + s[-width + 1] + s[1] -
+ 8 * s[0] + s[1] + s[width - 1] + s[width] + s[width + 1];
+ int d = ((256 - strength) * s[0] + strength * l) / 256;
+ if (d < 0)
+ d = 0;
+ if (d > 255)
+ d = 255;
+ dst[y * width + x] = d;
}
}
diff --git a/intern/libmv/libmv/image/convolve.h b/intern/libmv/libmv/image/convolve.h
index d3b6da9794b..3794550eb73 100644
--- a/intern/libmv/libmv/image/convolve.h
+++ b/intern/libmv/libmv/image/convolve.h
@@ -30,70 +30,71 @@ namespace libmv {
// Zero mean Gaussian.
inline double Gaussian(double x, double sigma) {
- return 1/sqrt(2*M_PI*sigma*sigma) * exp(-(x*x/2/sigma/sigma));
+ return 1 / sqrt(2 * M_PI * sigma * sigma) * exp(-(x * x / 2 / sigma / sigma));
}
// 2D gaussian (zero mean)
// (9) in http://mathworld.wolfram.com/GaussianFunction.html
inline double Gaussian2D(double x, double y, double sigma) {
- return 1.0/(2.0*M_PI*sigma*sigma) * exp( -(x*x+y*y)/(2.0*sigma*sigma));
+ return 1.0 / (2.0 * M_PI * sigma * sigma) *
+ exp(-(x * x + y * y) / (2.0 * sigma * sigma));
}
inline double GaussianDerivative(double x, double sigma) {
return -x / sigma / sigma * Gaussian(x, sigma);
}
// Solve the inverse of the Gaussian for positive x.
inline double GaussianInversePositive(double y, double sigma) {
- return sqrt(-2 * sigma * sigma * log(y * sigma * sqrt(2*M_PI)));
+ return sqrt(-2 * sigma * sigma * log(y * sigma * sqrt(2 * M_PI)));
}
-void ComputeGaussianKernel(double sigma, Vec *kernel, Vec *derivative);
-void ConvolveHorizontal(const FloatImage &in,
- const Vec &kernel,
- FloatImage *out_pointer,
+void ComputeGaussianKernel(double sigma, Vec* kernel, Vec* derivative);
+void ConvolveHorizontal(const FloatImage& in,
+ const Vec& kernel,
+ FloatImage* out_pointer,
int plane = -1);
-void ConvolveVertical(const FloatImage &in,
- const Vec &kernel,
- FloatImage *out_pointer,
+void ConvolveVertical(const FloatImage& in,
+ const Vec& kernel,
+ FloatImage* out_pointer,
int plane = -1);
-void ConvolveGaussian(const FloatImage &in,
+void ConvolveGaussian(const FloatImage& in,
double sigma,
- FloatImage *out_pointer);
+ FloatImage* out_pointer);
-void ImageDerivatives(const FloatImage &in,
+void ImageDerivatives(const FloatImage& in,
double sigma,
- FloatImage *gradient_x,
- FloatImage *gradient_y);
+ FloatImage* gradient_x,
+ FloatImage* gradient_y);
-void BlurredImageAndDerivatives(const FloatImage &in,
+void BlurredImageAndDerivatives(const FloatImage& in,
double sigma,
- FloatImage *blurred_image,
- FloatImage *gradient_x,
- FloatImage *gradient_y);
+ FloatImage* blurred_image,
+ FloatImage* gradient_x,
+ FloatImage* gradient_y);
// Blur and take the gradients of an image, storing the results inside the
// three channels of blurred_and_gradxy.
-void BlurredImageAndDerivativesChannels(const FloatImage &in,
+void BlurredImageAndDerivativesChannels(const FloatImage& in,
double sigma,
- FloatImage *blurred_and_gradxy);
+ FloatImage* blurred_and_gradxy);
-void BoxFilterHorizontal(const FloatImage &in,
+void BoxFilterHorizontal(const FloatImage& in,
int window_size,
- FloatImage *out_pointer);
+ FloatImage* out_pointer);
-void BoxFilterVertical(const FloatImage &in,
+void BoxFilterVertical(const FloatImage& in,
int window_size,
- FloatImage *out_pointer);
+ FloatImage* out_pointer);
-void BoxFilter(const FloatImage &in,
- int box_width,
- FloatImage *out);
+void BoxFilter(const FloatImage& in, int box_width, FloatImage* out);
/*!
Convolve \a src into \a dst with the discrete laplacian operator.
\a src and \a dst should be \a width x \a height images.
- \a strength is an interpolation coefficient (0-256) between original image and the laplacian.
+ \a strength is an interpolation coefficient (0-256) between original image
+ and the laplacian.
- \note Make sure the search region is filtered with the same strength as the pattern.
+ \note Make sure the search region is filtered with the same strength as the
+ pattern.
*/
void LaplaceFilter(unsigned char* src,
unsigned char* dst,
@@ -104,4 +105,3 @@ void LaplaceFilter(unsigned char* src,
} // namespace libmv
#endif // LIBMV_IMAGE_CONVOLVE_H_
-
diff --git a/intern/libmv/libmv/image/convolve_test.cc b/intern/libmv/libmv/image/convolve_test.cc
index 0cdef8e1e72..1ad4cb9a40e 100644
--- a/intern/libmv/libmv/image/convolve_test.cc
+++ b/intern/libmv/libmv/image/convolve_test.cc
@@ -85,26 +85,26 @@ TEST(Convolve, BlurredImageAndDerivativesChannelsHorizontalSlope) {
FloatImage image(10, 10), blurred_and_derivatives;
for (int j = 0; j < 10; ++j) {
for (int i = 0; i < 10; ++i) {
- image(j, i) = 2*i;
+ image(j, i) = 2 * i;
}
}
BlurredImageAndDerivativesChannels(image, 0.9, &blurred_and_derivatives);
EXPECT_NEAR(blurred_and_derivatives(5, 5, 0), 10.0, 1e-7);
- EXPECT_NEAR(blurred_and_derivatives(5, 5, 1), 2.0, 1e-7);
- EXPECT_NEAR(blurred_and_derivatives(5, 5, 2), 0.0, 1e-7);
+ EXPECT_NEAR(blurred_and_derivatives(5, 5, 1), 2.0, 1e-7);
+ EXPECT_NEAR(blurred_and_derivatives(5, 5, 2), 0.0, 1e-7);
}
TEST(Convolve, BlurredImageAndDerivativesChannelsVerticalSlope) {
FloatImage image(10, 10), blurred_and_derivatives;
for (int j = 0; j < 10; ++j) {
for (int i = 0; i < 10; ++i) {
- image(j, i) = 2*j;
+ image(j, i) = 2 * j;
}
}
BlurredImageAndDerivativesChannels(image, 0.9, &blurred_and_derivatives);
EXPECT_NEAR(blurred_and_derivatives(5, 5, 0), 10.0, 1e-7);
- EXPECT_NEAR(blurred_and_derivatives(5, 5, 1), 0.0, 1e-7);
- EXPECT_NEAR(blurred_and_derivatives(5, 5, 2), 2.0, 1e-7);
+ EXPECT_NEAR(blurred_and_derivatives(5, 5, 1), 0.0, 1e-7);
+ EXPECT_NEAR(blurred_and_derivatives(5, 5, 2), 2.0, 1e-7);
}
} // namespace
diff --git a/intern/libmv/libmv/image/correlation.h b/intern/libmv/libmv/image/correlation.h
index c354f7e891e..25123efe8d0 100644
--- a/intern/libmv/libmv/image/correlation.h
+++ b/intern/libmv/libmv/image/correlation.h
@@ -21,14 +21,14 @@
#ifndef LIBMV_IMAGE_CORRELATION_H
#define LIBMV_IMAGE_CORRELATION_H
-#include "libmv/logging/logging.h"
#include "libmv/image/image.h"
+#include "libmv/logging/logging.h"
namespace libmv {
inline double PearsonProductMomentCorrelation(
- const FloatImage &image_and_gradient1_sampled,
- const FloatImage &image_and_gradient2_sampled) {
+ const FloatImage& image_and_gradient1_sampled,
+ const FloatImage& image_and_gradient2_sampled) {
assert(image_and_gradient1_sampled.Width() ==
image_and_gradient2_sampled.Width());
assert(image_and_gradient1_sampled.Height() ==
@@ -63,9 +63,8 @@ inline double PearsonProductMomentCorrelation(
double covariance_xy = sXY - sX * sY;
double correlation = covariance_xy / sqrt(var_x * var_y);
- LG << "Covariance xy: " << covariance_xy
- << ", var 1: " << var_x << ", var 2: " << var_y
- << ", correlation: " << correlation;
+ LG << "Covariance xy: " << covariance_xy << ", var 1: " << var_x
+ << ", var 2: " << var_y << ", correlation: " << correlation;
return correlation;
}
diff --git a/intern/libmv/libmv/image/image.h b/intern/libmv/libmv/image/image.h
index e0f200a4c93..40d6aa6f70a 100644
--- a/intern/libmv/libmv/image/image.h
+++ b/intern/libmv/libmv/image/image.h
@@ -39,14 +39,11 @@ typedef Array3Ds ShortImage;
// is the best solution after all.
class Image {
public:
-
// Create an image from an array. The image takes ownership of the array.
- Image(Array3Du *array) : array_type_(BYTE), array_(array) {}
- Image(Array3Df *array) : array_type_(FLOAT), array_(array) {}
+ Image(Array3Du* array) : array_type_(BYTE), array_(array) {}
+ Image(Array3Df* array) : array_type_(FLOAT), array_(array) {}
- Image(const Image &img): array_type_(NONE), array_(NULL) {
- *this = img;
- }
+ Image(const Image& img) : array_type_(NONE), array_(NULL) { *this = img; }
// Underlying data type.
enum DataType {
@@ -62,20 +59,18 @@ class Image {
int size;
switch (array_type_) {
case BYTE:
- size = reinterpret_cast<Array3Du *>(array_)->MemorySizeInBytes();
- break;
+ size = reinterpret_cast<Array3Du*>(array_)->MemorySizeInBytes();
+ break;
case FLOAT:
- size = reinterpret_cast<Array3Df *>(array_)->MemorySizeInBytes();
- break;
+ size = reinterpret_cast<Array3Df*>(array_)->MemorySizeInBytes();
+ break;
case INT:
- size = reinterpret_cast<Array3Di *>(array_)->MemorySizeInBytes();
- break;
+ size = reinterpret_cast<Array3Di*>(array_)->MemorySizeInBytes();
+ break;
case SHORT:
- size = reinterpret_cast<Array3Ds *>(array_)->MemorySizeInBytes();
- break;
- default :
- size = 0;
- assert(0);
+ size = reinterpret_cast<Array3Ds*>(array_)->MemorySizeInBytes();
+ break;
+ default: size = 0; assert(0);
}
size += sizeof(*this);
return size;
@@ -83,71 +78,57 @@ class Image {
~Image() {
switch (array_type_) {
- case BYTE:
- delete reinterpret_cast<Array3Du *>(array_);
-
- break;
- case FLOAT:
- delete reinterpret_cast<Array3Df *>(array_);
-
- break;
- case INT:
- delete reinterpret_cast<Array3Di *>(array_);
-
- break;
- case SHORT:
- delete reinterpret_cast<Array3Ds *>(array_);
-
- break;
- default:
- assert(0);
- }
+ case BYTE: delete reinterpret_cast<Array3Du*>(array_); break;
+ case FLOAT: delete reinterpret_cast<Array3Df*>(array_); break;
+ case INT: delete reinterpret_cast<Array3Di*>(array_); break;
+ case SHORT: delete reinterpret_cast<Array3Ds*>(array_); break;
+ default: assert(0);
+ }
}
- Image& operator= (const Image& f) {
+ Image& operator=(const Image& f) {
if (this != &f) {
array_type_ = f.array_type_;
switch (array_type_) {
case BYTE:
- delete reinterpret_cast<Array3Du *>(array_);
- array_ = new Array3Du(*(Array3Du *)f.array_);
- break;
+ delete reinterpret_cast<Array3Du*>(array_);
+ array_ = new Array3Du(*(Array3Du*)f.array_);
+ break;
case FLOAT:
- delete reinterpret_cast<Array3Df *>(array_);
- array_ = new Array3Df(*(Array3Df *)f.array_);
- break;
+ delete reinterpret_cast<Array3Df*>(array_);
+ array_ = new Array3Df(*(Array3Df*)f.array_);
+ break;
case INT:
- delete reinterpret_cast<Array3Di *>(array_);
- array_ = new Array3Di(*(Array3Di *)f.array_);
- break;
+ delete reinterpret_cast<Array3Di*>(array_);
+ array_ = new Array3Di(*(Array3Di*)f.array_);
+ break;
case SHORT:
- delete reinterpret_cast<Array3Ds *>(array_);
- array_ = new Array3Ds(*(Array3Ds *)f.array_);
- break;
- default:
- assert(0);
+ delete reinterpret_cast<Array3Ds*>(array_);
+ array_ = new Array3Ds(*(Array3Ds*)f.array_);
+ break;
+ default: assert(0);
}
}
return *this;
}
- Array3Du *AsArray3Du() const {
+ Array3Du* AsArray3Du() const {
if (array_type_ == BYTE) {
- return reinterpret_cast<Array3Du *>(array_);
+ return reinterpret_cast<Array3Du*>(array_);
}
return NULL;
}
- Array3Df *AsArray3Df() const {
+ Array3Df* AsArray3Df() const {
if (array_type_ == FLOAT) {
- return reinterpret_cast<Array3Df *>(array_);
+ return reinterpret_cast<Array3Df*>(array_);
}
return NULL;
}
private:
DataType array_type_;
- BaseArray *array_;
+ BaseArray* array_;
};
} // namespace libmv
diff --git a/intern/libmv/libmv/image/image_converter.h b/intern/libmv/libmv/image/image_converter.h
index b3a3fa2bf8c..41d53be6722 100644
--- a/intern/libmv/libmv/image/image_converter.h
+++ b/intern/libmv/libmv/image/image_converter.h
@@ -28,7 +28,7 @@ namespace libmv {
// The factor comes from http://www.easyrgb.com/
// RGB to XYZ : Y is the luminance channel
// var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
-template<typename T>
+template <typename T>
inline T RGB2GRAY(const T r, const T g, const T b) {
return static_cast<T>(r * 0.2126 + g * 0.7152 + b * 0.0722);
}
@@ -42,8 +42,8 @@ inline unsigned char RGB2GRAY<unsigned char>(const unsigned char r,
return (unsigned char)(r * 0.2126 + g * 0.7152 + b * 0.0722 +0.5);
}*/
-template<class ImageIn, class ImageOut>
-void Rgb2Gray(const ImageIn &imaIn, ImageOut *imaOut) {
+template <class ImageIn, class ImageOut>
+void Rgb2Gray(const ImageIn& imaIn, ImageOut* imaOut) {
// It is all fine to cnvert RGBA image here as well,
// all the additional channels will be nicely ignored.
assert(imaIn.Depth() >= 3);
@@ -52,21 +52,22 @@ void Rgb2Gray(const ImageIn &imaIn, ImageOut *imaOut) {
// Convert each RGB pixel into Gray value (luminance)
for (int j = 0; j < imaIn.Height(); ++j) {
- for (int i = 0; i < imaIn.Width(); ++i) {
- (*imaOut)(j, i) = RGB2GRAY(imaIn(j, i, 0) , imaIn(j, i, 1), imaIn(j, i, 2));
+ for (int i = 0; i < imaIn.Width(); ++i) {
+ (*imaOut)(j, i) =
+ RGB2GRAY(imaIn(j, i, 0), imaIn(j, i, 1), imaIn(j, i, 2));
}
}
}
// Convert given float image to an unsigned char array of pixels.
-template<class Image>
-unsigned char *FloatImageToUCharArray(const Image &image) {
- unsigned char *buffer =
+template <class Image>
+unsigned char* FloatImageToUCharArray(const Image& image) {
+ unsigned char* buffer =
new unsigned char[image.Width() * image.Height() * image.Depth()];
for (int y = 0; y < image.Height(); y++) {
- for (int x = 0; x < image.Width(); x++) {
- for (int d = 0; d < image.Depth(); d++) {
+ for (int x = 0; x < image.Width(); x++) {
+ for (int d = 0; d < image.Depth(); d++) {
int index = (y * image.Width() + x) * image.Depth() + d;
buffer[index] = 255.0 * image(y, x, d);
}
diff --git a/intern/libmv/libmv/image/image_drawing.h b/intern/libmv/libmv/image/image_drawing.h
index f50e48b75a3..dd6a94dd7d4 100644
--- a/intern/libmv/libmv/image/image_drawing.h
+++ b/intern/libmv/libmv/image/image_drawing.h
@@ -34,9 +34,9 @@ namespace libmv {
/// Put the pixel in the image to the given color only if the point (xc,yc)
/// is inside the image.
template <class Image, class Color>
-inline void safePutPixel(int yc, int xc, const Color & col, Image *pim) {
+inline void safePutPixel(int yc, int xc, const Color& col, Image* pim) {
if (!pim)
- return;
+ return;
if (pim->Contains(yc, xc)) {
(*pim)(yc, xc) = col;
}
@@ -45,9 +45,9 @@ inline void safePutPixel(int yc, int xc, const Color & col, Image *pim) {
/// is inside the image. This function support multi-channel color
/// \note The color pointer col must have size as the image depth
template <class Image, class Color>
-inline void safePutPixel(int yc, int xc, const Color *col, Image *pim) {
+inline void safePutPixel(int yc, int xc, const Color* col, Image* pim) {
if (!pim)
- return;
+ return;
if (pim->Contains(yc, xc)) {
for (int i = 0; i < pim->Depth(); ++i)
(*pim)(yc, xc, i) = *(col + i);
@@ -59,19 +59,23 @@ inline void safePutPixel(int yc, int xc, const Color *col, Image *pim) {
// Add the rotation of the ellipse.
// As the algo. use symmetry we must use 4 rotations.
template <class Image, class Color>
-void DrawEllipse(int xc, int yc, int radiusA, int radiusB,
- const Color &col, Image *pim, double angle = 0.0) {
+void DrawEllipse(int xc,
+ int yc,
+ int radiusA,
+ int radiusB,
+ const Color& col,
+ Image* pim,
+ double angle = 0.0) {
int a = radiusA;
int b = radiusB;
// Counter Clockwise rotation matrix.
- double matXY[4] = { cos(angle), sin(angle),
- -sin(angle), cos(angle)};
+ double matXY[4] = {cos(angle), sin(angle), -sin(angle), cos(angle)};
int x, y;
double d1, d2;
x = 0;
y = b;
- d1 = b*b - a*a*b + a*a/4;
+ d1 = b * b - a * a * b + a * a / 4;
float rotX = (matXY[0] * x + matXY[1] * y);
float rotY = (matXY[2] * x + matXY[3] * y);
@@ -86,12 +90,12 @@ void DrawEllipse(int xc, int yc, int radiusA, int radiusB,
rotY = (-matXY[2] * x + matXY[3] * y);
safePutPixel(yc + rotY, xc + rotX, col, pim);
- while (a*a*(y-.5) > b*b*(x+1)) {
+ while (a * a * (y - .5) > b * b * (x + 1)) {
if (d1 < 0) {
- d1 += b*b*(2*x+3);
+ d1 += b * b * (2 * x + 3);
++x;
} else {
- d1 += b*b*(2*x+3) + a*a*(-2*y+2);
+ d1 += b * b * (2 * x + 3) + a * a * (-2 * y + 2);
++x;
--y;
}
@@ -108,14 +112,14 @@ void DrawEllipse(int xc, int yc, int radiusA, int radiusB,
rotY = (-matXY[2] * x + matXY[3] * y);
safePutPixel(yc + rotY, xc + rotX, col, pim);
}
- d2 = b*b*(x+.5)*(x+.5) + a*a*(y-1)*(y-1) - a*a*b*b;
+ d2 = b * b * (x + .5) * (x + .5) + a * a * (y - 1) * (y - 1) - a * a * b * b;
while (y > 0) {
if (d2 < 0) {
- d2 += b*b*(2*x+2) + a*a*(-2*y+3);
+ d2 += b * b * (2 * x + 2) + a * a * (-2 * y + 3);
--y;
++x;
} else {
- d2 += a*a*(-2*y+3);
+ d2 += a * a * (-2 * y + 3);
--y;
}
rotX = (matXY[0] * x + matXY[1] * y);
@@ -137,23 +141,23 @@ void DrawEllipse(int xc, int yc, int radiusA, int radiusB,
// So it's better the use the Andres method.
// http://fr.wikipedia.org/wiki/Algorithme_de_tracé_de_cercle_d'Andres.
template <class Image, class Color>
-void DrawCircle(int x, int y, int radius, const Color &col, Image *pim) {
- Image &im = *pim;
- if ( im.Contains(y + radius, x + radius)
- || im.Contains(y + radius, x - radius)
- || im.Contains(y - radius, x + radius)
- || im.Contains(y - radius, x - radius)) {
+void DrawCircle(int x, int y, int radius, const Color& col, Image* pim) {
+ Image& im = *pim;
+ if (im.Contains(y + radius, x + radius) ||
+ im.Contains(y + radius, x - radius) ||
+ im.Contains(y - radius, x + radius) ||
+ im.Contains(y - radius, x - radius)) {
int x1 = 0;
int y1 = radius;
int d = radius - 1;
while (y1 >= x1) {
// Draw the point for each octant.
- safePutPixel( y1 + y, x1 + x, col, pim);
- safePutPixel( x1 + y, y1 + x, col, pim);
- safePutPixel( y1 + y, -x1 + x, col, pim);
- safePutPixel( x1 + y, -y1 + x, col, pim);
- safePutPixel(-y1 + y, x1 + x, col, pim);
- safePutPixel(-x1 + y, y1 + x, col, pim);
+ safePutPixel(y1 + y, x1 + x, col, pim);
+ safePutPixel(x1 + y, y1 + x, col, pim);
+ safePutPixel(y1 + y, -x1 + x, col, pim);
+ safePutPixel(x1 + y, -y1 + x, col, pim);
+ safePutPixel(-y1 + y, x1 + x, col, pim);
+ safePutPixel(-x1 + y, y1 + x, col, pim);
safePutPixel(-y1 + y, -x1 + x, col, pim);
safePutPixel(-x1 + y, -y1 + x, col, pim);
if (d >= 2 * x1) {
@@ -163,7 +167,7 @@ void DrawCircle(int x, int y, int radius, const Color &col, Image *pim) {
if (d <= 2 * (radius - y1)) {
d = d + 2 * y1 - 1;
y1 -= 1;
- } else {
+ } else {
d = d + 2 * (y1 - x1 - 1);
y1 -= 1;
x1 += 1;
@@ -175,8 +179,8 @@ void DrawCircle(int x, int y, int radius, const Color &col, Image *pim) {
// Bresenham algorithm
template <class Image, class Color>
-void DrawLine(int xa, int ya, int xb, int yb, const Color &col, Image *pim) {
- Image &im = *pim;
+void DrawLine(int xa, int ya, int xb, int yb, const Color& col, Image* pim) {
+ Image& im = *pim;
// If one point is outside the image
// Replace the outside point by the intersection of the line and
@@ -185,35 +189,37 @@ void DrawLine(int xa, int ya, int xb, int yb, const Color &col, Image *pim) {
int width = pim->Width();
int height = pim->Height();
const bool xdir = xa < xb, ydir = ya < yb;
- float nx0 = xa, nx1 = xb, ny0 = ya, ny1 = yb,
- &xleft = xdir?nx0:nx1, &yleft = xdir?ny0:ny1,
- &xright = xdir?nx1:nx0, &yright = xdir?ny1:ny0,
- &xup = ydir?nx0:nx1, &yup = ydir?ny0:ny1,
- &xdown = ydir?nx1:nx0, &ydown = ydir?ny1:ny0;
+ float nx0 = xa, nx1 = xb, ny0 = ya, ny1 = yb, &xleft = xdir ? nx0 : nx1,
+ &yleft = xdir ? ny0 : ny1, &xright = xdir ? nx1 : nx0,
+ &yright = xdir ? ny1 : ny0, &xup = ydir ? nx0 : nx1,
+ &yup = ydir ? ny0 : ny1, &xdown = ydir ? nx1 : nx0,
+ &ydown = ydir ? ny1 : ny0;
- if (xright < 0 || xleft >= width) return;
+ if (xright < 0 || xleft >= width)
+ return;
if (xleft < 0) {
- yleft -= xleft*(yright - yleft)/(xright - xleft);
- xleft = 0;
+ yleft -= xleft * (yright - yleft) / (xright - xleft);
+ xleft = 0;
}
if (xright >= width) {
- yright -= (xright - width)*(yright - yleft)/(xright - xleft);
- xright = width - 1;
+ yright -= (xright - width) * (yright - yleft) / (xright - xleft);
+ xright = width - 1;
}
- if (ydown < 0 || yup >= height) return;
+ if (ydown < 0 || yup >= height)
+ return;
if (yup < 0) {
- xup -= yup*(xdown - xup)/(ydown - yup);
- yup = 0;
+ xup -= yup * (xdown - xup) / (ydown - yup);
+ yup = 0;
}
if (ydown >= height) {
- xdown -= (ydown - height)*(xdown - xup)/(ydown - yup);
- ydown = height - 1;
+ xdown -= (ydown - height) * (xdown - xup) / (ydown - yup);
+ ydown = height - 1;
}
- xa = (int) xleft;
- xb = (int) xright;
- ya = (int) yleft;
- yb = (int) yright;
+ xa = (int)xleft;
+ xb = (int)xright;
+ ya = (int)yleft;
+ yb = (int)yright;
}
int xbas, xhaut, ybas, yhaut;
@@ -241,7 +247,7 @@ void DrawLine(int xa, int ya, int xb, int yb, const Color &col, Image *pim) {
}
if (dy > 0) { // Positive slope will increment X.
incrmY = 1;
- } else { // Negative slope.
+ } else { // Negative slope.
incrmY = -1;
}
if (dx >= dy) {
@@ -255,9 +261,9 @@ void DrawLine(int xa, int ya, int xb, int yb, const Color &col, Image *pim) {
x += incrmX;
if (dp <= 0) { // Go in direction of the South Pixel.
dp += S;
- } else { // Go to the North.
+ } else { // Go to the North.
dp += N;
- y+=incrmY;
+ y += incrmY;
}
}
} else {
@@ -271,7 +277,7 @@ void DrawLine(int xa, int ya, int xb, int yb, const Color &col, Image *pim) {
y += incrmY;
if (dp <= 0) { // Go in direction of the South Pixel.
dp += S;
- } else { // Go to the North.
+ } else { // Go to the North.
dp += N;
x += incrmX;
}
diff --git a/intern/libmv/libmv/image/image_test.cc b/intern/libmv/libmv/image/image_test.cc
index 241f49f2244..a1730a9a55e 100644
--- a/intern/libmv/libmv/image/image_test.cc
+++ b/intern/libmv/libmv/image/image_test.cc
@@ -23,20 +23,20 @@
#include "libmv/image/image.h"
#include "testing/testing.h"
-using libmv::Image;
using libmv::Array3Df;
+using libmv::Image;
namespace {
TEST(Image, SimpleImageAccessors) {
- Array3Df *array = new Array3Df(2, 3);
+ Array3Df* array = new Array3Df(2, 3);
Image image(array);
EXPECT_EQ(array, image.AsArray3Df());
EXPECT_TRUE(NULL == image.AsArray3Du());
}
TEST(Image, MemorySizeInBytes) {
- Array3Df *array = new Array3Df(2, 3);
+ Array3Df* array = new Array3Df(2, 3);
Image image(array);
int size = sizeof(image) + array->MemorySizeInBytes();
EXPECT_EQ(size, image.MemorySizeInBytes());
diff --git a/intern/libmv/libmv/image/sample.h b/intern/libmv/libmv/image/sample.h
index 24eb9ccd57d..2b57baf27b9 100644
--- a/intern/libmv/libmv/image/sample.h
+++ b/intern/libmv/libmv/image/sample.h
@@ -26,17 +26,14 @@
namespace libmv {
/// Nearest neighbor interpolation.
-template<typename T>
-inline T SampleNearest(const Array3D<T> &image,
- float y, float x, int v = 0) {
+template <typename T>
+inline T SampleNearest(const Array3D<T>& image, float y, float x, int v = 0) {
const int i = int(round(y));
const int j = int(round(x));
return image(i, j, v);
}
-inline void LinearInitAxis(float x, int size,
- int *x1, int *x2,
- float *dx) {
+inline void LinearInitAxis(float x, int size, int* x1, int* x2, float* dx) {
const int ix = static_cast<int>(x);
if (ix < 0) {
*x1 = 0;
@@ -54,32 +51,32 @@ inline void LinearInitAxis(float x, int size,
}
/// Linear interpolation.
-template<typename T>
-inline T SampleLinear(const Array3D<T> &image, float y, float x, int v = 0) {
+template <typename T>
+inline T SampleLinear(const Array3D<T>& image, float y, float x, int v = 0) {
int x1, y1, x2, y2;
float dx, dy;
LinearInitAxis(y, image.Height(), &y1, &y2, &dy);
- LinearInitAxis(x, image.Width(), &x1, &x2, &dx);
+ LinearInitAxis(x, image.Width(), &x1, &x2, &dx);
const T im11 = image(y1, x1, v);
const T im12 = image(y1, x2, v);
const T im21 = image(y2, x1, v);
const T im22 = image(y2, x2, v);
- return T( dy * (dx * im11 + (1.0 - dx) * im12) +
+ return T(dy * (dx * im11 + (1.0 - dx) * im12) +
(1 - dy) * (dx * im21 + (1.0 - dx) * im22));
}
/// Linear interpolation, of all channels. The sample is assumed to have the
/// same size as the number of channels in image.
-template<typename T>
-inline void SampleLinear(const Array3D<T> &image, float y, float x, T *sample) {
+template <typename T>
+inline void SampleLinear(const Array3D<T>& image, float y, float x, T* sample) {
int x1, y1, x2, y2;
float dx, dy;
LinearInitAxis(y, image.Height(), &y1, &y2, &dy);
- LinearInitAxis(x, image.Width(), &x1, &x2, &dx);
+ LinearInitAxis(x, image.Width(), &x1, &x2, &dx);
for (int i = 0; i < image.Depth(); ++i) {
const T im11 = image(y1, x1, i);
@@ -87,7 +84,7 @@ inline void SampleLinear(const Array3D<T> &image, float y, float x, T *sample) {
const T im21 = image(y2, x1, i);
const T im22 = image(y2, x2, i);
- sample[i] = T( dy * (dx * im11 + (1.0 - dx) * im12) +
+ sample[i] = T(dy * (dx * im11 + (1.0 - dx) * im12) +
(1 - dy) * (dx * im21 + (1.0 - dx) * im22));
}
}
@@ -95,7 +92,7 @@ inline void SampleLinear(const Array3D<T> &image, float y, float x, T *sample) {
// Downsample all channels by 2. If the image has odd width or height, the last
// row or column is ignored.
// FIXME(MatthiasF): this implementation shouldn't be in an interface file
-inline void DownsampleChannelsBy2(const Array3Df &in, Array3Df *out) {
+inline void DownsampleChannelsBy2(const Array3Df& in, Array3Df* out) {
int height = in.Height() / 2;
int width = in.Width() / 2;
int depth = in.Depth();
@@ -106,10 +103,12 @@ inline void DownsampleChannelsBy2(const Array3Df &in, Array3Df *out) {
for (int r = 0; r < height; ++r) {
for (int c = 0; c < width; ++c) {
for (int k = 0; k < depth; ++k) {
+ // clang-format off
(*out)(r, c, k) = (in(2 * r, 2 * c, k) +
in(2 * r + 1, 2 * c, k) +
in(2 * r, 2 * c + 1, k) +
in(2 * r + 1, 2 * c + 1, k)) / 4.0f;
+ // clang-format on
}
}
}
@@ -117,11 +116,12 @@ inline void DownsampleChannelsBy2(const Array3Df &in, Array3Df *out) {
// Sample a region centered at x,y in image with size extending by half_width
// from x,y. Channels specifies the number of channels to sample from.
-inline void SamplePattern(const FloatImage &image,
- double x, double y,
- int half_width,
- int channels,
- FloatImage *sampled) {
+inline void SamplePattern(const FloatImage& image,
+ double x,
+ double y,
+ int half_width,
+ int channels,
+ FloatImage* sampled) {
sampled->Resize(2 * half_width + 1, 2 * half_width + 1, channels);
for (int r = -half_width; r <= half_width; ++r) {
for (int c = -half_width; c <= half_width; ++c) {
diff --git a/intern/libmv/libmv/image/sample_test.cc b/intern/libmv/libmv/image/sample_test.cc
index c8a0ce470c2..f1fb4c42c67 100644
--- a/intern/libmv/libmv/image/sample_test.cc
+++ b/intern/libmv/libmv/image/sample_test.cc
@@ -32,9 +32,9 @@ TEST(Image, Nearest) {
image(1, 0) = 2;
image(1, 1) = 3;
EXPECT_EQ(0, SampleNearest(image, -0.4f, -0.4f));
- EXPECT_EQ(0, SampleNearest(image, 0.4f, 0.4f));
- EXPECT_EQ(3, SampleNearest(image, 0.6f, 0.6f));
- EXPECT_EQ(3, SampleNearest(image, 1.4f, 1.4f));
+ EXPECT_EQ(0, SampleNearest(image, 0.4f, 0.4f));
+ EXPECT_EQ(3, SampleNearest(image, 0.6f, 0.6f));
+ EXPECT_EQ(3, SampleNearest(image, 1.4f, 1.4f));
}
TEST(Image, Linear) {
@@ -57,7 +57,7 @@ TEST(Image, DownsampleBy2) {
ASSERT_EQ(1, resampled_image.Height());
ASSERT_EQ(1, resampled_image.Width());
ASSERT_EQ(1, resampled_image.Depth());
- EXPECT_FLOAT_EQ(6./4., resampled_image(0, 0));
+ EXPECT_FLOAT_EQ(6. / 4., resampled_image(0, 0));
}
TEST(Image, DownsampleBy2MultiChannel) {
@@ -82,8 +82,8 @@ TEST(Image, DownsampleBy2MultiChannel) {
ASSERT_EQ(1, resampled_image.Height());
ASSERT_EQ(1, resampled_image.Width());
ASSERT_EQ(3, resampled_image.Depth());
- EXPECT_FLOAT_EQ((0+1+2+3)/4., resampled_image(0, 0, 0));
- EXPECT_FLOAT_EQ((5+6+7+8)/4., resampled_image(0, 0, 1));
- EXPECT_FLOAT_EQ((9+10+11+12)/4., resampled_image(0, 0, 2));
+ EXPECT_FLOAT_EQ((0 + 1 + 2 + 3) / 4., resampled_image(0, 0, 0));
+ EXPECT_FLOAT_EQ((5 + 6 + 7 + 8) / 4., resampled_image(0, 0, 1));
+ EXPECT_FLOAT_EQ((9 + 10 + 11 + 12) / 4., resampled_image(0, 0, 2));
}
} // namespace
diff --git a/intern/libmv/libmv/image/tuple.h b/intern/libmv/libmv/image/tuple.h
index c8dc36f2e18..447bf0cc81c 100644
--- a/intern/libmv/libmv/image/tuple.h
+++ b/intern/libmv/libmv/image/tuple.h
@@ -34,10 +34,14 @@ class Tuple {
Tuple(T initial_value) { Reset(initial_value); }
template <typename D>
- Tuple(D *values) { Reset(values); }
+ Tuple(D* values) {
+ Reset(values);
+ }
template <typename D>
- Tuple(const Tuple<D, N> &b) { Reset(b); }
+ Tuple(const Tuple<D, N>& b) {
+ Reset(b);
+ }
template <typename D>
Tuple& operator=(const Tuple<D, N>& b) {
@@ -46,30 +50,32 @@ class Tuple {
}
template <typename D>
- void Reset(const Tuple<D, N>& b) { Reset(b.Data()); }
+ void Reset(const Tuple<D, N>& b) {
+ Reset(b.Data());
+ }
template <typename D>
- void Reset(D *values) {
- for (int i = 0;i < N; i++) {
+ void Reset(D* values) {
+ for (int i = 0; i < N; i++) {
data_[i] = T(values[i]);
}
}
// Set all tuple values to the same thing.
void Reset(T value) {
- for (int i = 0;i < N; i++) {
+ for (int i = 0; i < N; i++) {
data_[i] = value;
}
}
// Pointer to the first element.
- T *Data() { return &data_[0]; }
- const T *Data() const { return &data_[0]; }
+ T* Data() { return &data_[0]; }
+ const T* Data() const { return &data_[0]; }
- T &operator()(int i) { return data_[i]; }
- const T &operator()(int i) const { return data_[i]; }
+ T& operator()(int i) { return data_[i]; }
+ const T& operator()(int i) const { return data_[i]; }
- bool operator==(const Tuple<T, N> &other) const {
+ bool operator==(const Tuple<T, N>& other) const {
for (int i = 0; i < N; ++i) {
if ((*this)(i) != other(i)) {
return false;
@@ -77,9 +83,7 @@ class Tuple {
}
return true;
}
- bool operator!=(const Tuple<T, N> &other) const {
- return !(*this == other);
- }
+ bool operator!=(const Tuple<T, N>& other) const { return !(*this == other); }
private:
T data_[N];
diff --git a/intern/libmv/libmv/multiview/conditioning.cc b/intern/libmv/libmv/multiview/conditioning.cc
index 0afbf119ea3..2f4bf653ca0 100644
--- a/intern/libmv/libmv/multiview/conditioning.cc
+++ b/intern/libmv/libmv/multiview/conditioning.cc
@@ -24,7 +24,7 @@
namespace libmv {
// HZ 4.4.4 pag.109: Point conditioning (non isotropic)
-void PreconditionerFromPoints(const Mat &points, Mat3 *T) {
+void PreconditionerFromPoints(const Mat& points, Mat3* T) {
Vec mean, variance;
MeanAndVarianceAlongRows(points, &mean, &variance);
@@ -38,12 +38,14 @@ void PreconditionerFromPoints(const Mat &points, Mat3 *T) {
if (variance(1) < 1e-8)
yfactor = mean(1) = 1.0;
+ // clang-format off
*T << xfactor, 0, -xfactor * mean(0),
0, yfactor, -yfactor * mean(1),
0, 0, 1;
+ // clang-format on
}
// HZ 4.4.4 pag.107: Point conditioning (isotropic)
-void IsotropicPreconditionerFromPoints(const Mat &points, Mat3 *T) {
+void IsotropicPreconditionerFromPoints(const Mat& points, Mat3* T) {
Vec mean, variance;
MeanAndVarianceAlongRows(points, &mean, &variance);
@@ -57,14 +59,16 @@ void IsotropicPreconditionerFromPoints(const Mat &points, Mat3 *T) {
mean.setOnes();
}
+ // clang-format off
*T << factor, 0, -factor * mean(0),
0, factor, -factor * mean(1),
0, 0, 1;
+ // clang-format on
}
-void ApplyTransformationToPoints(const Mat &points,
- const Mat3 &T,
- Mat *transformed_points) {
+void ApplyTransformationToPoints(const Mat& points,
+ const Mat3& T,
+ Mat* transformed_points) {
int n = points.cols();
transformed_points->resize(2, n);
Mat3X p(3, n);
@@ -73,26 +77,24 @@ void ApplyTransformationToPoints(const Mat &points,
HomogeneousToEuclidean(p, transformed_points);
}
-void NormalizePoints(const Mat &points,
- Mat *normalized_points,
- Mat3 *T) {
+void NormalizePoints(const Mat& points, Mat* normalized_points, Mat3* T) {
PreconditionerFromPoints(points, T);
ApplyTransformationToPoints(points, *T, normalized_points);
}
-void NormalizeIsotropicPoints(const Mat &points,
- Mat *normalized_points,
- Mat3 *T) {
+void NormalizeIsotropicPoints(const Mat& points,
+ Mat* normalized_points,
+ Mat3* T) {
IsotropicPreconditionerFromPoints(points, T);
ApplyTransformationToPoints(points, *T, normalized_points);
}
// Denormalize the results. See HZ page 109.
-void UnnormalizerT::Unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H) {
+void UnnormalizerT::Unnormalize(const Mat3& T1, const Mat3& T2, Mat3* H) {
*H = T2.transpose() * (*H) * T1;
}
-void UnnormalizerI::Unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H) {
+void UnnormalizerI::Unnormalize(const Mat3& T1, const Mat3& T2, Mat3* H) {
*H = T2.inverse() * (*H) * T1;
}
diff --git a/intern/libmv/libmv/multiview/conditioning.h b/intern/libmv/libmv/multiview/conditioning.h
index 8f3e3a76070..876c5af48e6 100644
--- a/intern/libmv/libmv/multiview/conditioning.h
+++ b/intern/libmv/libmv/multiview/conditioning.h
@@ -26,32 +26,30 @@
namespace libmv {
// Point conditioning (non isotropic)
-void PreconditionerFromPoints(const Mat &points, Mat3 *T);
+void PreconditionerFromPoints(const Mat& points, Mat3* T);
// Point conditioning (isotropic)
-void IsotropicPreconditionerFromPoints(const Mat &points, Mat3 *T);
+void IsotropicPreconditionerFromPoints(const Mat& points, Mat3* T);
-void ApplyTransformationToPoints(const Mat &points,
- const Mat3 &T,
- Mat *transformed_points);
+void ApplyTransformationToPoints(const Mat& points,
+ const Mat3& T,
+ Mat* transformed_points);
-void NormalizePoints(const Mat &points,
- Mat *normalized_points,
- Mat3 *T);
+void NormalizePoints(const Mat& points, Mat* normalized_points, Mat3* T);
-void NormalizeIsotropicPoints(const Mat &points,
- Mat *normalized_points,
- Mat3 *T);
+void NormalizeIsotropicPoints(const Mat& points,
+ Mat* normalized_points,
+ Mat3* T);
/// Use inverse for unnormalize
struct UnnormalizerI {
// Denormalize the results. See HZ page 109.
- static void Unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H);
+ static void Unnormalize(const Mat3& T1, const Mat3& T2, Mat3* H);
};
/// Use transpose for unnormalize
struct UnnormalizerT {
// Denormalize the results. See HZ page 109.
- static void Unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H);
+ static void Unnormalize(const Mat3& T1, const Mat3& T2, Mat3* H);
};
} // namespace libmv
diff --git a/intern/libmv/libmv/multiview/euclidean_resection.cc b/intern/libmv/libmv/multiview/euclidean_resection.cc
index 245b027fb7c..249d7ebef3d 100644
--- a/intern/libmv/libmv/multiview/euclidean_resection.cc
+++ b/intern/libmv/libmv/multiview/euclidean_resection.cc
@@ -23,8 +23,8 @@
#include <cmath>
#include <limits>
-#include <Eigen/SVD>
#include <Eigen/Geometry>
+#include <Eigen/SVD>
#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
@@ -35,9 +35,10 @@ namespace euclidean_resection {
typedef unsigned int uint;
-bool EuclideanResection(const Mat2X &x_camera,
- const Mat3X &X_world,
- Mat3 *R, Vec3 *t,
+bool EuclideanResection(const Mat2X& x_camera,
+ const Mat3X& X_world,
+ Mat3* R,
+ Vec3* t,
ResectionMethod method) {
switch (method) {
case RESECTION_ANSAR_DANIILIDIS:
@@ -49,20 +50,20 @@ bool EuclideanResection(const Mat2X &x_camera,
case RESECTION_PPNP:
return EuclideanResectionPPnP(x_camera, X_world, R, t);
break;
- default:
- LOG(FATAL) << "Unknown resection method.";
+ default: LOG(FATAL) << "Unknown resection method.";
}
return false;
}
-bool EuclideanResection(const Mat &x_image,
- const Mat3X &X_world,
- const Mat3 &K,
- Mat3 *R, Vec3 *t,
+bool EuclideanResection(const Mat& x_image,
+ const Mat3X& X_world,
+ const Mat3& K,
+ Mat3* R,
+ Vec3* t,
ResectionMethod method) {
CHECK(x_image.rows() == 2 || x_image.rows() == 3)
- << "Invalid size for x_image: "
- << x_image.rows() << "x" << x_image.cols();
+ << "Invalid size for x_image: " << x_image.rows() << "x"
+ << x_image.cols();
Mat2X x_camera;
if (x_image.rows() == 2) {
@@ -73,18 +74,15 @@ bool EuclideanResection(const Mat &x_image,
return EuclideanResection(x_camera, X_world, R, t, method);
}
-void AbsoluteOrientation(const Mat3X &X,
- const Mat3X &Xp,
- Mat3 *R,
- Vec3 *t) {
+void AbsoluteOrientation(const Mat3X& X, const Mat3X& Xp, Mat3* R, Vec3* t) {
int num_points = X.cols();
- Vec3 C = X.rowwise().sum() / num_points; // Centroid of X.
+ Vec3 C = X.rowwise().sum() / num_points; // Centroid of X.
Vec3 Cp = Xp.rowwise().sum() / num_points; // Centroid of Xp.
// Normalize the two point sets.
Mat3X Xn(3, num_points), Xpn(3, num_points);
for (int i = 0; i < num_points; ++i) {
- Xn.col(i) = X.col(i) - C;
+ Xn.col(i) = X.col(i) - C;
Xpn.col(i) = Xp.col(i) - Cp;
}
@@ -100,10 +98,12 @@ void AbsoluteOrientation(const Mat3X &X,
double Szy = Xn.row(2).dot(Xpn.row(1));
Mat4 N;
+ // clang-format off
N << Sxx + Syy + Szz, Syz - Szy, Szx - Sxz, Sxy - Syx,
Syz - Szy, Sxx - Syy - Szz, Sxy + Syx, Szx + Sxz,
Szx - Sxz, Sxy + Syx, -Sxx + Syy - Szz, Syz + Szy,
Sxy - Syx, Szx + Sxz, Syz + Szy, -Sxx - Syy + Szz;
+ // clang-format on
// Find the unit quaternion q that maximizes qNq. It is the eigenvector
// corresponding to the lagest eigenvalue.
@@ -118,6 +118,7 @@ void AbsoluteOrientation(const Mat3X &X,
double q1q3 = q(1) * q(3);
double q2q3 = q(2) * q(3);
+ // clang-format off
(*R) << qq(0) + qq(1) - qq(2) - qq(3),
2 * (q1q2 - q0q3),
2 * (q1q3 + q0q2),
@@ -127,6 +128,7 @@ void AbsoluteOrientation(const Mat3X &X,
2 * (q1q3 - q0q2),
2 * (q2q3 + q0q1),
qq(0) - qq(1) - qq(2) + qq(3);
+ // clang-format on
// Fix the handedness of the R matrix.
if (R->determinant() < 0) {
@@ -176,9 +178,7 @@ static int Sign(double value) {
// Lambda to create the constraints in equation (5) in "Linear Pose Estimation
// from Points or Lines", by Ansar, A. and Daniilidis, PAMI 2003. vol. 25, no.
// 5.
-static Vec MatrixToConstraint(const Mat &A,
- int num_k_columns,
- int num_lambda) {
+static Vec MatrixToConstraint(const Mat& A, int num_k_columns, int num_lambda) {
Vec C(num_k_columns);
C.setZero();
int idx = 0;
@@ -195,17 +195,17 @@ static Vec MatrixToConstraint(const Mat &A,
}
// Normalizes the columns of vectors.
-static void NormalizeColumnVectors(Mat3X *vectors) {
+static void NormalizeColumnVectors(Mat3X* vectors) {
int num_columns = vectors->cols();
for (int i = 0; i < num_columns; ++i) {
vectors->col(i).normalize();
}
}
-void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
- const Mat3X &X_world,
- Mat3 *R,
- Vec3 *t) {
+void EuclideanResectionAnsarDaniilidis(const Mat2X& x_camera,
+ const Mat3X& X_world,
+ Mat3* R,
+ Vec3* t) {
CHECK(x_camera.cols() == X_world.cols());
CHECK(x_camera.cols() > 3);
@@ -229,14 +229,14 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
// them into the M matrix (8). Also store the initial (i, j) indices.
int row = 0;
for (int i = 0; i < num_points; ++i) {
- for (int j = i+1; j < num_points; ++j) {
+ for (int j = i + 1; j < num_points; ++j) {
M(row, row) = -2 * x_camera_unit.col(i).dot(x_camera_unit.col(j));
M(row, num_m_rows + i) = x_camera_unit.col(i).dot(x_camera_unit.col(i));
M(row, num_m_rows + j) = x_camera_unit.col(j).dot(x_camera_unit.col(j));
Vec3 Xdiff = X_world.col(i) - X_world.col(j);
double center_to_point_distance = Xdiff.norm();
M(row, num_m_columns - 1) =
- - center_to_point_distance * center_to_point_distance;
+ -center_to_point_distance * center_to_point_distance;
ij_index(row, 0) = i;
ij_index(row, 1) = j;
++row;
@@ -246,17 +246,17 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
}
int num_lambda = num_points + 1; // Dimension of the null space of M.
- Mat V = M.jacobiSvd(Eigen::ComputeFullV).matrixV().block(0,
- num_m_rows,
- num_m_columns,
- num_lambda);
+ Mat V = M.jacobiSvd(Eigen::ComputeFullV)
+ .matrixV()
+ .block(0, num_m_rows, num_m_columns, num_lambda);
// TODO(vess): The number of constraint equations in K (num_k_rows) must be
// (num_points + 1) * (num_points + 2)/2. This creates a performance issue
// for more than 4 points. It is fine for 4 points at the moment with 18
// instead of 15 equations.
- int num_k_rows = num_m_rows + num_points *
- (num_points*(num_points-1)/2 - num_points+1);
+ int num_k_rows =
+ num_m_rows +
+ num_points * (num_points * (num_points - 1) / 2 - num_points + 1);
int num_k_columns = num_lambda * (num_lambda + 1) / 2;
Mat K(num_k_rows, num_k_columns);
K.setZero();
@@ -275,8 +275,8 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
int idx4 = IJToPointIndex(i, k, num_points);
K.row(counter_k_row) =
- MatrixToConstraint(V.row(idx1).transpose() * V.row(idx2)-
- V.row(idx3).transpose() * V.row(idx4),
+ MatrixToConstraint(V.row(idx1).transpose() * V.row(idx2) -
+ V.row(idx3).transpose() * V.row(idx4),
num_k_columns,
num_lambda);
++counter_k_row;
@@ -296,8 +296,8 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
int idx4 = IJToPointIndex(i, k, num_points);
K.row(counter_k_row) =
- MatrixToConstraint(V.row(idx1).transpose() * V.row(idx2)-
- V.row(idx3).transpose() * V.row(idx4),
+ MatrixToConstraint(V.row(idx1).transpose() * V.row(idx2) -
+ V.row(idx3).transpose() * V.row(idx4),
num_k_columns,
num_lambda);
++counter_k_row;
@@ -317,14 +317,12 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
}
}
// Ensure positiveness of the largest value corresponding to lambda_ii.
- L_sq = L_sq * Sign(L_sq(IJToIndex(max_L_sq_index,
- max_L_sq_index,
- num_lambda)));
+ L_sq =
+ L_sq * Sign(L_sq(IJToIndex(max_L_sq_index, max_L_sq_index, num_lambda)));
Vec L(num_lambda);
- L(max_L_sq_index) = sqrt(L_sq(IJToIndex(max_L_sq_index,
- max_L_sq_index,
- num_lambda)));
+ L(max_L_sq_index) =
+ sqrt(L_sq(IJToIndex(max_L_sq_index, max_L_sq_index, num_lambda)));
for (int i = 0; i < num_lambda; ++i) {
if (i != max_L_sq_index) {
@@ -353,9 +351,9 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
}
// Selects 4 virtual control points using mean and PCA.
-static void SelectControlPoints(const Mat3X &X_world,
- Mat *X_centered,
- Mat34 *X_control_points) {
+static void SelectControlPoints(const Mat3X& X_world,
+ Mat* X_centered,
+ Mat34* X_control_points) {
size_t num_points = X_world.cols();
// The first virtual control point, C0, is the centroid.
@@ -379,13 +377,13 @@ static void SelectControlPoints(const Mat3X &X_world,
}
// Computes the barycentric coordinates for all real points
-static void ComputeBarycentricCoordinates(const Mat3X &X_world_centered,
- const Mat34 &X_control_points,
- Mat4X *alphas) {
+static void ComputeBarycentricCoordinates(const Mat3X& X_world_centered,
+ const Mat34& X_control_points,
+ Mat4X* alphas) {
size_t num_points = X_world_centered.cols();
Mat3 C2;
for (size_t c = 1; c < 4; c++) {
- C2.col(c-1) = X_control_points.col(c) - X_control_points.col(0);
+ C2.col(c - 1) = X_control_points.col(c) - X_control_points.col(0);
}
Mat3 C2inv = C2.inverse();
@@ -401,14 +399,15 @@ static void ComputeBarycentricCoordinates(const Mat3X &X_world_centered,
// Estimates the coordinates of all real points in the camera coordinate frame
static void ComputePointsCoordinatesInCameraFrame(
- const Mat4X &alphas,
- const Vec4 &betas,
- const Eigen::Matrix<double, 12, 12> &U,
- Mat3X *X_camera) {
+ const Mat4X& alphas,
+ const Vec4& betas,
+ const Eigen::Matrix<double, 12, 12>& U,
+ Mat3X* X_camera) {
size_t num_points = alphas.cols();
// Estimates the control points in the camera reference frame.
- Mat34 C2b; C2b.setZero();
+ Mat34 C2b;
+ C2b.setZero();
for (size_t cu = 0; cu < 4; cu++) {
for (size_t c = 0; c < 4; c++) {
C2b.col(c) += betas(cu) * U.block(11 - cu, c * 3, 1, 3).transpose();
@@ -436,9 +435,10 @@ static void ComputePointsCoordinatesInCameraFrame(
}
}
-bool EuclideanResectionEPnP(const Mat2X &x_camera,
- const Mat3X &X_world,
- Mat3 *R, Vec3 *t) {
+bool EuclideanResectionEPnP(const Mat2X& x_camera,
+ const Mat3X& X_world,
+ Mat3* R,
+ Vec3* t) {
CHECK(x_camera.cols() == X_world.cols());
CHECK(x_camera.cols() > 3);
size_t num_points = X_world.cols();
@@ -462,6 +462,7 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
double a3 = alphas(3, c);
double ui = x_camera(0, c);
double vi = x_camera(1, c);
+ // clang-format off
M.block(2*c, 0, 2, 12) << a0, 0,
a0*(-ui), a1, 0,
a1*(-ui), a2, 0,
@@ -471,10 +472,11 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
a1, a1*(-vi), 0,
a2, a2*(-vi), 0,
a3, a3*(-vi);
+ // clang-format on
}
// TODO(julien): Avoid the transpose by rewriting the u2.block() calls.
- Eigen::JacobiSVD<Mat> MtMsvd(M.transpose()*M, Eigen::ComputeFullU);
+ Eigen::JacobiSVD<Mat> MtMsvd(M.transpose() * M, Eigen::ComputeFullU);
Eigen::Matrix<double, 12, 12> u2 = MtMsvd.matrixU().transpose();
// Estimate the L matrix.
@@ -495,21 +497,22 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
dv2.row(3) = u2.block(10, 3, 1, 3) - u2.block(10, 6, 1, 3);
dv2.row(4) = u2.block(10, 3, 1, 3) - u2.block(10, 9, 1, 3);
dv2.row(5) = u2.block(10, 6, 1, 3) - u2.block(10, 9, 1, 3);
- dv3.row(0) = u2.block(9, 0, 1, 3) - u2.block(9, 3, 1, 3);
- dv3.row(1) = u2.block(9, 0, 1, 3) - u2.block(9, 6, 1, 3);
- dv3.row(2) = u2.block(9, 0, 1, 3) - u2.block(9, 9, 1, 3);
- dv3.row(3) = u2.block(9, 3, 1, 3) - u2.block(9, 6, 1, 3);
- dv3.row(4) = u2.block(9, 3, 1, 3) - u2.block(9, 9, 1, 3);
- dv3.row(5) = u2.block(9, 6, 1, 3) - u2.block(9, 9, 1, 3);
- dv4.row(0) = u2.block(8, 0, 1, 3) - u2.block(8, 3, 1, 3);
- dv4.row(1) = u2.block(8, 0, 1, 3) - u2.block(8, 6, 1, 3);
- dv4.row(2) = u2.block(8, 0, 1, 3) - u2.block(8, 9, 1, 3);
- dv4.row(3) = u2.block(8, 3, 1, 3) - u2.block(8, 6, 1, 3);
- dv4.row(4) = u2.block(8, 3, 1, 3) - u2.block(8, 9, 1, 3);
- dv4.row(5) = u2.block(8, 6, 1, 3) - u2.block(8, 9, 1, 3);
+ dv3.row(0) = u2.block(9, 0, 1, 3) - u2.block(9, 3, 1, 3);
+ dv3.row(1) = u2.block(9, 0, 1, 3) - u2.block(9, 6, 1, 3);
+ dv3.row(2) = u2.block(9, 0, 1, 3) - u2.block(9, 9, 1, 3);
+ dv3.row(3) = u2.block(9, 3, 1, 3) - u2.block(9, 6, 1, 3);
+ dv3.row(4) = u2.block(9, 3, 1, 3) - u2.block(9, 9, 1, 3);
+ dv3.row(5) = u2.block(9, 6, 1, 3) - u2.block(9, 9, 1, 3);
+ dv4.row(0) = u2.block(8, 0, 1, 3) - u2.block(8, 3, 1, 3);
+ dv4.row(1) = u2.block(8, 0, 1, 3) - u2.block(8, 6, 1, 3);
+ dv4.row(2) = u2.block(8, 0, 1, 3) - u2.block(8, 9, 1, 3);
+ dv4.row(3) = u2.block(8, 3, 1, 3) - u2.block(8, 6, 1, 3);
+ dv4.row(4) = u2.block(8, 3, 1, 3) - u2.block(8, 9, 1, 3);
+ dv4.row(5) = u2.block(8, 6, 1, 3) - u2.block(8, 9, 1, 3);
Eigen::Matrix<double, 6, 10> L;
for (size_t r = 0; r < 6; r++) {
+ // clang-format off
L.row(r) << dv1.row(r).dot(dv1.row(r)),
2.0 * dv1.row(r).dot(dv2.row(r)),
dv2.row(r).dot(dv2.row(r)),
@@ -520,19 +523,23 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
2.0 * dv2.row(r).dot(dv4.row(r)),
2.0 * dv3.row(r).dot(dv4.row(r)),
dv4.row(r).dot(dv4.row(r));
+ // clang-format on
}
Vec6 rho;
+ // clang-format off
rho << (X_control_points.col(0) - X_control_points.col(1)).squaredNorm(),
(X_control_points.col(0) - X_control_points.col(2)).squaredNorm(),
(X_control_points.col(0) - X_control_points.col(3)).squaredNorm(),
(X_control_points.col(1) - X_control_points.col(2)).squaredNorm(),
(X_control_points.col(1) - X_control_points.col(3)).squaredNorm(),
(X_control_points.col(2) - X_control_points.col(3)).squaredNorm();
+ // clang-format on
// There are three possible solutions based on the three approximations of L
// (betas). Below, each one is solved for then the best one is chosen.
Mat3X X_camera;
- Mat3 K; K.setIdentity();
+ Mat3 K;
+ K.setIdentity();
vector<Mat3> Rs(3);
vector<Vec3> ts(3);
Vec rmse(3);
@@ -546,7 +553,7 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
//
// TODO(keir): Decide if setting this to infinity, effectively disabling the
// check, is the right approach. So far this seems the case.
- double kSuccessThreshold = std::numeric_limits<double>::max();
+ double kSuccessThreshold = std::numeric_limits<double>::max();
// Find the first possible solution for R, t corresponding to:
// Betas = [b00 b01 b11 b02 b12 b22 b03 b13 b23 b33]
@@ -563,7 +570,7 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
if (b4(0) < 0) {
b4 = -b4;
}
- b4(0) = std::sqrt(b4(0));
+ b4(0) = std::sqrt(b4(0));
betas << b4(0), b4(1) / b4(0), b4(2) / b4(0), b4(3) / b4(0);
ComputePointsCoordinatesInCameraFrame(alphas, betas, u2, &X_camera);
AbsoluteOrientation(X_world, X_camera, &Rs[0], &ts[0]);
@@ -669,12 +676,12 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
// TODO(julien): Improve the solutions with non-linear refinement.
return true;
}
-
+
/*
-
+
Straight from the paper:
http://www.diegm.uniud.it/fusiello/papers/3dimpvt12-b.pdf
-
+
function [R T] = ppnp(P,S,tol)
% input
% P : matrix (nx3) image coordinates in camera reference [u v 1]
@@ -708,33 +715,34 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
end
T = -R*c;
end
-
+
*/
// TODO(keir): Re-do all the variable names and add comments matching the paper.
// This implementation has too much of the terseness of the original. On the
// other hand, it did work on the first try.
-bool EuclideanResectionPPnP(const Mat2X &x_camera,
- const Mat3X &X_world,
- Mat3 *R, Vec3 *t) {
+bool EuclideanResectionPPnP(const Mat2X& x_camera,
+ const Mat3X& X_world,
+ Mat3* R,
+ Vec3* t) {
int n = x_camera.cols();
Mat Z = Mat::Zero(n, n);
Vec e = Vec::Ones(n);
Mat A = Mat::Identity(n, n) - (e * e.transpose() / n);
Vec II = e / n;
-
+
Mat P(n, 3);
P.col(0) = x_camera.row(0);
P.col(1) = x_camera.row(1);
P.col(2).setConstant(1.0);
-
+
Mat S = X_world.transpose();
-
+
double error = std::numeric_limits<double>::infinity();
Mat E_old = 1000 * Mat::Ones(n, 3);
-
+
Vec3 c;
Mat E(n, 3);
-
+
int iteration = 0;
double tolerance = 1e-5;
// TODO(keir): The limit of 100 can probably be reduced, but this will require
@@ -748,20 +756,21 @@ bool EuclideanResectionPPnP(const Mat2X &x_camera,
s << 1, 1, (U * VT).determinant();
*R = U * s.asDiagonal() * VT;
Mat PR = P * *R; // n x 3
- c = (S - Z*PR).transpose() * II;
- Mat Y = S - e*c.transpose(); // n x 3
- Vec Zmindiag = (PR * Y.transpose()).diagonal()
- .cwiseQuotient(P.rowwise().squaredNorm());
+ c = (S - Z * PR).transpose() * II;
+ Mat Y = S - e * c.transpose(); // n x 3
+ Vec Zmindiag = (PR * Y.transpose())
+ .diagonal()
+ .cwiseQuotient(P.rowwise().squaredNorm());
for (int i = 0; i < n; ++i) {
Zmindiag[i] = std::max(Zmindiag[i], 0.0);
}
Z = Zmindiag.asDiagonal();
- E = Y - Z*PR;
+ E = Y - Z * PR;
error = (E - E_old).norm();
- LOG(INFO) << "PPnP error(" << (iteration++) << "): " << error;
+ LG << "PPnP error(" << (iteration++) << "): " << error;
E_old = E;
}
- *t = -*R*c;
+ *t = -*R * c;
// TODO(keir): Figure out what the failure cases are. Is it too many
// iterations? Spend some time going through the math figuring out if there
@@ -769,6 +778,5 @@ bool EuclideanResectionPPnP(const Mat2X &x_camera,
return true;
}
-
-} // namespace resection
+} // namespace euclidean_resection
} // namespace libmv
diff --git a/intern/libmv/libmv/multiview/euclidean_resection.h b/intern/libmv/libmv/multiview/euclidean_resection.h
index 28eae92611c..3c4c3979ff6 100644
--- a/intern/libmv/libmv/multiview/euclidean_resection.h
+++ b/intern/libmv/libmv/multiview/euclidean_resection.h
@@ -21,8 +21,8 @@
#ifndef LIBMV_MULTIVIEW_EUCLIDEAN_RESECTION_H_
#define LIBMV_MULTIVIEW_EUCLIDEAN_RESECTION_H_
-#include "libmv/numeric/numeric.h"
#include "libmv/multiview/projection.h"
+#include "libmv/numeric/numeric.h"
namespace libmv {
namespace euclidean_resection {
@@ -33,7 +33,7 @@ enum ResectionMethod {
// The "EPnP" algorithm by Lepetit et al.
// http://cvlab.epfl.ch/~lepetit/papers/lepetit_ijcv08.pdf
RESECTION_EPNP,
-
+
// The Procrustes PNP algorithm ("PPnP")
// http://www.diegm.uniud.it/fusiello/papers/3dimpvt12-b.pdf
RESECTION_PPNP
@@ -50,9 +50,10 @@ enum ResectionMethod {
* \param t Solution for the camera translation vector
* \param method The resection method to use.
*/
-bool EuclideanResection(const Mat2X &x_camera,
- const Mat3X &X_world,
- Mat3 *R, Vec3 *t,
+bool EuclideanResection(const Mat2X& x_camera,
+ const Mat3X& X_world,
+ Mat3* R,
+ Vec3* t,
ResectionMethod method = RESECTION_EPNP);
/**
@@ -68,10 +69,11 @@ bool EuclideanResection(const Mat2X &x_camera,
* \param t Solution for the camera translation vector
* \param method Resection method
*/
-bool EuclideanResection(const Mat &x_image,
- const Mat3X &X_world,
- const Mat3 &K,
- Mat3 *R, Vec3 *t,
+bool EuclideanResection(const Mat& x_image,
+ const Mat3X& X_world,
+ const Mat3& K,
+ Mat3* R,
+ Vec3* t,
ResectionMethod method = RESECTION_EPNP);
/**
@@ -84,10 +86,7 @@ bool EuclideanResection(const Mat &x_image,
* Horn, Hilden, "Closed-form solution of absolute orientation using
* orthonormal matrices"
*/
-void AbsoluteOrientation(const Mat3X &X,
- const Mat3X &Xp,
- Mat3 *R,
- Vec3 *t);
+void AbsoluteOrientation(const Mat3X& X, const Mat3X& Xp, Mat3* R, Vec3* t);
/**
* Computes the extrinsic parameters, R and t for a calibrated camera from 4 or
@@ -102,9 +101,10 @@ void AbsoluteOrientation(const Mat3X &X,
* This is the algorithm described in: "Linear Pose Estimation from Points or
* Lines", by Ansar, A. and Daniilidis, PAMI 2003. vol. 25, no. 5.
*/
-void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
- const Mat3X &X_world,
- Mat3 *R, Vec3 *t);
+void EuclideanResectionAnsarDaniilidis(const Mat2X& x_camera,
+ const Mat3X& X_world,
+ Mat3* R,
+ Vec3* t);
/**
* Computes the extrinsic parameters, R and t for a calibrated camera from 4 or
* more 3D points and their images.
@@ -120,9 +120,10 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
* and F. Moreno-Noguer and P. Fua, IJCV 2009. vol. 81, no. 2
* \note: the non-linear optimization is not implemented here.
*/
-bool EuclideanResectionEPnP(const Mat2X &x_camera,
- const Mat3X &X_world,
- Mat3 *R, Vec3 *t);
+bool EuclideanResectionEPnP(const Mat2X& x_camera,
+ const Mat3X& X_world,
+ Mat3* R,
+ Vec3* t);
/**
* Computes the extrinsic parameters, R and t for a calibrated camera from 4 or
@@ -137,12 +138,12 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
* Straight from the paper:
* http://www.diegm.uniud.it/fusiello/papers/3dimpvt12-b.pdf
*/
-bool EuclideanResectionPPnP(const Mat2X &x_camera,
- const Mat3X &X_world,
- Mat3 *R, Vec3 *t);
+bool EuclideanResectionPPnP(const Mat2X& x_camera,
+ const Mat3X& X_world,
+ Mat3* R,
+ Vec3* t);
} // namespace euclidean_resection
} // namespace libmv
-
#endif /* LIBMV_MULTIVIEW_EUCLIDEAN_RESECTION_H_ */
diff --git a/intern/libmv/libmv/multiview/euclidean_resection_test.cc b/intern/libmv/libmv/multiview/euclidean_resection_test.cc
index 378837d3d2d..3bb8e6e1710 100644
--- a/intern/libmv/libmv/multiview/euclidean_resection_test.cc
+++ b/intern/libmv/libmv/multiview/euclidean_resection_test.cc
@@ -19,9 +19,9 @@
// IN THE SOFTWARE.
#include "libmv/multiview/euclidean_resection.h"
-#include "libmv/numeric/numeric.h"
#include "libmv/logging/logging.h"
#include "libmv/multiview/projection.h"
+#include "libmv/numeric/numeric.h"
#include "testing/testing.h"
using namespace libmv::euclidean_resection;
@@ -33,10 +33,10 @@ static void CreateCameraSystem(const Mat3& KK,
const Vec& X_distances,
const Mat3& R_input,
const Vec3& T_input,
- Mat2X *x_camera,
- Mat3X *X_world,
- Mat3 *R_expected,
- Vec3 *T_expected) {
+ Mat2X* x_camera,
+ Mat3X* X_world,
+ Mat3* R_expected,
+ Vec3* T_expected) {
int num_points = x_image.cols();
Mat3X x_unit_cam(3, num_points);
@@ -76,9 +76,9 @@ TEST(AbsoluteOrientation, QuaternionSolution) {
// Create a random translation and rotation.
Mat3 R_input;
- R_input = Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ())
- * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitY())
- * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ());
+ R_input = Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ()) *
+ Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitY()) *
+ Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ());
Vec3 t_input;
t_input.setRandom();
@@ -109,26 +109,29 @@ TEST(EuclideanResection, Points4KnownImagePointsRandomTranslationRotation) {
image_dimensions << 1600, 1200;
Mat3 KK;
+ // clang-format off
KK << 2796, 0, 804,
0 , 2796, 641,
0, 0, 1;
+ // clang-format on
// The real image points.
int num_points = 4;
Mat3X x_image(3, num_points);
+ // clang-format off
x_image << 1164.06, 734.948, 749.599, 430.727,
681.386, 844.59, 496.315, 580.775,
1, 1, 1, 1;
-
+ // clang-format on
// A vector of the 4 distances to the 3D points.
Vec X_distances = 100 * Vec::Random(num_points).array().abs();
// Create the random camera motion R and t that resection should recover.
Mat3 R_input;
- R_input = Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ())
- * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitY())
- * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ());
+ R_input = Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ()) *
+ Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitY()) *
+ Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ());
Vec3 T_input;
T_input.setRandom();
@@ -140,15 +143,21 @@ TEST(EuclideanResection, Points4KnownImagePointsRandomTranslationRotation) {
Vec3 T_expected;
Mat3X X_world;
Mat2X x_camera;
- CreateCameraSystem(KK, x_image, X_distances, R_input, T_input,
- &x_camera, &X_world, &R_expected, &T_expected);
+ CreateCameraSystem(KK,
+ x_image,
+ X_distances,
+ R_input,
+ T_input,
+ &x_camera,
+ &X_world,
+ &R_expected,
+ &T_expected);
// Finally, run the code under test.
Mat3 R_output;
Vec3 T_output;
- EuclideanResection(x_camera, X_world,
- &R_output, &T_output,
- RESECTION_ANSAR_DANIILIDIS);
+ EuclideanResection(
+ x_camera, X_world, &R_output, &T_output, RESECTION_ANSAR_DANIILIDIS);
EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);
@@ -173,9 +182,11 @@ TEST(EuclideanResection, Points4KnownImagePointsRandomTranslationRotation) {
// TODO(jmichot): Reduce the code duplication here with the code above.
TEST(EuclideanResection, Points6AllRandomInput) {
Mat3 KK;
+ // clang-format off
KK << 2796, 0, 804,
0 , 2796, 641,
0, 0, 1;
+ // clang-format on
// Create random image points for a 1600x1200 image.
int w = 1600;
@@ -192,9 +203,9 @@ TEST(EuclideanResection, Points6AllRandomInput) {
// Create the random camera motion R and t that resection should recover.
Mat3 R_input;
- R_input = Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ())
- * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitY())
- * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ());
+ R_input = Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ()) *
+ Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitY()) *
+ Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ());
Vec3 T_input;
T_input.setRandom();
@@ -204,33 +215,36 @@ TEST(EuclideanResection, Points6AllRandomInput) {
Mat3 R_expected;
Vec3 T_expected;
Mat3X X_world;
- CreateCameraSystem(KK, x_image, X_distances, R_input, T_input,
- &x_camera, &X_world, &R_expected, &T_expected);
+ CreateCameraSystem(KK,
+ x_image,
+ X_distances,
+ R_input,
+ T_input,
+ &x_camera,
+ &X_world,
+ &R_expected,
+ &T_expected);
// Test each of the resection methods.
{
Mat3 R_output;
Vec3 T_output;
- EuclideanResection(x_camera, X_world,
- &R_output, &T_output,
- RESECTION_ANSAR_DANIILIDIS);
+ EuclideanResection(
+ x_camera, X_world, &R_output, &T_output, RESECTION_ANSAR_DANIILIDIS);
EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);
}
{
Mat3 R_output;
Vec3 T_output;
- EuclideanResection(x_camera, X_world,
- &R_output, &T_output,
- RESECTION_EPNP);
+ EuclideanResection(x_camera, X_world, &R_output, &T_output, RESECTION_EPNP);
EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);
}
{
Mat3 R_output;
Vec3 T_output;
- EuclideanResection(x_image, X_world, KK,
- &R_output, &T_output);
+ EuclideanResection(x_image, X_world, KK, &R_output, &T_output);
EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);
}
diff --git a/intern/libmv/libmv/multiview/fundamental.cc b/intern/libmv/libmv/multiview/fundamental.cc
index ea8594c8cc0..c8c94ecd7bb 100644
--- a/intern/libmv/libmv/multiview/fundamental.cc
+++ b/intern/libmv/libmv/multiview/fundamental.cc
@@ -22,15 +22,15 @@
#include "ceres/ceres.h"
#include "libmv/logging/logging.h"
-#include "libmv/numeric/numeric.h"
-#include "libmv/numeric/poly.h"
#include "libmv/multiview/conditioning.h"
#include "libmv/multiview/projection.h"
#include "libmv/multiview/triangulation.h"
+#include "libmv/numeric/numeric.h"
+#include "libmv/numeric/poly.h"
namespace libmv {
-static void EliminateRow(const Mat34 &P, int row, Mat *X) {
+static void EliminateRow(const Mat34& P, int row, Mat* X) {
X->resize(2, 4);
int first_row = (row + 1) % 3;
@@ -42,7 +42,7 @@ static void EliminateRow(const Mat34 &P, int row, Mat *X) {
}
}
-void ProjectionsFromFundamental(const Mat3 &F, Mat34 *P1, Mat34 *P2) {
+void ProjectionsFromFundamental(const Mat3& F, Mat34* P1, Mat34* P2) {
*P1 << Mat3::Identity(), Vec3::Zero();
Vec3 e2;
Mat3 Ft = F.transpose();
@@ -51,7 +51,7 @@ void ProjectionsFromFundamental(const Mat3 &F, Mat34 *P1, Mat34 *P2) {
}
// Addapted from vgg_F_from_P.
-void FundamentalFromProjections(const Mat34 &P1, const Mat34 &P2, Mat3 *F) {
+void FundamentalFromProjections(const Mat34& P1, const Mat34& P2, Mat3* F) {
Mat X[3];
Mat Y[3];
Mat XY;
@@ -71,7 +71,7 @@ void FundamentalFromProjections(const Mat34 &P1, const Mat34 &P2, Mat3 *F) {
// HZ 11.1 pag.279 (x1 = x, x2 = x')
// http://www.cs.unc.edu/~marc/tutorial/node54.html
-static double EightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F) {
+static double EightPointSolver(const Mat& x1, const Mat& x2, Mat3* F) {
DCHECK_EQ(x1.rows(), 2);
DCHECK_GE(x1.cols(), 8);
DCHECK_EQ(x1.rows(), x2.rows());
@@ -98,7 +98,7 @@ static double EightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F) {
}
// HZ 11.1.1 pag.280
-void EnforceFundamentalRank2Constraint(Mat3 *F) {
+void EnforceFundamentalRank2Constraint(Mat3* F) {
Eigen::JacobiSVD<Mat3> USV(*F, Eigen::ComputeFullU | Eigen::ComputeFullV);
Vec3 d = USV.singularValues();
d(2) = 0.0;
@@ -106,9 +106,7 @@ void EnforceFundamentalRank2Constraint(Mat3 *F) {
}
// HZ 11.2 pag.281 (x1 = x, x2 = x')
-double NormalizedEightPointSolver(const Mat &x1,
- const Mat &x2,
- Mat3 *F) {
+double NormalizedEightPointSolver(const Mat& x1, const Mat& x2, Mat3* F) {
DCHECK_EQ(x1.rows(), 2);
DCHECK_GE(x1.cols(), 8);
DCHECK_EQ(x1.rows(), x2.rows());
@@ -135,9 +133,9 @@ double NormalizedEightPointSolver(const Mat &x1,
// Seven-point algorithm.
// http://www.cs.unc.edu/~marc/tutorial/node55.html
-double FundamentalFrom7CorrespondencesLinear(const Mat &x1,
- const Mat &x2,
- std::vector<Mat3> *F) {
+double FundamentalFrom7CorrespondencesLinear(const Mat& x1,
+ const Mat& x2,
+ std::vector<Mat3>* F) {
DCHECK_EQ(x1.rows(), 2);
DCHECK_EQ(x1.cols(), 7);
DCHECK_EQ(x1.rows(), x2.rows());
@@ -169,25 +167,29 @@ double FundamentalFrom7CorrespondencesLinear(const Mat &x1,
// Then, use the condition det(F) = 0 to determine F. In other words, solve
// det(F1 + a*F2) = 0 for a.
- double a = F1(0, 0), j = F2(0, 0),
- b = F1(0, 1), k = F2(0, 1),
- c = F1(0, 2), l = F2(0, 2),
- d = F1(1, 0), m = F2(1, 0),
- e = F1(1, 1), n = F2(1, 1),
- f = F1(1, 2), o = F2(1, 2),
- g = F1(2, 0), p = F2(2, 0),
- h = F1(2, 1), q = F2(2, 1),
- i = F1(2, 2), r = F2(2, 2);
+ double a = F1(0, 0), j = F2(0, 0);
+ double b = F1(0, 1), k = F2(0, 1);
+ double c = F1(0, 2), l = F2(0, 2);
+ double d = F1(1, 0), m = F2(1, 0);
+ double e = F1(1, 1), n = F2(1, 1);
+ double f = F1(1, 2), o = F2(1, 2);
+ double g = F1(2, 0), p = F2(2, 0);
+ double h = F1(2, 1), q = F2(2, 1);
+ double i = F1(2, 2), r = F2(2, 2);
// Run fundamental_7point_coeffs.py to get the below coefficients.
// The coefficients are in ascending powers of alpha, i.e. P[N]*x^N.
double P[4] = {
- a*e*i + b*f*g + c*d*h - a*f*h - b*d*i - c*e*g,
- a*e*r + a*i*n + b*f*p + b*g*o + c*d*q + c*h*m + d*h*l + e*i*j + f*g*k -
- a*f*q - a*h*o - b*d*r - b*i*m - c*e*p - c*g*n - d*i*k - e*g*l - f*h*j,
- a*n*r + b*o*p + c*m*q + d*l*q + e*j*r + f*k*p + g*k*o + h*l*m + i*j*n -
- a*o*q - b*m*r - c*n*p - d*k*r - e*l*p - f*j*q - g*l*n - h*j*o - i*k*m,
- j*n*r + k*o*p + l*m*q - j*o*q - k*m*r - l*n*p,
+ a * e * i + b * f * g + c * d * h - a * f * h - b * d * i - c * e * g,
+ a * e * r + a * i * n + b * f * p + b * g * o + c * d * q + c * h * m +
+ d * h * l + e * i * j + f * g * k - a * f * q - a * h * o -
+ b * d * r - b * i * m - c * e * p - c * g * n - d * i * k -
+ e * g * l - f * h * j,
+ a * n * r + b * o * p + c * m * q + d * l * q + e * j * r + f * k * p +
+ g * k * o + h * l * m + i * j * n - a * o * q - b * m * r -
+ c * n * p - d * k * r - e * l * p - f * j * q - g * l * n -
+ h * j * o - i * k * m,
+ j * n * r + k * o * p + l * m * q - j * o * q - k * m * r - l * n * p,
};
// Solve for the roots of P[3]*x^3 + P[2]*x^2 + P[1]*x + P[0] = 0.
@@ -195,15 +197,15 @@ double FundamentalFrom7CorrespondencesLinear(const Mat &x1,
int num_roots = SolveCubicPolynomial(P, roots);
// Build the fundamental matrix for each solution.
- for (int kk = 0; kk < num_roots; ++kk) {
+ for (int kk = 0; kk < num_roots; ++kk) {
F->push_back(F1 + roots[kk] * F2);
}
return s;
}
-double FundamentalFromCorrespondences7Point(const Mat &x1,
- const Mat &x2,
- std::vector<Mat3> *F) {
+double FundamentalFromCorrespondences7Point(const Mat& x1,
+ const Mat& x2,
+ std::vector<Mat3>* F) {
DCHECK_EQ(x1.rows(), 2);
DCHECK_GE(x1.cols(), 7);
DCHECK_EQ(x1.rows(), x2.rows());
@@ -218,25 +220,25 @@ double FundamentalFromCorrespondences7Point(const Mat &x1,
ApplyTransformationToPoints(x2, T2, &x2_normalized);
// Estimate the fundamental matrix.
- double smaller_singular_value =
- FundamentalFrom7CorrespondencesLinear(x1_normalized, x2_normalized, &(*F));
+ double smaller_singular_value = FundamentalFrom7CorrespondencesLinear(
+ x1_normalized, x2_normalized, &(*F));
for (int k = 0; k < F->size(); ++k) {
- Mat3 & Fmat = (*F)[k];
+ Mat3& Fmat = (*F)[k];
// Denormalize the fundamental matrix.
Fmat = T2.transpose() * Fmat * T1;
}
return smaller_singular_value;
}
-void NormalizeFundamental(const Mat3 &F, Mat3 *F_normalized) {
+void NormalizeFundamental(const Mat3& F, Mat3* F_normalized) {
*F_normalized = F / FrobeniusNorm(F);
if ((*F_normalized)(2, 2) < 0) {
*F_normalized *= -1;
}
}
-double SampsonDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2) {
+double SampsonDistance(const Mat& F, const Vec2& x1, const Vec2& x2) {
Vec3 x(x1(0), x1(1), 1.0);
Vec3 y(x2(0), x2(1), 1.0);
@@ -244,11 +246,11 @@ double SampsonDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2) {
Vec3 Ft_y = F.transpose() * y;
double y_F_x = y.dot(F_x);
- return Square(y_F_x) / ( F_x.head<2>().squaredNorm()
- + Ft_y.head<2>().squaredNorm());
+ return Square(y_F_x) /
+ (F_x.head<2>().squaredNorm() + Ft_y.head<2>().squaredNorm());
}
-double SymmetricEpipolarDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2) {
+double SymmetricEpipolarDistance(const Mat& F, const Vec2& x1, const Vec2& x2) {
Vec3 x(x1(0), x1(1), 1.0);
Vec3 y(x2(0), x2(1), 1.0);
@@ -256,43 +258,40 @@ double SymmetricEpipolarDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2) {
Vec3 Ft_y = F.transpose() * y;
double y_F_x = y.dot(F_x);
- return Square(y_F_x) * ( 1 / F_x.head<2>().squaredNorm()
- + 1 / Ft_y.head<2>().squaredNorm());
+ return Square(y_F_x) *
+ (1 / F_x.head<2>().squaredNorm() + 1 / Ft_y.head<2>().squaredNorm());
}
// HZ 9.6 pag 257 (formula 9.12)
-void EssentialFromFundamental(const Mat3 &F,
- const Mat3 &K1,
- const Mat3 &K2,
- Mat3 *E) {
+void EssentialFromFundamental(const Mat3& F,
+ const Mat3& K1,
+ const Mat3& K2,
+ Mat3* E) {
*E = K2.transpose() * F * K1;
}
// HZ 9.6 pag 257 (formula 9.12)
// Or http://ai.stanford.edu/~birch/projective/node20.html
-void FundamentalFromEssential(const Mat3 &E,
- const Mat3 &K1,
- const Mat3 &K2,
- Mat3 *F) {
+void FundamentalFromEssential(const Mat3& E,
+ const Mat3& K1,
+ const Mat3& K2,
+ Mat3* F) {
*F = K2.inverse().transpose() * E * K1.inverse();
}
-void RelativeCameraMotion(const Mat3 &R1,
- const Vec3 &t1,
- const Mat3 &R2,
- const Vec3 &t2,
- Mat3 *R,
- Vec3 *t) {
+void RelativeCameraMotion(const Mat3& R1,
+ const Vec3& t1,
+ const Mat3& R2,
+ const Vec3& t2,
+ Mat3* R,
+ Vec3* t) {
*R = R2 * R1.transpose();
*t = t2 - (*R) * t1;
}
// HZ 9.6 pag 257
-void EssentialFromRt(const Mat3 &R1,
- const Vec3 &t1,
- const Mat3 &R2,
- const Vec3 &t2,
- Mat3 *E) {
+void EssentialFromRt(
+ const Mat3& R1, const Vec3& t1, const Mat3& R2, const Vec3& t2, Mat3* E) {
Mat3 R;
Vec3 t;
RelativeCameraMotion(R1, t1, R2, t2, &R, &t);
@@ -301,11 +300,11 @@ void EssentialFromRt(const Mat3 &R1,
}
// HZ 9.6 pag 259 (Result 9.19)
-void MotionFromEssential(const Mat3 &E,
- std::vector<Mat3> *Rs,
- std::vector<Vec3> *ts) {
+void MotionFromEssential(const Mat3& E,
+ std::vector<Mat3>* Rs,
+ std::vector<Vec3>* ts) {
Eigen::JacobiSVD<Mat3> USV(E, Eigen::ComputeFullU | Eigen::ComputeFullV);
- Mat3 U = USV.matrixU();
+ Mat3 U = USV.matrixU();
Mat3 Vt = USV.matrixV().transpose();
// Last column of U is undetermined since d = (a a 0).
@@ -318,9 +317,11 @@ void MotionFromEssential(const Mat3 &E,
}
Mat3 W;
+ // clang-format off
W << 0, -1, 0,
1, 0, 0,
0, 0, 1;
+ // clang-format on
Mat3 U_W_Vt = U * W * Vt;
Mat3 U_Wt_Vt = U * W.transpose() * Vt;
@@ -332,18 +333,18 @@ void MotionFromEssential(const Mat3 &E,
(*Rs)[3] = U_Wt_Vt;
ts->resize(4);
- (*ts)[0] = U.col(2);
+ (*ts)[0] = U.col(2);
(*ts)[1] = -U.col(2);
- (*ts)[2] = U.col(2);
+ (*ts)[2] = U.col(2);
(*ts)[3] = -U.col(2);
}
-int MotionFromEssentialChooseSolution(const std::vector<Mat3> &Rs,
- const std::vector<Vec3> &ts,
- const Mat3 &K1,
- const Vec2 &x1,
- const Mat3 &K2,
- const Vec2 &x2) {
+int MotionFromEssentialChooseSolution(const std::vector<Mat3>& Rs,
+ const std::vector<Vec3>& ts,
+ const Mat3& K1,
+ const Vec2& x1,
+ const Mat3& K2,
+ const Vec2& x2) {
DCHECK_EQ(4, Rs.size());
DCHECK_EQ(4, ts.size());
@@ -354,8 +355,8 @@ int MotionFromEssentialChooseSolution(const std::vector<Mat3> &Rs,
t1.setZero();
P_From_KRt(K1, R1, t1, &P1);
for (int i = 0; i < 4; ++i) {
- const Mat3 &R2 = Rs[i];
- const Vec3 &t2 = ts[i];
+ const Mat3& R2 = Rs[i];
+ const Vec3& t2 = ts[i];
P_From_KRt(K2, R2, t2, &P2);
Vec3 X;
TriangulateDLT(P1, x1, P2, x2, &X);
@@ -369,13 +370,13 @@ int MotionFromEssentialChooseSolution(const std::vector<Mat3> &Rs,
return -1;
}
-bool MotionFromEssentialAndCorrespondence(const Mat3 &E,
- const Mat3 &K1,
- const Vec2 &x1,
- const Mat3 &K2,
- const Vec2 &x2,
- Mat3 *R,
- Vec3 *t) {
+bool MotionFromEssentialAndCorrespondence(const Mat3& E,
+ const Mat3& K1,
+ const Vec2& x1,
+ const Mat3& K2,
+ const Vec2& x2,
+ Mat3* R,
+ Vec3* t) {
std::vector<Mat3> Rs;
std::vector<Vec3> ts;
MotionFromEssential(E, &Rs, &ts);
@@ -389,7 +390,7 @@ bool MotionFromEssentialAndCorrespondence(const Mat3 &E,
}
}
-void FundamentalToEssential(const Mat3 &F, Mat3 *E) {
+void FundamentalToEssential(const Mat3& F, Mat3* E) {
Eigen::JacobiSVD<Mat3> svd(F, Eigen::ComputeFullU | Eigen::ComputeFullV);
// See Hartley & Zisserman page 294, result 11.1, which shows how to get the
@@ -399,8 +400,8 @@ void FundamentalToEssential(const Mat3 &F, Mat3 *E) {
double s = (a + b) / 2.0;
LG << "Initial reconstruction's rotation is non-euclidean by "
- << (((a - b) / std::max(a, b)) * 100) << "%; singular values:"
- << svd.singularValues().transpose();
+ << (((a - b) / std::max(a, b)) * 100)
+ << "%; singular values:" << svd.singularValues().transpose();
Vec3 diag;
diag << s, s, 0;
@@ -410,9 +411,8 @@ void FundamentalToEssential(const Mat3 &F, Mat3 *E) {
// Default settings for fundamental estimation which should be suitable
// for a wide range of use cases.
-EstimateFundamentalOptions::EstimateFundamentalOptions(void) :
- max_num_iterations(50),
- expected_average_symmetric_distance(1e-16) {
+EstimateFundamentalOptions::EstimateFundamentalOptions(void)
+ : max_num_iterations(50), expected_average_symmetric_distance(1e-16) {
}
namespace {
@@ -420,12 +420,11 @@ namespace {
// used for fundamental matrix refinement.
class FundamentalSymmetricEpipolarCostFunctor {
public:
- FundamentalSymmetricEpipolarCostFunctor(const Vec2 &x,
- const Vec2 &y)
- : x_(x), y_(y) {}
+ FundamentalSymmetricEpipolarCostFunctor(const Vec2& x, const Vec2& y)
+ : x_(x), y_(y) {}
- template<typename T>
- bool operator()(const T *fundamental_parameters, T *residuals) const {
+ template <typename T>
+ bool operator()(const T* fundamental_parameters, T* residuals) const {
typedef Eigen::Matrix<T, 3, 3> Mat3;
typedef Eigen::Matrix<T, 3, 1> Vec3;
@@ -454,9 +453,10 @@ class FundamentalSymmetricEpipolarCostFunctor {
// average value.
class TerminationCheckingCallback : public ceres::IterationCallback {
public:
- TerminationCheckingCallback(const Mat &x1, const Mat &x2,
- const EstimateFundamentalOptions &options,
- Mat3 *F)
+ TerminationCheckingCallback(const Mat& x1,
+ const Mat& x2,
+ const EstimateFundamentalOptions& options,
+ Mat3* F)
: options_(options), x1_(x1), x2_(x2), F_(F) {}
virtual ceres::CallbackReturnType operator()(
@@ -469,9 +469,7 @@ class TerminationCheckingCallback : public ceres::IterationCallback {
// Calculate average of symmetric epipolar distance.
double average_distance = 0.0;
for (int i = 0; i < x1_.cols(); i++) {
- average_distance = SymmetricEpipolarDistance(*F_,
- x1_.col(i),
- x2_.col(i));
+ average_distance = SymmetricEpipolarDistance(*F_, x1_.col(i), x2_.col(i));
}
average_distance /= x1_.cols();
@@ -483,19 +481,19 @@ class TerminationCheckingCallback : public ceres::IterationCallback {
}
private:
- const EstimateFundamentalOptions &options_;
- const Mat &x1_;
- const Mat &x2_;
- Mat3 *F_;
+ const EstimateFundamentalOptions& options_;
+ const Mat& x1_;
+ const Mat& x2_;
+ Mat3* F_;
};
} // namespace
/* Fundamental transformation estimation. */
bool EstimateFundamentalFromCorrespondences(
- const Mat &x1,
- const Mat &x2,
- const EstimateFundamentalOptions &options,
- Mat3 *F) {
+ const Mat& x1,
+ const Mat& x2,
+ const EstimateFundamentalOptions& options,
+ Mat3* F) {
// Step 1: Algebraic fundamental estimation.
// Assume algebraic estiation always succeeds,
@@ -506,16 +504,15 @@ bool EstimateFundamentalFromCorrespondences(
// Step 2: Refine matrix using Ceres minimizer.
ceres::Problem problem;
for (int i = 0; i < x1.cols(); i++) {
- FundamentalSymmetricEpipolarCostFunctor
- *fundamental_symmetric_epipolar_cost_function =
- new FundamentalSymmetricEpipolarCostFunctor(x1.col(i),
- x2.col(i));
+ FundamentalSymmetricEpipolarCostFunctor*
+ fundamental_symmetric_epipolar_cost_function =
+ new FundamentalSymmetricEpipolarCostFunctor(x1.col(i), x2.col(i));
problem.AddResidualBlock(
- new ceres::AutoDiffCostFunction<
- FundamentalSymmetricEpipolarCostFunctor,
- 2, // num_residuals
- 9>(fundamental_symmetric_epipolar_cost_function),
+ new ceres::AutoDiffCostFunction<FundamentalSymmetricEpipolarCostFunctor,
+ 2, // num_residuals
+ 9>(
+ fundamental_symmetric_epipolar_cost_function),
NULL,
F->data());
}
diff --git a/intern/libmv/libmv/multiview/fundamental.h b/intern/libmv/libmv/multiview/fundamental.h
index a6c7a6802fe..6d25691c4a3 100644
--- a/intern/libmv/libmv/multiview/fundamental.h
+++ b/intern/libmv/libmv/multiview/fundamental.h
@@ -27,36 +27,34 @@
namespace libmv {
-void ProjectionsFromFundamental(const Mat3 &F, Mat34 *P1, Mat34 *P2);
-void FundamentalFromProjections(const Mat34 &P1, const Mat34 &P2, Mat3 *F);
+void ProjectionsFromFundamental(const Mat3& F, Mat34* P1, Mat34* P2);
+void FundamentalFromProjections(const Mat34& P1, const Mat34& P2, Mat3* F);
/**
* 7 points (minimal case, points coordinates must be normalized before):
*/
-double FundamentalFrom7CorrespondencesLinear(const Mat &x1,
- const Mat &x2,
- std::vector<Mat3> *F);
+double FundamentalFrom7CorrespondencesLinear(const Mat& x1,
+ const Mat& x2,
+ std::vector<Mat3>* F);
/**
* 7 points (points coordinates must be in image space):
*/
-double FundamentalFromCorrespondences7Point(const Mat &x1,
- const Mat &x2,
- std::vector<Mat3> *F);
+double FundamentalFromCorrespondences7Point(const Mat& x1,
+ const Mat& x2,
+ std::vector<Mat3>* F);
/**
* 8 points (points coordinates must be in image space):
*/
-double NormalizedEightPointSolver(const Mat &x1,
- const Mat &x2,
- Mat3 *F);
+double NormalizedEightPointSolver(const Mat& x1, const Mat& x2, Mat3* F);
/**
* Fundamental matrix utility function:
*/
-void EnforceFundamentalRank2Constraint(Mat3 *F);
+void EnforceFundamentalRank2Constraint(Mat3* F);
-void NormalizeFundamental(const Mat3 &F, Mat3 *F_normalized);
+void NormalizeFundamental(const Mat3& F, Mat3* F_normalized);
/**
* Approximate squared reprojection errror.
@@ -64,14 +62,14 @@ void NormalizeFundamental(const Mat3 &F, Mat3 *F_normalized);
* See page 287 of HZ equation 11.9. This avoids triangulating the point,
* relying only on the entries in F.
*/
-double SampsonDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2);
+double SampsonDistance(const Mat& F, const Vec2& x1, const Vec2& x2);
/**
* Calculates the sum of the distances from the points to the epipolar lines.
*
* See page 288 of HZ equation 11.10.
*/
-double SymmetricEpipolarDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2);
+double SymmetricEpipolarDistance(const Mat& F, const Vec2& x1, const Vec2& x2);
/**
* Compute the relative camera motion between two cameras.
@@ -81,32 +79,29 @@ double SymmetricEpipolarDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2);
* If T1 and T2 are the camera motions, the computed relative motion is
* T = T2 T1^{-1}
*/
-void RelativeCameraMotion(const Mat3 &R1,
- const Vec3 &t1,
- const Mat3 &R2,
- const Vec3 &t2,
- Mat3 *R,
- Vec3 *t);
-
-void EssentialFromFundamental(const Mat3 &F,
- const Mat3 &K1,
- const Mat3 &K2,
- Mat3 *E);
-
-void FundamentalFromEssential(const Mat3 &E,
- const Mat3 &K1,
- const Mat3 &K2,
- Mat3 *F);
-
-void EssentialFromRt(const Mat3 &R1,
- const Vec3 &t1,
- const Mat3 &R2,
- const Vec3 &t2,
- Mat3 *E);
-
-void MotionFromEssential(const Mat3 &E,
- std::vector<Mat3> *Rs,
- std::vector<Vec3> *ts);
+void RelativeCameraMotion(const Mat3& R1,
+ const Vec3& t1,
+ const Mat3& R2,
+ const Vec3& t2,
+ Mat3* R,
+ Vec3* t);
+
+void EssentialFromFundamental(const Mat3& F,
+ const Mat3& K1,
+ const Mat3& K2,
+ Mat3* E);
+
+void FundamentalFromEssential(const Mat3& E,
+ const Mat3& K1,
+ const Mat3& K2,
+ Mat3* F);
+
+void EssentialFromRt(
+ const Mat3& R1, const Vec3& t1, const Mat3& R2, const Vec3& t2, Mat3* E);
+
+void MotionFromEssential(const Mat3& E,
+ std::vector<Mat3>* Rs,
+ std::vector<Vec3>* ts);
/**
* Choose one of the four possible motion solutions from an essential matrix.
@@ -117,25 +112,25 @@ void MotionFromEssential(const Mat3 &E,
*
* \return index of the right solution or -1 if no solution.
*/
-int MotionFromEssentialChooseSolution(const std::vector<Mat3> &Rs,
- const std::vector<Vec3> &ts,
- const Mat3 &K1,
- const Vec2 &x1,
- const Mat3 &K2,
- const Vec2 &x2);
-
-bool MotionFromEssentialAndCorrespondence(const Mat3 &E,
- const Mat3 &K1,
- const Vec2 &x1,
- const Mat3 &K2,
- const Vec2 &x2,
- Mat3 *R,
- Vec3 *t);
+int MotionFromEssentialChooseSolution(const std::vector<Mat3>& Rs,
+ const std::vector<Vec3>& ts,
+ const Mat3& K1,
+ const Vec2& x1,
+ const Mat3& K2,
+ const Vec2& x2);
+
+bool MotionFromEssentialAndCorrespondence(const Mat3& E,
+ const Mat3& K1,
+ const Vec2& x1,
+ const Mat3& K2,
+ const Vec2& x2,
+ Mat3* R,
+ Vec3* t);
/**
* Find closest essential matrix E to fundamental F
*/
-void FundamentalToEssential(const Mat3 &F, Mat3 *E);
+void FundamentalToEssential(const Mat3& F, Mat3* E);
/**
* This structure contains options that controls how the fundamental
@@ -170,10 +165,10 @@ struct EstimateFundamentalOptions {
* refinement.
*/
bool EstimateFundamentalFromCorrespondences(
- const Mat &x1,
- const Mat &x2,
- const EstimateFundamentalOptions &options,
- Mat3 *F);
+ const Mat& x1,
+ const Mat& x2,
+ const EstimateFundamentalOptions& options,
+ Mat3* F);
} // namespace libmv
diff --git a/intern/libmv/libmv/multiview/fundamental_test.cc b/intern/libmv/libmv/multiview/fundamental_test.cc
index da0eb449b8f..0ec91ca8d19 100644
--- a/intern/libmv/libmv/multiview/fundamental_test.cc
+++ b/intern/libmv/libmv/multiview/fundamental_test.cc
@@ -34,12 +34,14 @@ using namespace libmv;
TEST(Fundamental, FundamentalFromProjections) {
Mat34 P1_gt, P2_gt;
+ // clang-format off
P1_gt << 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0;
P2_gt << 1, 1, 1, 3,
0, 2, 0, 3,
0, 1, 1, 0;
+ // clang-format on
Mat3 F_gt;
FundamentalFromProjections(P1_gt, P2_gt, &F_gt);
@@ -55,8 +57,10 @@ TEST(Fundamental, FundamentalFromProjections) {
TEST(Fundamental, PreconditionerFromPoints) {
int n = 4;
Mat points(2, n);
+ // clang-format off
points << 0, 0, 1, 1,
0, 2, 1, 3;
+ // clang-format on
Mat3 T;
PreconditionerFromPoints(points, &T);
@@ -152,8 +156,8 @@ TEST(Fundamental, MotionFromEssentialAndCorrespondence) {
Mat3 R_estimated;
Vec3 t_estimated;
- MotionFromEssentialAndCorrespondence(E, d.K1, x1, d.K2, x2,
- &R_estimated, &t_estimated);
+ MotionFromEssentialAndCorrespondence(
+ E, d.K1, x1, d.K2, x2, &R_estimated, &t_estimated);
EXPECT_LE(FrobeniusDistance(R_estimated, R), 1e-8);
EXPECT_LE(DistanceL2(t_estimated, t), 1e-8);
diff --git a/intern/libmv/libmv/multiview/homography.cc b/intern/libmv/libmv/multiview/homography.cc
index 69177743f94..2db2c0cd3d5 100644
--- a/intern/libmv/libmv/multiview/homography.cc
+++ b/intern/libmv/libmv/multiview/homography.cc
@@ -26,7 +26,7 @@
#include "libmv/multiview/homography_parameterization.h"
namespace libmv {
-/** 2D Homography transformation estimation in the case that points are in
+/** 2D Homography transformation estimation in the case that points are in
* euclidean coordinates.
*
* x = H y
@@ -44,10 +44,7 @@ namespace libmv {
* (-x2*a+x1*d)*y1 + (-x2*b+x1*e)*y2 + -x2*c+x1*f |0|
*/
static bool Homography2DFromCorrespondencesLinearEuc(
- const Mat &x1,
- const Mat &x2,
- Mat3 *H,
- double expected_precision) {
+ const Mat& x1, const Mat& x2, Mat3* H, double expected_precision) {
assert(2 == x1.rows());
assert(4 <= x1.cols());
assert(x1.rows() == x2.rows());
@@ -58,27 +55,27 @@ static bool Homography2DFromCorrespondencesLinearEuc(
Mat b = Mat::Zero(n * 3, 1);
for (int i = 0; i < n; ++i) {
int j = 3 * i;
- L(j, 0) = x1(0, i); // a
- L(j, 1) = x1(1, i); // b
- L(j, 2) = 1.0; // c
+ L(j, 0) = x1(0, i); // a
+ L(j, 1) = x1(1, i); // b
+ L(j, 2) = 1.0; // c
L(j, 6) = -x2(0, i) * x1(0, i); // g
L(j, 7) = -x2(0, i) * x1(1, i); // h
- b(j, 0) = x2(0, i); // i
+ b(j, 0) = x2(0, i); // i
++j;
- L(j, 3) = x1(0, i); // d
- L(j, 4) = x1(1, i); // e
- L(j, 5) = 1.0; // f
+ L(j, 3) = x1(0, i); // d
+ L(j, 4) = x1(1, i); // e
+ L(j, 5) = 1.0; // f
L(j, 6) = -x2(1, i) * x1(0, i); // g
L(j, 7) = -x2(1, i) * x1(1, i); // h
- b(j, 0) = x2(1, i); // i
+ b(j, 0) = x2(1, i); // i
// This ensures better stability
// TODO(julien) make a lite version without this 3rd set
++j;
- L(j, 0) = x2(1, i) * x1(0, i); // a
- L(j, 1) = x2(1, i) * x1(1, i); // b
- L(j, 2) = x2(1, i); // c
+ L(j, 0) = x2(1, i) * x1(0, i); // a
+ L(j, 1) = x2(1, i) * x1(1, i); // b
+ L(j, 2) = x2(1, i); // c
L(j, 3) = -x2(0, i) * x1(0, i); // d
L(j, 4) = -x2(0, i) * x1(1, i); // e
L(j, 5) = -x2(0, i); // f
@@ -86,14 +83,15 @@ static bool Homography2DFromCorrespondencesLinearEuc(
// Solve Lx=B
Vec h = L.fullPivLu().solve(b);
Homography2DNormalizedParameterization<double>::To(h, H);
- if ((L * h).isApprox(b, expected_precision)) {
+ if ((L * h).isApprox(b, expected_precision)) {
return true;
} else {
return false;
}
}
-/** 2D Homography transformation estimation in the case that points are in
+// clang-format off
+/** 2D Homography transformation estimation in the case that points are in
* homogeneous coordinates.
*
* | 0 -x3 x2| |a b c| |y1| -x3*d+x2*g -x3*e+x2*h -x3*f+x2*1 |y1| (-x3*d+x2*g)*y1 (-x3*e+x2*h)*y2 (-x3*f+x2*1)*y3 |0|
@@ -101,13 +99,14 @@ static bool Homography2DFromCorrespondencesLinearEuc(
* |-x2 x1 0| |g h 1| |y3| -x2*a+x1*d -x2*b+x1*e -x2*c+x1*f |y3| (-x2*a+x1*d)*y1 (-x2*b+x1*e)*y2 (-x2*c+x1*f)*y3 |0|
* X = |a b c d e f g h|^t
*/
-bool Homography2DFromCorrespondencesLinear(const Mat &x1,
- const Mat &x2,
- Mat3 *H,
+// clang-format on
+bool Homography2DFromCorrespondencesLinear(const Mat& x1,
+ const Mat& x2,
+ Mat3* H,
double expected_precision) {
if (x1.rows() == 2) {
- return Homography2DFromCorrespondencesLinearEuc(x1, x2, H,
- expected_precision);
+ return Homography2DFromCorrespondencesLinearEuc(
+ x1, x2, H, expected_precision);
}
assert(3 == x1.rows());
assert(4 <= x1.cols());
@@ -122,33 +121,33 @@ bool Homography2DFromCorrespondencesLinear(const Mat &x1,
Mat b = Mat::Zero(n * 3, 1);
for (int i = 0; i < n; ++i) {
int j = 3 * i;
- L(j, 0) = x2(w, i) * x1(x, i); // a
- L(j, 1) = x2(w, i) * x1(y, i); // b
- L(j, 2) = x2(w, i) * x1(w, i); // c
+ L(j, 0) = x2(w, i) * x1(x, i); // a
+ L(j, 1) = x2(w, i) * x1(y, i); // b
+ L(j, 2) = x2(w, i) * x1(w, i); // c
L(j, 6) = -x2(x, i) * x1(x, i); // g
L(j, 7) = -x2(x, i) * x1(y, i); // h
- b(j, 0) = x2(x, i) * x1(w, i);
+ b(j, 0) = x2(x, i) * x1(w, i);
++j;
- L(j, 3) = x2(w, i) * x1(x, i); // d
- L(j, 4) = x2(w, i) * x1(y, i); // e
- L(j, 5) = x2(w, i) * x1(w, i); // f
+ L(j, 3) = x2(w, i) * x1(x, i); // d
+ L(j, 4) = x2(w, i) * x1(y, i); // e
+ L(j, 5) = x2(w, i) * x1(w, i); // f
L(j, 6) = -x2(y, i) * x1(x, i); // g
L(j, 7) = -x2(y, i) * x1(y, i); // h
- b(j, 0) = x2(y, i) * x1(w, i);
+ b(j, 0) = x2(y, i) * x1(w, i);
// This ensures better stability
++j;
- L(j, 0) = x2(y, i) * x1(x, i); // a
- L(j, 1) = x2(y, i) * x1(y, i); // b
- L(j, 2) = x2(y, i) * x1(w, i); // c
+ L(j, 0) = x2(y, i) * x1(x, i); // a
+ L(j, 1) = x2(y, i) * x1(y, i); // b
+ L(j, 2) = x2(y, i) * x1(w, i); // c
L(j, 3) = -x2(x, i) * x1(x, i); // d
L(j, 4) = -x2(x, i) * x1(y, i); // e
L(j, 5) = -x2(x, i) * x1(w, i); // f
}
// Solve Lx=B
Vec h = L.fullPivLu().solve(b);
- if ((L * h).isApprox(b, expected_precision)) {
+ if ((L * h).isApprox(b, expected_precision)) {
Homography2DNormalizedParameterization<double>::To(h, H);
return true;
} else {
@@ -158,32 +157,30 @@ bool Homography2DFromCorrespondencesLinear(const Mat &x1,
// Default settings for homography estimation which should be suitable
// for a wide range of use cases.
-EstimateHomographyOptions::EstimateHomographyOptions(void) :
- use_normalization(true),
- max_num_iterations(50),
- expected_average_symmetric_distance(1e-16) {
+EstimateHomographyOptions::EstimateHomographyOptions(void)
+ : use_normalization(true),
+ max_num_iterations(50),
+ expected_average_symmetric_distance(1e-16) {
}
namespace {
-void GetNormalizedPoints(const Mat &original_points,
- Mat *normalized_points,
- Mat3 *normalization_matrix) {
+void GetNormalizedPoints(const Mat& original_points,
+ Mat* normalized_points,
+ Mat3* normalization_matrix) {
IsotropicPreconditionerFromPoints(original_points, normalization_matrix);
- ApplyTransformationToPoints(original_points,
- *normalization_matrix,
- normalized_points);
+ ApplyTransformationToPoints(
+ original_points, *normalization_matrix, normalized_points);
}
// Cost functor which computes symmetric geometric distance
// used for homography matrix refinement.
class HomographySymmetricGeometricCostFunctor {
public:
- HomographySymmetricGeometricCostFunctor(const Vec2 &x,
- const Vec2 &y)
- : x_(x), y_(y) { }
+ HomographySymmetricGeometricCostFunctor(const Vec2& x, const Vec2& y)
+ : x_(x), y_(y) {}
- template<typename T>
- bool operator()(const T *homography_parameters, T *residuals) const {
+ template <typename T>
+ bool operator()(const T* homography_parameters, T* residuals) const {
typedef Eigen::Matrix<T, 3, 3> Mat3;
typedef Eigen::Matrix<T, 3, 1> Vec3;
@@ -221,9 +218,10 @@ class HomographySymmetricGeometricCostFunctor {
// average value.
class TerminationCheckingCallback : public ceres::IterationCallback {
public:
- TerminationCheckingCallback(const Mat &x1, const Mat &x2,
- const EstimateHomographyOptions &options,
- Mat3 *H)
+ TerminationCheckingCallback(const Mat& x1,
+ const Mat& x2,
+ const EstimateHomographyOptions& options,
+ Mat3* H)
: options_(options), x1_(x1), x2_(x2), H_(H) {}
virtual ceres::CallbackReturnType operator()(
@@ -236,9 +234,8 @@ class TerminationCheckingCallback : public ceres::IterationCallback {
// Calculate average of symmetric geometric distance.
double average_distance = 0.0;
for (int i = 0; i < x1_.cols(); i++) {
- average_distance = SymmetricGeometricDistance(*H_,
- x1_.col(i),
- x2_.col(i));
+ average_distance =
+ SymmetricGeometricDistance(*H_, x1_.col(i), x2_.col(i));
}
average_distance /= x1_.cols();
@@ -250,10 +247,10 @@ class TerminationCheckingCallback : public ceres::IterationCallback {
}
private:
- const EstimateHomographyOptions &options_;
- const Mat &x1_;
- const Mat &x2_;
- Mat3 *H_;
+ const EstimateHomographyOptions& options_;
+ const Mat& x1_;
+ const Mat& x2_;
+ Mat3* H_;
};
} // namespace
@@ -261,10 +258,10 @@ class TerminationCheckingCallback : public ceres::IterationCallback {
* euclidean coordinates.
*/
bool EstimateHomography2DFromCorrespondences(
- const Mat &x1,
- const Mat &x2,
- const EstimateHomographyOptions &options,
- Mat3 *H) {
+ const Mat& x1,
+ const Mat& x2,
+ const EstimateHomographyOptions& options,
+ Mat3* H) {
// TODO(sergey): Support homogenous coordinates, not just euclidean.
assert(2 == x1.rows());
@@ -272,8 +269,7 @@ bool EstimateHomography2DFromCorrespondences(
assert(x1.rows() == x2.rows());
assert(x1.cols() == x2.cols());
- Mat3 T1 = Mat3::Identity(),
- T2 = Mat3::Identity();
+ Mat3 T1 = Mat3::Identity(), T2 = Mat3::Identity();
// Step 1: Algebraic homography estimation.
Mat x1_normalized, x2_normalized;
@@ -300,16 +296,15 @@ bool EstimateHomography2DFromCorrespondences(
// Step 2: Refine matrix using Ceres minimizer.
ceres::Problem problem;
for (int i = 0; i < x1.cols(); i++) {
- HomographySymmetricGeometricCostFunctor
- *homography_symmetric_geometric_cost_function =
- new HomographySymmetricGeometricCostFunctor(x1.col(i),
- x2.col(i));
+ HomographySymmetricGeometricCostFunctor*
+ homography_symmetric_geometric_cost_function =
+ new HomographySymmetricGeometricCostFunctor(x1.col(i), x2.col(i));
problem.AddResidualBlock(
- new ceres::AutoDiffCostFunction<
- HomographySymmetricGeometricCostFunctor,
- 4, // num_residuals
- 9>(homography_symmetric_geometric_cost_function),
+ new ceres::AutoDiffCostFunction<HomographySymmetricGeometricCostFunctor,
+ 4, // num_residuals
+ 9>(
+ homography_symmetric_geometric_cost_function),
NULL,
H->data());
}
@@ -335,15 +330,16 @@ bool EstimateHomography2DFromCorrespondences(
return summary.IsSolutionUsable();
}
+// clang-format off
/**
* x2 ~ A * x1
* x2^t * Hi * A *x1 = 0
- * H1 = H2 = H3 =
+ * H1 = H2 = H3 =
* | 0 0 0 1| |-x2w| |0 0 0 0| | 0 | | 0 0 1 0| |-x2z|
* | 0 0 0 0| -> | 0 | |0 0 1 0| -> |-x2z| | 0 0 0 0| -> | 0 |
* | 0 0 0 0| | 0 | |0-1 0 0| | x2y| |-1 0 0 0| | x2x|
* |-1 0 0 0| | x2x| |0 0 0 0| | 0 | | 0 0 0 0| | 0 |
- * H4 = H5 = H6 =
+ * H4 = H5 = H6 =
* |0 0 0 0| | 0 | | 0 1 0 0| |-x2y| |0 0 0 0| | 0 |
* |0 0 0 1| -> |-x2w| |-1 0 0 0| -> | x2x| |0 0 0 0| -> | 0 |
* |0 0 0 0| | 0 | | 0 0 0 0| | 0 | |0 0 0 1| |-x2w|
@@ -361,10 +357,11 @@ bool EstimateHomography2DFromCorrespondences(
* x2^t * H6 * A *x1 = (-x2w*i +x2z*m )*x1x + (-x2w*j +x2z*n )*x1y + (-x2w*k +x2z*o )*x1z + (-x2w*l +x2z*1 )*x1w = 0
*
* X = |a b c d e f g h i j k l m n o|^t
-*/
-bool Homography3DFromCorrespondencesLinear(const Mat &x1,
- const Mat &x2,
- Mat4 *H,
+ */
+// clang-format on
+bool Homography3DFromCorrespondencesLinear(const Mat& x1,
+ const Mat& x2,
+ Mat4* H,
double expected_precision) {
assert(4 == x1.rows());
assert(5 <= x1.cols());
@@ -379,68 +376,68 @@ bool Homography3DFromCorrespondencesLinear(const Mat &x1,
Mat b = Mat::Zero(n * 6, 1);
for (int i = 0; i < n; ++i) {
int j = 6 * i;
- L(j, 0) = -x2(w, i) * x1(x, i); // a
- L(j, 1) = -x2(w, i) * x1(y, i); // b
- L(j, 2) = -x2(w, i) * x1(z, i); // c
- L(j, 3) = -x2(w, i) * x1(w, i); // d
- L(j, 12) = x2(x, i) * x1(x, i); // m
- L(j, 13) = x2(x, i) * x1(y, i); // n
- L(j, 14) = x2(x, i) * x1(z, i); // o
- b(j, 0) = -x2(x, i) * x1(w, i);
+ L(j, 0) = -x2(w, i) * x1(x, i); // a
+ L(j, 1) = -x2(w, i) * x1(y, i); // b
+ L(j, 2) = -x2(w, i) * x1(z, i); // c
+ L(j, 3) = -x2(w, i) * x1(w, i); // d
+ L(j, 12) = x2(x, i) * x1(x, i); // m
+ L(j, 13) = x2(x, i) * x1(y, i); // n
+ L(j, 14) = x2(x, i) * x1(z, i); // o
+ b(j, 0) = -x2(x, i) * x1(w, i);
++j;
- L(j, 4) = -x2(z, i) * x1(x, i); // e
- L(j, 5) = -x2(z, i) * x1(y, i); // f
- L(j, 6) = -x2(z, i) * x1(z, i); // g
- L(j, 7) = -x2(z, i) * x1(w, i); // h
- L(j, 8) = x2(y, i) * x1(x, i); // i
- L(j, 9) = x2(y, i) * x1(y, i); // j
- L(j, 10) = x2(y, i) * x1(z, i); // k
- L(j, 11) = x2(y, i) * x1(w, i); // l
+ L(j, 4) = -x2(z, i) * x1(x, i); // e
+ L(j, 5) = -x2(z, i) * x1(y, i); // f
+ L(j, 6) = -x2(z, i) * x1(z, i); // g
+ L(j, 7) = -x2(z, i) * x1(w, i); // h
+ L(j, 8) = x2(y, i) * x1(x, i); // i
+ L(j, 9) = x2(y, i) * x1(y, i); // j
+ L(j, 10) = x2(y, i) * x1(z, i); // k
+ L(j, 11) = x2(y, i) * x1(w, i); // l
++j;
- L(j, 0) = -x2(z, i) * x1(x, i); // a
- L(j, 1) = -x2(z, i) * x1(y, i); // b
- L(j, 2) = -x2(z, i) * x1(z, i); // c
- L(j, 3) = -x2(z, i) * x1(w, i); // d
- L(j, 8) = x2(x, i) * x1(x, i); // i
- L(j, 9) = x2(x, i) * x1(y, i); // j
- L(j, 10) = x2(x, i) * x1(z, i); // k
- L(j, 11) = x2(x, i) * x1(w, i); // l
+ L(j, 0) = -x2(z, i) * x1(x, i); // a
+ L(j, 1) = -x2(z, i) * x1(y, i); // b
+ L(j, 2) = -x2(z, i) * x1(z, i); // c
+ L(j, 3) = -x2(z, i) * x1(w, i); // d
+ L(j, 8) = x2(x, i) * x1(x, i); // i
+ L(j, 9) = x2(x, i) * x1(y, i); // j
+ L(j, 10) = x2(x, i) * x1(z, i); // k
+ L(j, 11) = x2(x, i) * x1(w, i); // l
++j;
- L(j, 4) = -x2(w, i) * x1(x, i); // e
- L(j, 5) = -x2(w, i) * x1(y, i); // f
- L(j, 6) = -x2(w, i) * x1(z, i); // g
- L(j, 7) = -x2(w, i) * x1(w, i); // h
- L(j, 12) = x2(y, i) * x1(x, i); // m
- L(j, 13) = x2(y, i) * x1(y, i); // n
- L(j, 14) = x2(y, i) * x1(z, i); // o
- b(j, 0) = -x2(y, i) * x1(w, i);
+ L(j, 4) = -x2(w, i) * x1(x, i); // e
+ L(j, 5) = -x2(w, i) * x1(y, i); // f
+ L(j, 6) = -x2(w, i) * x1(z, i); // g
+ L(j, 7) = -x2(w, i) * x1(w, i); // h
+ L(j, 12) = x2(y, i) * x1(x, i); // m
+ L(j, 13) = x2(y, i) * x1(y, i); // n
+ L(j, 14) = x2(y, i) * x1(z, i); // o
+ b(j, 0) = -x2(y, i) * x1(w, i);
++j;
L(j, 0) = -x2(y, i) * x1(x, i); // a
L(j, 1) = -x2(y, i) * x1(y, i); // b
L(j, 2) = -x2(y, i) * x1(z, i); // c
L(j, 3) = -x2(y, i) * x1(w, i); // d
- L(j, 4) = x2(x, i) * x1(x, i); // e
- L(j, 5) = x2(x, i) * x1(y, i); // f
- L(j, 6) = x2(x, i) * x1(z, i); // g
- L(j, 7) = x2(x, i) * x1(w, i); // h
+ L(j, 4) = x2(x, i) * x1(x, i); // e
+ L(j, 5) = x2(x, i) * x1(y, i); // f
+ L(j, 6) = x2(x, i) * x1(z, i); // g
+ L(j, 7) = x2(x, i) * x1(w, i); // h
++j;
- L(j, 8) = -x2(w, i) * x1(x, i); // i
- L(j, 9) = -x2(w, i) * x1(y, i); // j
+ L(j, 8) = -x2(w, i) * x1(x, i); // i
+ L(j, 9) = -x2(w, i) * x1(y, i); // j
L(j, 10) = -x2(w, i) * x1(z, i); // k
L(j, 11) = -x2(w, i) * x1(w, i); // l
- L(j, 12) = x2(z, i) * x1(x, i); // m
- L(j, 13) = x2(z, i) * x1(y, i); // n
- L(j, 14) = x2(z, i) * x1(z, i); // o
- b(j, 0) = -x2(z, i) * x1(w, i);
+ L(j, 12) = x2(z, i) * x1(x, i); // m
+ L(j, 13) = x2(z, i) * x1(y, i); // n
+ L(j, 14) = x2(z, i) * x1(z, i); // o
+ b(j, 0) = -x2(z, i) * x1(w, i);
}
// Solve Lx=B
Vec h = L.fullPivLu().solve(b);
- if ((L * h).isApprox(b, expected_precision)) {
+ if ((L * h).isApprox(b, expected_precision)) {
Homography3DNormalizedParameterization<double>::To(h, H);
return true;
} else {
@@ -448,9 +445,9 @@ bool Homography3DFromCorrespondencesLinear(const Mat &x1,
}
}
-double SymmetricGeometricDistance(const Mat3 &H,
- const Vec2 &x1,
- const Vec2 &x2) {
+double SymmetricGeometricDistance(const Mat3& H,
+ const Vec2& x1,
+ const Vec2& x2) {
Vec3 x(x1(0), x1(1), 1.0);
Vec3 y(x2(0), x2(1), 1.0);
diff --git a/intern/libmv/libmv/multiview/homography.h b/intern/libmv/libmv/multiview/homography.h
index a76aa9405a5..0742c6f7c70 100644
--- a/intern/libmv/libmv/multiview/homography.h
+++ b/intern/libmv/libmv/multiview/homography.h
@@ -49,11 +49,11 @@ namespace libmv {
* \return True if the transformation estimation has succeeded.
* \note There must be at least 4 non-colinear points.
*/
-bool Homography2DFromCorrespondencesLinear(const Mat &x1,
- const Mat &x2,
- Mat3 *H,
- double expected_precision =
- EigenDouble::dummy_precision());
+bool Homography2DFromCorrespondencesLinear(
+ const Mat& x1,
+ const Mat& x2,
+ Mat3* H,
+ double expected_precision = EigenDouble::dummy_precision());
/**
* This structure contains options that controls how the homography
@@ -101,10 +101,10 @@ struct EstimateHomographyOptions {
* refinement.
*/
bool EstimateHomography2DFromCorrespondences(
- const Mat &x1,
- const Mat &x2,
- const EstimateHomographyOptions &options,
- Mat3 *H);
+ const Mat& x1,
+ const Mat& x2,
+ const EstimateHomographyOptions& options,
+ Mat3* H);
/**
* 3D Homography transformation estimation.
@@ -129,20 +129,20 @@ bool EstimateHomography2DFromCorrespondences(
* \note Need at least 5 non coplanar points
* \note Points coordinates must be in homogeneous coordinates
*/
-bool Homography3DFromCorrespondencesLinear(const Mat &x1,
- const Mat &x2,
- Mat4 *H,
- double expected_precision =
- EigenDouble::dummy_precision());
+bool Homography3DFromCorrespondencesLinear(
+ const Mat& x1,
+ const Mat& x2,
+ Mat4* H,
+ double expected_precision = EigenDouble::dummy_precision());
/**
* Calculate symmetric geometric cost:
*
* D(H * x1, x2)^2 + D(H^-1 * x2, x1)
*/
-double SymmetricGeometricDistance(const Mat3 &H,
- const Vec2 &x1,
- const Vec2 &x2);
+double SymmetricGeometricDistance(const Mat3& H,
+ const Vec2& x1,
+ const Vec2& x2);
} // namespace libmv
diff --git a/intern/libmv/libmv/multiview/homography_error.h b/intern/libmv/libmv/multiview/homography_error.h
index f8b9d45e73c..786ca245ea6 100644
--- a/intern/libmv/libmv/multiview/homography_error.h
+++ b/intern/libmv/libmv/multiview/homography_error.h
@@ -27,18 +27,18 @@ namespace libmv {
namespace homography {
namespace homography2D {
- /**
- * Structure for estimating the asymmetric error between a vector x2 and the
- * transformed x1 such that
- * Error = ||x2 - Psi(H * x1)||^2
- * where Psi is the function that transforms homogeneous to euclidean coords.
- * \note It should be distributed as Chi-squared with k = 2.
- */
+/**
+ * Structure for estimating the asymmetric error between a vector x2 and the
+ * transformed x1 such that
+ * Error = ||x2 - Psi(H * x1)||^2
+ * where Psi is the function that transforms homogeneous to euclidean coords.
+ * \note It should be distributed as Chi-squared with k = 2.
+ */
struct AsymmetricError {
/**
- * Computes the asymmetric residuals between a set of 2D points x2 and the
+ * Computes the asymmetric residuals between a set of 2D points x2 and the
* transformed 2D point set x1 such that
- * Residuals_i = x2_i - Psi(H * x1_i)
+ * Residuals_i = x2_i - Psi(H * x1_i)
* where Psi is the function that transforms homogeneous to euclidean coords.
*
* \param[in] H The 3x3 homography matrix.
@@ -47,8 +47,7 @@ struct AsymmetricError {
* \param[in] x2 A set of 2D points (2xN or 3xN matrix of column vectors).
* \param[out] dx A 2xN matrix of column vectors of residuals errors
*/
- static void Residuals(const Mat &H, const Mat &x1,
- const Mat &x2, Mat2X *dx) {
+ static void Residuals(const Mat& H, const Mat& x1, const Mat& x2, Mat2X* dx) {
dx->resize(2, x1.cols());
Mat3X x2h_est;
if (x1.rows() == 2)
@@ -63,19 +62,18 @@ struct AsymmetricError {
*dx = HomogeneousToEuclidean(static_cast<Mat3X>(x2)) - *dx;
}
/**
- * Computes the asymmetric residuals between a 2D point x2 and the transformed
+ * Computes the asymmetric residuals between a 2D point x2 and the transformed
* 2D point x1 such that
- * Residuals = x2 - Psi(H * x1)
+ * Residuals = x2 - Psi(H * x1)
* where Psi is the function that transforms homogeneous to euclidean coords.
*
* \param[in] H The 3x3 homography matrix.
* The estimated homography should approximatelly hold the condition y = H x.
- * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
- * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
* \param[out] dx A vector of size 2 of the residual error
*/
- static void Residuals(const Mat &H, const Vec &x1,
- const Vec &x2, Vec2 *dx) {
+ static void Residuals(const Mat& H, const Vec& x1, const Vec& x2, Vec2* dx) {
Vec3 x2h_est;
if (x1.rows() == 2)
x2h_est = H * EuclideanToHomogeneous(static_cast<Vec2>(x1));
@@ -85,10 +83,10 @@ struct AsymmetricError {
*dx = x2 - x2h_est.head<2>() / x2h_est[2];
else
*dx = HomogeneousToEuclidean(static_cast<Vec3>(x2)) -
- x2h_est.head<2>() / x2h_est[2];
+ x2h_est.head<2>() / x2h_est[2];
}
/**
- * Computes the squared norm of the residuals between a set of 2D points x2
+ * Computes the squared norm of the residuals between a set of 2D points x2
* and the transformed 2D point set x1 such that
* Error = || x2 - Psi(H * x1) ||^2
* where Psi is the function that transforms homogeneous to euclidean coords.
@@ -99,70 +97,70 @@ struct AsymmetricError {
* \param[in] x2 A set of 2D points (2xN or 3xN matrix of column vectors).
* \return The squared norm of the asymmetric residuals errors
*/
- static double Error(const Mat &H, const Mat &x1, const Mat &x2) {
+ static double Error(const Mat& H, const Mat& x1, const Mat& x2) {
Mat2X dx;
Residuals(H, x1, x2, &dx);
return dx.squaredNorm();
}
/**
- * Computes the squared norm of the residuals between a 2D point x2 and the
- * transformed 2D point x1 such that rms = || x2 - Psi(H * x1) ||^2
+ * Computes the squared norm of the residuals between a 2D point x2 and the
+ * transformed 2D point x1 such that rms = || x2 - Psi(H * x1) ||^2
* where Psi is the function that transforms homogeneous to euclidean coords.
*
* \param[in] H The 3x3 homography matrix.
* The estimated homography should approximatelly hold the condition y = H x.
- * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
- * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
* \return The squared norm of the asymmetric residual error
*/
- static double Error(const Mat &H, const Vec &x1, const Vec &x2) {
+ static double Error(const Mat& H, const Vec& x1, const Vec& x2) {
Vec2 dx;
Residuals(H, x1, x2, &dx);
return dx.squaredNorm();
}
};
- /**
- * Structure for estimating the symmetric error
- * between a vector x2 and the transformed x1 such that
- * Error = ||x2 - Psi(H * x1)||^2 + ||x1 - Psi(H^-1 * x2)||^2
- * where Psi is the function that transforms homogeneous to euclidean coords.
- * \note It should be distributed as Chi-squared with k = 4.
- */
+/**
+ * Structure for estimating the symmetric error
+ * between a vector x2 and the transformed x1 such that
+ * Error = ||x2 - Psi(H * x1)||^2 + ||x1 - Psi(H^-1 * x2)||^2
+ * where Psi is the function that transforms homogeneous to euclidean coords.
+ * \note It should be distributed as Chi-squared with k = 4.
+ */
struct SymmetricError {
/**
- * Computes the squared norm of the residuals between x2 and the
- * transformed x1 such that
+ * Computes the squared norm of the residuals between x2 and the
+ * transformed x1 such that
* Error = ||x2 - Psi(H * x1)||^2 + ||x1 - Psi(H^-1 * x2)||^2
* where Psi is the function that transforms homogeneous to euclidean coords.
*
* \param[in] H The 3x3 homography matrix.
* The estimated homography should approximatelly hold the condition y = H x.
- * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
- * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
* \return The squared norm of the symmetric residuals errors
*/
- static double Error(const Mat &H, const Vec &x1, const Vec &x2) {
+ static double Error(const Mat& H, const Vec& x1, const Vec& x2) {
// TODO(keir): This is awesomely inefficient because it does a 3x3
// inversion for each evaluation.
Mat3 Hinv = H.inverse();
- return AsymmetricError::Error(H, x1, x2) +
+ return AsymmetricError::Error(H, x1, x2) +
AsymmetricError::Error(Hinv, x2, x1);
}
// TODO(julien) Add residuals function \see AsymmetricError
};
- /**
- * Structure for estimating the algebraic error (cross product)
- * between a vector x2 and the transformed x1 such that
- * Error = ||[x2] * H * x1||^^2
- * where [x2] is the skew matrix of x2.
- */
+/**
+ * Structure for estimating the algebraic error (cross product)
+ * between a vector x2 and the transformed x1 such that
+ * Error = ||[x2] * H * x1||^^2
+ * where [x2] is the skew matrix of x2.
+ */
struct AlgebraicError {
// TODO(julien) Make an AlgebraicError2Rows and AlgebraicError3Rows
/**
- * Computes the algebraic residuals (cross product) between a set of 2D
- * points x2 and the transformed 2D point set x1 such that
+ * Computes the algebraic residuals (cross product) between a set of 2D
+ * points x2 and the transformed 2D point set x1 such that
* [x2] * H * x1 where [x2] is the skew matrix of x2.
*
* \param[in] H The 3x3 homography matrix.
@@ -171,8 +169,7 @@ struct AlgebraicError {
* \param[in] x2 A set of 2D points (2xN or 3xN matrix of column vectors).
* \param[out] dx A 3xN matrix of column vectors of residuals errors
*/
- static void Residuals(const Mat &H, const Mat &x1,
- const Mat &x2, Mat3X *dx) {
+ static void Residuals(const Mat& H, const Mat& x1, const Mat& x2, Mat3X* dx) {
dx->resize(3, x1.cols());
Vec3 col;
for (int i = 0; i < x1.cols(); ++i) {
@@ -181,18 +178,17 @@ struct AlgebraicError {
}
}
/**
- * Computes the algebraic residuals (cross product) between a 2D point x2
- * and the transformed 2D point x1 such that
+ * Computes the algebraic residuals (cross product) between a 2D point x2
+ * and the transformed 2D point x1 such that
* [x2] * H * x1 where [x2] is the skew matrix of x2.
*
* \param[in] H The 3x3 homography matrix.
* The estimated homography should approximatelly hold the condition y = H x.
- * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
- * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
* \param[out] dx A vector of size 3 of the residual error
*/
- static void Residuals(const Mat &H, const Vec &x1,
- const Vec &x2, Vec3 *dx) {
+ static void Residuals(const Mat& H, const Vec& x1, const Vec& x2, Vec3* dx) {
Vec3 x2h_est;
if (x1.rows() == 2)
x2h_est = H * EuclideanToHomogeneous(static_cast<Vec2>(x1));
@@ -206,8 +202,8 @@ struct AlgebraicError {
// identical 3x3 skew matrix for each evaluation.
}
/**
- * Computes the squared norm of the algebraic residuals between a set of 2D
- * points x2 and the transformed 2D point set x1 such that
+ * Computes the squared norm of the algebraic residuals between a set of 2D
+ * points x2 and the transformed 2D point set x1 such that
* [x2] * H * x1 where [x2] is the skew matrix of x2.
*
* \param[in] H The 3x3 homography matrix.
@@ -216,23 +212,23 @@ struct AlgebraicError {
* \param[in] x2 A set of 2D points (2xN or 3xN matrix of column vectors).
* \return The squared norm of the asymmetric residuals errors
*/
- static double Error(const Mat &H, const Mat &x1, const Mat &x2) {
+ static double Error(const Mat& H, const Mat& x1, const Mat& x2) {
Mat3X dx;
Residuals(H, x1, x2, &dx);
return dx.squaredNorm();
}
/**
- * Computes the squared norm of the algebraic residuals between a 2D point x2
- * and the transformed 2D point x1 such that
+ * Computes the squared norm of the algebraic residuals between a 2D point x2
+ * and the transformed 2D point x1 such that
* [x2] * H * x1 where [x2] is the skew matrix of x2.
*
* \param[in] H The 3x3 homography matrix.
* The estimated homography should approximatelly hold the condition y = H x.
- * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
- * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
+ * \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
* \return The squared norm of the asymmetric residual error
*/
- static double Error(const Mat &H, const Vec &x1, const Vec &x2) {
+ static double Error(const Mat& H, const Vec& x1, const Vec& x2) {
Vec3 dx;
Residuals(H, x1, x2, &dx);
return dx.squaredNorm();
diff --git a/intern/libmv/libmv/multiview/homography_parameterization.h b/intern/libmv/libmv/multiview/homography_parameterization.h
index ca8fbd8066e..ae2d74da9ff 100644
--- a/intern/libmv/libmv/multiview/homography_parameterization.h
+++ b/intern/libmv/libmv/multiview/homography_parameterization.h
@@ -25,64 +25,72 @@
namespace libmv {
-/** A parameterization of the 2D homography matrix that uses 8 parameters so
+/** A parameterization of the 2D homography matrix that uses 8 parameters so
* that the matrix is normalized (H(2,2) == 1).
* The homography matrix H is built from a list of 8 parameters (a, b,...g, h)
* as follows
- * |a b c|
+ * |a b c|
* H = |d e f|
- * |g h 1|
+ * |g h 1|
*/
-template<typename T = double>
+template <typename T = double>
class Homography2DNormalizedParameterization {
public:
typedef Eigen::Matrix<T, 8, 1> Parameters; // a, b, ... g, h
typedef Eigen::Matrix<T, 3, 3> Parameterized; // H
/// Convert from the 8 parameters to a H matrix.
- static void To(const Parameters &p, Parameterized *h) {
+ static void To(const Parameters& p, Parameterized* h) {
+ // clang-format off
*h << p(0), p(1), p(2),
p(3), p(4), p(5),
p(6), p(7), 1.0;
+ // clang-format on
}
/// Convert from a H matrix to the 8 parameters.
- static void From(const Parameterized &h, Parameters *p) {
+ static void From(const Parameterized& h, Parameters* p) {
+ // clang-format off
*p << h(0, 0), h(0, 1), h(0, 2),
h(1, 0), h(1, 1), h(1, 2),
h(2, 0), h(2, 1);
+ // clang-format on
}
};
-/** A parameterization of the 2D homography matrix that uses 15 parameters so
+/** A parameterization of the 2D homography matrix that uses 15 parameters so
* that the matrix is normalized (H(3,3) == 1).
* The homography matrix H is built from a list of 15 parameters (a, b,...n, o)
* as follows
- * |a b c d|
+ * |a b c d|
* H = |e f g h|
* |i j k l|
- * |m n o 1|
+ * |m n o 1|
*/
-template<typename T = double>
+template <typename T = double>
class Homography3DNormalizedParameterization {
public:
- typedef Eigen::Matrix<T, 15, 1> Parameters; // a, b, ... n, o
- typedef Eigen::Matrix<T, 4, 4> Parameterized; // H
+ typedef Eigen::Matrix<T, 15, 1> Parameters; // a, b, ... n, o
+ typedef Eigen::Matrix<T, 4, 4> Parameterized; // H
/// Convert from the 15 parameters to a H matrix.
- static void To(const Parameters &p, Parameterized *h) {
+ static void To(const Parameters& p, Parameterized* h) {
+ // clang-format off
*h << p(0), p(1), p(2), p(3),
p(4), p(5), p(6), p(7),
p(8), p(9), p(10), p(11),
p(12), p(13), p(14), 1.0;
+ // clang-format on
}
/// Convert from a H matrix to the 15 parameters.
- static void From(const Parameterized &h, Parameters *p) {
+ static void From(const Parameterized& h, Parameters* p) {
+ // clang-format off
*p << h(0, 0), h(0, 1), h(0, 2), h(0, 3),
h(1, 0), h(1, 1), h(1, 2), h(1, 3),
h(2, 0), h(2, 1), h(2, 2), h(2, 3),
h(3, 0), h(3, 1), h(3, 2);
+ // clang-format on
}
};
diff --git a/intern/libmv/libmv/multiview/homography_test.cc b/intern/libmv/libmv/multiview/homography_test.cc
index 8d7266e3d11..87d1c85028d 100644
--- a/intern/libmv/libmv/multiview/homography_test.cc
+++ b/intern/libmv/libmv/multiview/homography_test.cc
@@ -18,10 +18,10 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-#include "testing/testing.h"
+#include "libmv/multiview/homography.h"
#include "libmv/logging/logging.h"
#include "libmv/multiview/projection.h"
-#include "libmv/multiview/homography.h"
+#include "testing/testing.h"
namespace {
using namespace libmv;
@@ -34,9 +34,7 @@ namespace {
// TODO(sergey): Consider using this in all tests since possible homography
// matrix is not fixed to a single value and different-looking matrices
// might actually crrespond to the same exact transform.
-void CheckHomography2DTransform(const Mat3 &H,
- const Mat &x1,
- const Mat &x2) {
+void CheckHomography2DTransform(const Mat3& H, const Mat& x1, const Mat& x2) {
for (int i = 0; i < x2.cols(); ++i) {
Vec3 x2_expected = x2.col(i);
Vec3 x2_observed = H * x1.col(i);
@@ -49,15 +47,19 @@ void CheckHomography2DTransform(const Mat3 &H,
TEST(Homography2DTest, Rotation45AndTranslationXY) {
Mat x1(3, 4);
+ // clang-format off
x1 << 0, 1, 0, 5,
0, 0, 2, 3,
1, 1, 1, 1;
+ // clang-format on
double angle = 45.0;
Mat3 m;
+ // clang-format off
m << cos(angle), -sin(angle), -2,
sin(angle), cos(angle), 5,
0, 0, 1;
+ // clang-format on
Mat x2 = x1;
// Transform point from ground truth matrix
@@ -76,13 +78,17 @@ TEST(Homography2DTest, Rotation45AndTranslationXY) {
TEST(Homography2DTest, AffineGeneral4) {
// TODO(julien) find why it doesn't work with 4 points!!!
Mat x1(3, 4);
+ // clang-format off
x1 << 0, 1, 0, 2,
0, 0, 1, 2,
1, 1, 1, 1;
+ // clang-format on
Mat3 m;
+ // clang-format off
m << 3, -1, 4,
6, -2, -3,
0, 0, 1;
+ // clang-format on
Mat x2 = x1;
for (int i = 0; i < x2.cols(); ++i) {
@@ -109,13 +115,17 @@ TEST(Homography2DTest, AffineGeneral4) {
TEST(Homography2DTest, AffineGeneral5) {
Mat x1(3, 5);
+ // clang-format off
x1 << 0, 1, 0, 2, 5,
0, 0, 1, 2, 2,
1, 1, 1, 1, 1;
+ // clang-format on
Mat3 m;
+ // clang-format off
m << 3, -1, 4,
6, -2, -3,
0, 0, 1;
+ // clang-format on
Mat x2 = x1;
for (int i = 0; i < x2.cols(); ++i)
@@ -142,13 +152,17 @@ TEST(Homography2DTest, AffineGeneral5) {
TEST(Homography2DTest, HomographyGeneral) {
Mat x1(3, 4);
+ // clang-format off
x1 << 0, 1, 0, 5,
0, 0, 2, 3,
1, 1, 1, 1;
+ // clang-format on
Mat3 m;
+ // clang-format off
m << 3, -1, 4,
6, -2, -3,
1, -3, 1;
+ // clang-format on
Mat x2 = x1;
for (int i = 0; i < x2.cols(); ++i)
@@ -164,10 +178,12 @@ TEST(Homography2DTest, HomographyGeneral) {
TEST(Homography3DTest, RotationAndTranslationXYZ) {
Mat x1(4, 5);
+ // clang-format off
x1 << 0, 0, 1, 5, 2,
0, 1, 2, 3, 5,
0, 2, 0, 1, 5,
1, 1, 1, 1, 1;
+ // clang-format on
Mat4 M;
M.setIdentity();
/*
@@ -178,24 +194,30 @@ TEST(Homography3DTest, RotationAndTranslationXYZ) {
// Rotation on x + translation
double angle = 45.0;
Mat4 rot;
+ // clang-format off
rot << 1, 0, 0, 1,
0, cos(angle), -sin(angle), 3,
0, sin(angle), cos(angle), -2,
0, 0, 0, 1;
+ // clang-format on
M *= rot;
// Rotation on y
angle = 25.0;
+ // clang-format off
rot << cos(angle), 0, sin(angle), 0,
0, 1, 0, 0,
-sin(angle), 0, cos(angle), 0,
0, 0, 0, 1;
+ // clang-format on
M *= rot;
// Rotation on z
angle = 5.0;
+ // clang-format off
rot << cos(angle), -sin(angle), 0, 0,
sin(angle), cos(angle), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1;
+ // clang-format on
M *= rot;
Mat x2 = x1;
for (int i = 0; i < x2.cols(); ++i) {
@@ -212,15 +234,19 @@ TEST(Homography3DTest, RotationAndTranslationXYZ) {
TEST(Homography3DTest, AffineGeneral) {
Mat x1(4, 5);
+ // clang-format off
x1 << 0, 0, 1, 5, 2,
0, 1, 2, 3, 5,
0, 2, 0, 1, 5,
1, 1, 1, 1, 1;
+ // clang-format on
Mat4 m;
+ // clang-format off
m << 3, -1, 4, 1,
6, -2, -3, -6,
1, 0, 1, 2,
0, 0, 0, 1;
+ // clang-format on
Mat x2 = x1;
for (int i = 0; i < x2.cols(); ++i) {
@@ -236,15 +262,19 @@ TEST(Homography3DTest, AffineGeneral) {
TEST(Homography3DTest, HomographyGeneral) {
Mat x1(4, 5);
+ // clang-format off
x1 << 0, 0, 1, 5, 2,
0, 1, 2, 3, 5,
0, 2, 0, 1, 5,
1, 1, 1, 1, 1;
+ // clang-format on
Mat4 m;
+ // clang-format off
m << 3, -1, 4, 1,
6, -2, -3, -6,
1, 0, 1, 2,
-3, 1, 0, 1;
+ // clang-format on
Mat x2 = x1;
for (int i = 0; i < x2.cols(); ++i) {
diff --git a/intern/libmv/libmv/multiview/nviewtriangulation.h b/intern/libmv/libmv/multiview/nviewtriangulation.h
index f4614ab1a5c..b2a320953a7 100644
--- a/intern/libmv/libmv/multiview/nviewtriangulation.h
+++ b/intern/libmv/libmv/multiview/nviewtriangulation.h
@@ -34,22 +34,22 @@ namespace libmv {
// x's are 2D coordinates (x,y,1) in each image; Ps are projective cameras. The
// output, X, is a homogeneous four vectors.
-template<typename T>
-void NViewTriangulate(const Matrix<T, 2, Dynamic> &x,
- const vector<Matrix<T, 3, 4> > &Ps,
- Matrix<T, 4, 1> *X) {
+template <typename T>
+void NViewTriangulate(const Matrix<T, 2, Dynamic>& x,
+ const vector<Matrix<T, 3, 4>>& Ps,
+ Matrix<T, 4, 1>* X) {
int nviews = x.cols();
assert(nviews == Ps.size());
- Matrix<T, Dynamic, Dynamic> design(3*nviews, 4 + nviews);
+ Matrix<T, Dynamic, Dynamic> design(3 * nviews, 4 + nviews);
design.setConstant(0.0);
for (int i = 0; i < nviews; i++) {
- design.template block<3, 4>(3*i, 0) = -Ps[i];
- design(3*i + 0, 4 + i) = x(0, i);
- design(3*i + 1, 4 + i) = x(1, i);
- design(3*i + 2, 4 + i) = 1.0;
+ design.template block<3, 4>(3 * i, 0) = -Ps[i];
+ design(3 * i + 0, 4 + i) = x(0, i);
+ design(3 * i + 1, 4 + i) = x(1, i);
+ design(3 * i + 2, 4 + i) = 1.0;
}
- Matrix<T, Dynamic, 1> X_and_alphas;
+ Matrix<T, Dynamic, 1> X_and_alphas;
Nullspace(&design, &X_and_alphas);
X->resize(4);
*X = X_and_alphas.head(4);
@@ -60,16 +60,16 @@ void NViewTriangulate(const Matrix<T, 2, Dynamic> &x,
// This method uses the algebraic distance approximation.
// Note that this method works better when the 2D points are normalized
// with an isotopic normalization.
-template<typename T>
-void NViewTriangulateAlgebraic(const Matrix<T, 2, Dynamic> &x,
- const vector<Matrix<T, 3, 4> > &Ps,
- Matrix<T, 4, 1> *X) {
+template <typename T>
+void NViewTriangulateAlgebraic(const Matrix<T, 2, Dynamic>& x,
+ const vector<Matrix<T, 3, 4>>& Ps,
+ Matrix<T, 4, 1>* X) {
int nviews = x.cols();
assert(nviews == Ps.size());
- Matrix<T, Dynamic, 4> design(2*nviews, 4);
+ Matrix<T, Dynamic, 4> design(2 * nviews, 4);
for (int i = 0; i < nviews; i++) {
- design.template block<2, 4>(2*i, 0) = SkewMatMinimal(x.col(i)) * Ps[i];
+ design.template block<2, 4>(2 * i, 0) = SkewMatMinimal(x.col(i)) * Ps[i];
}
X->resize(4);
Nullspace(&design, X);
diff --git a/intern/libmv/libmv/multiview/nviewtriangulation_test.cc b/intern/libmv/libmv/multiview/nviewtriangulation_test.cc
index 5a4d8499753..dba5fd07d5c 100644
--- a/intern/libmv/libmv/multiview/nviewtriangulation_test.cc
+++ b/intern/libmv/libmv/multiview/nviewtriangulation_test.cc
@@ -54,7 +54,7 @@ TEST(NViewTriangulate, FiveViews) {
// Check reprojection error. Should be nearly zero.
for (int j = 0; j < nviews; ++j) {
- Vec3 x_reprojected = Ps[j]*X;
+ Vec3 x_reprojected = Ps[j] * X;
x_reprojected /= x_reprojected(2);
double error = (x_reprojected.head(2) - xs.col(j)).norm();
EXPECT_NEAR(error, 0.0, 1e-9);
@@ -84,7 +84,7 @@ TEST(NViewTriangulateAlgebraic, FiveViews) {
// Check reprojection error. Should be nearly zero.
for (int j = 0; j < nviews; ++j) {
- Vec3 x_reprojected = Ps[j]*X;
+ Vec3 x_reprojected = Ps[j] * X;
x_reprojected /= x_reprojected(2);
double error = (x_reprojected.head<2>() - xs.col(j)).norm();
EXPECT_NEAR(error, 0.0, 1e-9);
diff --git a/intern/libmv/libmv/multiview/panography.cc b/intern/libmv/libmv/multiview/panography.cc
index b62802948c4..42b1c19d65e 100644
--- a/intern/libmv/libmv/multiview/panography.cc
+++ b/intern/libmv/libmv/multiview/panography.cc
@@ -24,8 +24,9 @@
namespace libmv {
static bool Build_Minimal2Point_PolynomialFactor(
- const Mat & x1, const Mat & x2,
- double * P) { // P must be a double[4]
+ const Mat& x1,
+ const Mat& x2,
+ double* P) { // P must be a double[4]
assert(2 == x1.rows());
assert(2 == x1.cols());
assert(x1.rows() == x2.rows());
@@ -40,11 +41,11 @@ static bool Build_Minimal2Point_PolynomialFactor(
Vec yx2 = (x2.col(1)).transpose();
double b12 = xx2.dot(yx2);
- double a1 = xx1.squaredNorm();
- double a2 = yx1.squaredNorm();
+ double a1 = xx1.squaredNorm();
+ double a2 = yx1.squaredNorm();
- double b1 = xx2.squaredNorm();
- double b2 = yx2.squaredNorm();
+ double b1 = xx2.squaredNorm();
+ double b2 = yx2.squaredNorm();
// Build the 3rd degre polynomial in F^2.
//
@@ -52,10 +53,12 @@ static bool Build_Minimal2Point_PolynomialFactor(
//
// Coefficients in ascending powers of alpha, i.e. P[N]*x^N.
// Run panography_coeffs.py to get the below coefficients.
- P[0] = b1*b2*a12*a12-a1*a2*b12*b12;
- P[1] = -2*a1*a2*b12+2*a12*b1*b2+b1*a12*a12+b2*a12*a12-a1*b12*b12-a2*b12*b12;
- P[2] = b1*b2-a1*a2-2*a1*b12-2*a2*b12+2*a12*b1+2*a12*b2+a12*a12-b12*b12;
- P[3] = b1+b2-2*b12-a1-a2+2*a12;
+ P[0] = b1 * b2 * a12 * a12 - a1 * a2 * b12 * b12;
+ P[1] = -2 * a1 * a2 * b12 + 2 * a12 * b1 * b2 + b1 * a12 * a12 +
+ b2 * a12 * a12 - a1 * b12 * b12 - a2 * b12 * b12;
+ P[2] = b1 * b2 - a1 * a2 - 2 * a1 * b12 - 2 * a2 * b12 + 2 * a12 * b1 +
+ 2 * a12 * b2 + a12 * a12 - b12 * b12;
+ P[3] = b1 + b2 - 2 * b12 - a1 - a2 + 2 * a12;
// If P[3] equal to 0 we get ill conditionned data
return (P[3] != 0.0);
@@ -67,8 +70,9 @@ static bool Build_Minimal2Point_PolynomialFactor(
//
// [1] M. Brown and R. Hartley and D. Nister. Minimal Solutions for Panoramic
// Stitching. CVPR07.
-void F_FromCorrespondance_2points(const Mat &x1, const Mat &x2,
- vector<double> *fs) {
+void F_FromCorrespondance_2points(const Mat& x1,
+ const Mat& x2,
+ vector<double>* fs) {
// Build Polynomial factor to get squared focal value.
double P[4];
Build_Minimal2Point_PolynomialFactor(x1, x2, &P[0]);
@@ -79,8 +83,8 @@ void F_FromCorrespondance_2points(const Mat &x1, const Mat &x2,
//
double roots[3];
int num_roots = SolveCubicPolynomial(P, roots);
- for (int i = 0; i < num_roots; ++i) {
- if (roots[i] > 0.0) {
+ for (int i = 0; i < num_roots; ++i) {
+ if (roots[i] > 0.0) {
fs->push_back(sqrt(roots[i]));
}
}
@@ -92,17 +96,18 @@ void F_FromCorrespondance_2points(const Mat &x1, const Mat &x2,
// K. Arun,T. Huand and D. Blostein. Least-squares fitting of 2 3-D point
// sets. IEEE Transactions on Pattern Analysis and Machine Intelligence,
// 9:698-700, 1987.
-void GetR_FixedCameraCenter(const Mat &x1, const Mat &x2,
+void GetR_FixedCameraCenter(const Mat& x1,
+ const Mat& x2,
const double focal,
- Mat3 *R) {
+ Mat3* R) {
assert(3 == x1.rows());
assert(2 <= x1.cols());
assert(x1.rows() == x2.rows());
assert(x1.cols() == x2.cols());
// Build simplified K matrix
- Mat3 K(Mat3::Identity() * 1.0/focal);
- K(2, 2)= 1.0;
+ Mat3 K(Mat3::Identity() * 1.0 / focal);
+ K(2, 2) = 1.0;
// Build the correlation matrix; equation (22) in [1].
Mat3 C = Mat3::Zero();
@@ -115,9 +120,9 @@ void GetR_FixedCameraCenter(const Mat &x1, const Mat &x2,
// Solve for rotation. Equations (24) and (25) in [1].
Eigen::JacobiSVD<Mat> svd(C, Eigen::ComputeThinU | Eigen::ComputeThinV);
Mat3 scale = Mat3::Identity();
- scale(2, 2) = ((svd.matrixU() * svd.matrixV().transpose()).determinant() > 0.0)
- ? 1.0
- : -1.0;
+ scale(2, 2) =
+ ((svd.matrixU() * svd.matrixV().transpose()).determinant() > 0.0) ? 1.0
+ : -1.0;
(*R) = svd.matrixU() * scale * svd.matrixV().transpose();
}
diff --git a/intern/libmv/libmv/multiview/panography.h b/intern/libmv/libmv/multiview/panography.h
index 6e87bd71304..5860a34d1fd 100644
--- a/intern/libmv/libmv/multiview/panography.h
+++ b/intern/libmv/libmv/multiview/panography.h
@@ -22,9 +22,9 @@
#ifndef LIBMV_MULTIVIEW_PANOGRAPHY_H
#define LIBMV_MULTIVIEW_PANOGRAPHY_H
+#include "libmv/base/vector.h"
#include "libmv/numeric/numeric.h"
#include "libmv/numeric/poly.h"
-#include "libmv/base/vector.h"
namespace libmv {
@@ -53,8 +53,9 @@ namespace libmv {
// K = [0 f 0]
// [0 0 1]
//
-void F_FromCorrespondance_2points(const Mat &x1, const Mat &x2,
- vector<double> *fs);
+void F_FromCorrespondance_2points(const Mat& x1,
+ const Mat& x2,
+ vector<double>* fs);
// Compute the 3x3 rotation matrix that fits two 3D point clouds in the least
// square sense. The method is from:
@@ -90,9 +91,10 @@ void F_FromCorrespondance_2points(const Mat &x1, const Mat &x2,
//
// R = arg min || X2 - R * x1 ||
//
-void GetR_FixedCameraCenter(const Mat &x1, const Mat &x2,
+void GetR_FixedCameraCenter(const Mat& x1,
+ const Mat& x2,
const double focal,
- Mat3 *R);
+ Mat3* R);
} // namespace libmv
diff --git a/intern/libmv/libmv/multiview/panography_kernel.cc b/intern/libmv/libmv/multiview/panography_kernel.cc
index 8fdc9e79aed..e8ba648e352 100644
--- a/intern/libmv/libmv/multiview/panography_kernel.cc
+++ b/intern/libmv/libmv/multiview/panography_kernel.cc
@@ -25,7 +25,7 @@ namespace libmv {
namespace panography {
namespace kernel {
-void TwoPointSolver::Solve(const Mat &x1, const Mat &x2, vector<Mat3> *Hs) {
+void TwoPointSolver::Solve(const Mat& x1, const Mat& x2, vector<Mat3>* Hs) {
// Solve for the focal lengths.
vector<double> fs;
F_FromCorrespondance_2points(x1, x2, &fs);
@@ -34,7 +34,7 @@ void TwoPointSolver::Solve(const Mat &x1, const Mat &x2, vector<Mat3> *Hs) {
Mat x1h, x2h;
EuclideanToHomogeneous(x1, &x1h);
EuclideanToHomogeneous(x2, &x2h);
- for (int i = 0; i < fs.size(); ++i) {
+ for (int i = 0; i < fs.size(); ++i) {
Mat3 K1 = Mat3::Identity() * fs[i];
K1(2, 2) = 1.0;
diff --git a/intern/libmv/libmv/multiview/panography_kernel.h b/intern/libmv/libmv/multiview/panography_kernel.h
index a6adbd54b20..d50d3ea0789 100644
--- a/intern/libmv/libmv/multiview/panography_kernel.h
+++ b/intern/libmv/libmv/multiview/panography_kernel.h
@@ -23,9 +23,9 @@
#include "libmv/base/vector.h"
#include "libmv/multiview/conditioning.h"
+#include "libmv/multiview/homography_error.h"
#include "libmv/multiview/projection.h"
#include "libmv/multiview/two_view_kernel.h"
-#include "libmv/multiview/homography_error.h"
#include "libmv/numeric/numeric.h"
namespace libmv {
@@ -34,18 +34,18 @@ namespace kernel {
struct TwoPointSolver {
enum { MINIMUM_SAMPLES = 2 };
- static void Solve(const Mat &x1, const Mat &x2, vector<Mat3> *Hs);
+ static void Solve(const Mat& x1, const Mat& x2, vector<Mat3>* Hs);
};
-typedef two_view::kernel::Kernel<
- TwoPointSolver, homography::homography2D::AsymmetricError, Mat3>
- UnnormalizedKernel;
+typedef two_view::kernel::
+ Kernel<TwoPointSolver, homography::homography2D::AsymmetricError, Mat3>
+ UnnormalizedKernel;
typedef two_view::kernel::Kernel<
- two_view::kernel::NormalizedSolver<TwoPointSolver, UnnormalizerI>,
- homography::homography2D::AsymmetricError,
- Mat3>
- Kernel;
+ two_view::kernel::NormalizedSolver<TwoPointSolver, UnnormalizerI>,
+ homography::homography2D::AsymmetricError,
+ Mat3>
+ Kernel;
} // namespace kernel
} // namespace panography
diff --git a/intern/libmv/libmv/multiview/panography_test.cc b/intern/libmv/libmv/multiview/panography_test.cc
index 96d52acfc3c..a7cbd371d40 100644
--- a/intern/libmv/libmv/multiview/panography_test.cc
+++ b/intern/libmv/libmv/multiview/panography_test.cc
@@ -18,8 +18,8 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-#include "libmv/logging/logging.h"
#include "libmv/multiview/panography.h"
+#include "libmv/logging/logging.h"
#include "libmv/multiview/panography_kernel.h"
#include "libmv/multiview/projection.h"
#include "libmv/numeric/numeric.h"
@@ -30,18 +30,16 @@ namespace {
TEST(Panography, PrintSomeSharedFocalEstimationValues) {
Mat x1(2, 2), x2(2, 2);
- x1<< 158, 78,
- 124, 113;
- x2<< 300, 214,
- 125, 114;
+ x1 << 158, 78, 124, 113;
+ x2 << 300, 214, 125, 114;
// Normalize data (set principal point 0,0 and image border to 1.0).
x1.block<1, 2>(0, 0) /= 320;
x1.block<1, 2>(1, 0) /= 240;
x2.block<1, 2>(0, 0) /= 320;
x2.block<1, 2>(1, 0) /= 240;
- x1+=Mat2::Constant(0.5);
- x2+=Mat2::Constant(0.5);
+ x1 += Mat2::Constant(0.5);
+ x2 += Mat2::Constant(0.5);
vector<double> fs;
F_FromCorrespondance_2points(x1, x2, &fs);
@@ -53,9 +51,11 @@ TEST(Panography, PrintSomeSharedFocalEstimationValues) {
TEST(Panography, GetR_FixedCameraCenterWithIdentity) {
Mat x1(3, 3);
+ // clang-format off
x1 << 0.5, 0.6, 0.7,
0.5, 0.5, 0.4,
10.0, 10.0, 10.0;
+ // clang-format on
Mat3 R;
GetR_FixedCameraCenter(x1, x1, 1.0, &R);
@@ -68,16 +68,20 @@ TEST(Panography, Homography_GetR_Test_PitchY30) {
int n = 3;
Mat x1(3, n);
+ // clang-format off
x1 << 0.5, 0.6, 0.7,
0.5, 0.5, 0.4,
10, 10, 10;
+ // clang-format on
Mat x2 = x1;
const double alpha = 30.0 * M_PI / 180.0;
Mat3 rotY;
+ // clang-format off
rotY << cos(alpha), 0, -sin(alpha),
0, 1, 0,
sin(alpha), 0, cos(alpha);
+ // clang-format on
for (int i = 0; i < n; ++i) {
x2.block<3, 1>(0, i) = rotY * x1.col(i);
@@ -101,17 +105,23 @@ TEST(Panography, Homography_GetR_Test_PitchY30) {
TEST(MinimalPanoramic, Real_Case_Kernel) {
const int n = 2;
Mat x1(2, n); // From image 0.jpg
+ // clang-format off
x1<< 158, 78,
124, 113;
+ // clang-format on
Mat x2(2, n); // From image 3.jpg
+ // clang-format off
x2<< 300, 214,
125, 114;
+ // clang-format on
Mat3 Ground_TruthHomography;
+ // clang-format off
Ground_TruthHomography<< 1, 0.02, 129.83,
-0.02, 1.012, 0.07823,
0, 0, 1;
+ // clang-format on
vector<Mat3> Hs;
@@ -130,7 +140,7 @@ TEST(MinimalPanoramic, Real_Case_Kernel) {
// Assert that residuals are small enough
for (int i = 0; i < n; ++i) {
Vec x1p = H * x1h.col(i);
- Vec residuals = x1p/x1p(2) - x2h.col(i);
+ Vec residuals = x1p / x1p(2) - x2h.col(i);
EXPECT_MATRIX_NEAR_ZERO(residuals, 1e-5);
}
}
diff --git a/intern/libmv/libmv/multiview/projection.cc b/intern/libmv/libmv/multiview/projection.cc
index f8bece3de68..001da89e127 100644
--- a/intern/libmv/libmv/multiview/projection.cc
+++ b/intern/libmv/libmv/multiview/projection.cc
@@ -23,13 +23,13 @@
namespace libmv {
-void P_From_KRt(const Mat3 &K, const Mat3 &R, const Vec3 &t, Mat34 *P) {
+void P_From_KRt(const Mat3& K, const Mat3& R, const Vec3& t, Mat34* P) {
P->block<3, 3>(0, 0) = R;
P->col(3) = t;
(*P) = K * (*P);
}
-void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp) {
+void KRt_From_P(const Mat34& P, Mat3* Kp, Mat3* Rp, Vec3* tp) {
// Decompose using the RQ decomposition HZ A4.1.1 pag.579.
Mat3 K = P.block(0, 0, 3, 3);
@@ -44,9 +44,11 @@ void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp) {
c /= l;
s /= l;
Mat3 Qx;
+ // clang-format off
Qx << 1, 0, 0,
0, c, -s,
0, s, c;
+ // clang-format on
K = K * Qx;
Q = Qx.transpose() * Q;
}
@@ -58,9 +60,11 @@ void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp) {
c /= l;
s /= l;
Mat3 Qy;
+ // clang-format off
Qy << c, 0, s,
0, 1, 0,
-s, 0, c;
+ // clang-format on
K = K * Qy;
Q = Qy.transpose() * Q;
}
@@ -72,9 +76,11 @@ void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp) {
c /= l;
s /= l;
Mat3 Qz;
+ // clang-format off
Qz << c, -s, 0,
s, c, 0,
0, 0, 1;
+ // clang-format on
K = K * Qz;
Q = Qz.transpose() * Q;
}
@@ -92,17 +98,21 @@ void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp) {
}
if (K(1, 1) < 0) {
Mat3 S;
+ // clang-format off
S << 1, 0, 0,
0, -1, 0,
0, 0, 1;
+ // clang-format on
K = K * S;
R = S * R;
}
if (K(0, 0) < 0) {
Mat3 S;
+ // clang-format off
S << -1, 0, 0,
0, 1, 0,
0, 0, 1;
+ // clang-format on
K = K * S;
R = S * R;
}
@@ -122,26 +132,30 @@ void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp) {
*tp = t;
}
-void ProjectionShiftPrincipalPoint(const Mat34 &P,
- const Vec2 &principal_point,
- const Vec2 &principal_point_new,
- Mat34 *P_new) {
+void ProjectionShiftPrincipalPoint(const Mat34& P,
+ const Vec2& principal_point,
+ const Vec2& principal_point_new,
+ Mat34* P_new) {
Mat3 T;
+ // clang-format off
T << 1, 0, principal_point_new(0) - principal_point(0),
0, 1, principal_point_new(1) - principal_point(1),
0, 0, 1;
+ // clang-format on
*P_new = T * P;
}
-void ProjectionChangeAspectRatio(const Mat34 &P,
- const Vec2 &principal_point,
+void ProjectionChangeAspectRatio(const Mat34& P,
+ const Vec2& principal_point,
double aspect_ratio,
double aspect_ratio_new,
- Mat34 *P_new) {
+ Mat34* P_new) {
Mat3 T;
+ // clang-format off
T << 1, 0, 0,
0, aspect_ratio_new / aspect_ratio, 0,
0, 0, 1;
+ // clang-format on
Mat34 P_temp;
ProjectionShiftPrincipalPoint(P, principal_point, Vec2(0, 0), &P_temp);
@@ -149,7 +163,7 @@ void ProjectionChangeAspectRatio(const Mat34 &P,
ProjectionShiftPrincipalPoint(P_temp, Vec2(0, 0), principal_point, P_new);
}
-void HomogeneousToEuclidean(const Mat &H, Mat *X) {
+void HomogeneousToEuclidean(const Mat& H, Mat* X) {
int d = H.rows() - 1;
int n = H.cols();
X->resize(d, n);
@@ -161,29 +175,29 @@ void HomogeneousToEuclidean(const Mat &H, Mat *X) {
}
}
-void HomogeneousToEuclidean(const Mat3X &h, Mat2X *e) {
+void HomogeneousToEuclidean(const Mat3X& h, Mat2X* e) {
e->resize(2, h.cols());
e->row(0) = h.row(0).array() / h.row(2).array();
e->row(1) = h.row(1).array() / h.row(2).array();
}
-void HomogeneousToEuclidean(const Mat4X &h, Mat3X *e) {
+void HomogeneousToEuclidean(const Mat4X& h, Mat3X* e) {
e->resize(3, h.cols());
e->row(0) = h.row(0).array() / h.row(3).array();
e->row(1) = h.row(1).array() / h.row(3).array();
e->row(2) = h.row(2).array() / h.row(3).array();
}
-void HomogeneousToEuclidean(const Vec3 &H, Vec2 *X) {
+void HomogeneousToEuclidean(const Vec3& H, Vec2* X) {
double w = H(2);
*X << H(0) / w, H(1) / w;
}
-void HomogeneousToEuclidean(const Vec4 &H, Vec3 *X) {
+void HomogeneousToEuclidean(const Vec4& H, Vec3* X) {
double w = H(3);
*X << H(0) / w, H(1) / w, H(2) / w;
}
-void EuclideanToHomogeneous(const Mat &X, Mat *H) {
+void EuclideanToHomogeneous(const Mat& X, Mat* H) {
int d = X.rows();
int n = X.cols();
H->resize(d + 1, n);
@@ -191,32 +205,32 @@ void EuclideanToHomogeneous(const Mat &X, Mat *H) {
H->row(d).setOnes();
}
-void EuclideanToHomogeneous(const Vec2 &X, Vec3 *H) {
+void EuclideanToHomogeneous(const Vec2& X, Vec3* H) {
*H << X(0), X(1), 1;
}
-void EuclideanToHomogeneous(const Vec3 &X, Vec4 *H) {
+void EuclideanToHomogeneous(const Vec3& X, Vec4* H) {
*H << X(0), X(1), X(2), 1;
}
// TODO(julien) Call conditioning.h/ApplyTransformationToPoints ?
-void EuclideanToNormalizedCamera(const Mat2X &x, const Mat3 &K, Mat2X *n) {
+void EuclideanToNormalizedCamera(const Mat2X& x, const Mat3& K, Mat2X* n) {
Mat3X x_image_h;
EuclideanToHomogeneous(x, &x_image_h);
Mat3X x_camera_h = K.inverse() * x_image_h;
HomogeneousToEuclidean(x_camera_h, n);
}
-void HomogeneousToNormalizedCamera(const Mat3X &x, const Mat3 &K, Mat2X *n) {
+void HomogeneousToNormalizedCamera(const Mat3X& x, const Mat3& K, Mat2X* n) {
Mat3X x_camera_h = K.inverse() * x;
HomogeneousToEuclidean(x_camera_h, n);
}
-double Depth(const Mat3 &R, const Vec3 &t, const Vec3 &X) {
- return (R*X)(2) + t(2);
+double Depth(const Mat3& R, const Vec3& t, const Vec3& X) {
+ return (R * X)(2) + t(2);
}
-double Depth(const Mat3 &R, const Vec3 &t, const Vec4 &X) {
+double Depth(const Mat3& R, const Vec3& t, const Vec4& X) {
Vec3 Xe = X.head<3>() / X(3);
return Depth(R, t, Xe);
}
diff --git a/intern/libmv/libmv/multiview/projection.h b/intern/libmv/libmv/multiview/projection.h
index 8f304f31ec6..ba8fc5d8303 100644
--- a/intern/libmv/libmv/multiview/projection.h
+++ b/intern/libmv/libmv/multiview/projection.h
@@ -25,108 +25,108 @@
namespace libmv {
-void P_From_KRt(const Mat3 &K, const Mat3 &R, const Vec3 &t, Mat34 *P);
-void KRt_From_P(const Mat34 &P, Mat3 *K, Mat3 *R, Vec3 *t);
+void P_From_KRt(const Mat3& K, const Mat3& R, const Vec3& t, Mat34* P);
+void KRt_From_P(const Mat34& P, Mat3* K, Mat3* R, Vec3* t);
// Applies a change of basis to the image coordinates of the projection matrix
// so that the principal point becomes principal_point_new.
-void ProjectionShiftPrincipalPoint(const Mat34 &P,
- const Vec2 &principal_point,
- const Vec2 &principal_point_new,
- Mat34 *P_new);
+void ProjectionShiftPrincipalPoint(const Mat34& P,
+ const Vec2& principal_point,
+ const Vec2& principal_point_new,
+ Mat34* P_new);
// Applies a change of basis to the image coordinates of the projection matrix
// so that the aspect ratio becomes aspect_ratio_new. This is done by
// stretching the y axis. The aspect ratio is defined as the quotient between
// the focal length of the y and the x axis.
-void ProjectionChangeAspectRatio(const Mat34 &P,
- const Vec2 &principal_point,
+void ProjectionChangeAspectRatio(const Mat34& P,
+ const Vec2& principal_point,
double aspect_ratio,
double aspect_ratio_new,
- Mat34 *P_new);
-
-void HomogeneousToEuclidean(const Mat &H, Mat *X);
-void HomogeneousToEuclidean(const Mat3X &h, Mat2X *e);
-void HomogeneousToEuclidean(const Mat4X &h, Mat3X *e);
-void HomogeneousToEuclidean(const Vec3 &H, Vec2 *X);
-void HomogeneousToEuclidean(const Vec4 &H, Vec3 *X);
-inline Vec2 HomogeneousToEuclidean(const Vec3 &h) {
+ Mat34* P_new);
+
+void HomogeneousToEuclidean(const Mat& H, Mat* X);
+void HomogeneousToEuclidean(const Mat3X& h, Mat2X* e);
+void HomogeneousToEuclidean(const Mat4X& h, Mat3X* e);
+void HomogeneousToEuclidean(const Vec3& H, Vec2* X);
+void HomogeneousToEuclidean(const Vec4& H, Vec3* X);
+inline Vec2 HomogeneousToEuclidean(const Vec3& h) {
return h.head<2>() / h(2);
}
-inline Vec3 HomogeneousToEuclidean(const Vec4 &h) {
+inline Vec3 HomogeneousToEuclidean(const Vec4& h) {
return h.head<3>() / h(3);
}
-inline Mat2X HomogeneousToEuclidean(const Mat3X &h) {
+inline Mat2X HomogeneousToEuclidean(const Mat3X& h) {
Mat2X e(2, h.cols());
e.row(0) = h.row(0).array() / h.row(2).array();
e.row(1) = h.row(1).array() / h.row(2).array();
return e;
}
-void EuclideanToHomogeneous(const Mat &X, Mat *H);
-inline Mat3X EuclideanToHomogeneous(const Mat2X &x) {
+void EuclideanToHomogeneous(const Mat& X, Mat* H);
+inline Mat3X EuclideanToHomogeneous(const Mat2X& x) {
Mat3X h(3, x.cols());
h.block(0, 0, 2, x.cols()) = x;
h.row(2).setOnes();
return h;
}
-inline void EuclideanToHomogeneous(const Mat2X &x, Mat3X *h) {
+inline void EuclideanToHomogeneous(const Mat2X& x, Mat3X* h) {
h->resize(3, x.cols());
h->block(0, 0, 2, x.cols()) = x;
h->row(2).setOnes();
}
-inline Mat4X EuclideanToHomogeneous(const Mat3X &x) {
+inline Mat4X EuclideanToHomogeneous(const Mat3X& x) {
Mat4X h(4, x.cols());
h.block(0, 0, 3, x.cols()) = x;
h.row(3).setOnes();
return h;
}
-inline void EuclideanToHomogeneous(const Mat3X &x, Mat4X *h) {
+inline void EuclideanToHomogeneous(const Mat3X& x, Mat4X* h) {
h->resize(4, x.cols());
h->block(0, 0, 3, x.cols()) = x;
h->row(3).setOnes();
}
-void EuclideanToHomogeneous(const Vec2 &X, Vec3 *H);
-void EuclideanToHomogeneous(const Vec3 &X, Vec4 *H);
-inline Vec3 EuclideanToHomogeneous(const Vec2 &x) {
+void EuclideanToHomogeneous(const Vec2& X, Vec3* H);
+void EuclideanToHomogeneous(const Vec3& X, Vec4* H);
+inline Vec3 EuclideanToHomogeneous(const Vec2& x) {
return Vec3(x(0), x(1), 1);
}
-inline Vec4 EuclideanToHomogeneous(const Vec3 &x) {
+inline Vec4 EuclideanToHomogeneous(const Vec3& x) {
return Vec4(x(0), x(1), x(2), 1);
}
// Conversion from image coordinates to normalized camera coordinates
-void EuclideanToNormalizedCamera(const Mat2X &x, const Mat3 &K, Mat2X *n);
-void HomogeneousToNormalizedCamera(const Mat3X &x, const Mat3 &K, Mat2X *n);
+void EuclideanToNormalizedCamera(const Mat2X& x, const Mat3& K, Mat2X* n);
+void HomogeneousToNormalizedCamera(const Mat3X& x, const Mat3& K, Mat2X* n);
-inline Vec2 Project(const Mat34 &P, const Vec3 &X) {
+inline Vec2 Project(const Mat34& P, const Vec3& X) {
Vec4 HX;
HX << X, 1.0;
Vec3 hx = P * HX;
return hx.head<2>() / hx(2);
}
-inline void Project(const Mat34 &P, const Vec4 &X, Vec3 *x) {
+inline void Project(const Mat34& P, const Vec4& X, Vec3* x) {
*x = P * X;
}
-inline void Project(const Mat34 &P, const Vec4 &X, Vec2 *x) {
+inline void Project(const Mat34& P, const Vec4& X, Vec2* x) {
Vec3 hx = P * X;
*x = hx.head<2>() / hx(2);
}
-inline void Project(const Mat34 &P, const Vec3 &X, Vec3 *x) {
+inline void Project(const Mat34& P, const Vec3& X, Vec3* x) {
Vec4 HX;
HX << X, 1.0;
Project(P, HX, x);
}
-inline void Project(const Mat34 &P, const Vec3 &X, Vec2 *x) {
+inline void Project(const Mat34& P, const Vec3& X, Vec2* x) {
Vec3 hx;
Project(P, X, &hx);
*x = hx.head<2>() / hx(2);
}
-inline void Project(const Mat34 &P, const Mat4X &X, Mat2X *x) {
+inline void Project(const Mat34& P, const Mat4X& X, Mat2X* x) {
x->resize(2, X.cols());
for (int c = 0; c < X.cols(); ++c) {
Vec3 hx = P * X.col(c);
@@ -134,13 +134,13 @@ inline void Project(const Mat34 &P, const Mat4X &X, Mat2X *x) {
}
}
-inline Mat2X Project(const Mat34 &P, const Mat4X &X) {
+inline Mat2X Project(const Mat34& P, const Mat4X& X) {
Mat2X x;
Project(P, X, &x);
return x;
}
-inline void Project(const Mat34 &P, const Mat3X &X, Mat2X *x) {
+inline void Project(const Mat34& P, const Mat3X& X, Mat2X* x) {
x->resize(2, X.cols());
for (int c = 0; c < X.cols(); ++c) {
Vec4 HX;
@@ -150,7 +150,7 @@ inline void Project(const Mat34 &P, const Mat3X &X, Mat2X *x) {
}
}
-inline void Project(const Mat34 &P, const Mat3X &X, const Vecu &ids, Mat2X *x) {
+inline void Project(const Mat34& P, const Mat3X& X, const Vecu& ids, Mat2X* x) {
x->resize(2, ids.size());
Vec4 HX;
Vec3 hx;
@@ -161,26 +161,26 @@ inline void Project(const Mat34 &P, const Mat3X &X, const Vecu &ids, Mat2X *x) {
}
}
-inline Mat2X Project(const Mat34 &P, const Mat3X &X) {
+inline Mat2X Project(const Mat34& P, const Mat3X& X) {
Mat2X x(2, X.cols());
Project(P, X, &x);
return x;
}
-inline Mat2X Project(const Mat34 &P, const Mat3X &X, const Vecu &ids) {
+inline Mat2X Project(const Mat34& P, const Mat3X& X, const Vecu& ids) {
Mat2X x(2, ids.size());
Project(P, X, ids, &x);
return x;
}
-double Depth(const Mat3 &R, const Vec3 &t, const Vec3 &X);
-double Depth(const Mat3 &R, const Vec3 &t, const Vec4 &X);
+double Depth(const Mat3& R, const Vec3& t, const Vec3& X);
+double Depth(const Mat3& R, const Vec3& t, const Vec4& X);
/**
-* Returns true if the homogenious 3D point X is in front of
-* the camera P.
-*/
-inline bool isInFrontOfCamera(const Mat34 &P, const Vec4 &X) {
+ * Returns true if the homogenious 3D point X is in front of
+ * the camera P.
+ */
+inline bool isInFrontOfCamera(const Mat34& P, const Vec4& X) {
double condition_1 = P.row(2).dot(X) * X[3];
double condition_2 = X[2] * X[3];
if (condition_1 > 0 && condition_2 > 0)
@@ -189,37 +189,37 @@ inline bool isInFrontOfCamera(const Mat34 &P, const Vec4 &X) {
return false;
}
-inline bool isInFrontOfCamera(const Mat34 &P, const Vec3 &X) {
+inline bool isInFrontOfCamera(const Mat34& P, const Vec3& X) {
Vec4 X_homo;
X_homo.segment<3>(0) = X;
X_homo(3) = 1;
- return isInFrontOfCamera( P, X_homo);
+ return isInFrontOfCamera(P, X_homo);
}
/**
-* Transforms a 2D point from pixel image coordinates to a 2D point in
-* normalized image coordinates.
-*/
-inline Vec2 ImageToNormImageCoordinates(Mat3 &Kinverse, Vec2 &x) {
- Vec3 x_h = Kinverse*EuclideanToHomogeneous(x);
- return HomogeneousToEuclidean( x_h );
+ * Transforms a 2D point from pixel image coordinates to a 2D point in
+ * normalized image coordinates.
+ */
+inline Vec2 ImageToNormImageCoordinates(Mat3& Kinverse, Vec2& x) {
+ Vec3 x_h = Kinverse * EuclideanToHomogeneous(x);
+ return HomogeneousToEuclidean(x_h);
}
/// Estimates the root mean square error (2D)
-inline double RootMeanSquareError(const Mat2X &x_image,
- const Mat4X &X_world,
- const Mat34 &P) {
+inline double RootMeanSquareError(const Mat2X& x_image,
+ const Mat4X& X_world,
+ const Mat34& P) {
size_t num_points = x_image.cols();
Mat2X dx = Project(P, X_world) - x_image;
return dx.norm() / num_points;
}
/// Estimates the root mean square error (2D)
-inline double RootMeanSquareError(const Mat2X &x_image,
- const Mat3X &X_world,
- const Mat3 &K,
- const Mat3 &R,
- const Vec3 &t) {
+inline double RootMeanSquareError(const Mat2X& x_image,
+ const Mat3X& X_world,
+ const Mat3& K,
+ const Mat3& R,
+ const Vec3& t) {
Mat34 P;
P_From_KRt(K, R, t, &P);
size_t num_points = x_image.cols();
diff --git a/intern/libmv/libmv/multiview/projection_test.cc b/intern/libmv/libmv/multiview/projection_test.cc
index 40e766bfae7..683edefa99c 100644
--- a/intern/libmv/libmv/multiview/projection_test.cc
+++ b/intern/libmv/libmv/multiview/projection_test.cc
@@ -29,14 +29,18 @@ using namespace libmv;
TEST(Projection, P_From_KRt) {
Mat3 K, Kp;
+ // clang-format off
K << 10, 1, 30,
0, 20, 40,
0, 0, 1;
+ // clang-format on
Mat3 R, Rp;
+ // clang-format off
R << 1, 0, 0,
0, 1, 0,
0, 0, 1;
+ // clang-format on
Vec3 t, tp;
t << 1, 2, 3;
@@ -62,16 +66,18 @@ Vec4 GetRandomPoint() {
TEST(Projection, isInFrontOfCamera) {
Mat34 P;
+ // clang-format off
P << 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0;
+ // clang-format on
Vec4 X_front = GetRandomPoint();
Vec4 X_back = GetRandomPoint();
- X_front(2) = 10; /* Any point in the positive Z direction
- * where Z > 1 is in front of the camera. */
- X_back(2) = -10; /* Any point in the negative Z direction
- * is behind the camera. */
+ X_front(2) = 10; /* Any point in the positive Z direction
+ * where Z > 1 is in front of the camera. */
+ X_back(2) = -10; /* Any point in the negative Z direction
+ * is behind the camera. */
bool res_front = isInFrontOfCamera(P, X_front);
bool res_back = isInFrontOfCamera(P, X_back);
@@ -82,12 +88,14 @@ TEST(Projection, isInFrontOfCamera) {
TEST(AutoCalibration, ProjectionShiftPrincipalPoint) {
Mat34 P1, P2;
+ // clang-format off
P1 << 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0;
P2 << 1, 0, 3, 0,
0, 1, 4, 0,
0, 0, 1, 0;
+ // clang-format on
Mat34 P1_computed, P2_computed;
ProjectionShiftPrincipalPoint(P1, Vec2(0, 0), Vec2(3, 4), &P2_computed);
ProjectionShiftPrincipalPoint(P2, Vec2(3, 4), Vec2(0, 0), &P1_computed);
@@ -98,12 +106,14 @@ TEST(AutoCalibration, ProjectionShiftPrincipalPoint) {
TEST(AutoCalibration, ProjectionChangeAspectRatio) {
Mat34 P1, P2;
+ // clang-format off
P1 << 1, 0, 3, 0,
0, 1, 4, 0,
0, 0, 1, 0;
P2 << 1, 0, 3, 0,
0, 2, 4, 0,
0, 0, 1, 0;
+ // clang-format on
Mat34 P1_computed, P2_computed;
ProjectionChangeAspectRatio(P1, Vec2(3, 4), 1, 2, &P2_computed);
ProjectionChangeAspectRatio(P2, Vec2(3, 4), 2, 1, &P1_computed);
diff --git a/intern/libmv/libmv/multiview/resection.h b/intern/libmv/libmv/multiview/resection.h
index c142d6deeb2..e543827c932 100644
--- a/intern/libmv/libmv/multiview/resection.h
+++ b/intern/libmv/libmv/multiview/resection.h
@@ -33,23 +33,23 @@ namespace libmv {
namespace resection {
// x's are 2D image coordinates, (x,y,1), and X's are homogeneous four vectors.
-template<typename T>
-void Resection(const Matrix<T, 2, Dynamic> &x,
- const Matrix<T, 4, Dynamic> &X,
- Matrix<T, 3, 4> *P) {
+template <typename T>
+void Resection(const Matrix<T, 2, Dynamic>& x,
+ const Matrix<T, 4, Dynamic>& X,
+ Matrix<T, 3, 4>* P) {
int N = x.cols();
assert(X.cols() == N);
- Matrix<T, Dynamic, 12> design(2*N, 12);
+ Matrix<T, Dynamic, 12> design(2 * N, 12);
design.setZero();
for (int i = 0; i < N; i++) {
T xi = x(0, i);
T yi = x(1, i);
// See equation (7.2) on page 179 of H&Z.
- design.template block<1, 4>(2*i, 4) = -X.col(i).transpose();
- design.template block<1, 4>(2*i, 8) = yi*X.col(i).transpose();
- design.template block<1, 4>(2*i + 1, 0) = X.col(i).transpose();
- design.template block<1, 4>(2*i + 1, 8) = -xi*X.col(i).transpose();
+ design.template block<1, 4>(2 * i, 4) = -X.col(i).transpose();
+ design.template block<1, 4>(2 * i, 8) = yi * X.col(i).transpose();
+ design.template block<1, 4>(2 * i + 1, 0) = X.col(i).transpose();
+ design.template block<1, 4>(2 * i + 1, 8) = -xi * X.col(i).transpose();
}
Matrix<T, 12, 1> p;
Nullspace(&design, &p);
diff --git a/intern/libmv/libmv/multiview/resection_test.cc b/intern/libmv/libmv/multiview/resection_test.cc
index 368e2281cfa..fb075d02d69 100644
--- a/intern/libmv/libmv/multiview/resection_test.cc
+++ b/intern/libmv/libmv/multiview/resection_test.cc
@@ -20,12 +20,12 @@
#include <iostream>
+#include "libmv/logging/logging.h"
#include "libmv/multiview/projection.h"
#include "libmv/multiview/resection.h"
#include "libmv/multiview/test_data_sets.h"
#include "libmv/numeric/numeric.h"
#include "testing/testing.h"
-#include "libmv/logging/logging.h"
namespace {
@@ -40,15 +40,15 @@ TEST(Resection, ThreeViews) {
Mat4X X(4, npoints);
X.block(0, 0, 3, npoints) = d.X;
X.row(3).setOnes();
- const Mat2X &x = d.x[i];
+ const Mat2X& x = d.x[i];
Mat34 P;
Resection(x, X, &P);
Mat34 P_expected = d.P(i);
// Because the P matrices are homogeneous, it is necessary to be tricky
// about the scale factor to make them match.
- P_expected *= 1/P_expected.array().abs().sum();
- P *= 1/P.array().abs().sum();
+ P_expected *= 1 / P_expected.array().abs().sum();
+ P *= 1 / P.array().abs().sum();
if (!((P(0, 0) > 0 && P_expected(0, 0) > 0) ||
(P(0, 0) < 0 && P_expected(0, 0) < 0))) {
P *= -1;
diff --git a/intern/libmv/libmv/multiview/test_data_sets.cc b/intern/libmv/libmv/multiview/test_data_sets.cc
index 110bde6f762..a927c166d19 100644
--- a/intern/libmv/libmv/multiview/test_data_sets.cc
+++ b/intern/libmv/libmv/multiview/test_data_sets.cc
@@ -22,24 +22,28 @@
#include <cmath>
-#include "libmv/numeric/numeric.h"
-#include "libmv/multiview/projection.h"
#include "libmv/multiview/fundamental.h"
+#include "libmv/multiview/projection.h"
+#include "libmv/numeric/numeric.h"
namespace libmv {
TwoViewDataSet TwoRealisticCameras(bool same_K) {
TwoViewDataSet d;
+ // clang-format off
d.K1 << 320, 0, 160,
0, 320, 120,
0, 0, 1;
+ // clang-format on
if (same_K) {
d.K2 = d.K1;
} else {
+ // clang-format off
d.K2 << 360, 0, 170,
0, 360, 110,
0, 0, 1;
+ // clang-format on
}
d.R1 = RotationAroundZ(-0.1);
d.R2 = RotationAroundX(-0.1);
@@ -59,10 +63,8 @@ TwoViewDataSet TwoRealisticCameras(bool same_K) {
return d;
}
-nViewDatasetConfigator::nViewDatasetConfigator(int fx , int fy,
- int cx, int cy,
- double distance,
- double jitter_amount) {
+nViewDatasetConfigator::nViewDatasetConfigator(
+ int fx, int fy, int cx, int cy, double distance, double jitter_amount) {
_fx = fx;
_fy = fy;
_cx = cx;
@@ -71,7 +73,8 @@ nViewDatasetConfigator::nViewDatasetConfigator(int fx , int fy,
_jitter_amount = jitter_amount;
}
-NViewDataSet NRealisticCamerasFull(int nviews, int npoints,
+NViewDataSet NRealisticCamerasFull(int nviews,
+ int npoints,
const nViewDatasetConfigator config) {
NViewDataSet d;
d.n = nviews;
@@ -102,9 +105,11 @@ NViewDataSet NRealisticCamerasFull(int nviews, int npoints,
jitter *= config._jitter_amount / camera_center.norm();
lookdir = -camera_center + jitter;
+ // clang-format off
d.K[i] << config._fx, 0, config._cx,
0, config._fy, config._cy,
0, 0, 1;
+ // clang-format on
d.R[i] = LookAt(lookdir);
d.t[i] = -d.R[i] * camera_center;
d.x[i] = Project(d.P(i), d.X);
@@ -113,9 +118,10 @@ NViewDataSet NRealisticCamerasFull(int nviews, int npoints,
return d;
}
-
-NViewDataSet NRealisticCamerasSparse(int nviews, int npoints,
- float view_ratio, unsigned min_projections,
+NViewDataSet NRealisticCamerasSparse(int nviews,
+ int npoints,
+ float view_ratio,
+ unsigned min_projections,
const nViewDatasetConfigator config) {
assert(view_ratio <= 1.0);
assert(view_ratio > 0.0);
@@ -137,7 +143,7 @@ NViewDataSet NRealisticCamerasSparse(int nviews, int npoints,
visibility.setZero();
Mat randoms(nviews, npoints);
randoms.setRandom();
- randoms = (randoms.array() + 1)/2.0;
+ randoms = (randoms.array() + 1) / 2.0;
unsigned num_visibles = 0;
for (size_t i = 0; i < nviews; ++i) {
num_visibles = 0;
@@ -174,15 +180,17 @@ NViewDataSet NRealisticCamerasSparse(int nviews, int npoints,
jitter *= config._jitter_amount / camera_center.norm();
lookdir = -camera_center + jitter;
+ // clang-format off
d.K[i] << config._fx, 0, config._cx,
0, config._fy, config._cy,
0, 0, 1;
+ // clang-format on
d.R[i] = LookAt(lookdir);
d.t[i] = -d.R[i] * camera_center;
j_visible = 0;
for (size_t j = 0; j < npoints; j++) {
if (visibility(i, j)) {
- X = d.X.col(j);
+ X = d.X.col(j);
d.x[i].col(j_visible) = Project(d.P(i), X);
d.x_ids[i][j_visible] = j;
j_visible++;
@@ -192,5 +200,4 @@ NViewDataSet NRealisticCamerasSparse(int nviews, int npoints,
return d;
}
-
} // namespace libmv
diff --git a/intern/libmv/libmv/multiview/test_data_sets.h b/intern/libmv/libmv/multiview/test_data_sets.h
index cf01663ca02..0c8785728bd 100644
--- a/intern/libmv/libmv/multiview/test_data_sets.h
+++ b/intern/libmv/libmv/multiview/test_data_sets.h
@@ -34,8 +34,8 @@ struct TwoViewDataSet {
Vec3 t1, t2; // Translation.
Mat34 P1, P2; // Projection matrix, P = K(R|t)
Mat3 F; // Fundamental matrix.
- Mat3X X; // 3D points.
- Mat2X x1, x2; // Projected points.
+ Mat3X X; // 3D points.
+ Mat2X x1, x2; // Projected points.
};
// Two cameras at (-1,-1,-10) and (2,1,-10) looking approximately towards z+.
@@ -45,13 +45,13 @@ TwoViewDataSet TwoRealisticCameras(bool same_K = false);
// and the other reconstruction data types is that all points are seen by all
// cameras.
struct NViewDataSet {
- vector<Mat3> K; // Internal parameters (fx, fy, etc).
- vector<Mat3> R; // Rotation.
- vector<Vec3> t; // Translation.
- vector<Vec3> C; // Camera centers.
- Mat3X X; // 3D points.
- vector<Mat2X> x; // Projected points; may have noise added.
- vector<Vecu> x_ids; // Indexes of points corresponding to the projections
+ vector<Mat3> K; // Internal parameters (fx, fy, etc).
+ vector<Mat3> R; // Rotation.
+ vector<Vec3> t; // Translation.
+ vector<Vec3> C; // Camera centers.
+ Mat3X X; // 3D points.
+ vector<Mat2X> x; // Projected points; may have noise added.
+ vector<Vecu> x_ids; // Indexes of points corresponding to the projections
int n; // Actual number of cameras.
@@ -83,22 +83,26 @@ struct nViewDatasetConfigator {
double _dist;
double _jitter_amount;
- nViewDatasetConfigator(int fx = 1000, int fy = 1000,
- int cx = 500, int cy = 500,
+ nViewDatasetConfigator(int fx = 1000,
+ int fy = 1000,
+ int cx = 500,
+ int cy = 500,
double distance = 1.5,
double jitter_amount = 0.01);
};
-NViewDataSet NRealisticCamerasFull(int nviews, int npoints,
- const nViewDatasetConfigator
- config = nViewDatasetConfigator());
+NViewDataSet NRealisticCamerasFull(
+ int nviews,
+ int npoints,
+ const nViewDatasetConfigator config = nViewDatasetConfigator());
// Generates sparse projections (not all points are projected)
-NViewDataSet NRealisticCamerasSparse(int nviews, int npoints,
- float view_ratio = 0.6,
- unsigned min_projections = 3,
- const nViewDatasetConfigator
- config = nViewDatasetConfigator());
+NViewDataSet NRealisticCamerasSparse(
+ int nviews,
+ int npoints,
+ float view_ratio = 0.6,
+ unsigned min_projections = 3,
+ const nViewDatasetConfigator config = nViewDatasetConfigator());
} // namespace libmv
diff --git a/intern/libmv/libmv/multiview/triangulation.cc b/intern/libmv/libmv/multiview/triangulation.cc
index 4d146c8f21b..568625de19d 100644
--- a/intern/libmv/libmv/multiview/triangulation.cc
+++ b/intern/libmv/libmv/multiview/triangulation.cc
@@ -20,15 +20,17 @@
#include "libmv/multiview/triangulation.h"
-#include "libmv/numeric/numeric.h"
#include "libmv/multiview/projection.h"
+#include "libmv/numeric/numeric.h"
namespace libmv {
// HZ 12.2 pag.312
-void TriangulateDLT(const Mat34 &P1, const Vec2 &x1,
- const Mat34 &P2, const Vec2 &x2,
- Vec4 *X_homogeneous) {
+void TriangulateDLT(const Mat34& P1,
+ const Vec2& x1,
+ const Mat34& P2,
+ const Vec2& x2,
+ Vec4* X_homogeneous) {
Mat4 design;
for (int i = 0; i < 4; ++i) {
design(0, i) = x1(0) * P1(2, i) - P1(0, i);
@@ -39,9 +41,11 @@ void TriangulateDLT(const Mat34 &P1, const Vec2 &x1,
Nullspace(&design, X_homogeneous);
}
-void TriangulateDLT(const Mat34 &P1, const Vec2 &x1,
- const Mat34 &P2, const Vec2 &x2,
- Vec3 *X_euclidean) {
+void TriangulateDLT(const Mat34& P1,
+ const Vec2& x1,
+ const Mat34& P2,
+ const Vec2& x2,
+ Vec3* X_euclidean) {
Vec4 X_homogeneous;
TriangulateDLT(P1, x1, P2, x2, &X_homogeneous);
HomogeneousToEuclidean(X_homogeneous, X_euclidean);
diff --git a/intern/libmv/libmv/multiview/triangulation.h b/intern/libmv/libmv/multiview/triangulation.h
index be878890242..c538433eb8b 100644
--- a/intern/libmv/libmv/multiview/triangulation.h
+++ b/intern/libmv/libmv/multiview/triangulation.h
@@ -25,13 +25,17 @@
namespace libmv {
-void TriangulateDLT(const Mat34 &P1, const Vec2 &x1,
- const Mat34 &P2, const Vec2 &x2,
- Vec4 *X_homogeneous);
+void TriangulateDLT(const Mat34& P1,
+ const Vec2& x1,
+ const Mat34& P2,
+ const Vec2& x2,
+ Vec4* X_homogeneous);
-void TriangulateDLT(const Mat34 &P1, const Vec2 &x1,
- const Mat34 &P2, const Vec2 &x2,
- Vec3 *X_euclidean);
+void TriangulateDLT(const Mat34& P1,
+ const Vec2& x1,
+ const Mat34& P2,
+ const Vec2& x2,
+ Vec3* X_euclidean);
} // namespace libmv
diff --git a/intern/libmv/libmv/multiview/triangulation_test.cc b/intern/libmv/libmv/multiview/triangulation_test.cc
index 66d1ee25a62..54d20f4ee17 100644
--- a/intern/libmv/libmv/multiview/triangulation_test.cc
+++ b/intern/libmv/libmv/multiview/triangulation_test.cc
@@ -20,10 +20,10 @@
#include <iostream>
-#include "libmv/multiview/triangulation.h"
#include "libmv/multiview/fundamental.h"
#include "libmv/multiview/projection.h"
#include "libmv/multiview/test_data_sets.h"
+#include "libmv/multiview/triangulation.h"
#include "libmv/numeric/numeric.h"
#include "testing/testing.h"
diff --git a/intern/libmv/libmv/multiview/two_view_kernel.h b/intern/libmv/libmv/multiview/two_view_kernel.h
index 7af0ed5ddab..4df99183ee0 100644
--- a/intern/libmv/libmv/multiview/two_view_kernel.h
+++ b/intern/libmv/libmv/multiview/two_view_kernel.h
@@ -30,10 +30,10 @@ namespace libmv {
namespace two_view {
namespace kernel {
-template<typename Solver, typename Unnormalizer>
+template <typename Solver, typename Unnormalizer>
struct NormalizedSolver {
enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
- static void Solve(const Mat &x1, const Mat &x2, vector<Mat3> *models) {
+ static void Solve(const Mat& x1, const Mat& x2, vector<Mat3>* models) {
assert(2 == x1.rows());
assert(MINIMUM_SAMPLES <= x1.cols());
assert(x1.rows() == x2.rows());
@@ -53,10 +53,10 @@ struct NormalizedSolver {
}
};
-template<typename Solver, typename Unnormalizer>
+template <typename Solver, typename Unnormalizer>
struct IsotropicNormalizedSolver {
enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
- static void Solve(const Mat &x1, const Mat &x2, vector<Mat3> *models) {
+ static void Solve(const Mat& x1, const Mat& x2, vector<Mat3>* models) {
assert(2 == x1.rows());
assert(MINIMUM_SAMPLES <= x1.cols());
assert(x1.rows() == x2.rows());
@@ -99,35 +99,32 @@ struct IsotropicNormalizedSolver {
//
// The fit routine must not clear existing entries in the vector of models; it
// should append new solutions to the end.
-template<typename SolverArg,
- typename ErrorArg,
- typename ModelArg = Mat3>
+template <typename SolverArg, typename ErrorArg, typename ModelArg = Mat3>
class Kernel {
public:
- Kernel(const Mat &x1, const Mat &x2) : x1_(x1), x2_(x2) {}
+ Kernel(const Mat& x1, const Mat& x2) : x1_(x1), x2_(x2) {}
typedef SolverArg Solver;
- typedef ModelArg Model;
+ typedef ModelArg Model;
enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
- void Fit(const vector<int> &samples, vector<Model> *models) const {
+ void Fit(const vector<int>& samples, vector<Model>* models) const {
Mat x1 = ExtractColumns(x1_, samples);
Mat x2 = ExtractColumns(x2_, samples);
Solver::Solve(x1, x2, models);
}
- double Error(int sample, const Model &model) const {
+ double Error(int sample, const Model& model) const {
return ErrorArg::Error(model,
static_cast<Vec>(x1_.col(sample)),
static_cast<Vec>(x2_.col(sample)));
}
- int NumSamples() const {
- return x1_.cols();
- }
- static void Solve(const Mat &x1, const Mat &x2, vector<Model> *models) {
+ int NumSamples() const { return x1_.cols(); }
+ static void Solve(const Mat& x1, const Mat& x2, vector<Model>* models) {
// By offering this, Kernel types can be passed to templates.
Solver::Solve(x1, x2, models);
}
+
protected:
- const Mat &x1_;
- const Mat &x2_;
+ const Mat& x1_;
+ const Mat& x2_;
};
} // namespace kernel
diff --git a/intern/libmv/libmv/numeric/dogleg.h b/intern/libmv/libmv/numeric/dogleg.h
index bf6f996ddaf..62abfbdcd4b 100644
--- a/intern/libmv/libmv/numeric/dogleg.h
+++ b/intern/libmv/libmv/numeric/dogleg.h
@@ -32,18 +32,18 @@
#include <cmath>
#include <cstdio>
-#include "libmv/numeric/numeric.h"
-#include "libmv/numeric/function_derivative.h"
#include "libmv/logging/logging.h"
+#include "libmv/numeric/function_derivative.h"
+#include "libmv/numeric/numeric.h"
namespace libmv {
-template<typename Function,
- typename Jacobian = NumericJacobian<Function>,
- typename Solver = Eigen::PartialPivLU<
- Matrix<typename Function::FMatrixType::RealScalar,
- Function::XMatrixType::RowsAtCompileTime,
- Function::XMatrixType::RowsAtCompileTime> > >
+template <typename Function,
+ typename Jacobian = NumericJacobian<Function>,
+ typename Solver = Eigen::PartialPivLU<
+ Matrix<typename Function::FMatrixType::RealScalar,
+ Function::XMatrixType::RowsAtCompileTime,
+ Function::XMatrixType::RowsAtCompileTime>>>
class Dogleg {
public:
typedef typename Function::XMatrixType::RealScalar Scalar;
@@ -51,10 +51,12 @@ class Dogleg {
typedef typename Function::XMatrixType Parameters;
typedef Matrix<typename Function::FMatrixType::RealScalar,
Function::FMatrixType::RowsAtCompileTime,
- Function::XMatrixType::RowsAtCompileTime> JMatrixType;
+ Function::XMatrixType::RowsAtCompileTime>
+ JMatrixType;
typedef Matrix<typename JMatrixType::RealScalar,
JMatrixType::ColsAtCompileTime,
- JMatrixType::ColsAtCompileTime> AMatrixType;
+ JMatrixType::ColsAtCompileTime>
+ AMatrixType;
enum Status {
RUNNING,
@@ -71,34 +73,38 @@ class Dogleg {
STEEPEST_DESCENT,
};
- Dogleg(const Function &f)
- : f_(f), df_(f) {}
+ Dogleg(const Function& f) : f_(f), df_(f) {}
struct SolverParameters {
SolverParameters()
- : gradient_threshold(1e-16),
- relative_step_threshold(1e-16),
- error_threshold(1e-16),
- initial_trust_radius(1e0),
- max_iterations(500) {}
+ : gradient_threshold(1e-16),
+ relative_step_threshold(1e-16),
+ error_threshold(1e-16),
+ initial_trust_radius(1e0),
+ max_iterations(500) {}
Scalar gradient_threshold; // eps > max(J'*f(x))
Scalar relative_step_threshold; // eps > ||dx|| / ||x||
Scalar error_threshold; // eps > ||f(x)||
Scalar initial_trust_radius; // Initial u for solving normal equations.
- int max_iterations; // Maximum number of solver iterations.
+ int max_iterations; // Maximum number of solver iterations.
};
struct Results {
Scalar error_magnitude; // ||f(x)||
Scalar gradient_magnitude; // ||J'f(x)||
- int iterations;
+ int iterations;
Status status;
};
- Status Update(const Parameters &x, const SolverParameters &params,
- JMatrixType *J, AMatrixType *A, FVec *error, Parameters *g) {
+ Status Update(const Parameters& x,
+ const SolverParameters& params,
+ JMatrixType* J,
+ AMatrixType* A,
+ FVec* error,
+ Parameters* g) {
*J = df_(x);
- // TODO(keir): In the case of m = n, avoid computing A and just do J^-1 directly.
+ // TODO(keir): In the case of m = n, avoid computing A and just do J^-1
+ // directly.
*A = (*J).transpose() * (*J);
*error = f_(x);
*g = (*J).transpose() * *error;
@@ -110,12 +116,12 @@ class Dogleg {
return RUNNING;
}
- Step SolveDoglegDirection(const Parameters &dx_sd,
- const Parameters &dx_gn,
+ Step SolveDoglegDirection(const Parameters& dx_sd,
+ const Parameters& dx_gn,
Scalar radius,
Scalar alpha,
- Parameters *dx_dl,
- Scalar *beta) {
+ Parameters* dx_dl,
+ Scalar* beta) {
Parameters a, b_minus_a;
// Solve for Dogleg step dx_dl.
if (dx_gn.norm() < radius) {
@@ -128,30 +134,29 @@ class Dogleg {
} else {
Parameters a = alpha * dx_sd;
- const Parameters &b = dx_gn;
+ const Parameters& b = dx_gn;
b_minus_a = a - b;
Scalar Mbma2 = b_minus_a.squaredNorm();
Scalar Ma2 = a.squaredNorm();
Scalar c = a.dot(b_minus_a);
- Scalar radius2 = radius*radius;
+ Scalar radius2 = radius * radius;
if (c <= 0) {
- *beta = (-c + sqrt(c*c + Mbma2*(radius2 - Ma2)))/(Mbma2);
+ *beta = (-c + sqrt(c * c + Mbma2 * (radius2 - Ma2))) / (Mbma2);
} else {
- *beta = (radius2 - Ma2) /
- (c + sqrt(c*c + Mbma2*(radius2 - Ma2)));
+ *beta = (radius2 - Ma2) / (c + sqrt(c * c + Mbma2 * (radius2 - Ma2)));
}
- *dx_dl = alpha * dx_sd + (*beta) * (dx_gn - alpha*dx_sd);
+ *dx_dl = alpha * dx_sd + (*beta) * (dx_gn - alpha * dx_sd);
return DOGLEG;
}
}
- Results minimize(Parameters *x_and_min) {
+ Results minimize(Parameters* x_and_min) {
SolverParameters params;
return minimize(params, x_and_min);
}
- Results minimize(const SolverParameters &params, Parameters *x_and_min) {
- Parameters &x = *x_and_min;
+ Results minimize(const SolverParameters& params, Parameters* x_and_min) {
+ Parameters& x = *x_and_min;
JMatrixType J;
AMatrixType A;
FVec error;
@@ -167,18 +172,21 @@ class Dogleg {
Parameters dx_sd; // Steepest descent step.
Parameters dx_dl; // Dogleg step.
Parameters dx_gn; // Gauss-Newton step.
- printf("iteration ||f(x)|| max(g) radius\n");
+ printf("iteration ||f(x)|| max(g) radius\n");
int i = 0;
for (; results.status == RUNNING && i < params.max_iterations; ++i) {
printf("%9d %12g %12g %12g",
- i, f_(x).norm(), g.array().abs().maxCoeff(), radius);
+ i,
+ f_(x).norm(),
+ g.array().abs().maxCoeff(),
+ radius);
- //LG << "iteration: " << i;
- //LG << "||f(x)||: " << f_(x).norm();
- //LG << "max(g): " << g.cwise().abs().maxCoeff();
- //LG << "radius: " << radius;
+ // LG << "iteration: " << i;
+ // LG << "||f(x)||: " << f_(x).norm();
+ // LG << "max(g): " << g.cwise().abs().maxCoeff();
+ // LG << "radius: " << radius;
// Eqn 3.19 from [1]
- Scalar alpha = g.squaredNorm() / (J*g).squaredNorm();
+ Scalar alpha = g.squaredNorm() / (J * g).squaredNorm();
// Solve for steepest descent direction dx_sd.
dx_sd = -g;
@@ -199,11 +207,11 @@ class Dogleg {
// Solve for dogleg direction dx_dl.
Scalar beta = 0;
- Step step = SolveDoglegDirection(dx_sd, dx_gn, radius, alpha,
- &dx_dl, &beta);
+ Step step =
+ SolveDoglegDirection(dx_sd, dx_gn, radius, alpha, &dx_dl, &beta);
Scalar e3 = params.relative_step_threshold;
- if (dx_dl.norm() < e3*(x.norm() + e3)) {
+ if (dx_dl.norm() < e3 * (x.norm() + e3)) {
results.status = RELATIVE_STEP_SIZE_TOO_SMALL;
break;
}
@@ -214,16 +222,19 @@ class Dogleg {
if (step == GAUSS_NEWTON) {
predicted = f_(x).squaredNorm();
} else if (step == STEEPEST_DESCENT) {
- predicted = radius * (2*alpha*g.norm() - radius) / 2 / alpha;
+ predicted = radius * (2 * alpha * g.norm() - radius) / 2 / alpha;
} else if (step == DOGLEG) {
- predicted = 0.5 * alpha * (1-beta)*(1-beta)*g.squaredNorm() +
- beta*(2-beta)*f_(x).squaredNorm();
+ predicted = 0.5 * alpha * (1 - beta) * (1 - beta) * g.squaredNorm() +
+ beta * (2 - beta) * f_(x).squaredNorm();
}
Scalar rho = actual / predicted;
- if (step == GAUSS_NEWTON) printf(" GAUSS");
- if (step == STEEPEST_DESCENT) printf(" STEE");
- if (step == DOGLEG) printf(" DOGL");
+ if (step == GAUSS_NEWTON)
+ printf(" GAUSS");
+ if (step == STEEPEST_DESCENT)
+ printf(" STEE");
+ if (step == DOGLEG)
+ printf(" DOGL");
printf(" %12g %12g %12g\n", rho, actual, predicted);
@@ -234,7 +245,7 @@ class Dogleg {
x_updated = true;
}
if (rho > 0.75) {
- radius = std::max(radius, 3*dx_dl.norm());
+ radius = std::max(radius, 3 * dx_dl.norm());
} else if (rho < 0.25) {
radius /= 2;
if (radius < e3 * (x.norm() + e3)) {
@@ -252,10 +263,10 @@ class Dogleg {
}
private:
- const Function &f_;
+ const Function& f_;
Jacobian df_;
};
-} // namespace mv
+} // namespace libmv
#endif // LIBMV_NUMERIC_DOGLEG_H
diff --git a/intern/libmv/libmv/numeric/dogleg_test.cc b/intern/libmv/libmv/numeric/dogleg_test.cc
index 90c46c31672..a5ab1957632 100644
--- a/intern/libmv/libmv/numeric/dogleg_test.cc
+++ b/intern/libmv/libmv/numeric/dogleg_test.cc
@@ -18,8 +18,8 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-#include "testing/testing.h"
#include "libmv/numeric/dogleg.h"
+#include "testing/testing.h"
using namespace libmv;
@@ -29,26 +29,26 @@ class F {
public:
typedef Vec4 FMatrixType;
typedef Vec3 XMatrixType;
- Vec4 operator()(const Vec3 &x) const {
+ Vec4 operator()(const Vec3& x) const {
double x1 = x.x() - 2;
double y1 = x.y() - 5;
double z1 = x.z();
- Vec4 fx; fx << x1*x1 + z1*z1,
- y1*y1 + z1*z1,
- z1*z1,
- x1*x1;
+ Vec4 fx;
+ fx << x1 * x1 + z1 * z1, y1 * y1 + z1 * z1, z1 * z1, x1 * x1;
return fx;
}
};
TEST(Dogleg, SimpleCase) {
- Vec3 x; x << 0.76026643, -30.01799744, 0.55192142;
+ Vec3 x;
+ x << 0.76026643, -30.01799744, 0.55192142;
F f;
Dogleg<F>::SolverParameters params;
Dogleg<F> lm(f);
/* TODO(sergey): Better error handling. */
/* Dogleg<F>::Results results = */ lm.minimize(params, &x);
- Vec3 expected_min_x; expected_min_x << 2, 5, 0;
+ Vec3 expected_min_x;
+ expected_min_x << 2, 5, 0;
EXPECT_MATRIX_NEAR(expected_min_x, x, 1e-5);
}
@@ -59,20 +59,21 @@ class F32 {
public:
typedef Vec2 FMatrixType;
typedef Vec2 XMatrixType;
- Vec2 operator()(const Vec2 &x) const {
+ Vec2 operator()(const Vec2& x) const {
double x1 = x(0);
- double x2 = 10*x(0)/(x(0) + 0.1) + 2*x(1)*x(1);
- Vec2 fx; fx << x1, x2;
+ double x2 = 10 * x(0) / (x(0) + 0.1) + 2 * x(1) * x(1);
+ Vec2 fx;
+ fx << x1, x2;
return fx;
}
};
class JF32 {
public:
- JF32(const F32 &f) { (void) f; }
- Mat2 operator()(const Vec2 &x) {
- Mat2 J; J << 1, 0,
- 1./pow(x(0) + 0.1, 2), 4*x(1)*x(1);
+ JF32(const F32& f) { (void)f; }
+ Mat2 operator()(const Vec2& x) {
+ Mat2 J;
+ J << 1, 0, 1. / pow(x(0) + 0.1, 2), 4 * x(1) * x(1);
return J;
}
};
diff --git a/intern/libmv/libmv/numeric/function_derivative.h b/intern/libmv/libmv/numeric/function_derivative.h
index 9820885f04e..30d7c4d34e9 100644
--- a/intern/libmv/libmv/numeric/function_derivative.h
+++ b/intern/libmv/libmv/numeric/function_derivative.h
@@ -23,8 +23,8 @@
#include <cmath>
-#include "libmv/numeric/numeric.h"
#include "libmv/logging/logging.h"
+#include "libmv/numeric/numeric.h"
namespace libmv {
@@ -36,7 +36,7 @@ enum NumericJacobianMode {
FORWARD,
};
-template<typename Function, NumericJacobianMode mode = CENTRAL>
+template <typename Function, NumericJacobianMode mode = CENTRAL>
class NumericJacobian {
public:
typedef typename Function::XMatrixType Parameters;
@@ -45,12 +45,12 @@ class NumericJacobian {
typedef Matrix<typename Function::FMatrixType::RealScalar,
Function::FMatrixType::RowsAtCompileTime,
Function::XMatrixType::RowsAtCompileTime>
- JMatrixType;
+ JMatrixType;
- NumericJacobian(const Function &f) : f_(f) {}
+ NumericJacobian(const Function& f) : f_(f) {}
// TODO(keir): Perhaps passing the jacobian back by value is not a good idea.
- JMatrixType operator()(const Parameters &x) {
+ JMatrixType operator()(const Parameters& x) {
// Empirically determined constant.
Parameters eps = x.array().abs() * XScalar(1e-5);
// To handle cases where a paremeter is exactly zero, instead use the mean
@@ -87,12 +87,13 @@ class NumericJacobian {
}
return jacobian;
}
+
private:
- const Function &f_;
+ const Function& f_;
};
-template<typename Function, typename Jacobian>
-bool CheckJacobian(const Function &f, const typename Function::XMatrixType &x) {
+template <typename Function, typename Jacobian>
+bool CheckJacobian(const Function& f, const typename Function::XMatrixType& x) {
Jacobian j_analytic(f);
NumericJacobian<Function> j_numeric(f);
diff --git a/intern/libmv/libmv/numeric/function_derivative_test.cc b/intern/libmv/libmv/numeric/function_derivative_test.cc
index 8d976d3e9a0..defeedaa8a4 100644
--- a/intern/libmv/libmv/numeric/function_derivative_test.cc
+++ b/intern/libmv/libmv/numeric/function_derivative_test.cc
@@ -18,9 +18,9 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-#include "testing/testing.h"
-#include "libmv/numeric/numeric.h"
#include "libmv/numeric/function_derivative.h"
+#include "libmv/numeric/numeric.h"
+#include "testing/testing.h"
using namespace libmv;
@@ -30,22 +30,22 @@ class F {
public:
typedef Vec2 FMatrixType;
typedef Vec3 XMatrixType;
- Vec2 operator()(const Vec3 &x) const {
+ Vec2 operator()(const Vec3& x) const {
Vec2 fx;
- fx << 0.19*x(0) + 0.19*x(1)*x(1) + x(2),
- 3*sin(x(0)) + 2*cos(x(1));
+ fx << 0.19 * x(0) + 0.19 * x(1) * x(1) + x(2),
+ 3 * sin(x(0)) + 2 * cos(x(1));
return fx;
}
- Mat23 J(const Vec3 &x) const {
+ Mat23 J(const Vec3& x) const {
Mat23 jacobian;
- jacobian << 0.19, 2*0.19*x(1), 1.0,
- 3*cos(x(0)), -2*sin(x(1)), 0;
+ jacobian << 0.19, 2 * 0.19 * x(1), 1.0, 3 * cos(x(0)), -2 * sin(x(1)), 0;
return jacobian;
}
};
TEST(FunctionDerivative, SimpleCase) {
- Vec3 x; x << 0.76026643, 0.01799744, 0.55192142;
+ Vec3 x;
+ x << 0.76026643, 0.01799744, 0.55192142;
F f;
NumericJacobian<F, CENTRAL> J(f);
EXPECT_MATRIX_NEAR(f.J(x), J(x), 1e-8);
diff --git a/intern/libmv/libmv/numeric/levenberg_marquardt.h b/intern/libmv/libmv/numeric/levenberg_marquardt.h
index 2af9a62cf7b..30c04a5ad5c 100644
--- a/intern/libmv/libmv/numeric/levenberg_marquardt.h
+++ b/intern/libmv/libmv/numeric/levenberg_marquardt.h
@@ -31,18 +31,18 @@
#include <cmath>
-#include "libmv/numeric/numeric.h"
-#include "libmv/numeric/function_derivative.h"
#include "libmv/logging/logging.h"
+#include "libmv/numeric/function_derivative.h"
+#include "libmv/numeric/numeric.h"
namespace libmv {
-template<typename Function,
- typename Jacobian = NumericJacobian<Function>,
- typename Solver = Eigen::PartialPivLU<
- Matrix<typename Function::FMatrixType::RealScalar,
- Function::XMatrixType::RowsAtCompileTime,
- Function::XMatrixType::RowsAtCompileTime> > >
+template <typename Function,
+ typename Jacobian = NumericJacobian<Function>,
+ typename Solver = Eigen::PartialPivLU<
+ Matrix<typename Function::FMatrixType::RealScalar,
+ Function::XMatrixType::RowsAtCompileTime,
+ Function::XMatrixType::RowsAtCompileTime>>>
class LevenbergMarquardt {
public:
typedef typename Function::XMatrixType::RealScalar Scalar;
@@ -50,10 +50,12 @@ class LevenbergMarquardt {
typedef typename Function::XMatrixType Parameters;
typedef Matrix<typename Function::FMatrixType::RealScalar,
Function::FMatrixType::RowsAtCompileTime,
- Function::XMatrixType::RowsAtCompileTime> JMatrixType;
+ Function::XMatrixType::RowsAtCompileTime>
+ JMatrixType;
typedef Matrix<typename JMatrixType::RealScalar,
JMatrixType::ColsAtCompileTime,
- JMatrixType::ColsAtCompileTime> AMatrixType;
+ JMatrixType::ColsAtCompileTime>
+ AMatrixType;
// TODO(keir): Some of these knobs can be derived from each other and
// removed, instead of requiring the user to set them.
@@ -65,32 +67,35 @@ class LevenbergMarquardt {
HIT_MAX_ITERATIONS,
};
- LevenbergMarquardt(const Function &f)
- : f_(f), df_(f) {}
+ LevenbergMarquardt(const Function& f) : f_(f), df_(f) {}
struct SolverParameters {
SolverParameters()
- : gradient_threshold(1e-16),
- relative_step_threshold(1e-16),
- error_threshold(1e-16),
- initial_scale_factor(1e-3),
- max_iterations(100) {}
+ : gradient_threshold(1e-16),
+ relative_step_threshold(1e-16),
+ error_threshold(1e-16),
+ initial_scale_factor(1e-3),
+ max_iterations(100) {}
Scalar gradient_threshold; // eps > max(J'*f(x))
Scalar relative_step_threshold; // eps > ||dx|| / ||x||
Scalar error_threshold; // eps > ||f(x)||
Scalar initial_scale_factor; // Initial u for solving normal equations.
- int max_iterations; // Maximum number of solver iterations.
+ int max_iterations; // Maximum number of solver iterations.
};
struct Results {
Scalar error_magnitude; // ||f(x)||
Scalar gradient_magnitude; // ||J'f(x)||
- int iterations;
+ int iterations;
Status status;
};
- Status Update(const Parameters &x, const SolverParameters &params,
- JMatrixType *J, AMatrixType *A, FVec *error, Parameters *g) {
+ Status Update(const Parameters& x,
+ const SolverParameters& params,
+ JMatrixType* J,
+ AMatrixType* A,
+ FVec* error,
+ Parameters* g) {
*J = df_(x);
*A = (*J).transpose() * (*J);
*error = -f_(x);
@@ -103,13 +108,13 @@ class LevenbergMarquardt {
return RUNNING;
}
- Results minimize(Parameters *x_and_min) {
+ Results minimize(Parameters* x_and_min) {
SolverParameters params;
minimize(params, x_and_min);
}
- Results minimize(const SolverParameters &params, Parameters *x_and_min) {
- Parameters &x = *x_and_min;
+ Results minimize(const SolverParameters& params, Parameters* x_and_min) {
+ Parameters& x = *x_and_min;
JMatrixType J;
AMatrixType A;
FVec error;
@@ -118,7 +123,7 @@ class LevenbergMarquardt {
Results results;
results.status = Update(x, params, &J, &A, &error, &g);
- Scalar u = Scalar(params.initial_scale_factor*A.diagonal().maxCoeff());
+ Scalar u = Scalar(params.initial_scale_factor * A.diagonal().maxCoeff());
Scalar v = 2;
Parameters dx, x_new;
@@ -130,7 +135,8 @@ class LevenbergMarquardt {
VLOG(3) << "u: " << u;
VLOG(3) << "v: " << v;
- AMatrixType A_augmented = A + u*AMatrixType::Identity(J.cols(), J.cols());
+ AMatrixType A_augmented =
+ A + u * AMatrixType::Identity(J.cols(), J.cols());
Solver solver(A_augmented);
dx = solver.solve(g);
bool solved = (A_augmented * dx).isApprox(g);
@@ -146,14 +152,14 @@ class LevenbergMarquardt {
// Rho is the ratio of the actual reduction in error to the reduction
// in error that would be obtained if the problem was linear.
// See [1] for details.
- Scalar rho((error.squaredNorm() - f_(x_new).squaredNorm())
- / dx.dot(u*dx + g));
+ Scalar rho((error.squaredNorm() - f_(x_new).squaredNorm()) /
+ dx.dot(u * dx + g));
if (rho > 0) {
// Accept the Gauss-Newton step because the linear model fits well.
x = x_new;
results.status = Update(x, params, &J, &A, &error, &g);
- Scalar tmp = Scalar(2*rho-1);
- u = u*std::max(1/3., 1 - (tmp*tmp*tmp));
+ Scalar tmp = Scalar(2 * rho - 1);
+ u = u * std::max(1 / 3., 1 - (tmp * tmp * tmp));
v = 2;
continue;
}
@@ -174,10 +180,10 @@ class LevenbergMarquardt {
}
private:
- const Function &f_;
+ const Function& f_;
Jacobian df_;
};
-} // namespace mv
+} // namespace libmv
#endif // LIBMV_NUMERIC_LEVENBERG_MARQUARDT_H
diff --git a/intern/libmv/libmv/numeric/levenberg_marquardt_test.cc b/intern/libmv/libmv/numeric/levenberg_marquardt_test.cc
index fc3f9ebbb29..805aac275b4 100644
--- a/intern/libmv/libmv/numeric/levenberg_marquardt_test.cc
+++ b/intern/libmv/libmv/numeric/levenberg_marquardt_test.cc
@@ -18,8 +18,8 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-#include "testing/testing.h"
#include "libmv/numeric/levenberg_marquardt.h"
+#include "testing/testing.h"
using namespace libmv;
@@ -29,14 +29,12 @@ class F {
public:
typedef Vec4 FMatrixType;
typedef Vec3 XMatrixType;
- Vec4 operator()(const Vec3 &x) const {
+ Vec4 operator()(const Vec3& x) const {
double x1 = x.x() - 2;
double y1 = x.y() - 5;
double z1 = x.z();
- Vec4 fx; fx << x1*x1 + z1*z1,
- y1*y1 + z1*z1,
- z1*z1,
- x1*x1;
+ Vec4 fx;
+ fx << x1 * x1 + z1 * z1, y1 * y1 + z1 * z1, z1 * z1, x1 * x1;
return fx;
}
};
diff --git a/intern/libmv/libmv/numeric/numeric.cc b/intern/libmv/libmv/numeric/numeric.cc
index 3fc1e3b2bfd..b7660950c2a 100644
--- a/intern/libmv/libmv/numeric/numeric.cc
+++ b/intern/libmv/libmv/numeric/numeric.cc
@@ -18,7 +18,6 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-
#include "libmv/numeric/numeric.h"
namespace libmv {
@@ -27,9 +26,11 @@ Mat3 RotationAroundX(double angle) {
double c, s;
sincos(angle, &s, &c);
Mat3 R;
+ // clang-format off
R << 1, 0, 0,
0, c, -s,
0, s, c;
+ // clang-format on
return R;
}
@@ -37,9 +38,11 @@ Mat3 RotationAroundY(double angle) {
double c, s;
sincos(angle, &s, &c);
Mat3 R;
+ // clang-format off
R << c, 0, s,
0, 1, 0,
-s, 0, c;
+ // clang-format on
return R;
}
@@ -47,14 +50,15 @@ Mat3 RotationAroundZ(double angle) {
double c, s;
sincos(angle, &s, &c);
Mat3 R;
+ // clang-format off
R << c, -s, 0,
s, c, 0,
0, 0, 1;
+ // clang-format on
return R;
}
-
-Mat3 RotationRodrigues(const Vec3 &axis) {
+Mat3 RotationRodrigues(const Vec3& axis) {
double theta = axis.norm();
Vec3 w = axis / theta;
Mat3 W = CrossProductMatrix(w);
@@ -62,7 +66,6 @@ Mat3 RotationRodrigues(const Vec3 &axis) {
return Mat3::Identity() + sin(theta) * W + (1 - cos(theta)) * W * W;
}
-
Mat3 LookAt(Vec3 center) {
Vec3 zc = center.normalized();
Vec3 xc = Vec3::UnitY().cross(zc).normalized();
@@ -74,19 +77,21 @@ Mat3 LookAt(Vec3 center) {
return R;
}
-Mat3 CrossProductMatrix(const Vec3 &x) {
+Mat3 CrossProductMatrix(const Vec3& x) {
Mat3 X;
+ // clang-format off
X << 0, -x(2), x(1),
x(2), 0, -x(0),
-x(1), x(0), 0;
+ // clang-format on
return X;
}
-void MeanAndVarianceAlongRows(const Mat &A,
- Vec *mean_pointer,
- Vec *variance_pointer) {
- Vec &mean = *mean_pointer;
- Vec &variance = *variance_pointer;
+void MeanAndVarianceAlongRows(const Mat& A,
+ Vec* mean_pointer,
+ Vec* variance_pointer) {
+ Vec& mean = *mean_pointer;
+ Vec& variance = *variance_pointer;
int n = A.rows();
int m = A.cols();
mean.resize(n);
@@ -108,29 +113,28 @@ void MeanAndVarianceAlongRows(const Mat &A,
}
}
-void HorizontalStack(const Mat &left, const Mat &right, Mat *stacked) {
+void HorizontalStack(const Mat& left, const Mat& right, Mat* stacked) {
assert(left.rows() == right.rows());
int n = left.rows();
int m1 = left.cols();
int m2 = right.cols();
stacked->resize(n, m1 + m2);
- stacked->block(0, 0, n, m1) = left;
+ stacked->block(0, 0, n, m1) = left;
stacked->block(0, m1, n, m2) = right;
}
-void MatrixColumn(const Mat &A, int i, Vec2 *v) {
+void MatrixColumn(const Mat& A, int i, Vec2* v) {
assert(A.rows() == 2);
*v << A(0, i), A(1, i);
}
-void MatrixColumn(const Mat &A, int i, Vec3 *v) {
+void MatrixColumn(const Mat& A, int i, Vec3* v) {
assert(A.rows() == 3);
*v << A(0, i), A(1, i), A(2, i);
}
-void MatrixColumn(const Mat &A, int i, Vec4 *v) {
+void MatrixColumn(const Mat& A, int i, Vec4* v) {
assert(A.rows() == 4);
*v << A(0, i), A(1, i), A(2, i), A(3, i);
}
} // namespace libmv
-
diff --git a/intern/libmv/libmv/numeric/numeric.h b/intern/libmv/libmv/numeric/numeric.h
index f5478bee6ab..e3d44226338 100644
--- a/intern/libmv/libmv/numeric/numeric.h
+++ b/intern/libmv/libmv/numeric/numeric.h
@@ -34,10 +34,9 @@
#include <Eigen/SVD>
#if !defined(__MINGW64__)
-# if defined(_WIN32) || defined(__APPLE__) || \
- defined(__FreeBSD__) || defined(__NetBSD__) || \
- defined(__HAIKU__)
-inline void sincos(double x, double *sinx, double *cosx) {
+# if defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__) || \
+ defined(__NetBSD__) || defined(__HAIKU__)
+inline void sincos(double x, double* sinx, double* cosx) {
*sinx = sin(x);
*cosx = cos(x);
}
@@ -46,11 +45,11 @@ inline void sincos(double x, double *sinx, double *cosx) {
#if (defined(WIN32) || defined(WIN64)) && !defined(__MINGW32__)
inline long lround(double d) {
- return (long)(d>0 ? d+0.5 : ceil(d-0.5));
+ return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
}
# if _MSC_VER < 1800
inline int round(double d) {
- return (d>0) ? int(d+0.5) : int(d-0.5);
+ return (d > 0) ? int(d + 0.5) : int(d - 0.5);
}
# endif // _MSC_VER < 1800
typedef unsigned int uint;
@@ -92,25 +91,25 @@ typedef Eigen::Matrix<double, 4, 4, Eigen::RowMajor> RMat4;
typedef Eigen::Matrix<double, 2, Eigen::Dynamic> Mat2X;
typedef Eigen::Matrix<double, 3, Eigen::Dynamic> Mat3X;
typedef Eigen::Matrix<double, 4, Eigen::Dynamic> Mat4X;
-typedef Eigen::Matrix<double, Eigen::Dynamic, 2> MatX2;
-typedef Eigen::Matrix<double, Eigen::Dynamic, 3> MatX3;
-typedef Eigen::Matrix<double, Eigen::Dynamic, 4> MatX4;
-typedef Eigen::Matrix<double, Eigen::Dynamic, 5> MatX5;
-typedef Eigen::Matrix<double, Eigen::Dynamic, 6> MatX6;
-typedef Eigen::Matrix<double, Eigen::Dynamic, 7> MatX7;
-typedef Eigen::Matrix<double, Eigen::Dynamic, 8> MatX8;
-typedef Eigen::Matrix<double, Eigen::Dynamic, 9> MatX9;
+typedef Eigen::Matrix<double, Eigen::Dynamic, 2> MatX2;
+typedef Eigen::Matrix<double, Eigen::Dynamic, 3> MatX3;
+typedef Eigen::Matrix<double, Eigen::Dynamic, 4> MatX4;
+typedef Eigen::Matrix<double, Eigen::Dynamic, 5> MatX5;
+typedef Eigen::Matrix<double, Eigen::Dynamic, 6> MatX6;
+typedef Eigen::Matrix<double, Eigen::Dynamic, 7> MatX7;
+typedef Eigen::Matrix<double, Eigen::Dynamic, 8> MatX8;
+typedef Eigen::Matrix<double, Eigen::Dynamic, 9> MatX9;
typedef Eigen::Matrix<double, Eigen::Dynamic, 15> MatX15;
typedef Eigen::Matrix<double, Eigen::Dynamic, 16> MatX16;
typedef Eigen::Vector2d Vec2;
typedef Eigen::Vector3d Vec3;
typedef Eigen::Vector4d Vec4;
-typedef Eigen::Matrix<double, 5, 1> Vec5;
-typedef Eigen::Matrix<double, 6, 1> Vec6;
-typedef Eigen::Matrix<double, 7, 1> Vec7;
-typedef Eigen::Matrix<double, 8, 1> Vec8;
-typedef Eigen::Matrix<double, 9, 1> Vec9;
+typedef Eigen::Matrix<double, 5, 1> Vec5;
+typedef Eigen::Matrix<double, 6, 1> Vec6;
+typedef Eigen::Matrix<double, 7, 1> Vec7;
+typedef Eigen::Matrix<double, 8, 1> Vec8;
+typedef Eigen::Matrix<double, 9, 1> Vec9;
typedef Eigen::Matrix<double, 10, 1> Vec10;
typedef Eigen::Matrix<double, 11, 1> Vec11;
typedef Eigen::Matrix<double, 12, 1> Vec12;
@@ -133,15 +132,13 @@ typedef Eigen::Vector2i Vec2i;
typedef Eigen::Vector3i Vec3i;
typedef Eigen::Vector4i Vec4i;
-typedef Eigen::Matrix<float,
- Eigen::Dynamic,
- Eigen::Dynamic,
- Eigen::RowMajor> RMatf;
+typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
+ RMatf;
typedef Eigen::NumTraits<double> EigenDouble;
-using Eigen::Map;
using Eigen::Dynamic;
+using Eigen::Map;
using Eigen::Matrix;
// Find U, s, and VT such that
@@ -149,7 +146,7 @@ using Eigen::Matrix;
// A = U * diag(s) * VT
//
template <typename TMat, typename TVec>
-inline void SVD(TMat * /*A*/, Vec * /*s*/, Mat * /*U*/, Mat * /*VT*/) {
+inline void SVD(TMat* /*A*/, Vec* /*s*/, Mat* /*U*/, Mat* /*VT*/) {
assert(0);
}
@@ -158,11 +155,11 @@ inline void SVD(TMat * /*A*/, Vec * /*s*/, Mat * /*U*/, Mat * /*VT*/) {
// Destroys A and resizes x if necessary.
// TODO(maclean): Take the SVD of the transpose instead of this zero padding.
template <typename TMat, typename TVec>
-double Nullspace(TMat *A, TVec *nullspace) {
+double Nullspace(TMat* A, TVec* nullspace) {
Eigen::JacobiSVD<TMat> svd(*A, Eigen::ComputeFullV);
- (*nullspace) = svd.matrixV().col(A->cols()-1);
+ (*nullspace) = svd.matrixV().col(A->cols() - 1);
if (A->rows() >= A->cols())
- return svd.singularValues()(A->cols()-1);
+ return svd.singularValues()(A->cols() - 1);
else
return 0.0;
}
@@ -173,55 +170,55 @@ double Nullspace(TMat *A, TVec *nullspace) {
// the singluar value corresponding to the solution x1. Destroys A and resizes
// x if necessary.
template <typename TMat, typename TVec1, typename TVec2>
-double Nullspace2(TMat *A, TVec1 *x1, TVec2 *x2) {
+double Nullspace2(TMat* A, TVec1* x1, TVec2* x2) {
Eigen::JacobiSVD<TMat> svd(*A, Eigen::ComputeFullV);
*x1 = svd.matrixV().col(A->cols() - 1);
*x2 = svd.matrixV().col(A->cols() - 2);
if (A->rows() >= A->cols())
- return svd.singularValues()(A->cols()-1);
+ return svd.singularValues()(A->cols() - 1);
else
return 0.0;
}
// In place transpose for square matrices.
-template<class TA>
-inline void TransposeInPlace(TA *A) {
+template <class TA>
+inline void TransposeInPlace(TA* A) {
*A = A->transpose().eval();
}
-template<typename TVec>
-inline double NormL1(const TVec &x) {
+template <typename TVec>
+inline double NormL1(const TVec& x) {
return x.array().abs().sum();
}
-template<typename TVec>
-inline double NormL2(const TVec &x) {
+template <typename TVec>
+inline double NormL2(const TVec& x) {
return x.norm();
}
-template<typename TVec>
-inline double NormLInfinity(const TVec &x) {
+template <typename TVec>
+inline double NormLInfinity(const TVec& x) {
return x.array().abs().maxCoeff();
}
-template<typename TVec>
-inline double DistanceL1(const TVec &x, const TVec &y) {
+template <typename TVec>
+inline double DistanceL1(const TVec& x, const TVec& y) {
return (x - y).array().abs().sum();
}
-template<typename TVec>
-inline double DistanceL2(const TVec &x, const TVec &y) {
+template <typename TVec>
+inline double DistanceL2(const TVec& x, const TVec& y) {
return (x - y).norm();
}
-template<typename TVec>
-inline double DistanceLInfinity(const TVec &x, const TVec &y) {
+template <typename TVec>
+inline double DistanceLInfinity(const TVec& x, const TVec& y) {
return (x - y).array().abs().maxCoeff();
}
// Normalize a vector with the L1 norm, and return the norm before it was
// normalized.
-template<typename TVec>
-inline double NormalizeL1(TVec *x) {
+template <typename TVec>
+inline double NormalizeL1(TVec* x) {
double norm = NormL1(*x);
*x /= norm;
return norm;
@@ -229,8 +226,8 @@ inline double NormalizeL1(TVec *x) {
// Normalize a vector with the L2 norm, and return the norm before it was
// normalized.
-template<typename TVec>
-inline double NormalizeL2(TVec *x) {
+template <typename TVec>
+inline double NormalizeL2(TVec* x) {
double norm = NormL2(*x);
*x /= norm;
return norm;
@@ -238,15 +235,15 @@ inline double NormalizeL2(TVec *x) {
// Normalize a vector with the L^Infinity norm, and return the norm before it
// was normalized.
-template<typename TVec>
-inline double NormalizeLInfinity(TVec *x) {
+template <typename TVec>
+inline double NormalizeLInfinity(TVec* x) {
double norm = NormLInfinity(*x);
*x /= norm;
return norm;
}
// Return the square of a number.
-template<typename T>
+template <typename T>
inline T Square(T x) {
return x * x;
}
@@ -258,7 +255,7 @@ Mat3 RotationAroundZ(double angle);
// Returns the rotation matrix of a rotation of angle |axis| around axis.
// This is computed using the Rodrigues formula, see:
// http://mathworld.wolfram.com/RodriguesRotationFormula.html
-Mat3 RotationRodrigues(const Vec3 &axis);
+Mat3 RotationRodrigues(const Vec3& axis);
// Make a rotation matrix such that center becomes the direction of the
// positive z-axis, and y is oriented close to up.
@@ -266,177 +263,173 @@ Mat3 LookAt(Vec3 center);
// Return a diagonal matrix from a vector containg the diagonal values.
template <typename TVec>
-inline Mat Diag(const TVec &x) {
+inline Mat Diag(const TVec& x) {
return x.asDiagonal();
}
-template<typename TMat>
-inline double FrobeniusNorm(const TMat &A) {
+template <typename TMat>
+inline double FrobeniusNorm(const TMat& A) {
return sqrt(A.array().abs2().sum());
}
-template<typename TMat>
-inline double FrobeniusDistance(const TMat &A, const TMat &B) {
+template <typename TMat>
+inline double FrobeniusDistance(const TMat& A, const TMat& B) {
return FrobeniusNorm(A - B);
}
-inline Vec3 CrossProduct(const Vec3 &x, const Vec3 &y) {
+inline Vec3 CrossProduct(const Vec3& x, const Vec3& y) {
return x.cross(y);
}
-Mat3 CrossProductMatrix(const Vec3 &x);
+Mat3 CrossProductMatrix(const Vec3& x);
-void MeanAndVarianceAlongRows(const Mat &A,
- Vec *mean_pointer,
- Vec *variance_pointer);
+void MeanAndVarianceAlongRows(const Mat& A,
+ Vec* mean_pointer,
+ Vec* variance_pointer);
#if defined(_WIN32)
- // TODO(bomboze): un-#if this for both platforms once tested under Windows
- /* This solution was extensively discussed here
- http://forum.kde.org/viewtopic.php?f=74&t=61940 */
- #define SUM_OR_DYNAMIC(x, y) (x == Eigen::Dynamic || y == Eigen::Dynamic) ? Eigen::Dynamic : (x+y)
-
- template<typename Derived1, typename Derived2>
- struct hstack_return {
- typedef typename Derived1::Scalar Scalar;
- enum {
- RowsAtCompileTime = Derived1::RowsAtCompileTime,
- ColsAtCompileTime = SUM_OR_DYNAMIC(Derived1::ColsAtCompileTime,
- Derived2::ColsAtCompileTime),
- Options = Derived1::Flags&Eigen::RowMajorBit ? Eigen::RowMajor : 0,
- MaxRowsAtCompileTime = Derived1::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = SUM_OR_DYNAMIC(Derived1::MaxColsAtCompileTime,
- Derived2::MaxColsAtCompileTime)
- };
- typedef Eigen::Matrix<Scalar,
- RowsAtCompileTime,
- ColsAtCompileTime,
- Options,
- MaxRowsAtCompileTime,
- MaxColsAtCompileTime> type;
+// TODO(bomboze): un-#if this for both platforms once tested under Windows
+/* This solution was extensively discussed here
+ http://forum.kde.org/viewtopic.php?f=74&t=61940 */
+# define SUM_OR_DYNAMIC(x, y) \
+ (x == Eigen::Dynamic || y == Eigen::Dynamic) ? Eigen::Dynamic : (x + y)
+
+template <typename Derived1, typename Derived2>
+struct hstack_return {
+ typedef typename Derived1::Scalar Scalar;
+ enum {
+ RowsAtCompileTime = Derived1::RowsAtCompileTime,
+ ColsAtCompileTime = SUM_OR_DYNAMIC(Derived1::ColsAtCompileTime,
+ Derived2::ColsAtCompileTime),
+ Options = Derived1::Flags & Eigen::RowMajorBit ? Eigen::RowMajor : 0,
+ MaxRowsAtCompileTime = Derived1::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = SUM_OR_DYNAMIC(Derived1::MaxColsAtCompileTime,
+ Derived2::MaxColsAtCompileTime)
};
-
- template<typename Derived1, typename Derived2>
- typename hstack_return<Derived1, Derived2>::type
- HStack(const Eigen::MatrixBase<Derived1>& lhs,
- const Eigen::MatrixBase<Derived2>& rhs) {
- typename hstack_return<Derived1, Derived2>::type res;
- res.resize(lhs.rows(), lhs.cols()+rhs.cols());
- res << lhs, rhs;
- return res;
- };
-
-
- template<typename Derived1, typename Derived2>
- struct vstack_return {
- typedef typename Derived1::Scalar Scalar;
- enum {
- RowsAtCompileTime = SUM_OR_DYNAMIC(Derived1::RowsAtCompileTime,
- Derived2::RowsAtCompileTime),
- ColsAtCompileTime = Derived1::ColsAtCompileTime,
- Options = Derived1::Flags&Eigen::RowMajorBit ? Eigen::RowMajor : 0,
- MaxRowsAtCompileTime = SUM_OR_DYNAMIC(Derived1::MaxRowsAtCompileTime,
- Derived2::MaxRowsAtCompileTime),
- MaxColsAtCompileTime = Derived1::MaxColsAtCompileTime
- };
- typedef Eigen::Matrix<Scalar,
- RowsAtCompileTime,
- ColsAtCompileTime,
- Options,
- MaxRowsAtCompileTime,
- MaxColsAtCompileTime> type;
+ typedef Eigen::Matrix<Scalar,
+ RowsAtCompileTime,
+ ColsAtCompileTime,
+ Options,
+ MaxRowsAtCompileTime,
+ MaxColsAtCompileTime>
+ type;
+};
+
+template <typename Derived1, typename Derived2>
+typename hstack_return<Derived1, Derived2>::type HStack(
+ const Eigen::MatrixBase<Derived1>& lhs,
+ const Eigen::MatrixBase<Derived2>& rhs) {
+ typename hstack_return<Derived1, Derived2>::type res;
+ res.resize(lhs.rows(), lhs.cols() + rhs.cols());
+ res << lhs, rhs;
+ return res;
+};
+
+template <typename Derived1, typename Derived2>
+struct vstack_return {
+ typedef typename Derived1::Scalar Scalar;
+ enum {
+ RowsAtCompileTime = SUM_OR_DYNAMIC(Derived1::RowsAtCompileTime,
+ Derived2::RowsAtCompileTime),
+ ColsAtCompileTime = Derived1::ColsAtCompileTime,
+ Options = Derived1::Flags & Eigen::RowMajorBit ? Eigen::RowMajor : 0,
+ MaxRowsAtCompileTime = SUM_OR_DYNAMIC(Derived1::MaxRowsAtCompileTime,
+ Derived2::MaxRowsAtCompileTime),
+ MaxColsAtCompileTime = Derived1::MaxColsAtCompileTime
};
-
- template<typename Derived1, typename Derived2>
- typename vstack_return<Derived1, Derived2>::type
- VStack(const Eigen::MatrixBase<Derived1>& lhs,
- const Eigen::MatrixBase<Derived2>& rhs) {
- typename vstack_return<Derived1, Derived2>::type res;
- res.resize(lhs.rows()+rhs.rows(), lhs.cols());
- res << lhs, rhs;
- return res;
- };
-
+ typedef Eigen::Matrix<Scalar,
+ RowsAtCompileTime,
+ ColsAtCompileTime,
+ Options,
+ MaxRowsAtCompileTime,
+ MaxColsAtCompileTime>
+ type;
+};
+
+template <typename Derived1, typename Derived2>
+typename vstack_return<Derived1, Derived2>::type VStack(
+ const Eigen::MatrixBase<Derived1>& lhs,
+ const Eigen::MatrixBase<Derived2>& rhs) {
+ typename vstack_return<Derived1, Derived2>::type res;
+ res.resize(lhs.rows() + rhs.rows(), lhs.cols());
+ res << lhs, rhs;
+ return res;
+};
#else // _WIN32
- // Since it is not possible to typedef privately here, use a macro.
- // Always take dynamic columns if either side is dynamic.
- #define COLS \
- ((ColsLeft == Eigen::Dynamic || ColsRight == Eigen::Dynamic) \
- ? Eigen::Dynamic : (ColsLeft + ColsRight))
-
- // Same as above, except that prefer fixed size if either is fixed.
- #define ROWS \
- ((RowsLeft == Eigen::Dynamic && RowsRight == Eigen::Dynamic) \
- ? Eigen::Dynamic \
- : ((RowsLeft == Eigen::Dynamic) \
- ? RowsRight \
- : RowsLeft \
- ) \
- )
-
- // TODO(keir): Add a static assert if both rows are at compiletime.
- template<typename T, int RowsLeft, int RowsRight, int ColsLeft, int ColsRight>
- Eigen::Matrix<T, ROWS, COLS>
- HStack(const Eigen::Matrix<T, RowsLeft, ColsLeft> &left,
- const Eigen::Matrix<T, RowsRight, ColsRight> &right) {
- assert(left.rows() == right.rows());
- int n = left.rows();
- int m1 = left.cols();
- int m2 = right.cols();
-
- Eigen::Matrix<T, ROWS, COLS> stacked(n, m1 + m2);
- stacked.block(0, 0, n, m1) = left;
- stacked.block(0, m1, n, m2) = right;
- return stacked;
- }
-
- // Reuse the above macros by swapping the order of Rows and Cols. Nasty, but
- // the duplication is worse.
- // TODO(keir): Add a static assert if both rows are at compiletime.
- // TODO(keir): Mail eigen list about making this work for general expressions
- // rather than only matrix types.
- template<typename T, int RowsLeft, int RowsRight, int ColsLeft, int ColsRight>
- Eigen::Matrix<T, COLS, ROWS>
- VStack(const Eigen::Matrix<T, ColsLeft, RowsLeft> &top,
- const Eigen::Matrix<T, ColsRight, RowsRight> &bottom) {
- assert(top.cols() == bottom.cols());
- int n1 = top.rows();
- int n2 = bottom.rows();
- int m = top.cols();
-
- Eigen::Matrix<T, COLS, ROWS> stacked(n1 + n2, m);
- stacked.block(0, 0, n1, m) = top;
- stacked.block(n1, 0, n2, m) = bottom;
- return stacked;
- }
- #undef COLS
- #undef ROWS
-#endif // _WIN32
+// Since it is not possible to typedef privately here, use a macro.
+// Always take dynamic columns if either side is dynamic.
+# define COLS \
+ ((ColsLeft == Eigen::Dynamic || ColsRight == Eigen::Dynamic) \
+ ? Eigen::Dynamic \
+ : (ColsLeft + ColsRight))
+
+// Same as above, except that prefer fixed size if either is fixed.
+# define ROWS \
+ ((RowsLeft == Eigen::Dynamic && RowsRight == Eigen::Dynamic) \
+ ? Eigen::Dynamic \
+ : ((RowsLeft == Eigen::Dynamic) ? RowsRight : RowsLeft))
+
+// TODO(keir): Add a static assert if both rows are at compiletime.
+template <typename T, int RowsLeft, int RowsRight, int ColsLeft, int ColsRight>
+Eigen::Matrix<T, ROWS, COLS> HStack(
+ const Eigen::Matrix<T, RowsLeft, ColsLeft>& left,
+ const Eigen::Matrix<T, RowsRight, ColsRight>& right) {
+ assert(left.rows() == right.rows());
+ int n = left.rows();
+ int m1 = left.cols();
+ int m2 = right.cols();
+
+ Eigen::Matrix<T, ROWS, COLS> stacked(n, m1 + m2);
+ stacked.block(0, 0, n, m1) = left;
+ stacked.block(0, m1, n, m2) = right;
+ return stacked;
+}
+// Reuse the above macros by swapping the order of Rows and Cols. Nasty, but
+// the duplication is worse.
+// TODO(keir): Add a static assert if both rows are at compiletime.
+// TODO(keir): Mail eigen list about making this work for general expressions
+// rather than only matrix types.
+template <typename T, int RowsLeft, int RowsRight, int ColsLeft, int ColsRight>
+Eigen::Matrix<T, COLS, ROWS> VStack(
+ const Eigen::Matrix<T, ColsLeft, RowsLeft>& top,
+ const Eigen::Matrix<T, ColsRight, RowsRight>& bottom) {
+ assert(top.cols() == bottom.cols());
+ int n1 = top.rows();
+ int n2 = bottom.rows();
+ int m = top.cols();
+ Eigen::Matrix<T, COLS, ROWS> stacked(n1 + n2, m);
+ stacked.block(0, 0, n1, m) = top;
+ stacked.block(n1, 0, n2, m) = bottom;
+ return stacked;
+}
+# undef COLS
+# undef ROWS
+#endif // _WIN32
-void HorizontalStack(const Mat &left, const Mat &right, Mat *stacked);
+void HorizontalStack(const Mat& left, const Mat& right, Mat* stacked);
-template<typename TTop, typename TBot, typename TStacked>
-void VerticalStack(const TTop &top, const TBot &bottom, TStacked *stacked) {
+template <typename TTop, typename TBot, typename TStacked>
+void VerticalStack(const TTop& top, const TBot& bottom, TStacked* stacked) {
assert(top.cols() == bottom.cols());
int n1 = top.rows();
int n2 = bottom.rows();
int m = top.cols();
stacked->resize(n1 + n2, m);
- stacked->block(0, 0, n1, m) = top;
+ stacked->block(0, 0, n1, m) = top;
stacked->block(n1, 0, n2, m) = bottom;
}
-void MatrixColumn(const Mat &A, int i, Vec2 *v);
-void MatrixColumn(const Mat &A, int i, Vec3 *v);
-void MatrixColumn(const Mat &A, int i, Vec4 *v);
+void MatrixColumn(const Mat& A, int i, Vec2* v);
+void MatrixColumn(const Mat& A, int i, Vec3* v);
+void MatrixColumn(const Mat& A, int i, Vec4* v);
template <typename TMat, typename TCols>
-TMat ExtractColumns(const TMat &A, const TCols &columns) {
+TMat ExtractColumns(const TMat& A, const TCols& columns) {
TMat compressed(A.rows(), columns.size());
for (int i = 0; i < columns.size(); ++i) {
compressed.col(i) = A.col(columns[i]);
@@ -445,12 +438,12 @@ TMat ExtractColumns(const TMat &A, const TCols &columns) {
}
template <typename TMat, typename TDest>
-void reshape(const TMat &a, int rows, int cols, TDest *b) {
- assert(a.rows()*a.cols() == rows*cols);
+void reshape(const TMat& a, int rows, int cols, TDest* b) {
+ assert(a.rows() * a.cols() == rows * cols);
b->resize(rows, cols);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
- (*b)(i, j) = a[cols*i + j];
+ (*b)(i, j) = a[cols * i + j];
}
}
}
@@ -467,24 +460,21 @@ inline bool isnan(double i) {
/// and negative values
template <typename FloatType>
FloatType ceil0(const FloatType& value) {
- FloatType result = std::ceil(std::fabs(value));
- return (value < 0.0) ? -result : result;
+ FloatType result = std::ceil(std::fabs(value));
+ return (value < 0.0) ? -result : result;
}
/// Returns the skew anti-symmetric matrix of a vector
-inline Mat3 SkewMat(const Vec3 &x) {
+inline Mat3 SkewMat(const Vec3& x) {
Mat3 skew;
- skew << 0 , -x(2), x(1),
- x(2), 0 , -x(0),
- -x(1), x(0), 0;
+ skew << 0, -x(2), x(1), x(2), 0, -x(0), -x(1), x(0), 0;
return skew;
}
/// Returns the skew anti-symmetric matrix of a vector with only
/// the first two (independent) lines
-inline Mat23 SkewMatMinimal(const Vec2 &x) {
+inline Mat23 SkewMatMinimal(const Vec2& x) {
Mat23 skew;
- skew << 0, -1, x(1),
- 1, 0, -x(0);
+ skew << 0, -1, x(1), 1, 0, -x(0);
return skew;
}
@@ -496,7 +486,8 @@ inline Mat3 RotationFromEulerVector(Vec3 euler_vector) {
}
Vec3 w = euler_vector / theta;
Mat3 w_hat = CrossProductMatrix(w);
- return Mat3::Identity() + w_hat*sin(theta) + w_hat*w_hat*(1 - cos(theta));
+ return Mat3::Identity() + w_hat * sin(theta) +
+ w_hat * w_hat * (1 - cos(theta));
}
} // namespace libmv
diff --git a/intern/libmv/libmv/numeric/numeric_test.cc b/intern/libmv/libmv/numeric/numeric_test.cc
index 0cdfaf33ab2..b2650a04658 100644
--- a/intern/libmv/libmv/numeric/numeric_test.cc
+++ b/intern/libmv/libmv/numeric/numeric_test.cc
@@ -27,9 +27,11 @@ namespace {
TEST(Numeric, DynamicSizedNullspace) {
Mat A(3, 4);
+ // clang-format off
A << 0.76026643, 0.01799744, 0.55192142, 0.8699745,
0.42016166, 0.97863392, 0.33711682, 0.14479271,
0.51016811, 0.66528302, 0.54395496, 0.57794893;
+ // clang-format on
Vec x;
double s = Nullspace(&A, &x);
EXPECT_NEAR(0.0, s, 1e-15);
@@ -39,9 +41,11 @@ TEST(Numeric, DynamicSizedNullspace) {
TEST(Numeric, FixedSizeMatrixNullspace) {
Mat34 A;
+ // clang-format off
A << 0.76026643, 0.01799744, 0.55192142, 0.8699745,
0.42016166, 0.97863392, 0.33711682, 0.14479271,
0.51016811, 0.66528302, 0.54395496, 0.57794893;
+ // clang-format on
Vec x;
double s = Nullspace(&A, &x);
EXPECT_NEAR(0.0, s, 1e-15);
@@ -51,10 +55,12 @@ TEST(Numeric, FixedSizeMatrixNullspace) {
TEST(Numeric, NullspaceMatchesLapackSVD) {
Mat43 A;
+ // clang-format off
A << 0.76026643, 0.01799744, 0.55192142,
0.8699745, 0.42016166, 0.97863392,
0.33711682, 0.14479271, 0.51016811,
0.66528302, 0.54395496, 0.57794893;
+ // clang-format on
Vec x;
double s = Nullspace(&A, &x);
EXPECT_NEAR(1.0, x.norm(), 1e-15);
@@ -68,10 +74,12 @@ TEST(Numeric, NullspaceMatchesLapackSVD) {
TEST(Numeric, Nullspace2) {
Mat43 A;
+ // clang-format off
A << 0.76026643, 0.01799744, 0.55192142,
0.8699745, 0.42016166, 0.97863392,
0.33711682, 0.14479271, 0.51016811,
0.66528302, 0.54395496, 0.57794893;
+ // clang-format on
Vec3 x1, x2;
double s = Nullspace2(&A, &x1, &x2);
EXPECT_NEAR(1.0, x1.norm(), 1e-15);
@@ -80,14 +88,14 @@ TEST(Numeric, Nullspace2) {
EXPECT_NEAR(-0.64999717, x1(0), 1e-8);
EXPECT_NEAR(-0.18452646, x1(1), 1e-8);
- EXPECT_NEAR( 0.7371931, x1(2), 1e-8);
+ EXPECT_NEAR(0.7371931, x1(2), 1e-8);
if (x2(0) < 0) {
x2 *= -1;
}
- EXPECT_NEAR( 0.34679618, x2(0), 1e-8);
+ EXPECT_NEAR(0.34679618, x2(0), 1e-8);
EXPECT_NEAR(-0.93519689, x2(1), 1e-8);
- EXPECT_NEAR( 0.07168809, x2(2), 1e-8);
+ EXPECT_NEAR(0.07168809, x2(2), 1e-8);
}
TEST(Numeric, TinyMatrixSquareTranspose) {
@@ -105,8 +113,8 @@ TEST(Numeric, NormalizeL1) {
x << 1, 2;
double l1 = NormalizeL1(&x);
EXPECT_DOUBLE_EQ(3., l1);
- EXPECT_DOUBLE_EQ(1./3., x(0));
- EXPECT_DOUBLE_EQ(2./3., x(1));
+ EXPECT_DOUBLE_EQ(1. / 3., x(0));
+ EXPECT_DOUBLE_EQ(2. / 3., x(1));
}
TEST(Numeric, NormalizeL2) {
@@ -114,8 +122,8 @@ TEST(Numeric, NormalizeL2) {
x << 1, 2;
double l2 = NormalizeL2(&x);
EXPECT_DOUBLE_EQ(sqrt(5.0), l2);
- EXPECT_DOUBLE_EQ(1./sqrt(5.), x(0));
- EXPECT_DOUBLE_EQ(2./sqrt(5.), x(1));
+ EXPECT_DOUBLE_EQ(1. / sqrt(5.), x(0));
+ EXPECT_DOUBLE_EQ(2. / sqrt(5.), x(1));
}
TEST(Numeric, Diag) {
@@ -130,31 +138,32 @@ TEST(Numeric, Diag) {
TEST(Numeric, Determinant) {
Mat A(2, 2);
- A << 1, 2,
- -1, 3;
+ A << 1, 2, -1, 3;
double detA = A.determinant();
EXPECT_NEAR(5, detA, 1e-8);
Mat B(4, 4);
+ // clang-format off
B << 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15;
+ // clang-format on
double detB = B.determinant();
EXPECT_NEAR(0, detB, 1e-8);
Mat3 C;
- C << 0, 1, 2,
- 3, 4, 5,
- 6, 7, 1;
+ C << 0, 1, 2, 3, 4, 5, 6, 7, 1;
double detC = C.determinant();
EXPECT_NEAR(21, detC, 1e-8);
}
TEST(Numeric, Inverse) {
Mat A(2, 2), A1;
+ // clang-format off
A << 1, 2,
-1, 3;
+ // clang-format on
Mat I = A * A.inverse();
EXPECT_NEAR(1, I(0, 0), 1e-8);
@@ -163,10 +172,12 @@ TEST(Numeric, Inverse) {
EXPECT_NEAR(1, I(1, 1), 1e-8);
Mat B(4, 4), B1;
+ // clang-format off
B << 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 2, 11,
12, 13, 14, 4;
+ // clang-format on
Mat I2 = B * B.inverse();
EXPECT_NEAR(1, I2(0, 0), 1e-8);
EXPECT_NEAR(0, I2(0, 1), 1e-8);
@@ -182,8 +193,10 @@ TEST(Numeric, Inverse) {
TEST(Numeric, MeanAndVarianceAlongRows) {
int n = 4;
Mat points(2, n);
+ // clang-format off
points << 0, 0, 1, 1,
0, 2, 1, 3;
+ // clang-format on
Vec mean, variance;
MeanAndVarianceAlongRows(points, &mean, &variance);
@@ -213,15 +226,17 @@ TEST(Numeric, HStack) {
Mat x(2, 1), y(2, 1), z(2, 2);
x << 1, 2;
y << 3, 4;
+ // clang-format off
z << 1, 3,
2, 4;
+ // clang-format on
Vec2 xC = x, yC = y;
- Mat2 xy = HStack(x, y);
+ Mat2 xy = HStack(x, y);
EXPECT_MATRIX_EQ(z, xy);
- EXPECT_MATRIX_EQ(z, HStack(x, y));
- EXPECT_MATRIX_EQ(z, HStack(x, yC));
+ EXPECT_MATRIX_EQ(z, HStack(x, y));
+ EXPECT_MATRIX_EQ(z, HStack(x, yC));
EXPECT_MATRIX_EQ(z, HStack(xC, y));
EXPECT_MATRIX_EQ(z, HStack(xC, yC));
}
@@ -230,6 +245,7 @@ TEST(Numeric, HStack) {
// resulting stacked matrices properly propagate the fixed dimensions.
TEST(Numeric, VStack) {
Mat x(2, 2), y(2, 2), z(4, 2);
+ // clang-format off
x << 1, 2,
3, 4;
y << 10, 20,
@@ -238,13 +254,14 @@ TEST(Numeric, VStack) {
3, 4,
10, 20,
30, 40;
+ // clang-format on
Mat2 xC = x, yC = y;
- Mat xy = VStack(x, y);
+ Mat xy = VStack(x, y);
EXPECT_MATRIX_EQ(z, xy);
- EXPECT_MATRIX_EQ(z, VStack(x, y));
- EXPECT_MATRIX_EQ(z, VStack(x, yC));
+ EXPECT_MATRIX_EQ(z, VStack(x, y));
+ EXPECT_MATRIX_EQ(z, VStack(x, yC));
EXPECT_MATRIX_EQ(z, VStack(xC, y));
EXPECT_MATRIX_EQ(z, VStack(xC, yC));
}
@@ -293,17 +310,21 @@ TEST(Numeric, CrossProductMatrix) {
TEST(Numeric, MatrixColumn) {
Mat A2(2, 3);
Vec2 v2;
+ // clang-format off
A2 << 1, 2, 3,
4, 5, 6;
+ // clang-format on
MatrixColumn(A2, 1, &v2);
EXPECT_EQ(2, v2(0));
EXPECT_EQ(5, v2(1));
Mat A3(3, 3);
Vec3 v3;
+ // clang-format off
A3 << 1, 2, 3,
4, 5, 6,
7, 8, 9;
+ // clang-format on
MatrixColumn(A3, 1, &v3);
EXPECT_EQ(2, v3(0));
EXPECT_EQ(5, v3(1));
@@ -311,14 +332,16 @@ TEST(Numeric, MatrixColumn) {
Mat A4(4, 3);
Vec4 v4;
+ // clang-format off
A4 << 1, 2, 3,
4, 5, 6,
7, 8, 9,
10, 11, 12;
+ // clang-format on
MatrixColumn(A4, 1, &v4);
- EXPECT_EQ( 2, v4(0));
- EXPECT_EQ( 5, v4(1));
- EXPECT_EQ( 8, v4(2));
+ EXPECT_EQ(2, v4(0));
+ EXPECT_EQ(5, v4(1));
+ EXPECT_EQ(8, v4(2));
EXPECT_EQ(11, v4(3));
}
@@ -337,7 +360,8 @@ TEST(Numeric, Mat3MatProduct) {
// This gives a compile error.
TEST(Numeric, Vec3Negative) {
- Vec3 y; y << 1, 2, 3;
+ Vec3 y;
+ y << 1, 2, 3;
Vec3 x = -y;
EXPECT_EQ(-1, x(0));
EXPECT_EQ(-2, x(1));
@@ -357,19 +381,23 @@ TEST(Numeric, Vec3VecInteroperability) {
// This segfaults inside lapack.
TEST(Numeric, DeterminantLU7) {
Mat A(5, 5);
+ // clang-format off
A << 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
0, 0, 0, 0, 1;
+ // clang-format on
EXPECT_NEAR(1, A.determinant(), 1e-8);
}
// This segfaults inside lapack.
TEST(Numeric, DeterminantLU) {
Mat A(2, 2);
+ // clang-format off
A << 1, 2,
-1, 3;
+ // clang-format on
EXPECT_NEAR(5, A.determinant(), 1e-8);
}
@@ -377,19 +405,24 @@ TEST(Numeric, DeterminantLU) {
// Keir: Not with eigen2!
TEST(Numeric, InplaceProduct) {
Mat2 K, S;
+ // clang-format off
K << 1, 0,
0, 1;
S << 1, 0,
0, 1;
K = K * S;
+ // clang-format on
EXPECT_MATRIX_NEAR(Mat2::Identity(), K, 1e-8);
}
TEST(Numeric, ExtractColumns) {
Mat2X A(2, 5);
+ // clang-format off
A << 1, 2, 3, 4, 5,
6, 7, 8, 9, 10;
- Vec2i columns; columns << 0, 2;
+ // clang-format on
+ Vec2i columns;
+ columns << 0, 2;
Mat2X extracted = ExtractColumns(A, columns);
EXPECT_NEAR(1, extracted(0, 0), 1e-15);
EXPECT_NEAR(3, extracted(0, 1), 1e-15);
@@ -418,21 +451,22 @@ TEST(Numeric, RotationRodrigues) {
TEST(Numeric, LookAt) {
// Simple orthogonality check.
- Vec3 e; e << 1, 2, 3;
+ Vec3 e;
+ e << 1, 2, 3;
Mat3 R = LookAt(e), I = Mat3::Identity();
- Mat3 RRT = R*R.transpose();
- Mat3 RTR = R.transpose()*R;
+ Mat3 RRT = R * R.transpose();
+ Mat3 RTR = R.transpose() * R;
EXPECT_MATRIX_NEAR(I, RRT, 1e-15);
EXPECT_MATRIX_NEAR(I, RTR, 1e-15);
}
TEST(Numeric, Reshape) {
- Vec4 x; x << 1, 2, 3, 4;
+ Vec4 x;
+ x << 1, 2, 3, 4;
Mat2 M, M_expected;
reshape(x, 2, 2, &M);
- M_expected << 1, 2,
- 3, 4;
+ M_expected << 1, 2, 3, 4;
EXPECT_MATRIX_NEAR(M_expected, M, 1e-15);
}
diff --git a/intern/libmv/libmv/numeric/poly.h b/intern/libmv/libmv/numeric/poly.h
index 76ba062d475..a3d3801a399 100644
--- a/intern/libmv/libmv/numeric/poly.h
+++ b/intern/libmv/libmv/numeric/poly.h
@@ -21,8 +21,8 @@
#ifndef LIBMV_NUMERIC_POLY_H_
#define LIBMV_NUMERIC_POLY_H_
-#include <cmath>
#include <stdio.h>
+#include <cmath>
namespace libmv {
@@ -35,9 +35,8 @@ namespace libmv {
// if there are 2 roots, only x0 and x1 are set.
//
// The GSL cubic solver was used as a reference for this routine.
-template<typename Real>
-int SolveCubicPolynomial(Real a, Real b, Real c,
- Real *x0, Real *x1, Real *x2) {
+template <typename Real>
+int SolveCubicPolynomial(Real a, Real b, Real c, Real* x0, Real* x1, Real* x2) {
Real q = a * a - 3 * b;
Real r = 2 * a * a * a - 9 * a * b + 27 * c;
@@ -65,12 +64,12 @@ int SolveCubicPolynomial(Real a, Real b, Real c,
Real sqrtQ = sqrt(Q);
if (R > 0) {
*x0 = -2 * sqrtQ - a / 3;
- *x1 = sqrtQ - a / 3;
- *x2 = sqrtQ - a / 3;
+ *x1 = sqrtQ - a / 3;
+ *x2 = sqrtQ - a / 3;
} else {
- *x0 = -sqrtQ - a / 3;
- *x1 = -sqrtQ - a / 3;
- *x2 = 2 * sqrtQ - a / 3;
+ *x0 = -sqrtQ - a / 3;
+ *x1 = -sqrtQ - a / 3;
+ *x2 = 2 * sqrtQ - a / 3;
}
return 3;
@@ -97,15 +96,15 @@ int SolveCubicPolynomial(Real a, Real b, Real c,
return 3;
}
Real sgnR = (R >= 0 ? 1 : -1);
- Real A = -sgnR * pow(fabs(R) + sqrt(R2 - Q3), 1.0/3.0);
+ Real A = -sgnR * pow(fabs(R) + sqrt(R2 - Q3), 1.0 / 3.0);
Real B = Q / A;
*x0 = A + B - a / 3;
return 1;
}
// The coefficients are in ascending powers, i.e. coeffs[N]*x^N.
-template<typename Real>
-int SolveCubicPolynomial(const Real *coeffs, Real *solutions) {
+template <typename Real>
+int SolveCubicPolynomial(const Real* coeffs, Real* solutions) {
if (coeffs[0] == 0.0) {
// TODO(keir): This is a quadratic not a cubic. Implement a quadratic
// solver!
@@ -114,10 +113,8 @@ int SolveCubicPolynomial(const Real *coeffs, Real *solutions) {
Real a = coeffs[2] / coeffs[3];
Real b = coeffs[1] / coeffs[3];
Real c = coeffs[0] / coeffs[3];
- return SolveCubicPolynomial(a, b, c,
- solutions + 0,
- solutions + 1,
- solutions + 2);
+ return SolveCubicPolynomial(
+ a, b, c, solutions + 0, solutions + 1, solutions + 2);
}
} // namespace libmv
#endif // LIBMV_NUMERIC_POLY_H_
diff --git a/intern/libmv/libmv/numeric/poly_test.cc b/intern/libmv/libmv/numeric/poly_test.cc
index 69f887b416c..cb85c068468 100644
--- a/intern/libmv/libmv/numeric/poly_test.cc
+++ b/intern/libmv/libmv/numeric/poly_test.cc
@@ -18,8 +18,8 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-#include "libmv/numeric/numeric.h"
#include "libmv/numeric/poly.h"
+#include "libmv/numeric/numeric.h"
#include "testing/testing.h"
using namespace libmv;
@@ -34,8 +34,8 @@ namespace {
//
// x^3 - (c+b+a) * x^2 + (a*b+(b+a)*c) * x - a*b*c = 0.
// = p = q = r
-void CoeffsForCubicZeros(double a, double b, double c,
- double *p, double *q, double *r) {
+void CoeffsForCubicZeros(
+ double a, double b, double c, double* p, double* q, double* r) {
*p = -(c + b + a);
*q = (a * b + (b + a) * c);
*r = -a * b * c;
@@ -45,35 +45,45 @@ TEST(Poly, SolveCubicPolynomial) {
double a, b, c, aa, bb, cc;
double p, q, r;
- a = 1; b = 2; c = 3;
+ a = 1;
+ b = 2;
+ c = 3;
CoeffsForCubicZeros(a, b, c, &p, &q, &r);
ASSERT_EQ(3, SolveCubicPolynomial(p, q, r, &aa, &bb, &cc));
EXPECT_NEAR(a, aa, 1e-10);
EXPECT_NEAR(b, bb, 1e-10);
EXPECT_NEAR(c, cc, 1e-10);
- a = 0; b = 1; c = 3;
+ a = 0;
+ b = 1;
+ c = 3;
CoeffsForCubicZeros(a, b, c, &p, &q, &r);
ASSERT_EQ(3, SolveCubicPolynomial(p, q, r, &aa, &bb, &cc));
EXPECT_NEAR(a, aa, 1e-10);
EXPECT_NEAR(b, bb, 1e-10);
EXPECT_NEAR(c, cc, 1e-10);
- a = -10; b = 0; c = 1;
+ a = -10;
+ b = 0;
+ c = 1;
CoeffsForCubicZeros(a, b, c, &p, &q, &r);
ASSERT_EQ(3, SolveCubicPolynomial(p, q, r, &aa, &bb, &cc));
EXPECT_NEAR(a, aa, 1e-10);
EXPECT_NEAR(b, bb, 1e-10);
EXPECT_NEAR(c, cc, 1e-10);
- a = -8; b = 1; c = 3;
+ a = -8;
+ b = 1;
+ c = 3;
CoeffsForCubicZeros(a, b, c, &p, &q, &r);
ASSERT_EQ(3, SolveCubicPolynomial(p, q, r, &aa, &bb, &cc));
EXPECT_NEAR(a, aa, 1e-10);
EXPECT_NEAR(b, bb, 1e-10);
EXPECT_NEAR(c, cc, 1e-10);
- a = 28; b = 28; c = 105;
+ a = 28;
+ b = 28;
+ c = 105;
CoeffsForCubicZeros(a, b, c, &p, &q, &r);
ASSERT_EQ(3, SolveCubicPolynomial(p, q, r, &aa, &bb, &cc));
EXPECT_NEAR(a, aa, 1e-10);
diff --git a/intern/libmv/libmv/simple_pipeline/bundle.cc b/intern/libmv/libmv/simple_pipeline/bundle.cc
index d62f0ebe94f..e86c3bca57f 100644
--- a/intern/libmv/libmv/simple_pipeline/bundle.cc
+++ b/intern/libmv/libmv/simple_pipeline/bundle.cc
@@ -32,16 +32,16 @@
#include "libmv/multiview/projection.h"
#include "libmv/numeric/numeric.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
-#include "libmv/simple_pipeline/reconstruction.h"
-#include "libmv/simple_pipeline/tracks.h"
#include "libmv/simple_pipeline/distortion_models.h"
#include "libmv/simple_pipeline/packed_intrinsics.h"
+#include "libmv/simple_pipeline/reconstruction.h"
+#include "libmv/simple_pipeline/tracks.h"
namespace libmv {
namespace {
-bool NeedUseInvertIntrinsicsPipeline(const CameraIntrinsics *intrinsics) {
+bool NeedUseInvertIntrinsicsPipeline(const CameraIntrinsics* intrinsics) {
const DistortionModelType distortion_model =
intrinsics->GetDistortionModelType();
return (distortion_model == DISTORTION_MODEL_NUKE);
@@ -59,12 +59,14 @@ bool NeedUseInvertIntrinsicsPipeline(const CameraIntrinsics *intrinsics) {
// The invariant_intrinsics are used to access intrinsics which are never
// packed into parameter block: for example, distortion model type and image
// dimension.
-template<typename T>
+template <typename T>
void ApplyDistortionModelUsingIntrinsicsBlock(
- const CameraIntrinsics *invariant_intrinsics,
+ const CameraIntrinsics* invariant_intrinsics,
const T* const intrinsics_block,
- const T& normalized_x, const T& normalized_y,
- T* distorted_x, T* distorted_y) {
+ const T& normalized_x,
+ const T& normalized_y,
+ T* distorted_x,
+ T* distorted_y) {
// Unpack the intrinsics.
const T& focal_length =
intrinsics_block[PackedIntrinsics::OFFSET_FOCAL_LENGTH];
@@ -76,65 +78,75 @@ void ApplyDistortionModelUsingIntrinsicsBlock(
// TODO(keir): Do early bailouts for zero distortion; these are expensive
// jet operations.
switch (invariant_intrinsics->GetDistortionModelType()) {
- case DISTORTION_MODEL_POLYNOMIAL:
- {
- const T& k1 = intrinsics_block[PackedIntrinsics::OFFSET_K1];
- const T& k2 = intrinsics_block[PackedIntrinsics::OFFSET_K2];
- const T& k3 = intrinsics_block[PackedIntrinsics::OFFSET_K3];
- const T& p1 = intrinsics_block[PackedIntrinsics::OFFSET_P1];
- const T& p2 = intrinsics_block[PackedIntrinsics::OFFSET_P2];
-
- ApplyPolynomialDistortionModel(focal_length,
- focal_length,
- principal_point_x,
- principal_point_y,
- k1, k2, k3,
- p1, p2,
- normalized_x, normalized_y,
- distorted_x, distorted_y);
- return;
- }
-
- case DISTORTION_MODEL_DIVISION:
- {
- const T& k1 = intrinsics_block[PackedIntrinsics::OFFSET_K1];
- const T& k2 = intrinsics_block[PackedIntrinsics::OFFSET_K2];
-
- ApplyDivisionDistortionModel(focal_length,
+ case DISTORTION_MODEL_POLYNOMIAL: {
+ const T& k1 = intrinsics_block[PackedIntrinsics::OFFSET_K1];
+ const T& k2 = intrinsics_block[PackedIntrinsics::OFFSET_K2];
+ const T& k3 = intrinsics_block[PackedIntrinsics::OFFSET_K3];
+ const T& p1 = intrinsics_block[PackedIntrinsics::OFFSET_P1];
+ const T& p2 = intrinsics_block[PackedIntrinsics::OFFSET_P2];
+
+ ApplyPolynomialDistortionModel(focal_length,
focal_length,
principal_point_x,
principal_point_y,
- k1, k2,
- normalized_x, normalized_y,
- distorted_x, distorted_y);
- return;
- }
+ k1,
+ k2,
+ k3,
+ p1,
+ p2,
+ normalized_x,
+ normalized_y,
+ distorted_x,
+ distorted_y);
+ return;
+ }
- case DISTORTION_MODEL_NUKE:
- {
- LOG(FATAL) << "Unsupported distortion model.";
- return;
- }
+ case DISTORTION_MODEL_DIVISION: {
+ const T& k1 = intrinsics_block[PackedIntrinsics::OFFSET_K1];
+ const T& k2 = intrinsics_block[PackedIntrinsics::OFFSET_K2];
+
+ ApplyDivisionDistortionModel(focal_length,
+ focal_length,
+ principal_point_x,
+ principal_point_y,
+ k1,
+ k2,
+ normalized_x,
+ normalized_y,
+ distorted_x,
+ distorted_y);
+ return;
+ }
- case DISTORTION_MODEL_BROWN:
- {
- const T& k1 = intrinsics_block[PackedIntrinsics::OFFSET_K1];
- const T& k2 = intrinsics_block[PackedIntrinsics::OFFSET_K2];
- const T& k3 = intrinsics_block[PackedIntrinsics::OFFSET_K3];
- const T& k4 = intrinsics_block[PackedIntrinsics::OFFSET_K4];
- const T& p1 = intrinsics_block[PackedIntrinsics::OFFSET_P1];
- const T& p2 = intrinsics_block[PackedIntrinsics::OFFSET_P2];
-
- ApplyBrownDistortionModel(focal_length,
- focal_length,
- principal_point_x,
- principal_point_y,
- k1, k2, k3, k4,
- p1, p2,
- normalized_x, normalized_y,
- distorted_x, distorted_y);
- return;
- }
+ case DISTORTION_MODEL_NUKE: {
+ LOG(FATAL) << "Unsupported distortion model.";
+ return;
+ }
+
+ case DISTORTION_MODEL_BROWN: {
+ const T& k1 = intrinsics_block[PackedIntrinsics::OFFSET_K1];
+ const T& k2 = intrinsics_block[PackedIntrinsics::OFFSET_K2];
+ const T& k3 = intrinsics_block[PackedIntrinsics::OFFSET_K3];
+ const T& k4 = intrinsics_block[PackedIntrinsics::OFFSET_K4];
+ const T& p1 = intrinsics_block[PackedIntrinsics::OFFSET_P1];
+ const T& p2 = intrinsics_block[PackedIntrinsics::OFFSET_P2];
+
+ ApplyBrownDistortionModel(focal_length,
+ focal_length,
+ principal_point_x,
+ principal_point_y,
+ k1,
+ k2,
+ k3,
+ k4,
+ p1,
+ p2,
+ normalized_x,
+ normalized_y,
+ distorted_x,
+ distorted_y);
+ return;
+ }
}
LOG(FATAL) << "Unknown distortion model.";
@@ -152,12 +164,14 @@ void ApplyDistortionModelUsingIntrinsicsBlock(
// The invariant_intrinsics are used to access intrinsics which are never
// packed into parameter block: for example, distortion model type and image
// dimension.
-template<typename T>
+template <typename T>
void InvertDistortionModelUsingIntrinsicsBlock(
- const CameraIntrinsics *invariant_intrinsics,
+ const CameraIntrinsics* invariant_intrinsics,
const T* const intrinsics_block,
- const T& image_x, const T& image_y,
- T* normalized_x, T* normalized_y) {
+ const T& image_x,
+ const T& image_y,
+ T* normalized_x,
+ T* normalized_y) {
// Unpack the intrinsics.
const T& focal_length =
intrinsics_block[PackedIntrinsics::OFFSET_FOCAL_LENGTH];
@@ -175,31 +189,35 @@ void InvertDistortionModelUsingIntrinsicsBlock(
LOG(FATAL) << "Unsupported distortion model.";
return;
- case DISTORTION_MODEL_NUKE:
- {
- const T& k1 = intrinsics_block[PackedIntrinsics::OFFSET_K1];
- const T& k2 = intrinsics_block[PackedIntrinsics::OFFSET_K2];
-
- InvertNukeDistortionModel(focal_length,
- focal_length,
- principal_point_x,
- principal_point_y,
- invariant_intrinsics->image_width(),
- invariant_intrinsics->image_height(),
- k1, k2,
- image_x, image_y,
- normalized_x, normalized_y);
- return;
- }
+ case DISTORTION_MODEL_NUKE: {
+ const T& k1 = intrinsics_block[PackedIntrinsics::OFFSET_K1];
+ const T& k2 = intrinsics_block[PackedIntrinsics::OFFSET_K2];
+
+ InvertNukeDistortionModel(focal_length,
+ focal_length,
+ principal_point_x,
+ principal_point_y,
+ invariant_intrinsics->image_width(),
+ invariant_intrinsics->image_height(),
+ k1,
+ k2,
+ image_x,
+ image_y,
+ normalized_x,
+ normalized_y);
+ return;
+ }
}
LOG(FATAL) << "Unknown distortion model.";
}
-template<typename T>
+template <typename T>
void NormalizedToImageSpace(const T* const intrinsics_block,
- const T& normalized_x, const T& normalized_y,
- T* image_x, T* image_y) {
+ const T& normalized_x,
+ const T& normalized_y,
+ T* image_x,
+ T* image_y) {
// Unpack the intrinsics.
const T& focal_length =
intrinsics_block[PackedIntrinsics::OFFSET_FOCAL_LENGTH];
@@ -219,11 +237,10 @@ void NormalizedToImageSpace(const T* const intrinsics_block,
// This functor can only be used for distortion models which have analytically
// defined Apply() function.
struct ReprojectionErrorApplyIntrinsics {
- ReprojectionErrorApplyIntrinsics(
- const CameraIntrinsics *invariant_intrinsics,
- const double observed_distorted_x,
- const double observed_distorted_y,
- const double weight)
+ ReprojectionErrorApplyIntrinsics(const CameraIntrinsics* invariant_intrinsics,
+ const double observed_distorted_x,
+ const double observed_distorted_y,
+ const double weight)
: invariant_intrinsics_(invariant_intrinsics),
observed_distorted_x_(observed_distorted_x),
observed_distorted_y_(observed_distorted_y),
@@ -253,11 +270,12 @@ struct ReprojectionErrorApplyIntrinsics {
T yn = x[1] / x[2];
T predicted_distorted_x, predicted_distorted_y;
- ApplyDistortionModelUsingIntrinsicsBlock(
- invariant_intrinsics_,
- intrinsics,
- xn, yn,
- &predicted_distorted_x, &predicted_distorted_y);
+ ApplyDistortionModelUsingIntrinsicsBlock(invariant_intrinsics_,
+ intrinsics,
+ xn,
+ yn,
+ &predicted_distorted_x,
+ &predicted_distorted_y);
// The error is the difference between the predicted and observed position.
residuals[0] = (predicted_distorted_x - T(observed_distorted_x_)) * weight_;
@@ -265,7 +283,7 @@ struct ReprojectionErrorApplyIntrinsics {
return true;
}
- const CameraIntrinsics *invariant_intrinsics_;
+ const CameraIntrinsics* invariant_intrinsics_;
const double observed_distorted_x_;
const double observed_distorted_y_;
const double weight_;
@@ -279,7 +297,7 @@ struct ReprojectionErrorApplyIntrinsics {
// defined Invert() function.
struct ReprojectionErrorInvertIntrinsics {
ReprojectionErrorInvertIntrinsics(
- const CameraIntrinsics *invariant_intrinsics,
+ const CameraIntrinsics* invariant_intrinsics,
const double observed_distorted_x,
const double observed_distorted_y,
const double weight)
@@ -295,8 +313,7 @@ struct ReprojectionErrorInvertIntrinsics {
const T* const X, // Point coordinates 3x1.
T* residuals) const {
// Unpack the intrinsics.
- const T& focal_length =
- intrinsics[PackedIntrinsics::OFFSET_FOCAL_LENGTH];
+ const T& focal_length = intrinsics[PackedIntrinsics::OFFSET_FOCAL_LENGTH];
const T& principal_point_x =
intrinsics[PackedIntrinsics::OFFSET_PRINCIPAL_POINT_X];
const T& principal_point_y =
@@ -327,14 +344,17 @@ struct ReprojectionErrorInvertIntrinsics {
InvertDistortionModelUsingIntrinsicsBlock(
invariant_intrinsics_,
intrinsics,
- T(observed_distorted_x_), T(observed_distorted_y_),
- &observed_undistorted_normalized_x, &observed_undistorted_normalized_y);
+ T(observed_distorted_x_),
+ T(observed_distorted_y_),
+ &observed_undistorted_normalized_x,
+ &observed_undistorted_normalized_y);
T observed_undistorted_image_x, observed_undistorted_image_y;
- NormalizedToImageSpace(
- intrinsics,
- observed_undistorted_normalized_x, observed_undistorted_normalized_y,
- &observed_undistorted_image_x, &observed_undistorted_image_y);
+ NormalizedToImageSpace(intrinsics,
+ observed_undistorted_normalized_x,
+ observed_undistorted_normalized_y,
+ &observed_undistorted_image_x,
+ &observed_undistorted_image_y);
// The error is the difference between the predicted and observed position.
residuals[0] = (predicted_x - observed_undistorted_image_x) * weight_;
@@ -343,7 +363,7 @@ struct ReprojectionErrorInvertIntrinsics {
return true;
}
- const CameraIntrinsics *invariant_intrinsics_;
+ const CameraIntrinsics* invariant_intrinsics_;
const double observed_distorted_x_;
const double observed_distorted_y_;
const double weight_;
@@ -352,28 +372,29 @@ struct ReprojectionErrorInvertIntrinsics {
// Print a message to the log which camera intrinsics are gonna to be optimized.
void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
- LOG(INFO) << "Bundling only camera positions.";
+ LG << "Bundling only camera positions.";
} else {
std::string bundling_message = "";
-#define APPEND_BUNDLING_INTRINSICS(name, flag) \
- if (bundle_intrinsics & flag) { \
- if (!bundling_message.empty()) { \
- bundling_message += ", "; \
- } \
- bundling_message += name; \
- } (void)0
+#define APPEND_BUNDLING_INTRINSICS(name, flag) \
+ if (bundle_intrinsics & flag) { \
+ if (!bundling_message.empty()) { \
+ bundling_message += ", "; \
+ } \
+ bundling_message += name; \
+ } \
+ (void)0
- APPEND_BUNDLING_INTRINSICS("f", BUNDLE_FOCAL_LENGTH);
+ APPEND_BUNDLING_INTRINSICS("f", BUNDLE_FOCAL_LENGTH);
APPEND_BUNDLING_INTRINSICS("px, py", BUNDLE_PRINCIPAL_POINT);
- APPEND_BUNDLING_INTRINSICS("k1", BUNDLE_RADIAL_K1);
- APPEND_BUNDLING_INTRINSICS("k2", BUNDLE_RADIAL_K2);
- APPEND_BUNDLING_INTRINSICS("k3", BUNDLE_RADIAL_K3);
- APPEND_BUNDLING_INTRINSICS("k4", BUNDLE_RADIAL_K4);
- APPEND_BUNDLING_INTRINSICS("p1", BUNDLE_TANGENTIAL_P1);
- APPEND_BUNDLING_INTRINSICS("p2", BUNDLE_TANGENTIAL_P2);
-
- LOG(INFO) << "Bundling " << bundling_message << ".";
+ APPEND_BUNDLING_INTRINSICS("k1", BUNDLE_RADIAL_K1);
+ APPEND_BUNDLING_INTRINSICS("k2", BUNDLE_RADIAL_K2);
+ APPEND_BUNDLING_INTRINSICS("k3", BUNDLE_RADIAL_K3);
+ APPEND_BUNDLING_INTRINSICS("k4", BUNDLE_RADIAL_K4);
+ APPEND_BUNDLING_INTRINSICS("p1", BUNDLE_TANGENTIAL_P1);
+ APPEND_BUNDLING_INTRINSICS("p2", BUNDLE_TANGENTIAL_P2);
+
+ LG << "Bundling " << bundling_message << ".";
}
}
@@ -383,7 +404,7 @@ void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
// Element with key i matches to a rotation+translation for
// camera at image i.
map<int, Vec6> PackCamerasRotationAndTranslation(
- const EuclideanReconstruction &reconstruction) {
+ const EuclideanReconstruction& reconstruction) {
map<int, Vec6> all_cameras_R_t;
vector<EuclideanCamera> all_cameras = reconstruction.AllCameras();
@@ -399,14 +420,13 @@ map<int, Vec6> PackCamerasRotationAndTranslation(
// Convert cameras rotations fro mangle axis back to rotation matrix.
void UnpackCamerasRotationAndTranslation(
- const map<int, Vec6> &all_cameras_R_t,
- EuclideanReconstruction *reconstruction) {
-
+ const map<int, Vec6>& all_cameras_R_t,
+ EuclideanReconstruction* reconstruction) {
for (map<int, Vec6>::value_type image_and_camera_R_T : all_cameras_R_t) {
const int image = image_and_camera_R_T.first;
const Vec6& camera_R_t = image_and_camera_R_T.second;
- EuclideanCamera *camera = reconstruction->CameraForImage(image);
+ EuclideanCamera* camera = reconstruction->CameraForImage(image);
if (!camera) {
continue;
}
@@ -421,8 +441,8 @@ void UnpackCamerasRotationAndTranslation(
//
// TODO(sergey): currently uses dense Eigen matrices, best would
// be to use sparse Eigen matrices
-void CRSMatrixToEigenMatrix(const ceres::CRSMatrix &crs_matrix,
- Mat *eigen_matrix) {
+void CRSMatrixToEigenMatrix(const ceres::CRSMatrix& crs_matrix,
+ Mat* eigen_matrix) {
eigen_matrix->resize(crs_matrix.num_rows, crs_matrix.num_cols);
eigen_matrix->setZero();
@@ -439,11 +459,11 @@ void CRSMatrixToEigenMatrix(const ceres::CRSMatrix &crs_matrix,
}
}
-void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
- EuclideanReconstruction *reconstruction,
- map<int, Vec6> *all_cameras_R_t,
- ceres::Problem *problem,
- BundleEvaluation *evaluation) {
+void EuclideanBundlerPerformEvaluation(const Tracks& tracks,
+ EuclideanReconstruction* reconstruction,
+ map<int, Vec6>* all_cameras_R_t,
+ ceres::Problem* problem,
+ BundleEvaluation* evaluation) {
int max_track = tracks.MaxTrack();
// Number of camera rotations equals to number of translation,
int num_cameras = all_cameras_R_t->size();
@@ -451,7 +471,7 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
vector<EuclideanPoint*> minimized_points;
for (int i = 0; i <= max_track; i++) {
- EuclideanPoint *point = reconstruction->PointForTrack(i);
+ EuclideanPoint* point = reconstruction->PointForTrack(i);
if (point) {
// We need to know whether the track is a constant zero weight.
// If it is so it wouldn't have a parameter block in the problem.
@@ -477,16 +497,16 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
evaluation->num_cameras = num_cameras;
evaluation->num_points = num_points;
- if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix.
+ if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix.
ceres::CRSMatrix evaluated_jacobian;
ceres::Problem::EvaluateOptions eval_options;
// Cameras goes first in the ordering.
int max_image = tracks.MaxImage();
for (int i = 0; i <= max_image; i++) {
- const EuclideanCamera *camera = reconstruction->CameraForImage(i);
+ const EuclideanCamera* camera = reconstruction->CameraForImage(i);
if (camera) {
- double *current_camera_R_t = &(*all_cameras_R_t)[i](0);
+ double* current_camera_R_t = &(*all_cameras_R_t)[i](0);
// All cameras are variable now.
problem->SetParameterBlockVariable(current_camera_R_t);
@@ -497,63 +517,65 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
// Points goes at the end of ordering,
for (int i = 0; i < minimized_points.size(); i++) {
- EuclideanPoint *point = minimized_points.at(i);
+ EuclideanPoint* point = minimized_points.at(i);
eval_options.parameter_blocks.push_back(&point->X(0));
}
- problem->Evaluate(eval_options,
- NULL, NULL, NULL,
- &evaluated_jacobian);
+ problem->Evaluate(eval_options, NULL, NULL, NULL, &evaluated_jacobian);
CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian);
}
}
-template<typename CostFunction>
-void AddResidualBlockToProblemImpl(const CameraIntrinsics *invariant_intrinsics,
- double observed_x, double observed_y,
+template <typename CostFunction>
+void AddResidualBlockToProblemImpl(const CameraIntrinsics* invariant_intrinsics,
+ double observed_x,
+ double observed_y,
double weight,
- double *intrinsics_block,
- double *camera_R_t,
- EuclideanPoint *point,
+ double* intrinsics_block,
+ double* camera_R_t,
+ EuclideanPoint* point,
ceres::Problem* problem) {
- problem->AddResidualBlock(new ceres::AutoDiffCostFunction<
- CostFunction, 2, PackedIntrinsics::NUM_PARAMETERS, 6, 3>(
- new CostFunction(
- invariant_intrinsics,
- observed_x, observed_y,
- weight)),
+ problem->AddResidualBlock(
+ new ceres::AutoDiffCostFunction<CostFunction,
+ 2,
+ PackedIntrinsics::NUM_PARAMETERS,
+ 6,
+ 3>(new CostFunction(
+ invariant_intrinsics, observed_x, observed_y, weight)),
NULL,
intrinsics_block,
camera_R_t,
&point->X(0));
}
-void AddResidualBlockToProblem(const CameraIntrinsics *invariant_intrinsics,
- const Marker &marker,
+void AddResidualBlockToProblem(const CameraIntrinsics* invariant_intrinsics,
+ const Marker& marker,
double marker_weight,
double* intrinsics_block,
- double *camera_R_t,
- EuclideanPoint *point,
+ double* camera_R_t,
+ EuclideanPoint* point,
ceres::Problem* problem) {
if (NeedUseInvertIntrinsicsPipeline(invariant_intrinsics)) {
AddResidualBlockToProblemImpl<ReprojectionErrorInvertIntrinsics>(
- invariant_intrinsics,
- marker.x, marker.y,
- marker_weight,
- intrinsics_block,
- camera_R_t,
- point,
- problem);
+ invariant_intrinsics,
+ marker.x,
+ marker.y,
+ marker_weight,
+ intrinsics_block,
+ camera_R_t,
+ point,
+ problem);
} else {
AddResidualBlockToProblemImpl<ReprojectionErrorApplyIntrinsics>(
- invariant_intrinsics,
- marker.x, marker.y,
- marker_weight,
- intrinsics_block,
- camera_R_t,
- point,
- problem);
+ invariant_intrinsics,
+ marker.x,
+ marker.y,
+ marker_weight,
+ intrinsics_block,
+ camera_R_t,
+ point,
+ problem);
}
}
@@ -566,25 +588,25 @@ void AddResidualBlockToProblem(const CameraIntrinsics *invariant_intrinsics,
//
// At this point we only need to bundle points positions, cameras
// are to be totally still here.
-void EuclideanBundlePointsOnly(const CameraIntrinsics *invariant_intrinsics,
- const vector<Marker> &markers,
- map<int, Vec6> &all_cameras_R_t,
+void EuclideanBundlePointsOnly(const CameraIntrinsics* invariant_intrinsics,
+ const vector<Marker>& markers,
+ map<int, Vec6>& all_cameras_R_t,
double* intrinsics_block,
- EuclideanReconstruction *reconstruction) {
+ EuclideanReconstruction* reconstruction) {
ceres::Problem::Options problem_options;
ceres::Problem problem(problem_options);
int num_residuals = 0;
for (int i = 0; i < markers.size(); ++i) {
- const Marker &marker = markers[i];
- EuclideanCamera *camera = reconstruction->CameraForImage(marker.image);
- EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
+ const Marker& marker = markers[i];
+ EuclideanCamera* camera = reconstruction->CameraForImage(marker.image);
+ EuclideanPoint* point = reconstruction->PointForTrack(marker.track);
if (camera == NULL || point == NULL) {
continue;
}
// Rotation of camera denoted in angle axis followed with
// camera translation.
- double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
+ double* current_camera_R_t = &all_cameras_R_t[camera->image](0);
AddResidualBlockToProblem(invariant_intrinsics,
marker,
@@ -625,8 +647,8 @@ void EuclideanBundlePointsOnly(const CameraIntrinsics *invariant_intrinsics,
} // namespace
-void EuclideanBundle(const Tracks &tracks,
- EuclideanReconstruction *reconstruction) {
+void EuclideanBundle(const Tracks& tracks,
+ EuclideanReconstruction* reconstruction) {
PolynomialCameraIntrinsics empty_intrinsics;
EuclideanBundleCommonIntrinsics(tracks,
BUNDLE_NO_INTRINSICS,
@@ -636,13 +658,12 @@ void EuclideanBundle(const Tracks &tracks,
NULL);
}
-void EuclideanBundleCommonIntrinsics(
- const Tracks &tracks,
- const int bundle_intrinsics,
- const int bundle_constraints,
- EuclideanReconstruction *reconstruction,
- CameraIntrinsics *intrinsics,
- BundleEvaluation *evaluation) {
+void EuclideanBundleCommonIntrinsics(const Tracks& tracks,
+ const int bundle_intrinsics,
+ const int bundle_constraints,
+ EuclideanReconstruction* reconstruction,
+ CameraIntrinsics* intrinsics,
+ BundleEvaluation* evaluation) {
LG << "Original intrinsics: " << *intrinsics;
vector<Marker> markers = tracks.AllMarkers();
@@ -661,19 +682,19 @@ void EuclideanBundleCommonIntrinsics(
// Block for minimization has got the following structure:
// <3 elements for angle-axis> <3 elements for translation>
map<int, Vec6> all_cameras_R_t =
- PackCamerasRotationAndTranslation(*reconstruction);
+ PackCamerasRotationAndTranslation(*reconstruction);
// Parameterization used to restrict camera motion for modal solvers.
- ceres::SubsetParameterization *constant_translation_parameterization = NULL;
+ ceres::SubsetParameterization* constant_translation_parameterization = NULL;
if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
- std::vector<int> constant_translation;
+ std::vector<int> constant_translation;
- // First three elements are rotation, ast three are translation.
- constant_translation.push_back(3);
- constant_translation.push_back(4);
- constant_translation.push_back(5);
+ // First three elements are rotation, ast three are translation.
+ constant_translation.push_back(3);
+ constant_translation.push_back(4);
+ constant_translation.push_back(5);
- constant_translation_parameterization =
+ constant_translation_parameterization =
new ceres::SubsetParameterization(6, constant_translation);
}
@@ -683,16 +704,16 @@ void EuclideanBundleCommonIntrinsics(
int num_residuals = 0;
bool have_locked_camera = false;
for (int i = 0; i < markers.size(); ++i) {
- const Marker &marker = markers[i];
- EuclideanCamera *camera = reconstruction->CameraForImage(marker.image);
- EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
+ const Marker& marker = markers[i];
+ EuclideanCamera* camera = reconstruction->CameraForImage(marker.image);
+ EuclideanPoint* point = reconstruction->PointForTrack(marker.track);
if (camera == NULL || point == NULL) {
continue;
}
// Rotation of camera denoted in angle axis followed with
// camera translation.
- double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
+ double* current_camera_R_t = &all_cameras_R_t[camera->image](0);
// Skip residual block for markers which does have absolutely
// no affect on the final solution.
@@ -706,7 +727,8 @@ void EuclideanBundleCommonIntrinsics(
point,
&problem);
- // We lock the first camera to better deal with scene orientation ambiguity.
+ // We lock the first camera to better deal with scene orientation
+ // ambiguity.
if (!have_locked_camera) {
problem.SetParameterBlockConstant(current_camera_R_t);
have_locked_camera = true;
@@ -729,7 +751,7 @@ void EuclideanBundleCommonIntrinsics(
}
if (intrinsics->GetDistortionModelType() == DISTORTION_MODEL_DIVISION &&
- (bundle_intrinsics & BUNDLE_TANGENTIAL) != 0) {
+ (bundle_intrinsics & BUNDLE_TANGENTIAL) != 0) {
LOG(FATAL) << "Division model doesn't support bundling "
"of tangential distortion";
}
@@ -745,29 +767,29 @@ void EuclideanBundleCommonIntrinsics(
// constant using some macro trickery.
std::vector<int> constant_intrinsics;
-#define MAYBE_SET_CONSTANT(bundle_enum, offset) \
- if (!(bundle_intrinsics & bundle_enum) || \
- !packed_intrinsics.IsParameterDefined(offset)) { \
- constant_intrinsics.push_back(offset); \
- }
+#define MAYBE_SET_CONSTANT(bundle_enum, offset) \
+ if (!(bundle_intrinsics & bundle_enum) || \
+ !packed_intrinsics.IsParameterDefined(offset)) { \
+ constant_intrinsics.push_back(offset); \
+ }
MAYBE_SET_CONSTANT(BUNDLE_FOCAL_LENGTH,
PackedIntrinsics::OFFSET_FOCAL_LENGTH);
MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT,
PackedIntrinsics::OFFSET_PRINCIPAL_POINT_X);
MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT,
PackedIntrinsics::OFFSET_PRINCIPAL_POINT_Y);
- MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K1, PackedIntrinsics::OFFSET_K1);
- MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K2, PackedIntrinsics::OFFSET_K2);
- MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K3, PackedIntrinsics::OFFSET_K3);
- MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K4, PackedIntrinsics::OFFSET_K4);
- MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P1, PackedIntrinsics::OFFSET_P1);
- MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P2, PackedIntrinsics::OFFSET_P2);
+ MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K1, PackedIntrinsics::OFFSET_K1);
+ MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K2, PackedIntrinsics::OFFSET_K2);
+ MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K3, PackedIntrinsics::OFFSET_K3);
+ MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K4, PackedIntrinsics::OFFSET_K4);
+ MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P1, PackedIntrinsics::OFFSET_P1);
+ MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P2, PackedIntrinsics::OFFSET_P2);
#undef MAYBE_SET_CONSTANT
if (!constant_intrinsics.empty()) {
- ceres::SubsetParameterization *subset_parameterization =
- new ceres::SubsetParameterization(PackedIntrinsics::NUM_PARAMETERS,
- constant_intrinsics);
+ ceres::SubsetParameterization* subset_parameterization =
+ new ceres::SubsetParameterization(PackedIntrinsics::NUM_PARAMETERS,
+ constant_intrinsics);
problem.SetParameterization(intrinsics_block, subset_parameterization);
}
@@ -800,8 +822,8 @@ void EuclideanBundleCommonIntrinsics(
LG << "Final intrinsics: " << *intrinsics;
if (evaluation) {
- EuclideanBundlerPerformEvaluation(tracks, reconstruction, &all_cameras_R_t,
- &problem, evaluation);
+ EuclideanBundlerPerformEvaluation(
+ tracks, reconstruction, &all_cameras_R_t, &problem, evaluation);
}
// Separate step to adjust positions of tracks which are
@@ -828,8 +850,8 @@ void EuclideanBundleCommonIntrinsics(
}
}
-void ProjectiveBundle(const Tracks & /*tracks*/,
- ProjectiveReconstruction * /*reconstruction*/) {
+void ProjectiveBundle(const Tracks& /*tracks*/,
+ ProjectiveReconstruction* /*reconstruction*/) {
// TODO(keir): Implement this! This can't work until we have a better bundler
// than SSBA, since SSBA has no support for projective bundling.
}
diff --git a/intern/libmv/libmv/simple_pipeline/bundle.h b/intern/libmv/libmv/simple_pipeline/bundle.h
index 5f420da0045..662313b396a 100644
--- a/intern/libmv/libmv/simple_pipeline/bundle.h
+++ b/intern/libmv/libmv/simple_pipeline/bundle.h
@@ -31,11 +31,8 @@ class ProjectiveReconstruction;
class Tracks;
struct BundleEvaluation {
- BundleEvaluation() :
- num_cameras(0),
- num_points(0),
- evaluate_jacobian(false) {
- }
+ BundleEvaluation()
+ : num_cameras(0), num_points(0), evaluate_jacobian(false) {}
// Number of cameras appeared in bundle adjustment problem
int num_cameras;
@@ -72,8 +69,8 @@ struct BundleEvaluation {
\sa EuclideanResect, EuclideanIntersect, EuclideanReconstructTwoFrames
*/
-void EuclideanBundle(const Tracks &tracks,
- EuclideanReconstruction *reconstruction);
+void EuclideanBundle(const Tracks& tracks,
+ EuclideanReconstruction* reconstruction);
/*!
Refine camera poses and 3D coordinates using bundle adjustment.
@@ -109,9 +106,7 @@ enum BundleIntrinsics {
BUNDLE_RADIAL_K2 = (1 << 3),
BUNDLE_RADIAL_K3 = (1 << 4),
BUNDLE_RADIAL_K4 = (1 << 5),
- BUNDLE_RADIAL = (BUNDLE_RADIAL_K1 |
- BUNDLE_RADIAL_K2 |
- BUNDLE_RADIAL_K3 |
+ BUNDLE_RADIAL = (BUNDLE_RADIAL_K1 | BUNDLE_RADIAL_K2 | BUNDLE_RADIAL_K3 |
BUNDLE_RADIAL_K4),
BUNDLE_TANGENTIAL_P1 = (1 << 6),
@@ -122,13 +117,12 @@ enum BundleConstraints {
BUNDLE_NO_CONSTRAINTS = 0,
BUNDLE_NO_TRANSLATION = 1,
};
-void EuclideanBundleCommonIntrinsics(
- const Tracks &tracks,
- const int bundle_intrinsics,
- const int bundle_constraints,
- EuclideanReconstruction *reconstruction,
- CameraIntrinsics *intrinsics,
- BundleEvaluation *evaluation = NULL);
+void EuclideanBundleCommonIntrinsics(const Tracks& tracks,
+ const int bundle_intrinsics,
+ const int bundle_constraints,
+ EuclideanReconstruction* reconstruction,
+ CameraIntrinsics* intrinsics,
+ BundleEvaluation* evaluation = NULL);
/*!
Refine camera poses and 3D coordinates using bundle adjustment.
@@ -147,10 +141,9 @@ void EuclideanBundleCommonIntrinsics(
\sa ProjectiveResect, ProjectiveIntersect, ProjectiveReconstructTwoFrames
*/
-void ProjectiveBundle(const Tracks &tracks,
- ProjectiveReconstruction *reconstruction);
+void ProjectiveBundle(const Tracks& tracks,
+ ProjectiveReconstruction* reconstruction);
} // namespace libmv
-#endif // LIBMV_SIMPLE_PIPELINE_BUNDLE_H
-
+#endif // LIBMV_SIMPLE_PIPELINE_BUNDLE_H
diff --git a/intern/libmv/libmv/simple_pipeline/callbacks.h b/intern/libmv/libmv/simple_pipeline/callbacks.h
index 58f7b0d3cc9..a6855a9e5e7 100644
--- a/intern/libmv/libmv/simple_pipeline/callbacks.h
+++ b/intern/libmv/libmv/simple_pipeline/callbacks.h
@@ -26,7 +26,7 @@ namespace libmv {
class ProgressUpdateCallback {
public:
virtual ~ProgressUpdateCallback() {}
- virtual void invoke(double progress, const char *message) = 0;
+ virtual void invoke(double progress, const char* message) = 0;
};
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
index ccb6e3d34c8..b86e316b139 100644
--- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
+++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
@@ -29,13 +29,10 @@ namespace libmv {
namespace internal {
LookupWarpGrid::LookupWarpGrid()
- : offset_(NULL),
- width_(0),
- height_(0),
- overscan_(0.0),
- threads_(1) {}
+ : offset_(NULL), width_(0), height_(0), overscan_(0.0), threads_(1) {
+}
-LookupWarpGrid::LookupWarpGrid(const LookupWarpGrid &from)
+LookupWarpGrid::LookupWarpGrid(const LookupWarpGrid& from)
: offset_(NULL),
width_(from.width_),
height_(from.height_),
@@ -48,11 +45,11 @@ LookupWarpGrid::LookupWarpGrid(const LookupWarpGrid &from)
}
LookupWarpGrid::~LookupWarpGrid() {
- delete [] offset_;
+ delete[] offset_;
}
void LookupWarpGrid::Reset() {
- delete [] offset_;
+ delete[] offset_;
offset_ = NULL;
}
@@ -64,16 +61,16 @@ void LookupWarpGrid::SetThreads(int threads) {
} // namespace internal
CameraIntrinsics::CameraIntrinsics()
- : image_width_(0),
- image_height_(0),
- K_(Mat3::Identity()) {}
+ : image_width_(0), image_height_(0), K_(Mat3::Identity()) {
+}
-CameraIntrinsics::CameraIntrinsics(const CameraIntrinsics &from)
+CameraIntrinsics::CameraIntrinsics(const CameraIntrinsics& from)
: image_width_(from.image_width_),
image_height_(from.image_height_),
K_(from.K_),
distort_(from.distort_),
- undistort_(from.undistort_) {}
+ undistort_(from.undistort_) {
+}
// Set the image size in pixels.
void CameraIntrinsics::SetImageSize(int width, int height) {
@@ -89,16 +86,14 @@ void CameraIntrinsics::SetK(const Mat3 new_k) {
}
// Set both x and y focal length in pixels.
-void CameraIntrinsics::SetFocalLength(double focal_x,
- double focal_y) {
+void CameraIntrinsics::SetFocalLength(double focal_x, double focal_y) {
K_(0, 0) = focal_x;
K_(1, 1) = focal_y;
ResetLookupGrids();
}
// Set principal point in pixels.
-void CameraIntrinsics::SetPrincipalPoint(double cx,
- double cy) {
+void CameraIntrinsics::SetPrincipalPoint(double cx, double cy) {
K_(0, 2) = cx;
K_(1, 2) = cy;
ResetLookupGrids();
@@ -112,16 +107,16 @@ void CameraIntrinsics::SetThreads(int threads) {
void CameraIntrinsics::ImageSpaceToNormalized(double image_x,
double image_y,
- double *normalized_x,
- double *normalized_y) const {
+ double* normalized_x,
+ double* normalized_y) const {
*normalized_x = (image_x - principal_point_x()) / focal_length_x();
*normalized_y = (image_y - principal_point_y()) / focal_length_y();
}
void CameraIntrinsics::NormalizedToImageSpace(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const {
+ double* image_x,
+ double* image_y) const {
*image_x = normalized_x * focal_length_x() + principal_point_x();
*image_y = normalized_y * focal_length_y() + principal_point_y();
}
@@ -148,14 +143,13 @@ void CameraIntrinsics::Unpack(const PackedIntrinsics& packed_intrinsics) {
// Polynomial model.
-PolynomialCameraIntrinsics::PolynomialCameraIntrinsics()
- : CameraIntrinsics() {
+PolynomialCameraIntrinsics::PolynomialCameraIntrinsics() : CameraIntrinsics() {
SetRadialDistortion(0.0, 0.0, 0.0);
SetTangentialDistortion(0.0, 0.0);
}
PolynomialCameraIntrinsics::PolynomialCameraIntrinsics(
- const PolynomialCameraIntrinsics &from)
+ const PolynomialCameraIntrinsics& from)
: CameraIntrinsics(from) {
SetRadialDistortion(from.k1(), from.k2(), from.k3());
SetTangentialDistortion(from.p1(), from.p2());
@@ -170,8 +164,7 @@ void PolynomialCameraIntrinsics::SetRadialDistortion(double k1,
ResetLookupGrids();
}
-void PolynomialCameraIntrinsics::SetTangentialDistortion(double p1,
- double p2) {
+void PolynomialCameraIntrinsics::SetTangentialDistortion(double p1, double p2) {
parameters_[OFFSET_P1] = p1;
parameters_[OFFSET_P2] = p2;
ResetLookupGrids();
@@ -179,31 +172,36 @@ void PolynomialCameraIntrinsics::SetTangentialDistortion(double p1,
void PolynomialCameraIntrinsics::ApplyIntrinsics(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const {
+ double* image_x,
+ double* image_y) const {
ApplyPolynomialDistortionModel(focal_length_x(),
focal_length_y(),
principal_point_x(),
principal_point_y(),
- k1(), k2(), k3(),
- p1(), p2(),
+ k1(),
+ k2(),
+ k3(),
+ p1(),
+ p2(),
normalized_x,
normalized_y,
image_x,
image_y);
}
-void PolynomialCameraIntrinsics::InvertIntrinsics(
- double image_x,
- double image_y,
- double *normalized_x,
- double *normalized_y) const {
+void PolynomialCameraIntrinsics::InvertIntrinsics(double image_x,
+ double image_y,
+ double* normalized_x,
+ double* normalized_y) const {
InvertPolynomialDistortionModel(focal_length_x(),
focal_length_y(),
principal_point_x(),
principal_point_y(),
- k1(), k2(), k3(),
- p1(), p2(),
+ k1(),
+ k2(),
+ k3(),
+ p1(),
+ p2(),
image_x,
image_y,
normalized_x,
@@ -230,25 +228,22 @@ void PolynomialCameraIntrinsics::Unpack(
packed_intrinsics.GetK2(),
packed_intrinsics.GetK3());
- SetTangentialDistortion(packed_intrinsics.GetP1(),
- packed_intrinsics.GetP2());
+ SetTangentialDistortion(packed_intrinsics.GetP1(), packed_intrinsics.GetP2());
}
// Division model.
-DivisionCameraIntrinsics::DivisionCameraIntrinsics()
- : CameraIntrinsics() {
+DivisionCameraIntrinsics::DivisionCameraIntrinsics() : CameraIntrinsics() {
SetDistortion(0.0, 0.0);
}
DivisionCameraIntrinsics::DivisionCameraIntrinsics(
- const DivisionCameraIntrinsics &from)
+ const DivisionCameraIntrinsics& from)
: CameraIntrinsics(from) {
SetDistortion(from.k1(), from.k1());
}
-void DivisionCameraIntrinsics::SetDistortion(double k1,
- double k2) {
+void DivisionCameraIntrinsics::SetDistortion(double k1, double k2) {
parameters_[OFFSET_K1] = k1;
parameters_[OFFSET_K2] = k2;
ResetLookupGrids();
@@ -256,13 +251,14 @@ void DivisionCameraIntrinsics::SetDistortion(double k1,
void DivisionCameraIntrinsics::ApplyIntrinsics(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const {
+ double* image_x,
+ double* image_y) const {
ApplyDivisionDistortionModel(focal_length_x(),
focal_length_y(),
principal_point_x(),
principal_point_y(),
- k1(), k2(),
+ k1(),
+ k2(),
normalized_x,
normalized_y,
image_x,
@@ -271,21 +267,21 @@ void DivisionCameraIntrinsics::ApplyIntrinsics(double normalized_x,
void DivisionCameraIntrinsics::InvertIntrinsics(double image_x,
double image_y,
- double *normalized_x,
- double *normalized_y) const {
+ double* normalized_x,
+ double* normalized_y) const {
InvertDivisionDistortionModel(focal_length_x(),
focal_length_y(),
principal_point_x(),
principal_point_y(),
- k1(), k2(),
+ k1(),
+ k2(),
image_x,
image_y,
normalized_x,
normalized_y);
}
-void DivisionCameraIntrinsics::Pack(
- PackedIntrinsics* packed_intrinsics) const {
+void DivisionCameraIntrinsics::Pack(PackedIntrinsics* packed_intrinsics) const {
CameraIntrinsics::Pack(packed_intrinsics);
packed_intrinsics->SetK1(k1());
@@ -301,13 +297,11 @@ void DivisionCameraIntrinsics::Unpack(
// Nuke model.
-NukeCameraIntrinsics::NukeCameraIntrinsics()
- : CameraIntrinsics() {
+NukeCameraIntrinsics::NukeCameraIntrinsics() : CameraIntrinsics() {
SetDistortion(0.0, 0.0);
}
-NukeCameraIntrinsics::NukeCameraIntrinsics(
- const NukeCameraIntrinsics &from)
+NukeCameraIntrinsics::NukeCameraIntrinsics(const NukeCameraIntrinsics& from)
: CameraIntrinsics(from) {
SetDistortion(from.k1(), from.k2());
}
@@ -320,14 +314,16 @@ void NukeCameraIntrinsics::SetDistortion(double k1, double k2) {
void NukeCameraIntrinsics::ApplyIntrinsics(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const {
+ double* image_x,
+ double* image_y) const {
ApplyNukeDistortionModel(focal_length_x(),
focal_length_y(),
principal_point_x(),
principal_point_y(),
- image_width(), image_height(),
- k1(), k2(),
+ image_width(),
+ image_height(),
+ k1(),
+ k2(),
normalized_x,
normalized_y,
image_x,
@@ -335,31 +331,31 @@ void NukeCameraIntrinsics::ApplyIntrinsics(double normalized_x,
}
void NukeCameraIntrinsics::InvertIntrinsics(double image_x,
- double image_y,
- double *normalized_x,
- double *normalized_y) const {
+ double image_y,
+ double* normalized_x,
+ double* normalized_y) const {
InvertNukeDistortionModel(focal_length_x(),
focal_length_y(),
principal_point_x(),
principal_point_y(),
- image_width(), image_height(),
- k1(), k2(),
+ image_width(),
+ image_height(),
+ k1(),
+ k2(),
image_x,
image_y,
normalized_x,
normalized_y);
}
-void NukeCameraIntrinsics::Pack(
- PackedIntrinsics* packed_intrinsics) const {
+void NukeCameraIntrinsics::Pack(PackedIntrinsics* packed_intrinsics) const {
CameraIntrinsics::Pack(packed_intrinsics);
packed_intrinsics->SetK1(k1());
packed_intrinsics->SetK2(k2());
}
-void NukeCameraIntrinsics::Unpack(
- const PackedIntrinsics& packed_intrinsics) {
+void NukeCameraIntrinsics::Unpack(const PackedIntrinsics& packed_intrinsics) {
CameraIntrinsics::Unpack(packed_intrinsics);
SetDistortion(packed_intrinsics.GetK1(), packed_intrinsics.GetK2());
@@ -367,14 +363,12 @@ void NukeCameraIntrinsics::Unpack(
// Brown model.
-BrownCameraIntrinsics::BrownCameraIntrinsics()
- : CameraIntrinsics() {
+BrownCameraIntrinsics::BrownCameraIntrinsics() : CameraIntrinsics() {
SetRadialDistortion(0.0, 0.0, 0.0, 0.0);
SetTangentialDistortion(0.0, 0.0);
}
-BrownCameraIntrinsics::BrownCameraIntrinsics(
- const BrownCameraIntrinsics &from)
+BrownCameraIntrinsics::BrownCameraIntrinsics(const BrownCameraIntrinsics& from)
: CameraIntrinsics(from) {
SetRadialDistortion(from.k1(), from.k2(), from.k3(), from.k4());
SetTangentialDistortion(from.p1(), from.p2());
@@ -391,8 +385,7 @@ void BrownCameraIntrinsics::SetRadialDistortion(double k1,
ResetLookupGrids();
}
-void BrownCameraIntrinsics::SetTangentialDistortion(double p1,
- double p2) {
+void BrownCameraIntrinsics::SetTangentialDistortion(double p1, double p2) {
parameters_[OFFSET_P1] = p1;
parameters_[OFFSET_P2] = p2;
ResetLookupGrids();
@@ -400,39 +393,45 @@ void BrownCameraIntrinsics::SetTangentialDistortion(double p1,
void BrownCameraIntrinsics::ApplyIntrinsics(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const {
+ double* image_x,
+ double* image_y) const {
ApplyBrownDistortionModel(focal_length_x(),
focal_length_y(),
principal_point_x(),
principal_point_y(),
- k1(), k2(), k3(), k4(),
- p1(), p2(),
+ k1(),
+ k2(),
+ k3(),
+ k4(),
+ p1(),
+ p2(),
normalized_x,
normalized_y,
image_x,
image_y);
}
-void BrownCameraIntrinsics::InvertIntrinsics(
- double image_x,
- double image_y,
- double *normalized_x,
- double *normalized_y) const {
+void BrownCameraIntrinsics::InvertIntrinsics(double image_x,
+ double image_y,
+ double* normalized_x,
+ double* normalized_y) const {
InvertBrownDistortionModel(focal_length_x(),
focal_length_y(),
principal_point_x(),
principal_point_y(),
- k1(), k2(), k3(), k4(),
- p1(), p2(),
+ k1(),
+ k2(),
+ k3(),
+ k4(),
+ p1(),
+ p2(),
image_x,
image_y,
normalized_x,
normalized_y);
}
-void BrownCameraIntrinsics::Pack(
- PackedIntrinsics* packed_intrinsics) const {
+void BrownCameraIntrinsics::Pack(PackedIntrinsics* packed_intrinsics) const {
CameraIntrinsics::Pack(packed_intrinsics);
packed_intrinsics->SetK1(k1());
@@ -444,8 +443,7 @@ void BrownCameraIntrinsics::Pack(
packed_intrinsics->SetP2(p2());
}
-void BrownCameraIntrinsics::Unpack(
- const PackedIntrinsics& packed_intrinsics) {
+void BrownCameraIntrinsics::Unpack(const PackedIntrinsics& packed_intrinsics) {
CameraIntrinsics::Unpack(packed_intrinsics);
SetRadialDistortion(packed_intrinsics.GetK1(),
@@ -453,72 +451,65 @@ void BrownCameraIntrinsics::Unpack(
packed_intrinsics.GetK3(),
packed_intrinsics.GetK4());
- SetTangentialDistortion(packed_intrinsics.GetP1(),
- packed_intrinsics.GetP2());
+ SetTangentialDistortion(packed_intrinsics.GetP1(), packed_intrinsics.GetP2());
}
-std::ostream& operator <<(std::ostream &os,
- const CameraIntrinsics &intrinsics) {
+std::ostream& operator<<(std::ostream& os, const CameraIntrinsics& intrinsics) {
if (intrinsics.focal_length_x() == intrinsics.focal_length_x()) {
os << "f=" << intrinsics.focal_length();
} else {
- os << "fx=" << intrinsics.focal_length_x()
+ os << "fx=" << intrinsics.focal_length_x()
<< " fy=" << intrinsics.focal_length_y();
}
os << " cx=" << intrinsics.principal_point_x()
<< " cy=" << intrinsics.principal_point_y()
- << " w=" << intrinsics.image_width()
- << " h=" << intrinsics.image_height();
+ << " w=" << intrinsics.image_width() << " h=" << intrinsics.image_height();
-#define PRINT_NONZERO_COEFFICIENT(intrinsics, coeff) \
- { \
- if (intrinsics->coeff() != 0.0) { \
- os << " " #coeff "=" << intrinsics->coeff(); \
- } \
- } (void) 0
+#define PRINT_NONZERO_COEFFICIENT(intrinsics, coeff) \
+ { \
+ if (intrinsics->coeff() != 0.0) { \
+ os << " " #coeff "=" << intrinsics->coeff(); \
+ } \
+ } \
+ (void)0
switch (intrinsics.GetDistortionModelType()) {
- case DISTORTION_MODEL_POLYNOMIAL:
- {
- const PolynomialCameraIntrinsics *polynomial_intrinsics =
- static_cast<const PolynomialCameraIntrinsics *>(&intrinsics);
- PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, k1);
- PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, k2);
- PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, k3);
- PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, p1);
- PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, p2);
- break;
- }
- case DISTORTION_MODEL_DIVISION:
- {
- const DivisionCameraIntrinsics *division_intrinsics =
- static_cast<const DivisionCameraIntrinsics *>(&intrinsics);
- PRINT_NONZERO_COEFFICIENT(division_intrinsics, k1);
- PRINT_NONZERO_COEFFICIENT(division_intrinsics, k2);
- break;
- }
- case DISTORTION_MODEL_NUKE:
- {
- const NukeCameraIntrinsics *nuke_intrinsics =
- static_cast<const NukeCameraIntrinsics *>(&intrinsics);
- PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k1);
- PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k2);
- break;
- }
- case DISTORTION_MODEL_BROWN:
- {
- const BrownCameraIntrinsics *brown_intrinsics =
- static_cast<const BrownCameraIntrinsics *>(&intrinsics);
- PRINT_NONZERO_COEFFICIENT(brown_intrinsics, k1);
- PRINT_NONZERO_COEFFICIENT(brown_intrinsics, k2);
- PRINT_NONZERO_COEFFICIENT(brown_intrinsics, k3);
- PRINT_NONZERO_COEFFICIENT(brown_intrinsics, k4);
- PRINT_NONZERO_COEFFICIENT(brown_intrinsics, p1);
- PRINT_NONZERO_COEFFICIENT(brown_intrinsics, p2);
- break;
- }
- default:
- LOG(FATAL) << "Unknown distortion model.";
+ case DISTORTION_MODEL_POLYNOMIAL: {
+ const PolynomialCameraIntrinsics* polynomial_intrinsics =
+ static_cast<const PolynomialCameraIntrinsics*>(&intrinsics);
+ PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, k1);
+ PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, k2);
+ PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, k3);
+ PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, p1);
+ PRINT_NONZERO_COEFFICIENT(polynomial_intrinsics, p2);
+ break;
+ }
+ case DISTORTION_MODEL_DIVISION: {
+ const DivisionCameraIntrinsics* division_intrinsics =
+ static_cast<const DivisionCameraIntrinsics*>(&intrinsics);
+ PRINT_NONZERO_COEFFICIENT(division_intrinsics, k1);
+ PRINT_NONZERO_COEFFICIENT(division_intrinsics, k2);
+ break;
+ }
+ case DISTORTION_MODEL_NUKE: {
+ const NukeCameraIntrinsics* nuke_intrinsics =
+ static_cast<const NukeCameraIntrinsics*>(&intrinsics);
+ PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k1);
+ PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k2);
+ break;
+ }
+ case DISTORTION_MODEL_BROWN: {
+ const BrownCameraIntrinsics* brown_intrinsics =
+ static_cast<const BrownCameraIntrinsics*>(&intrinsics);
+ PRINT_NONZERO_COEFFICIENT(brown_intrinsics, k1);
+ PRINT_NONZERO_COEFFICIENT(brown_intrinsics, k2);
+ PRINT_NONZERO_COEFFICIENT(brown_intrinsics, k3);
+ PRINT_NONZERO_COEFFICIENT(brown_intrinsics, k4);
+ PRINT_NONZERO_COEFFICIENT(brown_intrinsics, p1);
+ PRINT_NONZERO_COEFFICIENT(brown_intrinsics, p2);
+ break;
+ }
+ default: LOG(FATAL) << "Unknown distortion model.";
}
#undef PRINT_NONZERO_COEFFICIENT
diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h
index ba67ec468dc..efe0735bd93 100644
--- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h
+++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h
@@ -43,11 +43,11 @@ namespace internal {
class LookupWarpGrid {
public:
LookupWarpGrid();
- LookupWarpGrid(const LookupWarpGrid &from);
+ LookupWarpGrid(const LookupWarpGrid& from);
~LookupWarpGrid();
// Width and height og the image, measured in pixels.
- int width() const { return width_; }
+ int width() const { return width_; }
int height() const { return height_; }
// Overscan factor of the image, so that
@@ -61,8 +61,8 @@ class LookupWarpGrid {
//
// See comment for CameraIntrinsics::DistortBuffer to get more
// details about what overscan is.
- template<typename WarpFunction>
- void Update(const CameraIntrinsics &intrinsics,
+ template <typename WarpFunction>
+ void Update(const CameraIntrinsics& intrinsics,
int width,
int height,
double overscan);
@@ -71,12 +71,12 @@ class LookupWarpGrid {
//
// See comment for CameraIntrinsics::DistortBuffer to get more
// details about template type.
- template<typename PixelType>
- void Apply(const PixelType *input_buffer,
+ template <typename PixelType>
+ void Apply(const PixelType* input_buffer,
int width,
int height,
int channels,
- PixelType *output_buffer);
+ PixelType* output_buffer);
// Reset lookup grids.
// This will tag the grid for update without re-computing it.
@@ -105,15 +105,15 @@ class LookupWarpGrid {
//
// width and height corresponds to a size of buffer which will
// be warped later.
- template<typename WarpFunction>
- void Compute(const CameraIntrinsics &intrinsics,
+ template <typename WarpFunction>
+ void Compute(const CameraIntrinsics& intrinsics,
int width,
int height,
double overscan);
// This is a buffer which contains per-pixel offset of the
// pixels from input buffer to correspond the warping function.
- Offset *offset_;
+ Offset* offset_;
// Dimensions of the image this lookup grid processes.
int width_, height_;
@@ -130,19 +130,19 @@ class LookupWarpGrid {
class CameraIntrinsics {
public:
CameraIntrinsics();
- CameraIntrinsics(const CameraIntrinsics &from);
+ CameraIntrinsics(const CameraIntrinsics& from);
virtual ~CameraIntrinsics() {}
virtual DistortionModelType GetDistortionModelType() const = 0;
- int image_width() const { return image_width_; }
+ int image_width() const { return image_width_; }
int image_height() const { return image_height_; }
- const Mat3 &K() const { return K_; }
+ const Mat3& K() const { return K_; }
- double focal_length() const { return K_(0, 0); }
- double focal_length_x() const { return K_(0, 0); }
- double focal_length_y() const { return K_(1, 1); }
+ double focal_length() const { return K_(0, 0); }
+ double focal_length_x() const { return K_(0, 0); }
+ double focal_length_y() const { return K_(1, 1); }
double principal_point_x() const { return K_(0, 2); }
double principal_point_y() const { return K_(1, 2); }
@@ -166,14 +166,14 @@ class CameraIntrinsics {
// Convert image space coordinates to normalized.
void ImageSpaceToNormalized(double image_x,
double image_y,
- double *normalized_x,
- double *normalized_y) const;
+ double* normalized_x,
+ double* normalized_y) const;
// Convert normalized coordinates to image space.
void NormalizedToImageSpace(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const;
+ double* image_x,
+ double* image_y) const;
// Apply camera intrinsics to the normalized point to get image coordinates.
//
@@ -182,8 +182,8 @@ class CameraIntrinsics {
// coordinates in pixels.
virtual void ApplyIntrinsics(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const = 0;
+ double* image_x,
+ double* image_y) const = 0;
// Invert camera intrinsics on the image point to get normalized coordinates.
//
@@ -191,8 +191,8 @@ class CameraIntrinsics {
// coordinates to get normalized camera coordinates.
virtual void InvertIntrinsics(double image_x,
double image_y,
- double *normalized_x,
- double *normalized_y) const = 0;
+ double* normalized_x,
+ double* normalized_y) const = 0;
virtual void Pack(PackedIntrinsics* packed_intrinsics) const;
virtual void Unpack(const PackedIntrinsics& packed_intrinsics);
@@ -218,13 +218,13 @@ class CameraIntrinsics {
// But in fact PixelType might be any type for which multiplication by
// a scalar and addition are implemented. For example PixelType might be
// Vec3 as well.
- template<typename PixelType>
- void DistortBuffer(const PixelType *input_buffer,
+ template <typename PixelType>
+ void DistortBuffer(const PixelType* input_buffer,
int width,
int height,
double overscan,
int channels,
- PixelType *output_buffer);
+ PixelType* output_buffer);
// Undistort an image using the current camera instrinsics
//
@@ -247,13 +247,13 @@ class CameraIntrinsics {
// But in fact PixelType might be any type for which multiplication by
// a scalar and addition are implemented. For example PixelType might be
// Vec3 as well.
- template<typename PixelType>
- void UndistortBuffer(const PixelType *input_buffer,
+ template <typename PixelType>
+ void UndistortBuffer(const PixelType* input_buffer,
int width,
int height,
double overscan,
int channels,
- PixelType *output_buffer);
+ PixelType* output_buffer);
private:
// This is the size of the image. This is necessary to, for example, handle
@@ -290,7 +290,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics {
};
PolynomialCameraIntrinsics();
- PolynomialCameraIntrinsics(const PolynomialCameraIntrinsics &from);
+ PolynomialCameraIntrinsics(const PolynomialCameraIntrinsics& from);
DistortionModelType GetDistortionModelType() const override {
return DISTORTION_MODEL_POLYNOMIAL;
@@ -315,8 +315,8 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics {
// coordinates in pixels.
void ApplyIntrinsics(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const override;
+ double* image_x,
+ double* image_y) const override;
// Invert camera intrinsics on the image point to get normalized coordinates.
//
@@ -324,8 +324,8 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics {
// coordinates to get normalized camera coordinates.
void InvertIntrinsics(double image_x,
double image_y,
- double *normalized_x,
- double *normalized_y) const override;
+ double* normalized_x,
+ double* normalized_y) const override;
virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
@@ -352,7 +352,7 @@ class DivisionCameraIntrinsics : public CameraIntrinsics {
};
DivisionCameraIntrinsics();
- DivisionCameraIntrinsics(const DivisionCameraIntrinsics &from);
+ DivisionCameraIntrinsics(const DivisionCameraIntrinsics& from);
DistortionModelType GetDistortionModelType() const override {
return DISTORTION_MODEL_DIVISION;
@@ -371,8 +371,8 @@ class DivisionCameraIntrinsics : public CameraIntrinsics {
// coordinates in pixels.
void ApplyIntrinsics(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const override;
+ double* image_x,
+ double* image_y) const override;
// Invert camera intrinsics on the image point to get normalized coordinates.
//
@@ -380,8 +380,8 @@ class DivisionCameraIntrinsics : public CameraIntrinsics {
// coordinates to get normalized camera coordinates.
void InvertIntrinsics(double image_x,
double image_y,
- double *normalized_x,
- double *normalized_y) const override;
+ double* normalized_x,
+ double* normalized_y) const override;
virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
@@ -405,7 +405,7 @@ class NukeCameraIntrinsics : public CameraIntrinsics {
};
NukeCameraIntrinsics();
- NukeCameraIntrinsics(const NukeCameraIntrinsics &from);
+ NukeCameraIntrinsics(const NukeCameraIntrinsics& from);
DistortionModelType GetDistortionModelType() const override {
return DISTORTION_MODEL_NUKE;
@@ -424,8 +424,8 @@ class NukeCameraIntrinsics : public CameraIntrinsics {
// coordinates in pixels.
void ApplyIntrinsics(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const override;
+ double* image_x,
+ double* image_y) const override;
// Invert camera intrinsics on the image point to get normalized coordinates.
//
@@ -433,8 +433,8 @@ class NukeCameraIntrinsics : public CameraIntrinsics {
// coordinates to get normalized camera coordinates.
void InvertIntrinsics(double image_x,
double image_y,
- double *normalized_x,
- double *normalized_y) const override;
+ double* normalized_x,
+ double* normalized_y) const override;
virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
@@ -462,7 +462,7 @@ class BrownCameraIntrinsics : public CameraIntrinsics {
};
BrownCameraIntrinsics();
- BrownCameraIntrinsics(const BrownCameraIntrinsics &from);
+ BrownCameraIntrinsics(const BrownCameraIntrinsics& from);
DistortionModelType GetDistortionModelType() const override {
return DISTORTION_MODEL_BROWN;
@@ -488,8 +488,8 @@ class BrownCameraIntrinsics : public CameraIntrinsics {
// coordinates in pixels.
void ApplyIntrinsics(double normalized_x,
double normalized_y,
- double *image_x,
- double *image_y) const override;
+ double* image_x,
+ double* image_y) const override;
// Invert camera intrinsics on the image point to get normalized coordinates.
//
@@ -497,8 +497,8 @@ class BrownCameraIntrinsics : public CameraIntrinsics {
// coordinates to get normalized camera coordinates.
void InvertIntrinsics(double image_x,
double image_y,
- double *normalized_x,
- double *normalized_y) const override;
+ double* normalized_x,
+ double* normalized_y) const override;
virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
@@ -507,10 +507,8 @@ class BrownCameraIntrinsics : public CameraIntrinsics {
double parameters_[NUM_PARAMETERS];
};
-
/// A human-readable representation of the camera intrinsic parameters.
-std::ostream& operator <<(std::ostream &os,
- const CameraIntrinsics &intrinsics);
+std::ostream& operator<<(std::ostream& os, const CameraIntrinsics& intrinsics);
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics_impl.h b/intern/libmv/libmv/simple_pipeline/camera_intrinsics_impl.h
index e1b53992dfd..c8c4700f5c6 100644
--- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics_impl.h
+++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics_impl.h
@@ -25,11 +25,11 @@ namespace {
// FIXME: C++ templates limitations makes thing complicated,
// but maybe there is a simpler method.
struct ApplyIntrinsicsFunction {
- ApplyIntrinsicsFunction(const CameraIntrinsics &intrinsics,
+ ApplyIntrinsicsFunction(const CameraIntrinsics& intrinsics,
double x,
double y,
- double *warp_x,
- double *warp_y) {
+ double* warp_x,
+ double* warp_y) {
double normalized_x, normalized_y;
intrinsics.ImageSpaceToNormalized(x, y, &normalized_x, &normalized_y);
intrinsics.ApplyIntrinsics(normalized_x, normalized_y, warp_x, warp_y);
@@ -37,14 +37,15 @@ struct ApplyIntrinsicsFunction {
};
struct InvertIntrinsicsFunction {
- InvertIntrinsicsFunction(const CameraIntrinsics &intrinsics,
+ InvertIntrinsicsFunction(const CameraIntrinsics& intrinsics,
double x,
double y,
- double *warp_x,
- double *warp_y) {
+ double* warp_x,
+ double* warp_y) {
double normalized_x, normalized_y;
intrinsics.InvertIntrinsics(x, y, &normalized_x, &normalized_y);
- intrinsics.NormalizedToImageSpace(normalized_x, normalized_y, warp_x, warp_y);
+ intrinsics.NormalizedToImageSpace(
+ normalized_x, normalized_y, warp_x, warp_y);
}
};
@@ -53,18 +54,18 @@ struct InvertIntrinsicsFunction {
namespace internal {
// TODO(MatthiasF): downsample lookup
-template<typename WarpFunction>
-void LookupWarpGrid::Compute(const CameraIntrinsics &intrinsics,
+template <typename WarpFunction>
+void LookupWarpGrid::Compute(const CameraIntrinsics& intrinsics,
int width,
int height,
double overscan) {
- double w = (double) width / (1.0 + overscan);
- double h = (double) height / (1.0 + overscan);
- double aspx = (double) w / intrinsics.image_width();
- double aspy = (double) h / intrinsics.image_height();
+ double w = (double)width / (1.0 + overscan);
+ double h = (double)height / (1.0 + overscan);
+ double aspx = (double)w / intrinsics.image_width();
+ double aspy = (double)h / intrinsics.image_height();
#if defined(_OPENMP)
-# pragma omp parallel for schedule(static) num_threads(threads_) \
- if (threads_ > 1 && height > 100)
+# pragma omp parallel for schedule(static) \
+ num_threads(threads_) if (threads_ > 1 && height > 100)
#endif
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
@@ -76,40 +77,47 @@ void LookupWarpGrid::Compute(const CameraIntrinsics &intrinsics,
warp_y = warp_y * aspy + 0.5 * overscan * h;
int ix = int(warp_x), iy = int(warp_y);
int fx = round((warp_x - ix) * 256), fy = round((warp_y - iy) * 256);
- if (fx == 256) { fx = 0; ix++; } // NOLINT
- if (fy == 256) { fy = 0; iy++; } // NOLINT
+ if (fx == 256) {
+ fx = 0;
+ ix++;
+ } // NOLINT
+ if (fy == 256) {
+ fy = 0;
+ iy++;
+ } // NOLINT
// Use nearest border pixel
- if (ix < 0) { ix = 0, fx = 0; } // NOLINT
- if (iy < 0) { iy = 0, fy = 0; } // NOLINT
- if (ix >= width - 2) ix = width - 2;
- if (iy >= height - 2) iy = height - 2;
-
- Offset offset = { (short) (ix - x),
- (short) (iy - y),
- (unsigned char) fx,
- (unsigned char) fy };
+ if (ix < 0) {
+ ix = 0, fx = 0;
+ } // NOLINT
+ if (iy < 0) {
+ iy = 0, fy = 0;
+ } // NOLINT
+ if (ix >= width - 2)
+ ix = width - 2;
+ if (iy >= height - 2)
+ iy = height - 2;
+
+ Offset offset = {(short)(ix - x),
+ (short)(iy - y),
+ (unsigned char)fx,
+ (unsigned char)fy};
offset_[y * width + x] = offset;
}
}
}
-template<typename WarpFunction>
-void LookupWarpGrid::Update(const CameraIntrinsics &intrinsics,
+template <typename WarpFunction>
+void LookupWarpGrid::Update(const CameraIntrinsics& intrinsics,
int width,
int height,
double overscan) {
- if (width_ != width ||
- height_ != height ||
- overscan_ != overscan) {
+ if (width_ != width || height_ != height || overscan_ != overscan) {
Reset();
}
if (offset_ == NULL) {
offset_ = new Offset[width * height];
- Compute<WarpFunction>(intrinsics,
- width,
- height,
- overscan);
+ Compute<WarpFunction>(intrinsics, width, height, overscan);
}
width_ = width;
@@ -118,29 +126,30 @@ void LookupWarpGrid::Update(const CameraIntrinsics &intrinsics,
}
// TODO(MatthiasF): cubic B-Spline image sampling, bilinear lookup
-template<typename PixelType>
-void LookupWarpGrid::Apply(const PixelType *input_buffer,
+template <typename PixelType>
+void LookupWarpGrid::Apply(const PixelType* input_buffer,
int width,
int height,
int channels,
- PixelType *output_buffer) {
+ PixelType* output_buffer) {
#if defined(_OPENMP)
-# pragma omp parallel for schedule(static) num_threads(threads_) \
- if (threads_ > 1 && height > 100)
+# pragma omp parallel for schedule(static) \
+ num_threads(threads_) if (threads_ > 1 && height > 100)
#endif
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
Offset offset = offset_[y * width + x];
- const int pixel_index = ((y + offset.iy) * width +
- (x + offset.ix)) * channels;
- const PixelType *s = &input_buffer[pixel_index];
+ const int pixel_index =
+ ((y + offset.iy) * width + (x + offset.ix)) * channels;
+ const PixelType* s = &input_buffer[pixel_index];
for (int i = 0; i < channels; i++) {
output_buffer[(y * width + x) * channels + i] =
- ((s[i] * (256 - offset.fx) +
- s[channels + i] * offset.fx) * (256 - offset.fy) +
- (s[width * channels + i] * (256 - offset.fx) +
- s[width * channels + channels + i] * offset.fx) * offset.fy)
- / (256 * 256);
+ ((s[i] * (256 - offset.fx) + s[channels + i] * offset.fx) *
+ (256 - offset.fy) +
+ (s[width * channels + i] * (256 - offset.fx) +
+ s[width * channels + channels + i] * offset.fx) *
+ offset.fy) /
+ (256 * 256);
}
}
}
@@ -148,45 +157,33 @@ void LookupWarpGrid::Apply(const PixelType *input_buffer,
} // namespace internal
-template<typename PixelType>
-void CameraIntrinsics::DistortBuffer(const PixelType *input_buffer,
+template <typename PixelType>
+void CameraIntrinsics::DistortBuffer(const PixelType* input_buffer,
int width,
int height,
double overscan,
int channels,
- PixelType *output_buffer) {
+ PixelType* output_buffer) {
assert(channels >= 1);
assert(channels <= 4);
- distort_.Update<InvertIntrinsicsFunction>(*this,
- width,
- height,
- overscan);
- distort_.Apply<PixelType>(input_buffer,
- width,
- height,
- channels,
- output_buffer);
+ distort_.Update<InvertIntrinsicsFunction>(*this, width, height, overscan);
+ distort_.Apply<PixelType>(
+ input_buffer, width, height, channels, output_buffer);
}
-template<typename PixelType>
-void CameraIntrinsics::UndistortBuffer(const PixelType *input_buffer,
+template <typename PixelType>
+void CameraIntrinsics::UndistortBuffer(const PixelType* input_buffer,
int width,
int height,
double overscan,
int channels,
- PixelType *output_buffer) {
+ PixelType* output_buffer) {
assert(channels >= 1);
assert(channels <= 4);
- undistort_.Update<ApplyIntrinsicsFunction>(*this,
- width,
- height,
- overscan);
-
- undistort_.Apply<PixelType>(input_buffer,
- width,
- height,
- channels,
- output_buffer);
+ undistort_.Update<ApplyIntrinsicsFunction>(*this, width, height, overscan);
+
+ undistort_.Apply<PixelType>(
+ input_buffer, width, height, channels, output_buffer);
}
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics_test.cc b/intern/libmv/libmv/simple_pipeline/camera_intrinsics_test.cc
index 96d35a29ef8..cfcc2d16682 100644
--- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics_test.cc
+++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics_test.cc
@@ -22,10 +22,10 @@
#include <iostream>
-#include "testing/testing.h"
#include "libmv/image/image.h"
#include "libmv/image/image_drawing.h"
#include "libmv/logging/logging.h"
+#include "testing/testing.h"
namespace libmv {
@@ -59,26 +59,36 @@ TEST(PolynomialCameraIntrinsics, ApplyIntrinsics) {
const int N = 5;
double expected[N][N][2] = {
- { {75.312500, -24.687500}, {338.982239, -62.035522},
- {640.000000, -72.929688}, {941.017761, -62.035522},
- {1204.687500, -24.687500}},
-
- { {37.964478, 238.982239}, {323.664551, 223.664551},
- {640.000000, 219.193420}, {956.335449, 223.664551},
- {1242.035522, 238.982239}},
-
- { {27.070312, 540.000000}, {319.193420, 540.000000},
- {640.000000, 540.000000}, {960.806580, 540.000000},
- {1252.929688, 540.000000}},
-
- { {37.964478, 841.017761}, {323.664551, 856.335449},
- {640.000000, 860.806580}, {956.335449, 856.335449},
- {1242.035522, 841.017761}},
-
- { {75.312500, 1104.687500}, {338.982239, 1142.035522},
- {640.000000, 1152.929688}, {941.017761, 1142.035522},
- {1204.687500, 1104.687500}}
- };
+ {{75.312500, -24.687500},
+ {338.982239, -62.035522},
+ {640.000000, -72.929688},
+ {941.017761, -62.035522},
+ {1204.687500, -24.687500}},
+
+ {{37.964478, 238.982239},
+ {323.664551, 223.664551},
+ {640.000000, 219.193420},
+ {956.335449, 223.664551},
+ {1242.035522, 238.982239}},
+
+ {{27.070312, 540.000000},
+ {319.193420, 540.000000},
+ {640.000000, 540.000000},
+ {960.806580, 540.000000},
+ {1252.929688, 540.000000}},
+
+ {{37.964478, 841.017761},
+ {323.664551, 856.335449},
+ {640.000000, 860.806580},
+ {956.335449, 856.335449},
+ {1242.035522, 841.017761}},
+
+ {{75.312500, 1104.687500},
+ {338.982239, 1142.035522},
+ {640.000000, 1152.929688},
+ {941.017761, 1142.035522},
+ {1204.687500, 1104.687500}},
+ };
PolynomialCameraIntrinsics intrinsics;
intrinsics.SetFocalLength(1300.0, 1300.0);
@@ -89,12 +99,11 @@ TEST(PolynomialCameraIntrinsics, ApplyIntrinsics) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
- double normalized_x = j * step - 0.5,
- normalized_y = i * step - 0.5;
+ double normalized_x = j * step - 0.5, normalized_y = i * step - 0.5;
double distorted_x, distorted_y;
- intrinsics.ApplyIntrinsics(normalized_x, normalized_y,
- &distorted_x, &distorted_y);
+ intrinsics.ApplyIntrinsics(
+ normalized_x, normalized_y, &distorted_x, &distorted_y);
EXPECT_NEAR(expected[i][j][0], distorted_x, 1e-6);
EXPECT_NEAR(expected[i][j][1], distorted_y, 1e-6);
@@ -106,43 +115,51 @@ TEST(PolynomialCameraIntrinsics, InvertIntrinsics) {
const int N = 5;
double expected[N][N][2] = {
- { {-0.524482, -0.437069}, {-0.226237, -0.403994},
- { 0.031876, -0.398446}, { 0.293917, -0.408218},
- { 0.632438, -0.465028}},
-
- { {-0.493496, -0.189173}, {-0.219052, -0.179936},
- { 0.030975, -0.178107}, { 0.283742, -0.181280},
- { 0.574557, -0.194335}},
-
- { {-0.488013, 0.032534}, {-0.217537, 0.031077},
- { 0.030781, 0.030781}, { 0.281635, 0.031293},
- { 0.566344, 0.033314}},
-
- { {-0.498696, 0.257660}, {-0.220424, 0.244041},
- { 0.031150, 0.241409}, { 0.285660, 0.245985},
- { 0.582670, 0.265629}},
-
- { {-0.550617, 0.532263}, {-0.230399, 0.477255},
- { 0.032380, 0.469510}, { 0.299986, 0.483311},
- { 0.684740, 0.584043}}
- };
+ {{-0.524482, -0.437069},
+ {-0.226237, -0.403994},
+ {0.031876, -0.398446},
+ {0.293917, -0.408218},
+ {0.632438, -0.465028}},
+
+ {{-0.493496, -0.189173},
+ {-0.219052, -0.179936},
+ {0.030975, -0.178107},
+ {0.283742, -0.181280},
+ {0.574557, -0.194335}},
+
+ {{-0.488013, 0.032534},
+ {-0.217537, 0.031077},
+ {0.030781, 0.030781},
+ {0.281635, 0.031293},
+ {0.566344, 0.033314}},
+
+ {{-0.498696, 0.257660},
+ {-0.220424, 0.244041},
+ {0.031150, 0.241409},
+ {0.285660, 0.245985},
+ {0.582670, 0.265629}},
+
+ {{-0.550617, 0.532263},
+ {-0.230399, 0.477255},
+ {0.032380, 0.469510},
+ {0.299986, 0.483311},
+ {0.684740, 0.584043}},
+ };
PolynomialCameraIntrinsics intrinsics;
intrinsics.SetFocalLength(1300.0, 1300.0);
intrinsics.SetPrincipalPoint(600.0, 500.0);
intrinsics.SetRadialDistortion(-0.2, -0.1, -0.05);
- double step_x = 1280.0 / (N - 1),
- step_y = 1080.0 / (N - 1);
+ double step_x = 1280.0 / (N - 1), step_y = 1080.0 / (N - 1);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
- double distorted_x = j * step_x,
- distorted_y = i * step_y;
+ double distorted_x = j * step_x, distorted_y = i * step_y;
double normalized_x, normalized_y;
- intrinsics.InvertIntrinsics(distorted_x, distorted_y,
- &normalized_x, &normalized_y);
+ intrinsics.InvertIntrinsics(
+ distorted_x, distorted_y, &normalized_x, &normalized_y);
EXPECT_NEAR(expected[i][j][0], normalized_x, 1e-6);
EXPECT_NEAR(expected[i][j][1], normalized_y, 1e-6);
@@ -190,10 +207,11 @@ TEST(PolynomialCameraIntrinsics, IdentityDistortBuffer) {
FloatImage distorted_image(h, w);
intrinsics.SetImageSize(w, h);
intrinsics.SetFocalLength(10.0, 10.0);
- intrinsics.SetPrincipalPoint((double) w / 2.0, (double) h / 2.0);
+ intrinsics.SetPrincipalPoint((double)w / 2.0, (double)h / 2.0);
intrinsics.SetRadialDistortion(0.0, 0.0, 0.0);
intrinsics.DistortBuffer(image.Data(),
- image.Width(), image.Height(),
+ image.Width(),
+ image.Height(),
0.0,
image.Depth(),
distorted_image.Data());
@@ -221,10 +239,11 @@ TEST(PolynomialCameraIntrinsics, IdentityUndistortBuffer) {
FloatImage distorted_image(h, w);
intrinsics.SetImageSize(w, h);
intrinsics.SetFocalLength(10.0, 10.0);
- intrinsics.SetPrincipalPoint((double) w / 2.0, (double) h / 2.0);
+ intrinsics.SetPrincipalPoint((double)w / 2.0, (double)h / 2.0);
intrinsics.SetRadialDistortion(0.0, 0.0, 0.0);
intrinsics.UndistortBuffer(image.Data(),
- image.Width(), image.Height(),
+ image.Width(),
+ image.Height(),
0.0,
image.Depth(),
distorted_image.Data());
diff --git a/intern/libmv/libmv/simple_pipeline/detect.cc b/intern/libmv/libmv/simple_pipeline/detect.cc
index 46599a4c49e..0897c5598c6 100644
--- a/intern/libmv/libmv/simple_pipeline/detect.cc
+++ b/intern/libmv/libmv/simple_pipeline/detect.cc
@@ -22,14 +22,14 @@
**
****************************************************************************/
-#include <stdlib.h>
#include <memory.h>
+#include <stdlib.h>
#include <queue>
#include "libmv/base/scoped_ptr.h"
#include "libmv/image/array_nd.h"
-#include "libmv/image/image_converter.h"
#include "libmv/image/convolve.h"
+#include "libmv/image/image_converter.h"
#include "libmv/logging/logging.h"
#include "libmv/simple_pipeline/detect.h"
@@ -55,7 +55,7 @@ double kDefaultHarrisThreshold = 1e-5;
class FeatureComparison {
public:
- bool operator() (const Feature &left, const Feature &right) const {
+ bool operator()(const Feature& left, const Feature& right) const {
return right.score > left.score;
}
};
@@ -63,18 +63,17 @@ class FeatureComparison {
// Filter the features so there are no features closer than
// minimal distance to each other.
// This is a naive implementation with O(n^2) asymptotic.
-void FilterFeaturesByDistance(const vector<Feature> &all_features,
+void FilterFeaturesByDistance(const vector<Feature>& all_features,
int min_distance,
- vector<Feature> *detected_features) {
+ vector<Feature>* detected_features) {
const int min_distance_squared = min_distance * min_distance;
// Use priority queue to sort the features by their score.
//
// Do this on copy of the input features to prevent possible
// distortion in callee function behavior.
- std::priority_queue<Feature,
- std::vector<Feature>,
- FeatureComparison> priority_features;
+ std::priority_queue<Feature, std::vector<Feature>, FeatureComparison>
+ priority_features;
for (int i = 0; i < all_features.size(); i++) {
priority_features.push(all_features.at(i));
@@ -85,7 +84,7 @@ void FilterFeaturesByDistance(const vector<Feature> &all_features,
Feature a = priority_features.top();
for (int i = 0; i < detected_features->size(); i++) {
- Feature &b = detected_features->at(i);
+ Feature& b = detected_features->at(i);
if (Square(a.x - b.x) + Square(a.y - b.y) < min_distance_squared) {
ok = false;
break;
@@ -100,9 +99,9 @@ void FilterFeaturesByDistance(const vector<Feature> &all_features,
}
}
-void DetectFAST(const FloatImage &grayscale_image,
- const DetectOptions &options,
- vector<Feature> *detected_features) {
+void DetectFAST(const FloatImage& grayscale_image,
+ const DetectOptions& options,
+ vector<Feature>* detected_features) {
#ifndef LIBMV_NO_FAST_DETECTOR
const int min_distance = options.min_distance;
const int min_trackness = options.fast_min_trackness;
@@ -111,12 +110,14 @@ void DetectFAST(const FloatImage &grayscale_image,
const int height = grayscale_image.Width() - 2 * margin;
const int stride = grayscale_image.Width();
- scoped_array<unsigned char> byte_image(FloatImageToUCharArray(grayscale_image));
+ scoped_array<unsigned char> byte_image(
+ FloatImageToUCharArray(grayscale_image));
const int byte_image_offset = margin * stride + margin;
- // TODO(MatthiasF): Support targetting a feature count (binary search trackness)
+ // TODO(MatthiasF): Support targetting a feature count (binary search
+ // trackness)
int num_features;
- xy *all = fast9_detect(byte_image.get() + byte_image_offset,
+ xy* all = fast9_detect(byte_image.get() + byte_image_offset,
width,
height,
stride,
@@ -126,13 +127,13 @@ void DetectFAST(const FloatImage &grayscale_image,
free(all);
return;
}
- int *scores = fast9_score(byte_image.get() + byte_image_offset,
+ int* scores = fast9_score(byte_image.get() + byte_image_offset,
stride,
all,
num_features,
min_trackness);
// TODO(MatthiasF): merge with close feature suppression
- xy *nonmax = nonmax_suppression(all, scores, num_features, &num_features);
+ xy* nonmax = nonmax_suppression(all, scores, num_features, &num_features);
free(all);
// Remove too close features
// TODO(MatthiasF): A resolution independent parameter would be better than
@@ -152,89 +153,104 @@ void DetectFAST(const FloatImage &grayscale_image,
free(scores);
free(nonmax);
#else
- (void) grayscale_image; // Ignored.
- (void) options; // Ignored.
- (void) detected_features; // Ignored.
+ (void)grayscale_image; // Ignored.
+ (void)options; // Ignored.
+ (void)detected_features; // Ignored.
LOG(FATAL) << "FAST detector is disabled in this build.";
#endif
}
#ifdef __SSE2__
-static unsigned int SAD(const ubyte* imageA, const ubyte* imageB,
- int strideA, int strideB) {
+static unsigned int SAD(const ubyte* imageA,
+ const ubyte* imageB,
+ int strideA,
+ int strideB) {
__m128i a = _mm_setzero_si128();
for (int i = 0; i < 16; i++) {
- a = _mm_adds_epu16(a,
- _mm_sad_epu8(_mm_loadu_si128((__m128i*)(imageA+i*strideA)),
- _mm_loadu_si128((__m128i*)(imageB+i*strideB))));
+ a = _mm_adds_epu16(
+ a,
+ _mm_sad_epu8(_mm_loadu_si128((__m128i*)(imageA + i * strideA)),
+ _mm_loadu_si128((__m128i*)(imageB + i * strideB))));
}
return _mm_extract_epi16(a, 0) + _mm_extract_epi16(a, 4);
}
#else
-static unsigned int SAD(const ubyte* imageA, const ubyte* imageB,
- int strideA, int strideB) {
+static unsigned int SAD(const ubyte* imageA,
+ const ubyte* imageB,
+ int strideA,
+ int strideB) {
unsigned int sad = 0;
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
- sad += abs((int)imageA[i*strideA+j] - imageB[i*strideB+j]);
+ sad += abs((int)imageA[i * strideA + j] - imageB[i * strideB + j]);
}
}
return sad;
}
#endif
-void DetectMORAVEC(const FloatImage &grayscale_image,
- const DetectOptions &options,
- vector<Feature> *detected_features) {
+void DetectMORAVEC(const FloatImage& grayscale_image,
+ const DetectOptions& options,
+ vector<Feature>* detected_features) {
const int distance = options.min_distance;
const int margin = options.margin;
- const unsigned char *pattern = options.moravec_pattern;
+ const unsigned char* pattern = options.moravec_pattern;
const int count = options.moravec_max_count;
const int width = grayscale_image.Width() - 2 * margin;
const int height = grayscale_image.Width() - 2 * margin;
const int stride = grayscale_image.Width();
- scoped_array<unsigned char> byte_image(FloatImageToUCharArray(grayscale_image));
+ scoped_array<unsigned char> byte_image(
+ FloatImageToUCharArray(grayscale_image));
unsigned short histogram[256];
memset(histogram, 0, sizeof(histogram));
- scoped_array<ubyte> scores(new ubyte[width*height]);
- memset(scores.get(), 0, width*height);
+ scoped_array<ubyte> scores(new ubyte[width * height]);
+ memset(scores.get(), 0, width * height);
const int r = 1; // radius for self similarity comparison
- for (int y = distance; y < height-distance; y++) {
- for (int x = distance; x < width-distance; x++) {
- const ubyte* s = &byte_image[y*stride+x];
- int score = // low self-similarity with overlapping patterns
- // OPTI: load pattern once
+ for (int y = distance; y < height - distance; y++) {
+ for (int x = distance; x < width - distance; x++) {
+ const ubyte* s = &byte_image[y * stride + x];
+ // low self-similarity with overlapping patterns
+ // OPTI: load pattern once
+ // clang-format off
+ int score =
SAD(s, s-r*stride-r, stride, stride)+SAD(s, s-r*stride, stride, stride)+SAD(s, s-r*stride+r, stride, stride)+
SAD(s, s -r, stride, stride)+ SAD(s, s +r, stride, stride)+
SAD(s, s+r*stride-r, stride, stride)+SAD(s, s+r*stride, stride, stride)+SAD(s, s+r*stride+r, stride, stride);
+ // clang-format on
+
score /= 256; // normalize
- if (pattern) // find only features similar to pattern
+ if (pattern) // find only features similar to pattern
score -= SAD(s, pattern, stride, 16);
- if (score <= 16) continue; // filter very self-similar features
+ if (score <= 16)
+ continue; // filter very self-similar features
score -= 16; // translate to score/histogram values
- if (score>255) score=255; // clip
- ubyte* c = &scores[y*width+x];
+ if (score > 255)
+ score = 255; // clip
+ ubyte* c = &scores[y * width + x];
for (int i = -distance; i < 0; i++) {
for (int j = -distance; j < distance; j++) {
- int s = c[i*width+j];
- if (s == 0) continue;
- if (s >= score) goto nonmax;
- c[i*width+j] = 0;
+ int s = c[i * width + j];
+ if (s == 0)
+ continue;
+ if (s >= score)
+ goto nonmax;
+ c[i * width + j] = 0;
histogram[s]--;
}
}
for (int i = 0, j = -distance; j < 0; j++) {
- int s = c[i*width+j];
- if (s == 0) continue;
- if (s >= score) goto nonmax;
- c[i*width+j] = 0;
+ int s = c[i * width + j];
+ if (s == 0)
+ continue;
+ if (s >= score)
+ goto nonmax;
+ c[i * width + j] = 0;
histogram[s]--;
}
c[0] = score, histogram[score]++;
- nonmax:
- { } // Do nothing.
+ nonmax : {} // Do nothing.
}
}
int min = 255, total = 0;
@@ -254,18 +270,16 @@ void DetectMORAVEC(const FloatImage &grayscale_image,
// Score calculation above uses top left corner of the
// patch as the origin, here we need to convert this value
// to a pattrn center by adding 8 pixels.
- detected_features->push_back(Feature((float) x + 8.0f,
- (float) y + 8.0f,
- (float) s,
- 16.0f));
+ detected_features->push_back(
+ Feature((float)x + 8.0f, (float)y + 8.0f, (float)s, 16.0f));
}
}
}
}
-void DetectHarris(const FloatImage &grayscale_image,
- const DetectOptions &options,
- vector<Feature> *detected_features) {
+void DetectHarris(const FloatImage& grayscale_image,
+ const DetectOptions& options,
+ vector<Feature>* detected_features) {
const double alpha = 0.06;
const double sigma = 0.9;
@@ -281,9 +295,7 @@ void DetectHarris(const FloatImage &grayscale_image,
MultiplyElements(gradient_y, gradient_y, &gradient_yy);
MultiplyElements(gradient_x, gradient_y, &gradient_xy);
- FloatImage gradient_xx_blurred,
- gradient_yy_blurred,
- gradient_xy_blurred;
+ FloatImage gradient_xx_blurred, gradient_yy_blurred, gradient_xy_blurred;
ConvolveGaussian(gradient_xx, sigma, &gradient_xx_blurred);
ConvolveGaussian(gradient_yy, sigma, &gradient_yy_blurred);
ConvolveGaussian(gradient_xy, sigma, &gradient_xy_blurred);
@@ -304,10 +316,8 @@ void DetectHarris(const FloatImage &grayscale_image,
double traceA = A.trace();
double harris_function = detA - alpha * traceA * traceA;
if (harris_function > threshold) {
- all_features.push_back(Feature((float) x,
- (float) y,
- (float) harris_function,
- 5.0f));
+ all_features.push_back(
+ Feature((float)x, (float)y, (float)harris_function, 5.0f));
}
}
}
@@ -318,17 +328,18 @@ void DetectHarris(const FloatImage &grayscale_image,
} // namespace
DetectOptions::DetectOptions()
- : type(DetectOptions::HARRIS),
- margin(0),
- min_distance(120),
- fast_min_trackness(kDefaultFastMinTrackness),
- moravec_max_count(0),
- moravec_pattern(NULL),
- harris_threshold(kDefaultHarrisThreshold) {}
-
-void Detect(const FloatImage &image,
- const DetectOptions &options,
- vector<Feature> *detected_features) {
+ : type(DetectOptions::HARRIS),
+ margin(0),
+ min_distance(120),
+ fast_min_trackness(kDefaultFastMinTrackness),
+ moravec_max_count(0),
+ moravec_pattern(NULL),
+ harris_threshold(kDefaultHarrisThreshold) {
+}
+
+void Detect(const FloatImage& image,
+ const DetectOptions& options,
+ vector<Feature>* detected_features) {
// Currently all the detectors requires image to be grayscale.
// Do it here to avoid code duplication.
FloatImage grayscale_image;
@@ -350,8 +361,7 @@ void Detect(const FloatImage &image,
}
}
-std::ostream& operator <<(std::ostream &os,
- const Feature &feature) {
+std::ostream& operator<<(std::ostream& os, const Feature& feature) {
os << "x: " << feature.x << ", y: " << feature.y;
os << ", score: " << feature.score;
os << ", size: " << feature.size;
diff --git a/intern/libmv/libmv/simple_pipeline/detect.h b/intern/libmv/libmv/simple_pipeline/detect.h
index 1035287bcf2..8ddf0025e4b 100644
--- a/intern/libmv/libmv/simple_pipeline/detect.h
+++ b/intern/libmv/libmv/simple_pipeline/detect.h
@@ -39,7 +39,7 @@ typedef unsigned char ubyte;
struct Feature {
Feature(float x, float y) : x(x), y(y) {}
Feature(float x, float y, float score, float size)
- : x(x), y(y), score(score), size(size) {}
+ : x(x), y(y), score(score), size(size) {}
// Position of the feature in pixels from top-left corner.
// Note: Libmv detector might eventually support subpixel precision.
@@ -88,9 +88,9 @@ struct DetectOptions {
// Find only features similar to this pattern. Only used by MORAVEC detector.
//
- // This is an image patch denoted in byte array with dimensions of 16px by 16px
- // used to filter features by similarity to this patch.
- unsigned char *moravec_pattern;
+ // This is an image patch denoted in byte array with dimensions of 16px by
+ // 16px used to filter features by similarity to this patch.
+ unsigned char* moravec_pattern;
// Threshold value of the Harris function to add new featrue
// to the result.
@@ -101,12 +101,11 @@ struct DetectOptions {
//
// Image could have 1-4 channels, it'll be converted to a grayscale
// by the detector function if needed.
-void Detect(const FloatImage &image,
- const DetectOptions &options,
- vector<Feature> *detected_features);
+void Detect(const FloatImage& image,
+ const DetectOptions& options,
+ vector<Feature>* detected_features);
-std::ostream& operator <<(std::ostream &os,
- const Feature &feature);
+std::ostream& operator<<(std::ostream& os, const Feature& feature);
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/detect_test.cc b/intern/libmv/libmv/simple_pipeline/detect_test.cc
index b226ad96595..718598d04e1 100644
--- a/intern/libmv/libmv/simple_pipeline/detect_test.cc
+++ b/intern/libmv/libmv/simple_pipeline/detect_test.cc
@@ -20,14 +20,14 @@
#include "libmv/simple_pipeline/detect.h"
-#include "testing/testing.h"
#include "libmv/logging/logging.h"
+#include "testing/testing.h"
namespace libmv {
namespace {
-void PreformSinglePointTest(const DetectOptions &options) {
+void PreformSinglePointTest(const DetectOptions& options) {
// Prepare the image.
FloatImage image(15, 15);
image.fill(1.0);
@@ -40,7 +40,7 @@ void PreformSinglePointTest(const DetectOptions &options) {
// Check detected features matches our expectations.
EXPECT_EQ(1, detected_features.size());
if (detected_features.size() == 1) {
- Feature &feature = detected_features[0];
+ Feature& feature = detected_features[0];
EXPECT_EQ(7, feature.x);
EXPECT_EQ(7, feature.y);
}
@@ -83,8 +83,8 @@ void PreformCheckerBoardTest(const DetectOptions &options) {
}
#endif
-void CheckExpectedFeatures(const vector<Feature> &detected_features,
- const vector<Feature> &expected_features) {
+void CheckExpectedFeatures(const vector<Feature>& detected_features,
+ const vector<Feature>& expected_features) {
EXPECT_EQ(expected_features.size(), detected_features.size());
// That's unsafe to iterate over vectors when their lengths
@@ -95,10 +95,10 @@ void CheckExpectedFeatures(const vector<Feature> &detected_features,
}
for (int i = 0; i < expected_features.size(); ++i) {
- const Feature &extected_feature = expected_features[i];
+ const Feature& extected_feature = expected_features[i];
bool found = false;
for (int j = 0; j < detected_features.size(); ++j) {
- const Feature &detected_feature = detected_features[j];
+ const Feature& detected_feature = detected_features[j];
if (extected_feature.x == detected_feature.x &&
extected_feature.y == detected_feature.y) {
found = true;
@@ -109,15 +109,14 @@ void CheckExpectedFeatures(const vector<Feature> &detected_features,
}
}
-void PreformSingleTriangleTest(const DetectOptions &options) {
+void PreformSingleTriangleTest(const DetectOptions& options) {
// Prepare the image.
FloatImage image(15, 21);
image.fill(1.0);
int vertex_x = 10, vertex_y = 5;
for (int i = 0; i < 6; ++i) {
- int current_x = vertex_x - i,
- current_y = vertex_y + i;
+ int current_x = vertex_x - i, current_y = vertex_y + i;
for (int j = 0; j < i * 2 + 1; ++j, ++current_x) {
image(current_y, current_x) = 0.0;
}
diff --git a/intern/libmv/libmv/simple_pipeline/distortion_models.cc b/intern/libmv/libmv/simple_pipeline/distortion_models.cc
index f602234b630..4556e3ceaf9 100644
--- a/intern/libmv/libmv/simple_pipeline/distortion_models.cc
+++ b/intern/libmv/libmv/simple_pipeline/distortion_models.cc
@@ -41,25 +41,34 @@ struct InvertPolynomialIntrinsicsCostFunction {
const double p2,
const double image_x,
const double image_y)
- : focal_length_x_(focal_length_x),
- focal_length_y_(focal_length_y),
- principal_point_x_(principal_point_x),
- principal_point_y_(principal_point_y),
- k1_(k1), k2_(k2), k3_(k3),
- p1_(p1), p2_(p2),
- x_(image_x), y_(image_y) {}
-
- Vec2 operator()(const Vec2 &u) const {
+ : focal_length_x_(focal_length_x),
+ focal_length_y_(focal_length_y),
+ principal_point_x_(principal_point_x),
+ principal_point_y_(principal_point_y),
+ k1_(k1),
+ k2_(k2),
+ k3_(k3),
+ p1_(p1),
+ p2_(p2),
+ x_(image_x),
+ y_(image_y) {}
+
+ Vec2 operator()(const Vec2& u) const {
double xx, yy;
ApplyPolynomialDistortionModel(focal_length_x_,
focal_length_y_,
principal_point_x_,
principal_point_y_,
- k1_, k2_, k3_,
- p1_, p2_,
- u(0), u(1),
- &xx, &yy);
+ k1_,
+ k2_,
+ k3_,
+ p1_,
+ p2_,
+ u(0),
+ u(1),
+ &xx,
+ &yy);
Vec2 fx;
fx << (xx - x_), (yy - y_);
@@ -87,23 +96,28 @@ struct InvertDivisionIntrinsicsCostFunction {
const double k2,
const double image_x,
const double image_y)
- : focal_length_x_(focal_length_x),
- focal_length_y_(focal_length_y),
- principal_point_x_(principal_point_x),
- principal_point_y_(principal_point_y),
- k1_(k1), k2_(k2),
- x_(image_x), y_(image_y) {}
-
- Vec2 operator()(const Vec2 &u) const {
+ : focal_length_x_(focal_length_x),
+ focal_length_y_(focal_length_y),
+ principal_point_x_(principal_point_x),
+ principal_point_y_(principal_point_y),
+ k1_(k1),
+ k2_(k2),
+ x_(image_x),
+ y_(image_y) {}
+
+ Vec2 operator()(const Vec2& u) const {
double xx, yy;
ApplyDivisionDistortionModel(focal_length_x_,
focal_length_y_,
principal_point_x_,
principal_point_y_,
- k1_, k2_,
- u(0), u(1),
- &xx, &yy);
+ k1_,
+ k2_,
+ u(0),
+ u(1),
+ &xx,
+ &yy);
Vec2 fx;
fx << (xx - x_), (yy - y_);
@@ -134,25 +148,36 @@ struct InvertBrownIntrinsicsCostFunction {
const double p2,
const double image_x,
const double image_y)
- : focal_length_x_(focal_length_x),
- focal_length_y_(focal_length_y),
- principal_point_x_(principal_point_x),
- principal_point_y_(principal_point_y),
- k1_(k1), k2_(k2), k3_(k3), k4_(k4),
- p1_(p1), p2_(p2),
- x_(image_x), y_(image_y) {}
-
- Vec2 operator()(const Vec2 &u) const {
+ : focal_length_x_(focal_length_x),
+ focal_length_y_(focal_length_y),
+ principal_point_x_(principal_point_x),
+ principal_point_y_(principal_point_y),
+ k1_(k1),
+ k2_(k2),
+ k3_(k3),
+ k4_(k4),
+ p1_(p1),
+ p2_(p2),
+ x_(image_x),
+ y_(image_y) {}
+
+ Vec2 operator()(const Vec2& u) const {
double xx, yy;
ApplyBrownDistortionModel(focal_length_x_,
focal_length_y_,
principal_point_x_,
principal_point_y_,
- k1_, k2_, k3_, k4_,
- p1_, p2_,
- u(0), u(1),
- &xx, &yy);
+ k1_,
+ k2_,
+ k3_,
+ k4_,
+ p1_,
+ p2_,
+ u(0),
+ u(1),
+ &xx,
+ &yy);
Vec2 fx;
fx << (xx - x_), (yy - y_);
@@ -180,8 +205,8 @@ void InvertPolynomialDistortionModel(const double focal_length_x,
const double p2,
const double image_x,
const double image_y,
- double *normalized_x,
- double *normalized_y) {
+ double* normalized_x,
+ double* normalized_y) {
// Compute the initial guess. For a camera with no distortion, this will also
// be the final answer; the LM iteration will terminate immediately.
Vec2 normalized;
@@ -194,13 +219,17 @@ void InvertPolynomialDistortionModel(const double focal_length_x,
focal_length_y,
principal_point_x,
principal_point_y,
- k1, k2, k3,
- p1, p2,
- image_x, image_y);
+ k1,
+ k2,
+ k3,
+ p1,
+ p2,
+ image_x,
+ image_y);
Solver::SolverParameters params;
Solver solver(intrinsics_cost);
- /*Solver::Results results =*/ solver.minimize(params, &normalized);
+ /*Solver::Results results =*/solver.minimize(params, &normalized);
// TODO(keir): Better error handling.
@@ -216,8 +245,8 @@ void InvertDivisionDistortionModel(const double focal_length_x,
const double k2,
const double image_x,
const double image_y,
- double *normalized_x,
- double *normalized_y) {
+ double* normalized_x,
+ double* normalized_y) {
// Compute the initial guess. For a camera with no distortion, this will also
// be the final answer; the LM iteration will terminate immediately.
Vec2 normalized;
@@ -231,12 +260,14 @@ void InvertDivisionDistortionModel(const double focal_length_x,
focal_length_y,
principal_point_x,
principal_point_y,
- k1, k2,
- image_x, image_y);
+ k1,
+ k2,
+ image_x,
+ image_y);
Solver::SolverParameters params;
Solver solver(intrinsics_cost);
- /*Solver::Results results =*/ solver.minimize(params, &normalized);
+ /*Solver::Results results =*/solver.minimize(params, &normalized);
// TODO(keir): Better error handling.
@@ -256,8 +287,8 @@ void InvertBrownDistortionModel(const double focal_length_x,
const double p2,
const double image_x,
const double image_y,
- double *normalized_x,
- double *normalized_y) {
+ double* normalized_x,
+ double* normalized_y) {
// Compute the initial guess. For a camera with no distortion, this will also
// be the final answer; the LM iteration will terminate immediately.
Vec2 normalized;
@@ -270,13 +301,18 @@ void InvertBrownDistortionModel(const double focal_length_x,
focal_length_y,
principal_point_x,
principal_point_y,
- k1, k2, k3, k4,
- p1, p2,
- image_x, image_y);
+ k1,
+ k2,
+ k3,
+ k4,
+ p1,
+ p2,
+ image_x,
+ image_y);
Solver::SolverParameters params;
Solver solver(intrinsics_cost);
- /*Solver::Results results =*/ solver.minimize(params, &normalized);
+ /*Solver::Results results =*/solver.minimize(params, &normalized);
// TODO(keir): Better error handling.
@@ -299,31 +335,36 @@ struct ApplyNukeIntrinsicsCostFunction {
const double k2,
const double expected_normalized_x,
const double expected_normalized_y)
- : focal_length_x_(focal_length_x),
- focal_length_y_(focal_length_y),
- principal_point_x_(principal_point_x),
- principal_point_y_(principal_point_y),
- image_width_(image_width),
- image_height_(image_height),
- k1_(k1), k2_(k2),
- expected_normalized_x_(expected_normalized_x),
- expected_normalized_y_(expected_normalized_y) {}
-
- Vec2 operator()(const Vec2 &image_coordinate) const {
+ : focal_length_x_(focal_length_x),
+ focal_length_y_(focal_length_y),
+ principal_point_x_(principal_point_x),
+ principal_point_y_(principal_point_y),
+ image_width_(image_width),
+ image_height_(image_height),
+ k1_(k1),
+ k2_(k2),
+ expected_normalized_x_(expected_normalized_x),
+ expected_normalized_y_(expected_normalized_y) {}
+
+ Vec2 operator()(const Vec2& image_coordinate) const {
double actual_normalized_x, actual_normalized_y;
InvertNukeDistortionModel(focal_length_x_,
focal_length_y_,
principal_point_x_,
principal_point_y_,
- image_width_, image_height_,
- k1_, k2_,
- image_coordinate(0), image_coordinate(1),
- &actual_normalized_x, &actual_normalized_y);
+ image_width_,
+ image_height_,
+ k1_,
+ k2_,
+ image_coordinate(0),
+ image_coordinate(1),
+ &actual_normalized_x,
+ &actual_normalized_y);
Vec2 fx;
fx << (actual_normalized_x - expected_normalized_x_),
- (actual_normalized_y - expected_normalized_y_);
+ (actual_normalized_y - expected_normalized_y_);
return fx;
}
double focal_length_x_;
@@ -346,8 +387,8 @@ void ApplyNukeDistortionModel(const double focal_length_x,
const double k2,
const double normalized_x,
const double normalized_y,
- double *image_x,
- double *image_y) {
+ double* image_x,
+ double* image_y) {
// Compute the initial guess. For a camera with no distortion, this will also
// be the final answer; the LM iteration will terminate immediately.
Vec2 image;
@@ -363,12 +404,14 @@ void ApplyNukeDistortionModel(const double focal_length_x,
principal_point_y,
image_width,
image_height,
- k1, k2,
- normalized_x, normalized_y);
+ k1,
+ k2,
+ normalized_x,
+ normalized_y);
Solver::SolverParameters params;
Solver solver(intrinsics_cost);
- /*Solver::Results results =*/ solver.minimize(params, &image);
+ /*Solver::Results results =*/solver.minimize(params, &image);
// TODO(keir): Better error handling.
diff --git a/intern/libmv/libmv/simple_pipeline/distortion_models.h b/intern/libmv/libmv/simple_pipeline/distortion_models.h
index 51300477956..5fe9fee8d54 100644
--- a/intern/libmv/libmv/simple_pipeline/distortion_models.h
+++ b/intern/libmv/libmv/simple_pipeline/distortion_models.h
@@ -46,37 +46,37 @@ void InvertPolynomialDistortionModel(const double focal_length_x,
const double p2,
const double image_x,
const double image_y,
- double *normalized_x,
- double *normalized_y);
+ double* normalized_x,
+ double* normalized_y);
// Apply camera intrinsics to the normalized point to get image coordinates.
// This applies the radial lens distortion to a point which is in normalized
// camera coordinates (i.e. the principal point is at (0, 0)) to get image
// coordinates in pixels. Templated for use with autodifferentiation.
template <typename T>
-inline void ApplyPolynomialDistortionModel(const T &focal_length_x,
- const T &focal_length_y,
- const T &principal_point_x,
- const T &principal_point_y,
- const T &k1,
- const T &k2,
- const T &k3,
- const T &p1,
- const T &p2,
- const T &normalized_x,
- const T &normalized_y,
- T *image_x,
- T *image_y) {
+inline void ApplyPolynomialDistortionModel(const T& focal_length_x,
+ const T& focal_length_y,
+ const T& principal_point_x,
+ const T& principal_point_y,
+ const T& k1,
+ const T& k2,
+ const T& k3,
+ const T& p1,
+ const T& p2,
+ const T& normalized_x,
+ const T& normalized_y,
+ T* image_x,
+ T* image_y) {
T x = normalized_x;
T y = normalized_y;
// Apply distortion to the normalized points to get (xd, yd).
- T r2 = x*x + y*y;
+ T r2 = x * x + y * y;
T r4 = r2 * r2;
T r6 = r4 * r2;
- T r_coeff = (T(1) + k1*r2 + k2*r4 + k3*r6);
- T xd = x * r_coeff + T(2)*p1*x*y + p2*(r2 + T(2)*x*x);
- T yd = y * r_coeff + T(2)*p2*x*y + p1*(r2 + T(2)*y*y);
+ T r_coeff = (T(1) + k1 * r2 + k2 * r4 + k3 * r6);
+ T xd = x * r_coeff + T(2) * p1 * x * y + p2 * (r2 + T(2) * x * x);
+ T yd = y * r_coeff + T(2) * p2 * x * y + p1 * (r2 + T(2) * y * y);
// Apply focal length and principal point to get the final image coordinates.
*image_x = focal_length_x * xd + principal_point_x;
@@ -96,8 +96,8 @@ void InvertDivisionDistortionModel(const double focal_length_x,
const double k2,
const double image_x,
const double image_y,
- double *normalized_x,
- double *normalized_y);
+ double* normalized_x,
+ double* normalized_y);
// Apply camera intrinsics to the normalized point to get image coordinates.
// This applies the radial lens distortion to a point which is in normalized
@@ -106,20 +106,19 @@ void InvertDivisionDistortionModel(const double focal_length_x,
//
// Uses division distortion model.
template <typename T>
-inline void ApplyDivisionDistortionModel(const T &focal_length_x,
- const T &focal_length_y,
- const T &principal_point_x,
- const T &principal_point_y,
- const T &k1,
- const T &k2,
- const T &normalized_x,
- const T &normalized_y,
- T *image_x,
- T *image_y) {
-
+inline void ApplyDivisionDistortionModel(const T& focal_length_x,
+ const T& focal_length_y,
+ const T& principal_point_x,
+ const T& principal_point_y,
+ const T& k1,
+ const T& k2,
+ const T& normalized_x,
+ const T& normalized_y,
+ T* image_x,
+ T* image_y) {
T x = normalized_x;
T y = normalized_y;
- T r2 = x*x + y*y;
+ T r2 = x * x + y * y;
T r4 = r2 * r2;
T xd = x / (T(1) + k1 * r2 + k2 * r4);
@@ -136,18 +135,18 @@ inline void ApplyDivisionDistortionModel(const T &focal_length_x,
//
// Uses Nuke distortion model.
template <typename T>
-void InvertNukeDistortionModel(const T &focal_length_x,
- const T &focal_length_y,
- const T &principal_point_x,
- const T &principal_point_y,
+void InvertNukeDistortionModel(const T& focal_length_x,
+ const T& focal_length_y,
+ const T& principal_point_x,
+ const T& principal_point_y,
const int image_width,
const int image_height,
- const T &k1,
- const T &k2,
- const T &image_x,
- const T &image_y,
- T *normalized_x,
- T *normalized_y) {
+ const T& k1,
+ const T& k2,
+ const T& image_x,
+ const T& image_y,
+ T* normalized_x,
+ T* normalized_y) {
// According to the documentation:
//
// xu = xd / (1 + k0 * rd^2 + k1 * rd^4)
@@ -174,9 +173,9 @@ void InvertNukeDistortionModel(const T &focal_length_x,
const T xd = (image_x - principal_point_x) / max_half_image_size;
const T yd = (image_y - principal_point_y) / max_half_image_size;
- T rd2 = xd*xd + yd*yd;
+ T rd2 = xd * xd + yd * yd;
T rd4 = rd2 * rd2;
- T r_coeff = T(1) / (T(1) + k1*rd2 + k2*rd4);
+ T r_coeff = T(1) / (T(1) + k1 * rd2 + k2 * rd4);
T xu = xd * r_coeff;
T yu = yd * r_coeff;
@@ -200,8 +199,8 @@ void ApplyNukeDistortionModel(const double focal_length_x,
const double k2,
const double normalized_x,
const double normalized_y,
- double *image_x,
- double *image_y);
+ double* image_x,
+ double* image_y);
// Invert camera intrinsics on the image point to get normalized coordinates.
// This inverts the radial lens distortion to a point which is in image pixel
@@ -218,24 +217,24 @@ void InvertBrownDistortionModel(const double focal_length_x,
const double p2,
const double image_x,
const double image_y,
- double *normalized_x,
- double *normalized_y);
+ double* normalized_x,
+ double* normalized_y);
template <typename T>
-inline void ApplyBrownDistortionModel(const T &focal_length_x,
- const T &focal_length_y,
- const T &principal_point_x,
- const T &principal_point_y,
- const T &k1,
- const T &k2,
- const T &k3,
- const T &k4,
- const T &p1,
- const T &p2,
- const T &normalized_x,
- const T &normalized_y,
- T *image_x,
- T *image_y) {
+inline void ApplyBrownDistortionModel(const T& focal_length_x,
+ const T& focal_length_y,
+ const T& principal_point_x,
+ const T& principal_point_y,
+ const T& k1,
+ const T& k2,
+ const T& k3,
+ const T& k4,
+ const T& p1,
+ const T& p2,
+ const T& normalized_x,
+ const T& normalized_y,
+ T* image_x,
+ T* image_y) {
T x = normalized_x;
T y = normalized_y;
@@ -253,8 +252,8 @@ inline void ApplyBrownDistortionModel(const T &focal_length_x,
// Apply focal length and principal point to get the final image coordinates.
*image_x = focal_length_x * xd + principal_point_x;
*image_y = focal_length_y * yd + principal_point_y;
-} // namespace libmv
+} // namespace libmv
-}
+} // namespace libmv
#endif // LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_
diff --git a/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc b/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc
index 7a086c375d5..10ad0929007 100644
--- a/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc
+++ b/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc
@@ -32,8 +32,9 @@
namespace libmv {
namespace {
-void GetImagesInMarkers(const vector<Marker> &markers,
- int *image1, int *image2) {
+void GetImagesInMarkers(const vector<Marker>& markers,
+ int* image1,
+ int* image2) {
if (markers.size() < 2) {
return;
}
@@ -50,10 +51,11 @@ void GetImagesInMarkers(const vector<Marker> &markers,
} // namespace
-bool EuclideanReconstructTwoFrames(const vector<Marker> &markers,
- EuclideanReconstruction *reconstruction) {
+bool EuclideanReconstructTwoFrames(const vector<Marker>& markers,
+ EuclideanReconstruction* reconstruction) {
if (markers.size() < 16) {
- LG << "Not enough markers to initialize from two frames: " << markers.size();
+ LG << "Not enough markers to initialize from two frames: "
+ << markers.size();
return false;
}
@@ -76,10 +78,8 @@ bool EuclideanReconstructTwoFrames(const vector<Marker> &markers,
Mat3 R;
Vec3 t;
Mat3 K = Mat3::Identity();
- if (!MotionFromEssentialAndCorrespondence(E,
- K, x1.col(0),
- K, x2.col(0),
- &R, &t)) {
+ if (!MotionFromEssentialAndCorrespondence(
+ E, K, x1.col(0), K, x2.col(0), &R, &t)) {
LG << "Failed to compute R and t from E and K.";
return false;
}
@@ -88,14 +88,14 @@ bool EuclideanReconstructTwoFrames(const vector<Marker> &markers,
reconstruction->InsertCamera(image1, Mat3::Identity(), Vec3::Zero());
reconstruction->InsertCamera(image2, R, t);
- LG << "From two frame reconstruction got:\nR:\n" << R
- << "\nt:" << t.transpose();
+ LG << "From two frame reconstruction got:\nR:\n"
+ << R << "\nt:" << t.transpose();
return true;
}
namespace {
-Mat3 DecodeF(const Vec9 &encoded_F) {
+Mat3 DecodeF(const Vec9& encoded_F) {
// Decode F and force it to be rank 2.
Map<const Mat3> full_rank_F(encoded_F.data(), 3, 3);
Eigen::JacobiSVD<Mat3> svd(full_rank_F,
@@ -110,22 +110,22 @@ Mat3 DecodeF(const Vec9 &encoded_F) {
// doing a full SVD of F at each iteration. This uses sampson error.
struct FundamentalSampsonCostFunction {
public:
- typedef Vec FMatrixType;
+ typedef Vec FMatrixType;
typedef Vec9 XMatrixType;
// Assumes markers are ordered by track.
- explicit FundamentalSampsonCostFunction(const vector<Marker> &markers)
- : markers(markers) {}
+ explicit FundamentalSampsonCostFunction(const vector<Marker>& markers)
+ : markers(markers) {}
- Vec operator()(const Vec9 &encoded_F) const {
+ Vec operator()(const Vec9& encoded_F) const {
// Decode F and force it to be rank 2.
Mat3 F = DecodeF(encoded_F);
Vec residuals(markers.size() / 2);
residuals.setZero();
for (int i = 0; i < markers.size() / 2; ++i) {
- const Marker &marker1 = markers[2*i + 0];
- const Marker &marker2 = markers[2*i + 1];
+ const Marker& marker1 = markers[2 * i + 0];
+ const Marker& marker2 = markers[2 * i + 1];
CHECK_EQ(marker1.track, marker2.track);
Vec2 x1(marker1.x, marker1.y);
Vec2 x2(marker2.x, marker2.y);
@@ -134,13 +134,13 @@ struct FundamentalSampsonCostFunction {
}
return residuals;
}
- const vector<Marker> &markers;
+ const vector<Marker>& markers;
};
} // namespace
-bool ProjectiveReconstructTwoFrames(const vector<Marker> &markers,
- ProjectiveReconstruction *reconstruction) {
+bool ProjectiveReconstructTwoFrames(const vector<Marker>& markers,
+ ProjectiveReconstruction* reconstruction) {
if (markers.size() < 16) {
return false;
}
diff --git a/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h b/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h
index 32cd4285190..354db14971f 100644
--- a/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h
+++ b/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h
@@ -37,18 +37,19 @@ class ProjectiveReconstruction;
tracks visible in both frames. The pose estimation of the camera for
these frames will be inserted into \a *reconstruction.
- \note The two frames need to have both enough parallax and enough common tracks
- for accurate reconstruction. At least 8 tracks are suggested.
- \note The origin of the coordinate system is defined to be the camera of
- the first keyframe.
- \note This assumes a calibrated reconstruction, e.g. the markers are
- already corrected for camera intrinsics and radial distortion.
+ \note The two frames need to have both enough parallax and enough common
+ tracks for accurate reconstruction. At least 8 tracks are suggested.
+ \note The origin of the coordinate system is defined to be the camera of the
+ first keyframe.
+ \note This assumes a calibrated reconstruction, e.g. the
+ markers are already corrected for camera intrinsics and radial
+ distortion.
\note This assumes an outlier-free set of markers.
\sa EuclideanResect, EuclideanIntersect, EuclideanBundle
*/
-bool EuclideanReconstructTwoFrames(const vector<Marker> &markers,
- EuclideanReconstruction *reconstruction);
+bool EuclideanReconstructTwoFrames(const vector<Marker>& markers,
+ EuclideanReconstruction* reconstruction);
/*!
Initialize the \link ProjectiveReconstruction reconstruction \endlink using
@@ -58,17 +59,17 @@ bool EuclideanReconstructTwoFrames(const vector<Marker> &markers,
tracks visible in both frames. An estimate of the projection matrices for
the two frames will get added to the reconstruction.
- \note The two frames need to have both enough parallax and enough common tracks
- for accurate reconstruction. At least 8 tracks are suggested.
- \note The origin of the coordinate system is defined to be the camera of
- the first keyframe.
+ \note The two frames need to have both enough parallax and enough common
+ tracks for accurate reconstruction. At least 8 tracks are suggested.
+ \note The origin of the coordinate system is defined to be the camera of the
+ first keyframe.
\note This assumes the markers are already corrected for radial distortion.
\note This assumes an outlier-free set of markers.
\sa ProjectiveResect, ProjectiveIntersect, ProjectiveBundle
*/
-bool ProjectiveReconstructTwoFrames(const vector<Marker> &markers,
- ProjectiveReconstruction *reconstruction);
+bool ProjectiveReconstructTwoFrames(const vector<Marker>& markers,
+ ProjectiveReconstruction* reconstruction);
} // namespace libmv
#endif // LIBMV_SIMPLE_PIPELINE_INITIALIZE_RECONSTRUCTION_H
diff --git a/intern/libmv/libmv/simple_pipeline/intersect.cc b/intern/libmv/libmv/simple_pipeline/intersect.cc
index ddb713684a4..86efd26f778 100644
--- a/intern/libmv/libmv/simple_pipeline/intersect.cc
+++ b/intern/libmv/libmv/simple_pipeline/intersect.cc
@@ -22,11 +22,11 @@
#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
+#include "libmv/multiview/nviewtriangulation.h"
#include "libmv/multiview/projection.h"
#include "libmv/multiview/triangulation.h"
-#include "libmv/multiview/nviewtriangulation.h"
-#include "libmv/numeric/numeric.h"
#include "libmv/numeric/levenberg_marquardt.h"
+#include "libmv/numeric/numeric.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"
@@ -38,12 +38,12 @@ namespace {
class EuclideanIntersectCostFunctor {
public:
- EuclideanIntersectCostFunctor(const Marker &marker,
- const EuclideanCamera &camera)
+ EuclideanIntersectCostFunctor(const Marker& marker,
+ const EuclideanCamera& camera)
: marker_(marker), camera_(camera) {}
- template<typename T>
- bool operator()(const T *X, T *residuals) const {
+ template <typename T>
+ bool operator()(const T* X, T* residuals) const {
typedef Eigen::Matrix<T, 3, 3> Mat3;
typedef Eigen::Matrix<T, 3, 1> Vec3;
@@ -60,14 +60,14 @@ class EuclideanIntersectCostFunctor {
return true;
}
- const Marker &marker_;
- const EuclideanCamera &camera_;
+ const Marker& marker_;
+ const EuclideanCamera& camera_;
};
} // namespace
-bool EuclideanIntersect(const vector<Marker> &markers,
- EuclideanReconstruction *reconstruction) {
+bool EuclideanIntersect(const vector<Marker>& markers,
+ EuclideanReconstruction* reconstruction) {
if (markers.size() < 2) {
return false;
}
@@ -78,7 +78,7 @@ bool EuclideanIntersect(const vector<Marker> &markers,
vector<Mat34> cameras;
Mat34 P;
for (int i = 0; i < markers.size(); ++i) {
- EuclideanCamera *camera = reconstruction->CameraForImage(markers[i].image);
+ EuclideanCamera* camera = reconstruction->CameraForImage(markers[i].image);
P_From_KRt(K, camera->R, camera->t, &P);
cameras.push_back(P);
}
@@ -103,19 +103,19 @@ bool EuclideanIntersect(const vector<Marker> &markers,
// Add residual blocks to the problem.
int num_residuals = 0;
for (int i = 0; i < markers.size(); ++i) {
- const Marker &marker = markers[i];
+ const Marker& marker = markers[i];
if (marker.weight != 0.0) {
- const EuclideanCamera &camera =
+ const EuclideanCamera& camera =
*reconstruction->CameraForImage(marker.image);
problem.AddResidualBlock(
- new ceres::AutoDiffCostFunction<
- EuclideanIntersectCostFunctor,
- 2, /* num_residuals */
- 3>(new EuclideanIntersectCostFunctor(marker, camera)),
+ new ceres::AutoDiffCostFunction<EuclideanIntersectCostFunctor,
+ 2, /* num_residuals */
+ 3>(
+ new EuclideanIntersectCostFunctor(marker, camera)),
NULL,
&X(0));
- num_residuals++;
+ num_residuals++;
}
}
@@ -126,9 +126,9 @@ bool EuclideanIntersect(const vector<Marker> &markers,
if (!num_residuals) {
LG << "Skipping running minimizer with zero residuals";
- // We still add 3D point for the track regardless it was
- // optimized or not. If track is a constant zero it'll use
- // algebraic intersection result as a 3D coordinate.
+ // We still add 3D point for the track regardless it was
+ // optimized or not. If track is a constant zero it'll use
+ // algebraic intersection result as a 3D coordinate.
Vec3 point = X.head<3>();
reconstruction->InsertPoint(markers[0].track, point);
@@ -152,12 +152,12 @@ bool EuclideanIntersect(const vector<Marker> &markers,
// Try projecting the point; make sure it's in front of everyone.
for (int i = 0; i < cameras.size(); ++i) {
- const EuclideanCamera &camera =
+ const EuclideanCamera& camera =
*reconstruction->CameraForImage(markers[i].image);
Vec3 x = camera.R * X + camera.t;
if (x(2) < 0) {
- LOG(ERROR) << "POINT BEHIND CAMERA " << markers[i].image
- << ": " << x.transpose();
+ LOG(ERROR) << "POINT BEHIND CAMERA " << markers[i].image << ": "
+ << x.transpose();
return false;
}
}
@@ -173,35 +173,35 @@ namespace {
struct ProjectiveIntersectCostFunction {
public:
- typedef Vec FMatrixType;
+ typedef Vec FMatrixType;
typedef Vec4 XMatrixType;
ProjectiveIntersectCostFunction(
- const vector<Marker> &markers,
- const ProjectiveReconstruction &reconstruction)
- : markers(markers), reconstruction(reconstruction) {}
+ const vector<Marker>& markers,
+ const ProjectiveReconstruction& reconstruction)
+ : markers(markers), reconstruction(reconstruction) {}
- Vec operator()(const Vec4 &X) const {
+ Vec operator()(const Vec4& X) const {
Vec residuals(2 * markers.size());
residuals.setZero();
for (int i = 0; i < markers.size(); ++i) {
- const ProjectiveCamera &camera =
+ const ProjectiveCamera& camera =
*reconstruction.CameraForImage(markers[i].image);
Vec3 projected = camera.P * X;
projected /= projected(2);
- residuals[2*i + 0] = projected(0) - markers[i].x;
- residuals[2*i + 1] = projected(1) - markers[i].y;
+ residuals[2 * i + 0] = projected(0) - markers[i].x;
+ residuals[2 * i + 1] = projected(1) - markers[i].y;
}
return residuals;
}
- const vector<Marker> &markers;
- const ProjectiveReconstruction &reconstruction;
+ const vector<Marker>& markers;
+ const ProjectiveReconstruction& reconstruction;
};
} // namespace
-bool ProjectiveIntersect(const vector<Marker> &markers,
- ProjectiveReconstruction *reconstruction) {
+bool ProjectiveIntersect(const vector<Marker>& markers,
+ ProjectiveReconstruction* reconstruction) {
if (markers.size() < 2) {
return false;
}
@@ -209,7 +209,7 @@ bool ProjectiveIntersect(const vector<Marker> &markers,
// Get the cameras to use for the intersection.
vector<Mat34> cameras;
for (int i = 0; i < markers.size(); ++i) {
- ProjectiveCamera *camera = reconstruction->CameraForImage(markers[i].image);
+ ProjectiveCamera* camera = reconstruction->CameraForImage(markers[i].image);
cameras.push_back(camera->P);
}
@@ -232,16 +232,16 @@ bool ProjectiveIntersect(const vector<Marker> &markers,
Solver solver(triangulate_cost);
Solver::Results results = solver.minimize(params, &X);
- (void) results; // TODO(keir): Ensure results are good.
+ (void)results; // TODO(keir): Ensure results are good.
// Try projecting the point; make sure it's in front of everyone.
for (int i = 0; i < cameras.size(); ++i) {
- const ProjectiveCamera &camera =
+ const ProjectiveCamera& camera =
*reconstruction->CameraForImage(markers[i].image);
Vec3 x = camera.P * X;
if (x(2) < 0) {
- LOG(ERROR) << "POINT BEHIND CAMERA " << markers[i].image
- << ": " << x.transpose();
+ LOG(ERROR) << "POINT BEHIND CAMERA " << markers[i].image << ": "
+ << x.transpose();
}
}
diff --git a/intern/libmv/libmv/simple_pipeline/intersect.h b/intern/libmv/libmv/simple_pipeline/intersect.h
index 15d6f998557..aff3ffe66e2 100644
--- a/intern/libmv/libmv/simple_pipeline/intersect.h
+++ b/intern/libmv/libmv/simple_pipeline/intersect.h
@@ -22,8 +22,8 @@
#define LIBMV_SIMPLE_PIPELINE_INTERSECT_H
#include "libmv/base/vector.h"
-#include "libmv/simple_pipeline/tracks.h"
#include "libmv/simple_pipeline/reconstruction.h"
+#include "libmv/simple_pipeline/tracks.h"
namespace libmv {
@@ -38,7 +38,8 @@ namespace libmv {
\a markers should contain all \link Marker markers \endlink belonging to
tracks visible in all frames.
\a reconstruction should contain the cameras for all frames.
- The new \link Point points \endlink will be inserted in \a reconstruction.
+ The new \link Point points \endlink will be inserted in \a
+ reconstruction.
\note This assumes a calibrated reconstruction, e.g. the markers are
already corrected for camera intrinsics and radial distortion.
@@ -46,8 +47,8 @@ namespace libmv {
\sa EuclideanResect
*/
-bool EuclideanIntersect(const vector<Marker> &markers,
- EuclideanReconstruction *reconstruction);
+bool EuclideanIntersect(const vector<Marker>& markers,
+ EuclideanReconstruction* reconstruction);
/*!
Estimate the homogeneous coordinates of a track by intersecting rays.
@@ -60,7 +61,8 @@ bool EuclideanIntersect(const vector<Marker> &markers,
\a markers should contain all \link Marker markers \endlink belonging to
tracks visible in all frames.
\a reconstruction should contain the cameras for all frames.
- The new \link Point points \endlink will be inserted in \a reconstruction.
+ The new \link Point points \endlink will be inserted in \a
+ reconstruction.
\note This assumes that radial distortion is already corrected for, but
does not assume that e.g. focal length and principal point are
@@ -69,8 +71,8 @@ bool EuclideanIntersect(const vector<Marker> &markers,
\sa Resect
*/
-bool ProjectiveIntersect(const vector<Marker> &markers,
- ProjectiveReconstruction *reconstruction);
+bool ProjectiveIntersect(const vector<Marker>& markers,
+ ProjectiveReconstruction* reconstruction);
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/intersect_test.cc b/intern/libmv/libmv/simple_pipeline/intersect_test.cc
index dd4fdc789af..447cc095cb0 100644
--- a/intern/libmv/libmv/simple_pipeline/intersect_test.cc
+++ b/intern/libmv/libmv/simple_pipeline/intersect_test.cc
@@ -22,10 +22,10 @@
#include <iostream>
-#include "testing/testing.h"
+#include "libmv/logging/logging.h"
#include "libmv/multiview/projection.h"
#include "libmv/numeric/numeric.h"
-#include "libmv/logging/logging.h"
+#include "testing/testing.h"
namespace libmv {
@@ -40,13 +40,15 @@ TEST(Intersect, EuclideanIntersect) {
// 0, 0, 1;
Mat3 R1 = RotationAroundZ(-0.1);
Mat3 R2 = RotationAroundX(-0.1);
- Vec3 t1; t1 << 1, 1, 10;
- Vec3 t2; t2 << -2, -1, 10;
+ Vec3 t1;
+ t1 << 1, 1, 10;
+ Vec3 t2;
+ t2 << -2, -1, 10;
Mat34 P1, P2;
P_From_KRt(K1, R1, t1, &P1);
P_From_KRt(K2, R2, t2, &P2);
- //Mat3 F; FundamentalFromProjections(P1, P2, &F);
+ // Mat3 F; FundamentalFromProjections(P1, P2, &F);
Mat3X X;
X.resize(3, 30);
@@ -68,9 +70,9 @@ TEST(Intersect, EuclideanIntersect) {
reconstruction.InsertCamera(2, R2, t2);
vector<Marker> markers;
- Marker a = { 1, 0, x1.x(), x1.y(), 1.0 };
+ Marker a = {1, 0, x1.x(), x1.y(), 1.0};
markers.push_back(a);
- Marker b = { 2, 0, x2.x(), x2.y(), 1.0 };
+ Marker b = {2, 0, x2.x(), x2.y(), 1.0};
markers.push_back(b);
EuclideanIntersect(markers, &reconstruction);
@@ -78,4 +80,4 @@ TEST(Intersect, EuclideanIntersect) {
EXPECT_NEAR(0, DistanceLInfinity(estimated, expected), 1e-8);
}
}
-} // namespace
+} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/keyframe_selection.cc b/intern/libmv/libmv/simple_pipeline/keyframe_selection.cc
index 241b5600505..5526d730651 100644
--- a/intern/libmv/libmv/simple_pipeline/keyframe_selection.cc
+++ b/intern/libmv/libmv/simple_pipeline/keyframe_selection.cc
@@ -20,20 +20,20 @@
#include "libmv/simple_pipeline/keyframe_selection.h"
-#include "libmv/numeric/numeric.h"
#include "ceres/ceres.h"
#include "libmv/logging/logging.h"
-#include "libmv/multiview/homography.h"
#include "libmv/multiview/fundamental.h"
-#include "libmv/simple_pipeline/intersect.h"
+#include "libmv/multiview/homography.h"
+#include "libmv/numeric/numeric.h"
#include "libmv/simple_pipeline/bundle.h"
+#include "libmv/simple_pipeline/intersect.h"
#include <Eigen/Eigenvalues>
namespace libmv {
namespace {
-Mat3 IntrinsicsNormalizationMatrix(const CameraIntrinsics &intrinsics) {
+Mat3 IntrinsicsNormalizationMatrix(const CameraIntrinsics& intrinsics) {
Mat3 T = Mat3::Identity(), S = Mat3::Identity();
T(0, 2) = -intrinsics.principal_point_x();
@@ -56,7 +56,7 @@ Mat3 IntrinsicsNormalizationMatrix(const CameraIntrinsics &intrinsics) {
// (k = 7 for a fundamental matrix or 8 for a homography)
// r is the dimension of the data
// (r = 4 for 2D correspondences between two frames)
-double GRIC(const Vec &e, int d, int k, int r) {
+double GRIC(const Vec& e, int d, int k, int r) {
int n = e.rows();
double lambda1 = log(static_cast<double>(r));
double lambda2 = log(static_cast<double>(r * n));
@@ -89,7 +89,7 @@ double GRIC(const Vec &e, int d, int k, int r) {
//
// TODO(keir): Consider moving this into the numeric code, since this is not
// related to keyframe selection.
-Mat PseudoInverseWithClampedEigenvalues(const Mat &matrix,
+Mat PseudoInverseWithClampedEigenvalues(const Mat& matrix,
int num_eigenvalues_to_clamp) {
Eigen::EigenSolver<Mat> eigen_solver(matrix);
Mat D = eigen_solver.pseudoEigenvalueMatrix();
@@ -112,27 +112,24 @@ Mat PseudoInverseWithClampedEigenvalues(const Mat &matrix,
return V * D * V.inverse();
}
-void FilterZeroWeightMarkersFromTracks(const Tracks &tracks,
- Tracks *filtered_tracks) {
+void FilterZeroWeightMarkersFromTracks(const Tracks& tracks,
+ Tracks* filtered_tracks) {
vector<Marker> all_markers = tracks.AllMarkers();
for (int i = 0; i < all_markers.size(); ++i) {
- Marker &marker = all_markers[i];
+ Marker& marker = all_markers[i];
if (marker.weight != 0.0) {
- filtered_tracks->Insert(marker.image,
- marker.track,
- marker.x,
- marker.y,
- marker.weight);
+ filtered_tracks->Insert(
+ marker.image, marker.track, marker.x, marker.y, marker.weight);
}
}
}
} // namespace
-void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
- const CameraIntrinsics &intrinsics,
- vector<int> &keyframes) {
+void SelectKeyframesBasedOnGRICAndVariance(const Tracks& _tracks,
+ const CameraIntrinsics& intrinsics,
+ vector<int>& keyframes) {
// Mirza Tahir Ahmed, Matthew N. Dailey
// Robust key frame extraction for 3D reconstruction from video streams
//
@@ -172,23 +169,21 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
candidate_image <= max_image;
candidate_image++) {
// Conjunction of all markers from both keyframes
- vector<Marker> all_markers =
- filtered_tracks.MarkersInBothImages(current_keyframe,
- candidate_image);
+ vector<Marker> all_markers = filtered_tracks.MarkersInBothImages(
+ current_keyframe, candidate_image);
// Match keypoints between frames current_keyframe and candidate_image
vector<Marker> tracked_markers =
- filtered_tracks.MarkersForTracksInBothImages(current_keyframe,
- candidate_image);
+ filtered_tracks.MarkersForTracksInBothImages(current_keyframe,
+ candidate_image);
// Correspondences in normalized space
Mat x1, x2;
CoordinatesForMarkersInImage(tracked_markers, current_keyframe, &x1);
CoordinatesForMarkersInImage(tracked_markers, candidate_image, &x2);
- LG << "Found " << x1.cols()
- << " correspondences between " << current_keyframe
- << " and " << candidate_image;
+ LG << "Found " << x1.cols() << " correspondences between "
+ << current_keyframe << " and " << candidate_image;
// Not enough points to construct fundamental matrix
if (x1.cols() < 8 || x2.cols() < 8)
@@ -199,9 +194,8 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
int Tf = all_markers.size();
double Rc = static_cast<double>(Tc) / Tf;
- LG << "Correspondence between " << current_keyframe
- << " and " << candidate_image
- << ": " << Rc;
+ LG << "Correspondence between " << current_keyframe << " and "
+ << candidate_image << ": " << Rc;
if (Rc < Tmin || Rc > Tmax)
continue;
@@ -210,19 +204,15 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
// Estimate homography using default options.
EstimateHomographyOptions estimate_homography_options;
- EstimateHomography2DFromCorrespondences(x1,
- x2,
- estimate_homography_options,
- &H);
+ EstimateHomography2DFromCorrespondences(
+ x1, x2, estimate_homography_options, &H);
// Convert homography to original pixel space.
H = N_inverse * H * N;
EstimateFundamentalOptions estimate_fundamental_options;
- EstimateFundamentalFromCorrespondences(x1,
- x2,
- estimate_fundamental_options,
- &F);
+ EstimateFundamentalFromCorrespondences(
+ x1, x2, estimate_fundamental_options, &F);
// Convert fundamental to original pixel space.
F = N_inverse * F * N;
@@ -238,11 +228,11 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
for (int i = 0; i < x1.cols(); i++) {
Vec2 current_x1, current_x2;
- intrinsics.NormalizedToImageSpace(x1(0, i), x1(1, i),
- &current_x1(0), &current_x1(1));
+ intrinsics.NormalizedToImageSpace(
+ x1(0, i), x1(1, i), &current_x1(0), &current_x1(1));
- intrinsics.NormalizedToImageSpace(x2(0, i), x2(1, i),
- &current_x2(0), &current_x2(1));
+ intrinsics.NormalizedToImageSpace(
+ x2(0, i), x2(1, i), &current_x2(0), &current_x2(1));
H_e(i) = SymmetricGeometricDistance(H, current_x1, current_x2);
F_e(i) = SymmetricEpipolarDistance(F, current_x1, current_x2);
@@ -255,10 +245,8 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
double GRIC_H = GRIC(H_e, 2, 8, 4);
double GRIC_F = GRIC(F_e, 3, 7, 4);
- LG << "GRIC values for frames " << current_keyframe
- << " and " << candidate_image
- << ", H-GRIC: " << GRIC_H
- << ", F-GRIC: " << GRIC_F;
+ LG << "GRIC values for frames " << current_keyframe << " and "
+ << candidate_image << ", H-GRIC: " << GRIC_H << ", F-GRIC: " << GRIC_F;
if (GRIC_H <= GRIC_F)
continue;
@@ -295,23 +283,19 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
Vec3 t;
Mat3 K = Mat3::Identity();
- if (!MotionFromEssentialAndCorrespondence(E,
- K, x1.col(0),
- K, x2.col(0),
- &R, &t)) {
+ if (!MotionFromEssentialAndCorrespondence(
+ E, K, x1.col(0), K, x2.col(0), &R, &t)) {
LG << "Failed to compute R and t from E and K";
continue;
}
- LG << "Camera transform between frames " << current_keyframe
- << " and " << candidate_image
- << ":\nR:\n" << R
- << "\nt:" << t.transpose();
+ LG << "Camera transform between frames " << current_keyframe << " and "
+ << candidate_image << ":\nR:\n"
+ << R << "\nt:" << t.transpose();
// First camera is identity, second one is relative to it
- reconstruction.InsertCamera(current_keyframe,
- Mat3::Identity(),
- Vec3::Zero());
+ reconstruction.InsertCamera(
+ current_keyframe, Mat3::Identity(), Vec3::Zero());
reconstruction.InsertCamera(candidate_image, R, t);
// Reconstruct 3D points
@@ -349,7 +333,7 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
}
double success_intersects_factor =
- (double) intersects_success / intersects_total;
+ (double)intersects_success / intersects_total;
if (success_intersects_factor < success_intersects_factor_best) {
LG << "Skip keyframe candidate because of "
@@ -372,7 +356,7 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
&empty_intrinsics,
&evaluation);
- Mat &jacobian = evaluation.jacobian;
+ Mat& jacobian = evaluation.jacobian;
Mat JT_J = jacobian.transpose() * jacobian;
// There are 7 degrees of freedom, so clamp them out.
@@ -380,10 +364,10 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
Mat temp_derived = JT_J * JT_J_inv * JT_J;
bool is_inversed = (temp_derived - JT_J).cwiseAbs2().sum() <
- 1e-4 * std::min(temp_derived.cwiseAbs2().sum(),
- JT_J.cwiseAbs2().sum());
+ 1e-4 * std::min(temp_derived.cwiseAbs2().sum(),
+ JT_J.cwiseAbs2().sum());
- LG << "Check on inversed: " << (is_inversed ? "true" : "false" )
+ LG << "Check on inversed: " << (is_inversed ? "true" : "false")
<< ", det(JT_J): " << JT_J.determinant();
if (!is_inversed) {
@@ -400,8 +384,7 @@ void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks,
double Sc = static_cast<double>(I + A) / Square(3 * I) * Sigma_P.trace();
- LG << "Expected estimation error between "
- << current_keyframe << " and "
+ LG << "Expected estimation error between " << current_keyframe << " and "
<< candidate_image << ": " << Sc;
// Pairing with a lower Sc indicates a better choice
diff --git a/intern/libmv/libmv/simple_pipeline/keyframe_selection.h b/intern/libmv/libmv/simple_pipeline/keyframe_selection.h
index 25253af32fe..a1b3910abd4 100644
--- a/intern/libmv/libmv/simple_pipeline/keyframe_selection.h
+++ b/intern/libmv/libmv/simple_pipeline/keyframe_selection.h
@@ -22,8 +22,8 @@
#define LIBMV_SIMPLE_PIPELINE_KEYFRAME_SELECTION_H_
#include "libmv/base/vector.h"
-#include "libmv/simple_pipeline/tracks.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
+#include "libmv/simple_pipeline/tracks.h"
namespace libmv {
@@ -43,10 +43,9 @@ namespace libmv {
// \param intrinsics: is camera intrinsics.
// \param keyframes: will contain all images number which are considered
// good to be used for reconstruction.
-void SelectKeyframesBasedOnGRICAndVariance(
- const Tracks &tracks,
- const CameraIntrinsics &intrinsics,
- vector<int> &keyframes);
+void SelectKeyframesBasedOnGRICAndVariance(const Tracks& tracks,
+ const CameraIntrinsics& intrinsics,
+ vector<int>& keyframes);
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/keyframe_selection_test.cc b/intern/libmv/libmv/simple_pipeline/keyframe_selection_test.cc
index 9d88362cc88..983349c0c5a 100644
--- a/intern/libmv/libmv/simple_pipeline/keyframe_selection_test.cc
+++ b/intern/libmv/libmv/simple_pipeline/keyframe_selection_test.cc
@@ -1,15 +1,15 @@
// Copyright (c) 2011 libmv authors.
-//
+//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
-//
+//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
-//
+//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -20,9 +20,9 @@
#include "libmv/simple_pipeline/keyframe_selection.h"
-#include "testing/testing.h"
-#include "libmv/simple_pipeline/camera_intrinsics.h"
#include "libmv/logging/logging.h"
+#include "libmv/simple_pipeline/camera_intrinsics.h"
+#include "testing/testing.h"
namespace libmv {
@@ -30,7 +30,7 @@ namespace libmv {
// Should not be keyframe
TEST(KeyframeSelection, SyntheticNeighborFrame) {
PolynomialCameraIntrinsics intrinsics;
- intrinsics.SetFocalLength(900.0,900.0);
+ intrinsics.SetFocalLength(900.0, 900.0);
intrinsics.SetPrincipalPoint(640.0, 540.0);
intrinsics.SetRadialDistortion(0.0, 0.0, 0.0);
@@ -66,25 +66,56 @@ TEST(KeyframeSelection, FabrikEingangNeighborFrames) {
intrinsics.SetPrincipalPoint(960.000, 544.000);
intrinsics.SetRadialDistortion(0.0, 0.0, 0.0);
- Marker markers[] = {
- {1, 0, 737.599983, 646.397594, 1.0}, {2, 0, 737.906628, 648.113327, 1.0}, {1, 1, 863.045425, 646.081905, 1.0},
- {2, 1, 863.339767, 647.650040, 1.0}, {1, 2, 736.959972, 574.080151, 1.0}, {2, 2, 737.217350, 575.604900, 1.0},
- {1, 3, 864.097424, 573.374908, 1.0}, {2, 3, 864.383469, 574.900307, 1.0}, {1, 4, 789.429073, 631.677521, 1.0},
- {2, 4, 789.893131, 633.124451, 1.0}, {1, 5, 791.051960, 573.442028, 1.0}, {2, 5, 791.336575, 575.088890, 1.0},
- {1, 6, 738.973961, 485.130308, 1.0}, {2, 6, 739.435501, 486.734207, 1.0}, {1, 7, 862.403240, 514.866074, 1.0},
- {2, 7, 862.660618, 516.413261, 1.0}, {1, 8, 802.240162, 485.759838, 1.0}, {2, 8, 802.602253, 487.432899, 1.0},
- {1, 9, 754.340630, 500.624559, 1.0}, {2, 9, 754.559956, 502.079920, 1.0}, {1, 10, 849.398689, 484.480545, 1.0},
- {2, 10, 849.599934, 486.079937, 1.0}, {1, 11, 788.803768, 515.924391, 1.0}, {2, 11, 789.119911, 517.439932, 1.0},
- {1, 12, 838.733940, 558.212688, 1.0}, {2, 12, 839.039898, 559.679916, 1.0}, {1, 13, 760.014782, 575.194466, 1.0},
- {2, 13, 760.319881, 576.639904, 1.0}, {1, 14, 765.321636, 616.015957, 1.0}, {2, 14, 765.759945, 617.599915, 1.0},
- {1, 15, 800.963230, 660.032082, 1.0}, {2, 15, 801.279945, 661.759876, 1.0}, {1, 16, 846.321087, 602.313053, 1.0},
- {2, 16, 846.719913, 603.839878, 1.0}, {1, 17, 864.288311, 616.790524, 1.0}, {2, 17, 864.639931, 618.239918, 1.0},
- {1, 18, 800.006790, 602.573425, 1.0}, {2, 18, 800.319958, 604.159912, 1.0}, {1, 19, 739.026890, 617.944138, 1.0},
- {2, 19, 739.199924, 619.519924, 1.0}, {1, 20, 801.987419, 544.134888, 1.0}, {2, 20, 802.239933, 545.599911, 1.0},
- {1, 21, 753.619823, 542.961300, 1.0}, {2, 21, 753.919945, 544.639874, 1.0}, {1, 22, 787.921257, 499.910206, 1.0},
- {2, 22, 788.159924, 501.439917, 1.0}, {1, 23, 839.095459, 529.287903, 1.0}, {2, 23, 839.359932, 530.879934, 1.0},
- {1, 24, 811.760330, 630.732269, 1.0}, {2, 24, 812.159901, 632.319859, 1.0}
- };
+ Marker markers[] = {{1, 0, 737.599983, 646.397594, 1.0},
+ {2, 0, 737.906628, 648.113327, 1.0},
+ {1, 1, 863.045425, 646.081905, 1.0},
+ {2, 1, 863.339767, 647.650040, 1.0},
+ {1, 2, 736.959972, 574.080151, 1.0},
+ {2, 2, 737.217350, 575.604900, 1.0},
+ {1, 3, 864.097424, 573.374908, 1.0},
+ {2, 3, 864.383469, 574.900307, 1.0},
+ {1, 4, 789.429073, 631.677521, 1.0},
+ {2, 4, 789.893131, 633.124451, 1.0},
+ {1, 5, 791.051960, 573.442028, 1.0},
+ {2, 5, 791.336575, 575.088890, 1.0},
+ {1, 6, 738.973961, 485.130308, 1.0},
+ {2, 6, 739.435501, 486.734207, 1.0},
+ {1, 7, 862.403240, 514.866074, 1.0},
+ {2, 7, 862.660618, 516.413261, 1.0},
+ {1, 8, 802.240162, 485.759838, 1.0},
+ {2, 8, 802.602253, 487.432899, 1.0},
+ {1, 9, 754.340630, 500.624559, 1.0},
+ {2, 9, 754.559956, 502.079920, 1.0},
+ {1, 10, 849.398689, 484.480545, 1.0},
+ {2, 10, 849.599934, 486.079937, 1.0},
+ {1, 11, 788.803768, 515.924391, 1.0},
+ {2, 11, 789.119911, 517.439932, 1.0},
+ {1, 12, 838.733940, 558.212688, 1.0},
+ {2, 12, 839.039898, 559.679916, 1.0},
+ {1, 13, 760.014782, 575.194466, 1.0},
+ {2, 13, 760.319881, 576.639904, 1.0},
+ {1, 14, 765.321636, 616.015957, 1.0},
+ {2, 14, 765.759945, 617.599915, 1.0},
+ {1, 15, 800.963230, 660.032082, 1.0},
+ {2, 15, 801.279945, 661.759876, 1.0},
+ {1, 16, 846.321087, 602.313053, 1.0},
+ {2, 16, 846.719913, 603.839878, 1.0},
+ {1, 17, 864.288311, 616.790524, 1.0},
+ {2, 17, 864.639931, 618.239918, 1.0},
+ {1, 18, 800.006790, 602.573425, 1.0},
+ {2, 18, 800.319958, 604.159912, 1.0},
+ {1, 19, 739.026890, 617.944138, 1.0},
+ {2, 19, 739.199924, 619.519924, 1.0},
+ {1, 20, 801.987419, 544.134888, 1.0},
+ {2, 20, 802.239933, 545.599911, 1.0},
+ {1, 21, 753.619823, 542.961300, 1.0},
+ {2, 21, 753.919945, 544.639874, 1.0},
+ {1, 22, 787.921257, 499.910206, 1.0},
+ {2, 22, 788.159924, 501.439917, 1.0},
+ {1, 23, 839.095459, 529.287903, 1.0},
+ {2, 23, 839.359932, 530.879934, 1.0},
+ {1, 24, 811.760330, 630.732269, 1.0},
+ {2, 24, 812.159901, 632.319859, 1.0}};
int num_markers = sizeof(markers) / sizeof(Marker);
Tracks tracks;
@@ -108,18 +139,34 @@ TEST(KeyframeSelection, FabrikEingangFarFrames) {
intrinsics.SetPrincipalPoint(960.000, 544.000);
intrinsics.SetRadialDistortion(0.0, 0.0, 0.0);
- Marker markers[] = {
- {1, 0, 369.459200, 619.315258, 1.0}, {2, 0, 279.677496, 722.086842, 1.0}, {1, 1, 376.831970, 370.278397, 1.0},
- {2, 1, 221.695247, 460.065418, 1.0}, {1, 2, 1209.139023, 567.705605, 1.0}, {2, 2, 1080.760117, 659.230083, 1.0},
- {1, 3, 1643.495750, 903.620453, 1.0}, {2, 3, 1618.405037, 1015.374908, 1.0}, {1, 4, 1494.849815, 425.302460, 1.0},
- {2, 4, 1457.467575, 514.727587, 1.0}, {1, 5, 1794.637299, 328.728609, 1.0}, {2, 5, 1742.161446, 408.988636, 1.0},
- {1, 6, 1672.822723, 102.240358, 1.0}, {2, 6, 1539.287224, 153.536892, 1.0}, {1, 7, 1550.843925, 53.424943, 1.0},
- {2, 7, 1385.579109, 96.450085, 1.0}, {1, 8, 852.953281, 465.399578, 1.0}, {2, 8, 779.404564, 560.091843, 1.0},
- {1, 9, 906.853752, 299.827040, 1.0}, {2, 9, 786.923218, 385.570770, 1.0}, {1, 10, 406.322966, 87.556041, 1.0},
- {2, 10, 140.339413, 150.877481, 1.0}, {1, 11, 254.811573, 851.296478, 1.0}, {2, 11, 94.478302, 969.350189, 1.0},
- {1, 12, 729.087868, 806.092758, 1.0}, {2, 12, 606.212139, 919.876560, 1.0}, {1, 13, 1525.719452, 920.398083, 1.0},
- {2, 13, 1495.579720, 1031.971218, 1.0}
- };
+ Marker markers[] = {{1, 0, 369.459200, 619.315258, 1.0},
+ {2, 0, 279.677496, 722.086842, 1.0},
+ {1, 1, 376.831970, 370.278397, 1.0},
+ {2, 1, 221.695247, 460.065418, 1.0},
+ {1, 2, 1209.139023, 567.705605, 1.0},
+ {2, 2, 1080.760117, 659.230083, 1.0},
+ {1, 3, 1643.495750, 903.620453, 1.0},
+ {2, 3, 1618.405037, 1015.374908, 1.0},
+ {1, 4, 1494.849815, 425.302460, 1.0},
+ {2, 4, 1457.467575, 514.727587, 1.0},
+ {1, 5, 1794.637299, 328.728609, 1.0},
+ {2, 5, 1742.161446, 408.988636, 1.0},
+ {1, 6, 1672.822723, 102.240358, 1.0},
+ {2, 6, 1539.287224, 153.536892, 1.0},
+ {1, 7, 1550.843925, 53.424943, 1.0},
+ {2, 7, 1385.579109, 96.450085, 1.0},
+ {1, 8, 852.953281, 465.399578, 1.0},
+ {2, 8, 779.404564, 560.091843, 1.0},
+ {1, 9, 906.853752, 299.827040, 1.0},
+ {2, 9, 786.923218, 385.570770, 1.0},
+ {1, 10, 406.322966, 87.556041, 1.0},
+ {2, 10, 140.339413, 150.877481, 1.0},
+ {1, 11, 254.811573, 851.296478, 1.0},
+ {2, 11, 94.478302, 969.350189, 1.0},
+ {1, 12, 729.087868, 806.092758, 1.0},
+ {2, 12, 606.212139, 919.876560, 1.0},
+ {1, 13, 1525.719452, 920.398083, 1.0},
+ {2, 13, 1495.579720, 1031.971218, 1.0}};
int num_markers = sizeof(markers) / sizeof(Marker);
Tracks tracks;
@@ -144,17 +191,35 @@ TEST(KeyframeSelection, CopterManualKeyFrames) {
intrinsics.SetRadialDistortion(-0.08590, 0.0, 0.0);
Marker markers[] = {
- {1, 0, 645.792694, 403.115931, 1.0}, {2, 0, 630.641174, 307.996409, 1.0}, {1, 1, 783.469086, 403.904328, 1.0},
- {2, 1, 766.001129, 308.998225, 1.0}, {1, 2, 650.000000, 160.000001, 1.0}, {1, 3, 785.225906, 158.619039, 1.0},
- {2, 3, 767.526474, 70.449695, 1.0}, {1, 4, 290.640526, 382.335634, 1.0}, {2, 4, 273.001728, 86.993319, 1.0},
- {1, 5, 291.162739, 410.602684, 1.0}, {2, 5, 273.287849, 111.937487, 1.0}, {1, 6, 136.919317, 349.895797, 1.0},
- {1, 7, 490.844345, 47.572222, 1.0}, {1, 8, 454.406433, 488.935761, 1.0}, {1, 9, 378.655815, 618.522248, 1.0},
- {2, 9, 357.061806, 372.265077, 1.0}, {1, 10, 496.011391, 372.668824, 1.0}, {2, 10, 477.979164, 222.986112, 1.0},
- {1, 11, 680.060272, 256.103625, 1.0}, {2, 11, 670.587540, 204.830453, 1.0}, {1, 12, 1070.817108, 218.775322, 1.0},
- {2, 12, 1046.129913, 128.969783, 1.0}, {1, 14, 242.516403, 596.048512, 1.0}, {2, 14, 224.182606, 248.272154, 1.0},
- {1, 15, 613.936272, 287.519073, 1.0}, {2, 15, 600.467644, 196.085722, 1.0}, {1, 31, 844.637451, 256.354315, 1.0},
+ {1, 0, 645.792694, 403.115931, 1.0},
+ {2, 0, 630.641174, 307.996409, 1.0},
+ {1, 1, 783.469086, 403.904328, 1.0},
+ {2, 1, 766.001129, 308.998225, 1.0},
+ {1, 2, 650.000000, 160.000001, 1.0},
+ {1, 3, 785.225906, 158.619039, 1.0},
+ {2, 3, 767.526474, 70.449695, 1.0},
+ {1, 4, 290.640526, 382.335634, 1.0},
+ {2, 4, 273.001728, 86.993319, 1.0},
+ {1, 5, 291.162739, 410.602684, 1.0},
+ {2, 5, 273.287849, 111.937487, 1.0},
+ {1, 6, 136.919317, 349.895797, 1.0},
+ {1, 7, 490.844345, 47.572222, 1.0},
+ {1, 8, 454.406433, 488.935761, 1.0},
+ {1, 9, 378.655815, 618.522248, 1.0},
+ {2, 9, 357.061806, 372.265077, 1.0},
+ {1, 10, 496.011391, 372.668824, 1.0},
+ {2, 10, 477.979164, 222.986112, 1.0},
+ {1, 11, 680.060272, 256.103625, 1.0},
+ {2, 11, 670.587540, 204.830453, 1.0},
+ {1, 12, 1070.817108, 218.775322, 1.0},
+ {2, 12, 1046.129913, 128.969783, 1.0},
+ {1, 14, 242.516403, 596.048512, 1.0},
+ {2, 14, 224.182606, 248.272154, 1.0},
+ {1, 15, 613.936272, 287.519073, 1.0},
+ {2, 15, 600.467644, 196.085722, 1.0},
+ {1, 31, 844.637451, 256.354315, 1.0},
{2, 31, 823.200150, 165.714952, 1.0},
- };
+ };
int num_markers = sizeof(markers) / sizeof(Marker);
Tracks tracks;
@@ -180,52 +245,140 @@ TEST(KeyframeSelection, ElevatorManualKeyframesFrames) {
intrinsics.SetRadialDistortion(-0.034, 0.0, 0.0);
Marker markers[] = {
- {1, 2, 1139.861412, 1034.634984, 1.0}, {2, 2, 1143.512192, 1065.355718, 1.0}, {1, 3, 1760.821953, 644.658036, 1.0},
- {2, 3, 1770.901108, 697.899928, 1.0}, {1, 4, 858.071823, 1068.520746, 1.0}, {1, 6, 1633.952408, 797.050145, 1.0},
- {2, 6, 1642.508469, 849.157140, 1.0}, {1, 8, 1716.695824, 451.805491, 1.0}, {2, 8, 1726.513939, 502.095687, 1.0},
- {1, 9, 269.577627, 724.986935, 1.0}, {2, 9, 269.424820, 764.154246, 1.0}, {1, 10, 1891.321907, 706.948843, 1.0},
- {2, 10, 1903.338547, 766.068377, 1.0}, {1, 12, 1806.227074, 956.089604, 1.0}, {2, 12, 1816.619568, 1013.767376, 1.0},
- {1, 14, 269.544153, 1002.333570, 1.0}, {2, 14, 269.367542, 1043.509254, 1.0}, {1, 15, 1402.772141, 281.392962, 1.0},
- {2, 15, 1409.089165, 318.731629, 1.0}, {1, 16, 195.877233, 919.454341, 1.0}, {2, 16, 192.531109, 997.367899, 1.0},
- {1, 17, 1789.584045, 120.036661, 1.0}, {2, 17, 1800.391846, 167.822964, 1.0}, {1, 18, 999.363213, 765.004807, 1.0},
- {2, 18, 1002.345772, 790.560122, 1.0}, {1, 19, 647.342491, 1044.805727, 1.0}, {2, 19, 649.328041, 1058.682940, 1.0},
- {1, 20, 1365.486832, 440.901829, 1.0}, {2, 20, 1371.413040, 477.888730, 1.0}, {1, 21, 1787.125282, 301.431606, 1.0},
- {2, 21, 1798.527260, 355.224531, 1.0}, {1, 22, 1257.805824, 932.797258, 1.0}, {2, 22, 1263.017578, 969.376774, 1.0},
- {1, 23, 961.969528, 843.148112, 1.0}, {2, 23, 964.869461, 868.587620, 1.0}, {1, 24, 158.076110, 1052.643592, 1.0},
- {1, 25, 1072.884521, 1005.296981, 1.0}, {2, 25, 1076.091156, 1032.776856, 1.0}, {1, 26, 1107.656937, 526.577228, 1.0},
- {2, 26, 1111.618423, 555.524454, 1.0}, {1, 27, 1416.410751, 529.857581, 1.0}, {2, 27, 1422.663574, 570.025957, 1.0},
- {1, 28, 1498.673630, 1005.453086, 1.0}, {2, 28, 1505.381813, 1051.827149, 1.0}, {1, 29, 1428.647804, 652.473629, 1.0},
- {2, 29, 1434.898224, 692.715390, 1.0}, {1, 30, 1332.318764, 503.673599, 1.0}, {2, 30, 1338.000069, 540.507967, 1.0},
- {1, 32, 1358.642693, 709.837904, 1.0}, {2, 32, 1364.231529, 748.678265, 1.0}, {1, 33, 1850.911560, 460.475668, 1.0},
- {2, 33, 1862.221413, 512.797347, 1.0}, {1, 34, 1226.117821, 607.053959, 1.0}, {2, 34, 1230.736084, 641.091449, 1.0},
- {1, 35, 619.598236, 523.341744, 1.0}, {2, 35, 621.601124, 554.453287, 1.0}, {1, 36, 956.591492, 958.223183, 1.0},
- {2, 36, 959.289265, 983.289263, 1.0}, {1, 37, 1249.922218, 419.095856, 1.0}, {2, 37, 1255.005913, 452.556177, 1.0},
- {1, 39, 1300.528450, 386.251166, 1.0}, {2, 39, 1305.957413, 420.185595, 1.0}, {1, 40, 1128.689919, 972.558346, 1.0},
- {2, 40, 1132.413712, 1003.984737, 1.0}, {1, 41, 503.304749, 1053.504388, 1.0}, {2, 41, 505.019703, 1069.175613, 1.0},
- {1, 42, 1197.352982, 472.681564, 1.0}, {2, 42, 1201.910706, 503.459880, 1.0}, {1, 43, 1794.391022, 383.911400, 1.0},
- {2, 43, 1805.324135, 436.116468, 1.0}, {1, 44, 789.641418, 1058.045647, 1.0}, {1, 45, 1376.575241, 928.714979, 1.0},
- {2, 45, 1381.995850, 969.511957, 1.0}, {1, 46, 1598.023567, 93.975592, 1.0}, {2, 46, 1606.937141, 136.827035, 1.0},
- {1, 47, 1455.550232, 762.128685, 1.0}, {2, 47, 1462.014313, 805.164878, 1.0}, {1, 48, 1357.123489, 354.460326, 1.0},
- {2, 48, 1363.071899, 390.363121, 1.0}, {1, 49, 939.792652, 781.549895, 1.0}, {2, 49, 942.802620, 806.164012, 1.0},
- {1, 50, 1380.251083, 805.948620, 1.0}, {2, 50, 1385.637932, 845.592098, 1.0}, {1, 51, 1021.769943, 1049.802361, 1.0},
- {1, 52, 1065.634918, 608.099055, 1.0}, {2, 52, 1069.142189, 635.361736, 1.0}, {1, 53, 624.324188, 463.202863, 1.0},
- {2, 53, 626.395454, 494.994088, 1.0}, {1, 54, 1451.459885, 881.557624, 1.0}, {2, 54, 1457.679634, 924.345531, 1.0},
- {1, 55, 1201.885986, 1057.079022, 1.0}, {1, 56, 581.157532, 947.661438, 1.0}, {2, 56, 583.242359, 960.831449, 1.0},
- {1, 58, 513.593102, 954.175858, 1.0}, {2, 58, 515.470047, 971.309574, 1.0}, {1, 59, 928.069038, 901.774421, 1.0},
- {2, 59, 930.847950, 925.613744, 1.0}, {1, 60, 1065.860023, 740.395389, 1.0}, {2, 60, 1069.484253, 768.971086, 1.0},
- {1, 61, 990.479393, 906.264632, 1.0}, {2, 61, 993.217506, 933.088803, 1.0}, {1, 62, 1776.196747, 776.278453, 1.0},
- {2, 62, 1786.292496, 831.136880, 1.0}, {1, 63, 834.454365, 1012.449725, 1.0}, {2, 63, 836.868324, 1033.451807, 1.0},
- {1, 64, 1355.190697, 869.184809, 1.0}, {2, 64, 1360.736618, 909.773347, 1.0}, {1, 65, 702.072487, 897.519686, 1.0},
- {2, 65, 704.203377, 911.931131, 1.0}, {1, 66, 1214.022903, 856.199934, 1.0}, {2, 66, 1218.109016, 890.753052, 1.0},
- {1, 67, 327.676048, 236.814036, 1.0}, {2, 67, 328.335285, 277.251878, 1.0}, {1, 68, 289.064083, 454.793912, 1.0},
- {2, 68, 288.651924, 498.882444, 1.0}, {1, 69, 1626.240692, 278.374350, 1.0}, {2, 69, 1634.131508, 315.853672, 1.0},
- {1, 70, 1245.375710, 734.862142, 1.0}, {2, 70, 1250.047417, 769.670885, 1.0}, {1, 71, 497.015305, 510.718904, 1.0},
- {2, 71, 498.682308, 541.070201, 1.0}, {1, 72, 1280.542030, 153.939185, 1.0}, {2, 72, 1286.993637, 198.436196, 1.0},
- {1, 73, 1534.748840, 138.601043, 1.0}, {2, 73, 1542.961349, 180.170819, 1.0}, {1, 74, 1477.412682, 200.608061, 1.0},
- {2, 74, 1484.683914, 240.413260, 1.0}, {1, 76, 450.637321, 407.279642, 1.0}, {2, 76, 451.695642, 441.666291, 1.0},
- {1, 78, 246.981239, 220.786298, 1.0}, {2, 78, 244.524879, 290.016564, 1.0}, {1, 79, 36.696489, 420.023407, 1.0},
+ {1, 2, 1139.861412, 1034.634984, 1.0},
+ {2, 2, 1143.512192, 1065.355718, 1.0},
+ {1, 3, 1760.821953, 644.658036, 1.0},
+ {2, 3, 1770.901108, 697.899928, 1.0},
+ {1, 4, 858.071823, 1068.520746, 1.0},
+ {1, 6, 1633.952408, 797.050145, 1.0},
+ {2, 6, 1642.508469, 849.157140, 1.0},
+ {1, 8, 1716.695824, 451.805491, 1.0},
+ {2, 8, 1726.513939, 502.095687, 1.0},
+ {1, 9, 269.577627, 724.986935, 1.0},
+ {2, 9, 269.424820, 764.154246, 1.0},
+ {1, 10, 1891.321907, 706.948843, 1.0},
+ {2, 10, 1903.338547, 766.068377, 1.0},
+ {1, 12, 1806.227074, 956.089604, 1.0},
+ {2, 12, 1816.619568, 1013.767376, 1.0},
+ {1, 14, 269.544153, 1002.333570, 1.0},
+ {2, 14, 269.367542, 1043.509254, 1.0},
+ {1, 15, 1402.772141, 281.392962, 1.0},
+ {2, 15, 1409.089165, 318.731629, 1.0},
+ {1, 16, 195.877233, 919.454341, 1.0},
+ {2, 16, 192.531109, 997.367899, 1.0},
+ {1, 17, 1789.584045, 120.036661, 1.0},
+ {2, 17, 1800.391846, 167.822964, 1.0},
+ {1, 18, 999.363213, 765.004807, 1.0},
+ {2, 18, 1002.345772, 790.560122, 1.0},
+ {1, 19, 647.342491, 1044.805727, 1.0},
+ {2, 19, 649.328041, 1058.682940, 1.0},
+ {1, 20, 1365.486832, 440.901829, 1.0},
+ {2, 20, 1371.413040, 477.888730, 1.0},
+ {1, 21, 1787.125282, 301.431606, 1.0},
+ {2, 21, 1798.527260, 355.224531, 1.0},
+ {1, 22, 1257.805824, 932.797258, 1.0},
+ {2, 22, 1263.017578, 969.376774, 1.0},
+ {1, 23, 961.969528, 843.148112, 1.0},
+ {2, 23, 964.869461, 868.587620, 1.0},
+ {1, 24, 158.076110, 1052.643592, 1.0},
+ {1, 25, 1072.884521, 1005.296981, 1.0},
+ {2, 25, 1076.091156, 1032.776856, 1.0},
+ {1, 26, 1107.656937, 526.577228, 1.0},
+ {2, 26, 1111.618423, 555.524454, 1.0},
+ {1, 27, 1416.410751, 529.857581, 1.0},
+ {2, 27, 1422.663574, 570.025957, 1.0},
+ {1, 28, 1498.673630, 1005.453086, 1.0},
+ {2, 28, 1505.381813, 1051.827149, 1.0},
+ {1, 29, 1428.647804, 652.473629, 1.0},
+ {2, 29, 1434.898224, 692.715390, 1.0},
+ {1, 30, 1332.318764, 503.673599, 1.0},
+ {2, 30, 1338.000069, 540.507967, 1.0},
+ {1, 32, 1358.642693, 709.837904, 1.0},
+ {2, 32, 1364.231529, 748.678265, 1.0},
+ {1, 33, 1850.911560, 460.475668, 1.0},
+ {2, 33, 1862.221413, 512.797347, 1.0},
+ {1, 34, 1226.117821, 607.053959, 1.0},
+ {2, 34, 1230.736084, 641.091449, 1.0},
+ {1, 35, 619.598236, 523.341744, 1.0},
+ {2, 35, 621.601124, 554.453287, 1.0},
+ {1, 36, 956.591492, 958.223183, 1.0},
+ {2, 36, 959.289265, 983.289263, 1.0},
+ {1, 37, 1249.922218, 419.095856, 1.0},
+ {2, 37, 1255.005913, 452.556177, 1.0},
+ {1, 39, 1300.528450, 386.251166, 1.0},
+ {2, 39, 1305.957413, 420.185595, 1.0},
+ {1, 40, 1128.689919, 972.558346, 1.0},
+ {2, 40, 1132.413712, 1003.984737, 1.0},
+ {1, 41, 503.304749, 1053.504388, 1.0},
+ {2, 41, 505.019703, 1069.175613, 1.0},
+ {1, 42, 1197.352982, 472.681564, 1.0},
+ {2, 42, 1201.910706, 503.459880, 1.0},
+ {1, 43, 1794.391022, 383.911400, 1.0},
+ {2, 43, 1805.324135, 436.116468, 1.0},
+ {1, 44, 789.641418, 1058.045647, 1.0},
+ {1, 45, 1376.575241, 928.714979, 1.0},
+ {2, 45, 1381.995850, 969.511957, 1.0},
+ {1, 46, 1598.023567, 93.975592, 1.0},
+ {2, 46, 1606.937141, 136.827035, 1.0},
+ {1, 47, 1455.550232, 762.128685, 1.0},
+ {2, 47, 1462.014313, 805.164878, 1.0},
+ {1, 48, 1357.123489, 354.460326, 1.0},
+ {2, 48, 1363.071899, 390.363121, 1.0},
+ {1, 49, 939.792652, 781.549895, 1.0},
+ {2, 49, 942.802620, 806.164012, 1.0},
+ {1, 50, 1380.251083, 805.948620, 1.0},
+ {2, 50, 1385.637932, 845.592098, 1.0},
+ {1, 51, 1021.769943, 1049.802361, 1.0},
+ {1, 52, 1065.634918, 608.099055, 1.0},
+ {2, 52, 1069.142189, 635.361736, 1.0},
+ {1, 53, 624.324188, 463.202863, 1.0},
+ {2, 53, 626.395454, 494.994088, 1.0},
+ {1, 54, 1451.459885, 881.557624, 1.0},
+ {2, 54, 1457.679634, 924.345531, 1.0},
+ {1, 55, 1201.885986, 1057.079022, 1.0},
+ {1, 56, 581.157532, 947.661438, 1.0},
+ {2, 56, 583.242359, 960.831449, 1.0},
+ {1, 58, 513.593102, 954.175858, 1.0},
+ {2, 58, 515.470047, 971.309574, 1.0},
+ {1, 59, 928.069038, 901.774421, 1.0},
+ {2, 59, 930.847950, 925.613744, 1.0},
+ {1, 60, 1065.860023, 740.395389, 1.0},
+ {2, 60, 1069.484253, 768.971086, 1.0},
+ {1, 61, 990.479393, 906.264632, 1.0},
+ {2, 61, 993.217506, 933.088803, 1.0},
+ {1, 62, 1776.196747, 776.278453, 1.0},
+ {2, 62, 1786.292496, 831.136880, 1.0},
+ {1, 63, 834.454365, 1012.449725, 1.0},
+ {2, 63, 836.868324, 1033.451807, 1.0},
+ {1, 64, 1355.190697, 869.184809, 1.0},
+ {2, 64, 1360.736618, 909.773347, 1.0},
+ {1, 65, 702.072487, 897.519686, 1.0},
+ {2, 65, 704.203377, 911.931131, 1.0},
+ {1, 66, 1214.022903, 856.199934, 1.0},
+ {2, 66, 1218.109016, 890.753052, 1.0},
+ {1, 67, 327.676048, 236.814036, 1.0},
+ {2, 67, 328.335285, 277.251878, 1.0},
+ {1, 68, 289.064083, 454.793912, 1.0},
+ {2, 68, 288.651924, 498.882444, 1.0},
+ {1, 69, 1626.240692, 278.374350, 1.0},
+ {2, 69, 1634.131508, 315.853672, 1.0},
+ {1, 70, 1245.375710, 734.862142, 1.0},
+ {2, 70, 1250.047417, 769.670885, 1.0},
+ {1, 71, 497.015305, 510.718904, 1.0},
+ {2, 71, 498.682308, 541.070201, 1.0},
+ {1, 72, 1280.542030, 153.939185, 1.0},
+ {2, 72, 1286.993637, 198.436196, 1.0},
+ {1, 73, 1534.748840, 138.601043, 1.0},
+ {2, 73, 1542.961349, 180.170819, 1.0},
+ {1, 74, 1477.412682, 200.608061, 1.0},
+ {2, 74, 1484.683914, 240.413260, 1.0},
+ {1, 76, 450.637321, 407.279642, 1.0},
+ {2, 76, 451.695642, 441.666291, 1.0},
+ {1, 78, 246.981239, 220.786298, 1.0},
+ {2, 78, 244.524879, 290.016564, 1.0},
+ {1, 79, 36.696489, 420.023407, 1.0},
{2, 79, 21.364746, 591.245492, 1.0},
- };
+ };
int num_markers = sizeof(markers) / sizeof(Marker);
Tracks tracks;
@@ -249,41 +402,110 @@ TEST(KeyframeSelection, ElevatorReconstructionVarianceTest) {
intrinsics.SetRadialDistortion(-0.034, 0.0, 0.0);
Marker markers[] = {
- {1, 0, 182.999997, 1047.000010, 1.0}, {2, 0, 181.475730, 1052.091079, 1.0}, {3, 0, 181.741562, 1057.893341, 1.0},
- {4, 0, 183.190498, 1068.310440, 1.0}, {1, 1, 271.000013, 666.000009, 1.0}, {2, 1, 270.596180, 668.665760, 1.0},
- {3, 1, 270.523510, 671.559069, 1.0}, {4, 1, 271.856518, 676.818151, 1.0}, {5, 1, 268.989000, 727.051570, 1.0},
- {1, 2, 264.999990, 1018.000031, 1.0}, {2, 2, 264.020061, 1021.157591, 1.0}, {3, 2, 264.606056, 1024.823506, 1.0},
- {4, 2, 266.200933, 1031.168690, 1.0}, {1, 3, 270.000000, 938.000014, 1.0}, {2, 3, 269.022617, 941.153390, 1.0},
- {3, 3, 269.605579, 944.454954, 1.0}, {4, 3, 271.281366, 949.452167, 1.0}, {5, 3, 268.963480, 1004.417453, 1.0},
- {1, 4, 200.999994, 799.000003, 1.0}, {2, 4, 199.841366, 803.891838, 1.0}, {3, 4, 200.262208, 809.323246, 1.0},
- {4, 4, 201.456513, 819.271195, 1.0}, {5, 4, 195.026493, 924.363234, 1.0}, {1, 5, 1775.000038, 49.999998, 1.0},
- {2, 5, 1775.255127, 53.718264, 1.0}, {3, 5, 1776.449890, 55.951670, 1.0}, {4, 5, 1778.815727, 61.923309, 1.0},
- {5, 5, 1790.274124, 123.074923, 1.0}, {1, 6, 164.000001, 927.999988, 1.0}, {2, 6, 162.665462, 933.169527, 1.0},
- {3, 6, 163.067923, 938.577182, 1.0}, {4, 6, 164.370360, 948.840945, 1.0}, {5, 6, 157.199407, 1057.762341, 1.0},
- {1, 7, 618.000011, 477.999998, 1.0}, {2, 7, 617.583504, 480.124243, 1.0}, {3, 7, 618.356495, 482.441897, 1.0},
- {4, 7, 619.792500, 486.428132, 1.0}, {5, 7, 619.546051, 525.222627, 1.0}, {1, 8, 499.999981, 1036.999984, 1.0},
- {2, 8, 499.080162, 1038.720160, 1.0}, {3, 8, 499.949398, 1039.014344, 1.0}, {4, 8, 501.828003, 1041.286647, 1.0},
- {5, 8, 502.777576, 1055.196369, 1.0}, {1, 9, 1587.000046, 31.999999, 1.0}, {2, 9, 1586.988373, 34.635853, 1.0},
- {3, 9, 1588.155899, 37.444186, 1.0}, {4, 9, 1589.973106, 42.492081, 1.0}, {5, 9, 1598.683205, 96.526332, 1.0},
- {1, 10, 622.999992, 416.999999, 1.0}, {2, 10, 622.449017, 419.233485, 1.0}, {3, 10, 623.283234, 421.500703, 1.0},
- {4, 10, 624.620132, 425.537406, 1.0}, {5, 10, 624.290829, 465.078338, 1.0}, {1, 11, 577.999992, 931.999998, 1.0},
- {2, 11, 577.042294, 932.872703, 1.0}, {3, 11, 577.832451, 934.045451, 1.0}, {4, 11, 579.729137, 935.735435, 1.0},
- {5, 11, 580.691242, 948.396256, 1.0}, {1, 12, 510.999985, 931.999998, 1.0}, {2, 12, 510.111237, 933.152146, 1.0},
- {3, 12, 510.797081, 934.454219, 1.0}, {4, 12, 512.647362, 936.595910, 1.0}, {5, 12, 513.247204, 955.144157, 1.0},
- {1, 13, 330.459995, 177.059993, 1.0}, {2, 13, 329.876347, 179.615586, 1.0}, {3, 13, 330.681696, 182.757810, 1.0},
- {4, 13, 331.345053, 187.903853, 1.0}, {5, 13, 327.824135, 239.611639, 1.0}, {1, 14, 291.813097, 388.516195, 1.0},
- {2, 14, 290.984058, 391.382725, 1.0}, {3, 14, 291.526737, 394.778595, 1.0}, {4, 14, 292.763815, 400.310973, 1.0},
- {5, 14, 288.714552, 457.548015, 1.0}, {1, 15, 496.491680, 466.534005, 1.0}, {2, 15, 495.909519, 468.518561, 1.0},
- {3, 15, 496.588383, 470.853596, 1.0}, {4, 15, 497.976780, 474.731458, 1.0}, {5, 15, 496.998882, 512.568694, 1.0},
- {1, 16, 1273.000031, 89.000000, 1.0}, {2, 16, 1272.951965, 92.003637, 1.0}, {3, 16, 1273.934784, 94.972191, 1.0},
- {4, 16, 1275.493584, 100.139952, 1.0}, {5, 16, 1281.003571, 156.880163, 1.0}, {1, 17, 1524.713173, 78.852922, 1.0},
- {2, 17, 1524.782066, 81.427142, 1.0}, {3, 17, 1525.759048, 84.057939, 1.0}, {4, 17, 1527.579689, 88.966550, 1.0},
- {5, 17, 1535.262451, 141.186054, 1.0}, {1, 18, 1509.425011, 94.371824, 1.0}, {1, 19, 451.000013, 357.000003, 1.0},
- {2, 19, 450.354881, 359.312410, 1.0}, {3, 19, 451.107473, 361.837088, 1.0}, {4, 19, 452.186537, 366.318061, 1.0},
- {5, 19, 450.507660, 409.257599, 1.0}, {1, 20, 254.004936, 114.784185, 1.0}, {2, 20, 253.291512, 119.288486, 1.0},
- {3, 20, 253.745584, 124.114957, 1.0}, {4, 20, 254.453287, 132.795120, 1.0}, {5, 20, 246.772242, 225.165337, 1.0},
- {1, 21, 65.262880, 147.889409, 1.0}, {2, 21, 63.634465, 157.656807, 1.0}, {3, 21, 63.306799, 169.067053, 1.0},
- {4, 21, 62.462311, 189.724241, 1.0}, {5, 21, 35.396615, 430.308380, 1.0},
+ {1, 0, 182.999997, 1047.000010, 1.0},
+ {2, 0, 181.475730, 1052.091079, 1.0},
+ {3, 0, 181.741562, 1057.893341, 1.0},
+ {4, 0, 183.190498, 1068.310440, 1.0},
+ {1, 1, 271.000013, 666.000009, 1.0},
+ {2, 1, 270.596180, 668.665760, 1.0},
+ {3, 1, 270.523510, 671.559069, 1.0},
+ {4, 1, 271.856518, 676.818151, 1.0},
+ {5, 1, 268.989000, 727.051570, 1.0},
+ {1, 2, 264.999990, 1018.000031, 1.0},
+ {2, 2, 264.020061, 1021.157591, 1.0},
+ {3, 2, 264.606056, 1024.823506, 1.0},
+ {4, 2, 266.200933, 1031.168690, 1.0},
+ {1, 3, 270.000000, 938.000014, 1.0},
+ {2, 3, 269.022617, 941.153390, 1.0},
+ {3, 3, 269.605579, 944.454954, 1.0},
+ {4, 3, 271.281366, 949.452167, 1.0},
+ {5, 3, 268.963480, 1004.417453, 1.0},
+ {1, 4, 200.999994, 799.000003, 1.0},
+ {2, 4, 199.841366, 803.891838, 1.0},
+ {3, 4, 200.262208, 809.323246, 1.0},
+ {4, 4, 201.456513, 819.271195, 1.0},
+ {5, 4, 195.026493, 924.363234, 1.0},
+ {1, 5, 1775.000038, 49.999998, 1.0},
+ {2, 5, 1775.255127, 53.718264, 1.0},
+ {3, 5, 1776.449890, 55.951670, 1.0},
+ {4, 5, 1778.815727, 61.923309, 1.0},
+ {5, 5, 1790.274124, 123.074923, 1.0},
+ {1, 6, 164.000001, 927.999988, 1.0},
+ {2, 6, 162.665462, 933.169527, 1.0},
+ {3, 6, 163.067923, 938.577182, 1.0},
+ {4, 6, 164.370360, 948.840945, 1.0},
+ {5, 6, 157.199407, 1057.762341, 1.0},
+ {1, 7, 618.000011, 477.999998, 1.0},
+ {2, 7, 617.583504, 480.124243, 1.0},
+ {3, 7, 618.356495, 482.441897, 1.0},
+ {4, 7, 619.792500, 486.428132, 1.0},
+ {5, 7, 619.546051, 525.222627, 1.0},
+ {1, 8, 499.999981, 1036.999984, 1.0},
+ {2, 8, 499.080162, 1038.720160, 1.0},
+ {3, 8, 499.949398, 1039.014344, 1.0},
+ {4, 8, 501.828003, 1041.286647, 1.0},
+ {5, 8, 502.777576, 1055.196369, 1.0},
+ {1, 9, 1587.000046, 31.999999, 1.0},
+ {2, 9, 1586.988373, 34.635853, 1.0},
+ {3, 9, 1588.155899, 37.444186, 1.0},
+ {4, 9, 1589.973106, 42.492081, 1.0},
+ {5, 9, 1598.683205, 96.526332, 1.0},
+ {1, 10, 622.999992, 416.999999, 1.0},
+ {2, 10, 622.449017, 419.233485, 1.0},
+ {3, 10, 623.283234, 421.500703, 1.0},
+ {4, 10, 624.620132, 425.537406, 1.0},
+ {5, 10, 624.290829, 465.078338, 1.0},
+ {1, 11, 577.999992, 931.999998, 1.0},
+ {2, 11, 577.042294, 932.872703, 1.0},
+ {3, 11, 577.832451, 934.045451, 1.0},
+ {4, 11, 579.729137, 935.735435, 1.0},
+ {5, 11, 580.691242, 948.396256, 1.0},
+ {1, 12, 510.999985, 931.999998, 1.0},
+ {2, 12, 510.111237, 933.152146, 1.0},
+ {3, 12, 510.797081, 934.454219, 1.0},
+ {4, 12, 512.647362, 936.595910, 1.0},
+ {5, 12, 513.247204, 955.144157, 1.0},
+ {1, 13, 330.459995, 177.059993, 1.0},
+ {2, 13, 329.876347, 179.615586, 1.0},
+ {3, 13, 330.681696, 182.757810, 1.0},
+ {4, 13, 331.345053, 187.903853, 1.0},
+ {5, 13, 327.824135, 239.611639, 1.0},
+ {1, 14, 291.813097, 388.516195, 1.0},
+ {2, 14, 290.984058, 391.382725, 1.0},
+ {3, 14, 291.526737, 394.778595, 1.0},
+ {4, 14, 292.763815, 400.310973, 1.0},
+ {5, 14, 288.714552, 457.548015, 1.0},
+ {1, 15, 496.491680, 466.534005, 1.0},
+ {2, 15, 495.909519, 468.518561, 1.0},
+ {3, 15, 496.588383, 470.853596, 1.0},
+ {4, 15, 497.976780, 474.731458, 1.0},
+ {5, 15, 496.998882, 512.568694, 1.0},
+ {1, 16, 1273.000031, 89.000000, 1.0},
+ {2, 16, 1272.951965, 92.003637, 1.0},
+ {3, 16, 1273.934784, 94.972191, 1.0},
+ {4, 16, 1275.493584, 100.139952, 1.0},
+ {5, 16, 1281.003571, 156.880163, 1.0},
+ {1, 17, 1524.713173, 78.852922, 1.0},
+ {2, 17, 1524.782066, 81.427142, 1.0},
+ {3, 17, 1525.759048, 84.057939, 1.0},
+ {4, 17, 1527.579689, 88.966550, 1.0},
+ {5, 17, 1535.262451, 141.186054, 1.0},
+ {1, 18, 1509.425011, 94.371824, 1.0},
+ {1, 19, 451.000013, 357.000003, 1.0},
+ {2, 19, 450.354881, 359.312410, 1.0},
+ {3, 19, 451.107473, 361.837088, 1.0},
+ {4, 19, 452.186537, 366.318061, 1.0},
+ {5, 19, 450.507660, 409.257599, 1.0},
+ {1, 20, 254.004936, 114.784185, 1.0},
+ {2, 20, 253.291512, 119.288486, 1.0},
+ {3, 20, 253.745584, 124.114957, 1.0},
+ {4, 20, 254.453287, 132.795120, 1.0},
+ {5, 20, 246.772242, 225.165337, 1.0},
+ {1, 21, 65.262880, 147.889409, 1.0},
+ {2, 21, 63.634465, 157.656807, 1.0},
+ {3, 21, 63.306799, 169.067053, 1.0},
+ {4, 21, 62.462311, 189.724241, 1.0},
+ {5, 21, 35.396615, 430.308380, 1.0},
};
int num_markers = sizeof(markers) / sizeof(Marker);
@@ -304,4 +526,4 @@ TEST(KeyframeSelection, ElevatorReconstructionVarianceTest) {
}
}
-} // namespace libmv
+} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/modal_solver.cc b/intern/libmv/libmv/simple_pipeline/modal_solver.cc
index 687c328b004..845b299e31e 100644
--- a/intern/libmv/libmv/simple_pipeline/modal_solver.cc
+++ b/intern/libmv/libmv/simple_pipeline/modal_solver.cc
@@ -34,7 +34,7 @@
namespace libmv {
namespace {
-void ProjectMarkerOnSphere(const Marker &marker, Vec3 &X) {
+void ProjectMarkerOnSphere(const Marker& marker, Vec3& X) {
X(0) = marker.x;
X(1) = marker.y;
X(2) = 1.0;
@@ -42,12 +42,14 @@ void ProjectMarkerOnSphere(const Marker &marker, Vec3 &X) {
X *= 5.0 / X.norm();
}
-void ModalSolverLogProgress(ProgressUpdateCallback *update_callback,
- double progress) {
+void ModalSolverLogProgress(ProgressUpdateCallback* update_callback,
+ double progress) {
if (update_callback) {
char message[256];
- snprintf(message, sizeof(message), "Solving progress %d%%",
+ snprintf(message,
+ sizeof(message),
+ "Solving progress %d%%",
(int)(progress * 100));
update_callback->invoke(progress, message);
@@ -58,25 +60,27 @@ struct ModalReprojectionError {
ModalReprojectionError(double observed_x,
double observed_y,
const double weight,
- const Vec3 &bundle)
- : observed_x_(observed_x), observed_y_(observed_y),
- weight_(weight), bundle_(bundle) { }
+ const Vec3& bundle)
+ : observed_x_(observed_x),
+ observed_y_(observed_y),
+ weight_(weight),
+ bundle_(bundle) {}
// TODO(keir): This should support bundling focal length as well.
template <typename T>
bool operator()(const T* quaternion, T* residuals) const {
// Convert bundle position from double to T.
- T X[3] = { T(bundle_(0)), T(bundle_(1)), T(bundle_(2)) };
+ T X[3] = {T(bundle_(0)), T(bundle_(1)), T(bundle_(2))};
// Compute the point position in camera coordinates: x = RX.
T x[3];
// This flips the sense of the quaternion, to adhere to Blender conventions.
T quaternion_inverse[4] = {
- quaternion[0],
- -quaternion[1],
- -quaternion[2],
- -quaternion[3],
+ quaternion[0],
+ -quaternion[1],
+ -quaternion[2],
+ -quaternion[3],
};
ceres::QuaternionRotatePoint(quaternion_inverse, X, x);
@@ -99,9 +103,9 @@ struct ModalReprojectionError {
};
} // namespace
-void ModalSolver(const Tracks &tracks,
- EuclideanReconstruction *reconstruction,
- ProgressUpdateCallback *update_callback) {
+void ModalSolver(const Tracks& tracks,
+ EuclideanReconstruction* reconstruction,
+ ProgressUpdateCallback* update_callback) {
int max_image = tracks.MaxImage();
int max_track = tracks.MaxTrack();
@@ -116,7 +120,7 @@ void ModalSolver(const Tracks &tracks,
for (int image = 0; image <= max_image; ++image) {
vector<Marker> all_markers = tracks.MarkersInImage(image);
- ModalSolverLogProgress(update_callback, (float) image / max_image);
+ ModalSolverLogProgress(update_callback, (float)image / max_image);
// Skip empty images without doing anything.
if (all_markers.size() == 0) {
@@ -133,8 +137,8 @@ void ModalSolver(const Tracks &tracks,
// 3D positions.
Mat x1, x2;
for (int i = 0; i < all_markers.size(); ++i) {
- Marker &marker = all_markers[i];
- EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
+ Marker& marker = all_markers[i];
+ EuclideanPoint* point = reconstruction->PointForTrack(marker.track);
if (point) {
Vec3 X;
ProjectMarkerOnSphere(marker, X);
@@ -168,8 +172,7 @@ void ModalSolver(const Tracks &tracks,
ceres::AngleAxisToQuaternion(&angle_axis(0), &quaternion(0));
- LG << "Analytically computed quaternion "
- << quaternion.transpose();
+ LG << "Analytically computed quaternion " << quaternion.transpose();
}
// STEP 2: Refine rotation with Ceres.
@@ -181,17 +184,15 @@ void ModalSolver(const Tracks &tracks,
int num_residuals = 0;
for (int i = 0; i < all_markers.size(); ++i) {
- Marker &marker = all_markers[i];
- EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
+ Marker& marker = all_markers[i];
+ EuclideanPoint* point = reconstruction->PointForTrack(marker.track);
if (point && marker.weight != 0.0) {
- problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
- ModalReprojectionError,
- 2, /* num_residuals */
- 4>(new ModalReprojectionError(marker.x,
- marker.y,
- marker.weight,
- point->X)),
+ problem.AddResidualBlock(
+ new ceres::AutoDiffCostFunction<ModalReprojectionError,
+ 2, /* num_residuals */
+ 4>(new ModalReprojectionError(
+ marker.x, marker.y, marker.weight, point->X)),
NULL,
&quaternion(0));
num_residuals++;
diff --git a/intern/libmv/libmv/simple_pipeline/modal_solver.h b/intern/libmv/libmv/simple_pipeline/modal_solver.h
index 9801fd21d81..f7ce394b4b2 100644
--- a/intern/libmv/libmv/simple_pipeline/modal_solver.h
+++ b/intern/libmv/libmv/simple_pipeline/modal_solver.h
@@ -21,9 +21,9 @@
#ifndef LIBMV_SIMPLE_PIPELINE_MODAL_SOLVER_H_
#define LIBMV_SIMPLE_PIPELINE_MODAL_SOLVER_H_
-#include "libmv/simple_pipeline/tracks.h"
-#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/callbacks.h"
+#include "libmv/simple_pipeline/reconstruction.h"
+#include "libmv/simple_pipeline/tracks.h"
namespace libmv {
@@ -39,9 +39,9 @@ namespace libmv {
Reconstructed cameras and projected bundles would be added to reconstruction
object.
*/
-void ModalSolver(const Tracks &tracks,
- EuclideanReconstruction *reconstruction,
- ProgressUpdateCallback *update_callback = NULL);
+void ModalSolver(const Tracks& tracks,
+ EuclideanReconstruction* reconstruction,
+ ProgressUpdateCallback* update_callback = NULL);
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/modal_solver_test.cc b/intern/libmv/libmv/simple_pipeline/modal_solver_test.cc
index b4cae8defb2..0acf978e6f5 100644
--- a/intern/libmv/libmv/simple_pipeline/modal_solver_test.cc
+++ b/intern/libmv/libmv/simple_pipeline/modal_solver_test.cc
@@ -20,10 +20,10 @@
#include "libmv/simple_pipeline/modal_solver.h"
-#include "testing/testing.h"
#include "libmv/logging/logging.h"
#include "libmv/simple_pipeline/bundle.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
+#include "testing/testing.h"
#include <stdio.h>
@@ -38,14 +38,21 @@ TEST(ModalSolver, SyntheticCubeSceneMotion) {
intrinsics.SetRadialDistortion(0.0, 0.0, 0.0);
Marker markers[] = {
- {1, 0, 212.172775, 354.713538, 1.0}, {2, 0, 773.468399, 358.735306, 1.0},
- {1, 1, 62.415197, 287.905354, 1.0}, {2, 1, 619.103336, 324.402537, 1.0},
- {1, 2, 206.847939, 237.567925, 1.0}, {2, 2, 737.496986, 247.881383, 1.0},
- {1, 3, 351.743889, 316.415906, 1.0}, {2, 3, 908.779621, 290.703617, 1.0},
- {1, 4, 232.941413, 54.265443, 1.0}, {2, 4, 719.444847, 63.062531, 1.0},
- {1, 5, 96.391611, 119.283537, 1.0}, {2, 5, 611.413136, 160.890715, 1.0},
- {1, 6, 363.444958, 150.838144, 1.0}, {2, 6, 876.374531, 114.916206, 1.0},
- };
+ {1, 0, 212.172775, 354.713538, 1.0},
+ {2, 0, 773.468399, 358.735306, 1.0},
+ {1, 1, 62.415197, 287.905354, 1.0},
+ {2, 1, 619.103336, 324.402537, 1.0},
+ {1, 2, 206.847939, 237.567925, 1.0},
+ {2, 2, 737.496986, 247.881383, 1.0},
+ {1, 3, 351.743889, 316.415906, 1.0},
+ {2, 3, 908.779621, 290.703617, 1.0},
+ {1, 4, 232.941413, 54.265443, 1.0},
+ {2, 4, 719.444847, 63.062531, 1.0},
+ {1, 5, 96.391611, 119.283537, 1.0},
+ {2, 5, 611.413136, 160.890715, 1.0},
+ {1, 6, 363.444958, 150.838144, 1.0},
+ {2, 6, 876.374531, 114.916206, 1.0},
+ };
int num_markers = sizeof(markers) / sizeof(Marker);
Tracks tracks;
@@ -65,12 +72,14 @@ TEST(ModalSolver, SyntheticCubeSceneMotion) {
NULL);
Mat3 expected_rotation;
+ // clang-format off
expected_rotation << 0.98215101743472, 0.17798354937546, 0.06083777694542,
-0.16875283983360, 0.97665300495333, -0.13293376908719,
-0.08307742172243, 0.12029448893171, 0.98925597189636;
+ // clang-format on
- Mat3 &first_camera_R = reconstruction.CameraForImage(1)->R;
- Mat3 &second_camera_R = reconstruction.CameraForImage(2)->R;
+ Mat3& first_camera_R = reconstruction.CameraForImage(1)->R;
+ Mat3& second_camera_R = reconstruction.CameraForImage(2)->R;
EXPECT_TRUE(Mat3::Identity().isApprox(first_camera_R, kTolerance));
EXPECT_TRUE(expected_rotation.isApprox(second_camera_R, kTolerance));
diff --git a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h
index cbea599fccd..79fa3ab8379 100644
--- a/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h
+++ b/intern/libmv/libmv/simple_pipeline/packed_intrinsics.h
@@ -40,7 +40,7 @@ class PackedIntrinsics {
OFFSET_FOCAL_LENGTH,
OFFSET_PRINCIPAL_POINT_X,
OFFSET_PRINCIPAL_POINT_Y,
-
+
// Distortion model coefficients.
OFFSET_K1,
OFFSET_K2,
@@ -48,7 +48,7 @@ class PackedIntrinsics {
OFFSET_K4,
OFFSET_P1,
OFFSET_P2,
-
+
// Number of parameters which are to be stored in the block.
NUM_PARAMETERS,
};
@@ -66,12 +66,12 @@ class PackedIntrinsics {
// point.
#define DEFINE_PARAMETER(parameter_name) \
- void Set ## parameter_name(double value) { \
- SetParameter(OFFSET_ ## parameter_name, value); \
- } \
- double Get ## parameter_name() const { \
- return GetParameter(OFFSET_ ## parameter_name); \
+ void Set##parameter_name(double value) { \
+ SetParameter(OFFSET_##parameter_name, value); \
} \
+ double Get##parameter_name() const { \
+ return GetParameter(OFFSET_##parameter_name); \
+ }
DEFINE_PARAMETER(K1)
DEFINE_PARAMETER(K2)
@@ -94,11 +94,11 @@ class PackedIntrinsics {
// All intrinsics parameters packed into a single block.
// Use OFFSET_FOO indexes to access corresponding values.
- array<double, NUM_PARAMETERS> parameters_;
+ array<double, NUM_PARAMETERS> parameters_;
// Indexed by parameter offset, set to truth if the value of the parameter is
// explicitly specified.
- array<bool, NUM_PARAMETERS> known_parameters_;
+ array<bool, NUM_PARAMETERS> known_parameters_;
};
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/pipeline.cc b/intern/libmv/libmv/simple_pipeline/pipeline.cc
index 728601f3732..5d52aeb7406 100644
--- a/intern/libmv/libmv/simple_pipeline/pipeline.cc
+++ b/intern/libmv/libmv/simple_pipeline/pipeline.cc
@@ -24,11 +24,11 @@
#include "libmv/logging/logging.h"
#include "libmv/simple_pipeline/bundle.h"
+#include "libmv/simple_pipeline/camera_intrinsics.h"
#include "libmv/simple_pipeline/intersect.h"
-#include "libmv/simple_pipeline/resect.h"
#include "libmv/simple_pipeline/reconstruction.h"
+#include "libmv/simple_pipeline/resect.h"
#include "libmv/simple_pipeline/tracks.h"
-#include "libmv/simple_pipeline/camera_intrinsics.h"
#ifdef _MSC_VER
# define snprintf _snprintf
@@ -46,24 +46,25 @@ struct EuclideanPipelineRoutines {
typedef EuclideanCamera Camera;
typedef EuclideanPoint Point;
- static void Bundle(const Tracks &tracks,
- EuclideanReconstruction *reconstruction) {
+ static void Bundle(const Tracks& tracks,
+ EuclideanReconstruction* reconstruction) {
EuclideanBundle(tracks, reconstruction);
}
- static bool Resect(const vector<Marker> &markers,
- EuclideanReconstruction *reconstruction, bool final_pass) {
+ static bool Resect(const vector<Marker>& markers,
+ EuclideanReconstruction* reconstruction,
+ bool final_pass) {
return EuclideanResect(markers, reconstruction, final_pass);
}
- static bool Intersect(const vector<Marker> &markers,
- EuclideanReconstruction *reconstruction) {
+ static bool Intersect(const vector<Marker>& markers,
+ EuclideanReconstruction* reconstruction) {
return EuclideanIntersect(markers, reconstruction);
}
- static Marker ProjectMarker(const EuclideanPoint &point,
- const EuclideanCamera &camera,
- const CameraIntrinsics &intrinsics) {
+ static Marker ProjectMarker(const EuclideanPoint& point,
+ const EuclideanCamera& camera,
+ const CameraIntrinsics& intrinsics) {
Vec3 projected = camera.R * point.X + camera.t;
projected /= projected(2);
@@ -84,26 +85,27 @@ struct ProjectivePipelineRoutines {
typedef ProjectiveCamera Camera;
typedef ProjectivePoint Point;
- static void Bundle(const Tracks &tracks,
- ProjectiveReconstruction *reconstruction) {
+ static void Bundle(const Tracks& tracks,
+ ProjectiveReconstruction* reconstruction) {
ProjectiveBundle(tracks, reconstruction);
}
- static bool Resect(const vector<Marker> &markers,
- ProjectiveReconstruction *reconstruction, bool final_pass) {
- (void) final_pass; // Ignored.
+ static bool Resect(const vector<Marker>& markers,
+ ProjectiveReconstruction* reconstruction,
+ bool final_pass) {
+ (void)final_pass; // Ignored.
return ProjectiveResect(markers, reconstruction);
}
- static bool Intersect(const vector<Marker> &markers,
- ProjectiveReconstruction *reconstruction) {
+ static bool Intersect(const vector<Marker>& markers,
+ ProjectiveReconstruction* reconstruction) {
return ProjectiveIntersect(markers, reconstruction);
}
- static Marker ProjectMarker(const ProjectivePoint &point,
- const ProjectiveCamera &camera,
- const CameraIntrinsics &intrinsics) {
+ static Marker ProjectMarker(const ProjectivePoint& point,
+ const ProjectiveCamera& camera,
+ const CameraIntrinsics& intrinsics) {
Vec3 projected = camera.P * point.X;
projected /= projected(2);
@@ -122,28 +124,33 @@ struct ProjectivePipelineRoutines {
} // namespace
static void CompleteReconstructionLogProgress(
- ProgressUpdateCallback *update_callback,
+ ProgressUpdateCallback* update_callback,
double progress,
- const char *step = NULL) {
+ const char* step = NULL) {
if (update_callback) {
char message[256];
if (step)
- snprintf(message, sizeof(message), "Completing solution %d%% | %s",
- (int)(progress*100), step);
+ snprintf(message,
+ sizeof(message),
+ "Completing solution %d%% | %s",
+ (int)(progress * 100),
+ step);
else
- snprintf(message, sizeof(message), "Completing solution %d%%",
- (int)(progress*100));
+ snprintf(message,
+ sizeof(message),
+ "Completing solution %d%%",
+ (int)(progress * 100));
update_callback->invoke(progress, message);
}
}
-template<typename PipelineRoutines>
+template <typename PipelineRoutines>
void InternalCompleteReconstruction(
- const Tracks &tracks,
- typename PipelineRoutines::Reconstruction *reconstruction,
- ProgressUpdateCallback *update_callback = NULL) {
+ const Tracks& tracks,
+ typename PipelineRoutines::Reconstruction* reconstruction,
+ ProgressUpdateCallback* update_callback = NULL) {
int max_track = tracks.MaxTrack();
int max_image = tracks.MaxImage();
int num_resects = -1;
@@ -173,7 +180,7 @@ void InternalCompleteReconstruction(
<< " reconstructed markers for track " << track;
if (reconstructed_markers.size() >= 2) {
CompleteReconstructionLogProgress(update_callback,
- (double)tot_resects/(max_image));
+ (double)tot_resects / (max_image));
if (PipelineRoutines::Intersect(reconstructed_markers,
reconstruction)) {
num_intersects++;
@@ -184,9 +191,8 @@ void InternalCompleteReconstruction(
}
}
if (num_intersects) {
- CompleteReconstructionLogProgress(update_callback,
- (double)tot_resects/(max_image),
- "Bundling...");
+ CompleteReconstructionLogProgress(
+ update_callback, (double)tot_resects / (max_image), "Bundling...");
PipelineRoutines::Bundle(tracks, reconstruction);
LG << "Ran Bundle() after intersections.";
}
@@ -212,9 +218,9 @@ void InternalCompleteReconstruction(
<< " reconstructed markers for image " << image;
if (reconstructed_markers.size() >= 5) {
CompleteReconstructionLogProgress(update_callback,
- (double)tot_resects/(max_image));
- if (PipelineRoutines::Resect(reconstructed_markers,
- reconstruction, false)) {
+ (double)tot_resects / (max_image));
+ if (PipelineRoutines::Resect(
+ reconstructed_markers, reconstruction, false)) {
num_resects++;
tot_resects++;
LG << "Ran Resect() for image " << image;
@@ -224,9 +230,8 @@ void InternalCompleteReconstruction(
}
}
if (num_resects) {
- CompleteReconstructionLogProgress(update_callback,
- (double)tot_resects/(max_image),
- "Bundling...");
+ CompleteReconstructionLogProgress(
+ update_callback, (double)tot_resects / (max_image), "Bundling...");
PipelineRoutines::Bundle(tracks, reconstruction);
}
LG << "Did " << num_resects << " resects.";
@@ -249,9 +254,9 @@ void InternalCompleteReconstruction(
}
if (reconstructed_markers.size() >= 5) {
CompleteReconstructionLogProgress(update_callback,
- (double)tot_resects/(max_image));
- if (PipelineRoutines::Resect(reconstructed_markers,
- reconstruction, true)) {
+ (double)tot_resects / (max_image));
+ if (PipelineRoutines::Resect(
+ reconstructed_markers, reconstruction, true)) {
num_resects++;
LG << "Ran final Resect() for image " << image;
} else {
@@ -260,27 +265,26 @@ void InternalCompleteReconstruction(
}
}
if (num_resects) {
- CompleteReconstructionLogProgress(update_callback,
- (double)tot_resects/(max_image),
- "Bundling...");
+ CompleteReconstructionLogProgress(
+ update_callback, (double)tot_resects / (max_image), "Bundling...");
PipelineRoutines::Bundle(tracks, reconstruction);
}
}
-template<typename PipelineRoutines>
+template <typename PipelineRoutines>
double InternalReprojectionError(
- const Tracks &image_tracks,
- const typename PipelineRoutines::Reconstruction &reconstruction,
- const CameraIntrinsics &intrinsics) {
+ const Tracks& image_tracks,
+ const typename PipelineRoutines::Reconstruction& reconstruction,
+ const CameraIntrinsics& intrinsics) {
int num_skipped = 0;
int num_reprojected = 0;
double total_error = 0.0;
vector<Marker> markers = image_tracks.AllMarkers();
for (int i = 0; i < markers.size(); ++i) {
double weight = markers[i].weight;
- const typename PipelineRoutines::Camera *camera =
+ const typename PipelineRoutines::Camera* camera =
reconstruction.CameraForImage(markers[i].image);
- const typename PipelineRoutines::Point *point =
+ const typename PipelineRoutines::Point* point =
reconstruction.PointForTrack(markers[i].track);
if (!camera || !point || weight == 0.0) {
num_skipped++;
@@ -295,24 +299,25 @@ double InternalReprojectionError(
const int N = 100;
char line[N];
- snprintf(line, N,
- "image %-3d track %-3d "
- "x %7.1f y %7.1f "
- "rx %7.1f ry %7.1f "
- "ex %7.1f ey %7.1f"
- " e %7.1f",
- markers[i].image,
- markers[i].track,
- markers[i].x,
- markers[i].y,
- reprojected_marker.x,
- reprojected_marker.y,
- ex,
- ey,
- sqrt(ex*ex + ey*ey));
+ snprintf(line,
+ N,
+ "image %-3d track %-3d "
+ "x %7.1f y %7.1f "
+ "rx %7.1f ry %7.1f "
+ "ex %7.1f ey %7.1f"
+ " e %7.1f",
+ markers[i].image,
+ markers[i].track,
+ markers[i].x,
+ markers[i].y,
+ reprojected_marker.x,
+ reprojected_marker.y,
+ ex,
+ ey,
+ sqrt(ex * ex + ey * ey));
VLOG(1) << line;
- total_error += sqrt(ex*ex + ey*ey);
+ total_error += sqrt(ex * ex + ey * ey);
}
LG << "Skipped " << num_skipped << " markers.";
LG << "Reprojected " << num_reprojected << " markers.";
@@ -321,46 +326,41 @@ double InternalReprojectionError(
return total_error / num_reprojected;
}
-double EuclideanReprojectionError(const Tracks &image_tracks,
- const EuclideanReconstruction &reconstruction,
- const CameraIntrinsics &intrinsics) {
- return InternalReprojectionError<EuclideanPipelineRoutines>(image_tracks,
- reconstruction,
- intrinsics);
+double EuclideanReprojectionError(const Tracks& image_tracks,
+ const EuclideanReconstruction& reconstruction,
+ const CameraIntrinsics& intrinsics) {
+ return InternalReprojectionError<EuclideanPipelineRoutines>(
+ image_tracks, reconstruction, intrinsics);
}
double ProjectiveReprojectionError(
- const Tracks &image_tracks,
- const ProjectiveReconstruction &reconstruction,
- const CameraIntrinsics &intrinsics) {
- return InternalReprojectionError<ProjectivePipelineRoutines>(image_tracks,
- reconstruction,
- intrinsics);
+ const Tracks& image_tracks,
+ const ProjectiveReconstruction& reconstruction,
+ const CameraIntrinsics& intrinsics) {
+ return InternalReprojectionError<ProjectivePipelineRoutines>(
+ image_tracks, reconstruction, intrinsics);
}
-void EuclideanCompleteReconstruction(const Tracks &tracks,
- EuclideanReconstruction *reconstruction,
- ProgressUpdateCallback *update_callback) {
- InternalCompleteReconstruction<EuclideanPipelineRoutines>(tracks,
- reconstruction,
- update_callback);
+void EuclideanCompleteReconstruction(const Tracks& tracks,
+ EuclideanReconstruction* reconstruction,
+ ProgressUpdateCallback* update_callback) {
+ InternalCompleteReconstruction<EuclideanPipelineRoutines>(
+ tracks, reconstruction, update_callback);
}
-void ProjectiveCompleteReconstruction(const Tracks &tracks,
- ProjectiveReconstruction *reconstruction) {
+void ProjectiveCompleteReconstruction(
+ const Tracks& tracks, ProjectiveReconstruction* reconstruction) {
InternalCompleteReconstruction<ProjectivePipelineRoutines>(tracks,
reconstruction);
}
-void InvertIntrinsicsForTracks(const Tracks &raw_tracks,
- const CameraIntrinsics &camera_intrinsics,
- Tracks *calibrated_tracks) {
+void InvertIntrinsicsForTracks(const Tracks& raw_tracks,
+ const CameraIntrinsics& camera_intrinsics,
+ Tracks* calibrated_tracks) {
vector<Marker> markers = raw_tracks.AllMarkers();
for (int i = 0; i < markers.size(); ++i) {
- camera_intrinsics.InvertIntrinsics(markers[i].x,
- markers[i].y,
- &(markers[i].x),
- &(markers[i].y));
+ camera_intrinsics.InvertIntrinsics(
+ markers[i].x, markers[i].y, &(markers[i].x), &(markers[i].y));
}
*calibrated_tracks = Tracks(markers);
}
diff --git a/intern/libmv/libmv/simple_pipeline/pipeline.h b/intern/libmv/libmv/simple_pipeline/pipeline.h
index 4d1bd00c51f..d6b43536d46 100644
--- a/intern/libmv/libmv/simple_pipeline/pipeline.h
+++ b/intern/libmv/libmv/simple_pipeline/pipeline.h
@@ -22,8 +22,8 @@
#define LIBMV_SIMPLE_PIPELINE_PIPELINE_H_
#include "libmv/simple_pipeline/callbacks.h"
-#include "libmv/simple_pipeline/tracks.h"
#include "libmv/simple_pipeline/reconstruction.h"
+#include "libmv/simple_pipeline/tracks.h"
namespace libmv {
@@ -47,9 +47,9 @@ namespace libmv {
\sa EuclideanResect, EuclideanIntersect, EuclideanBundle
*/
void EuclideanCompleteReconstruction(
- const Tracks &tracks,
- EuclideanReconstruction *reconstruction,
- ProgressUpdateCallback *update_callback = NULL);
+ const Tracks& tracks,
+ EuclideanReconstruction* reconstruction,
+ ProgressUpdateCallback* update_callback = NULL);
/*!
Estimate camera matrices and homogeneous 3D coordinates for all frames and
@@ -71,27 +71,26 @@ void EuclideanCompleteReconstruction(
\sa ProjectiveResect, ProjectiveIntersect, ProjectiveBundle
*/
-void ProjectiveCompleteReconstruction(const Tracks &tracks,
- ProjectiveReconstruction *reconstruction);
-
+void ProjectiveCompleteReconstruction(const Tracks& tracks,
+ ProjectiveReconstruction* reconstruction);
class CameraIntrinsics;
// TODO(keir): Decide if we want these in the public API, and if so, what the
// appropriate include file is.
-double EuclideanReprojectionError(const Tracks &image_tracks,
- const EuclideanReconstruction &reconstruction,
- const CameraIntrinsics &intrinsics);
+double EuclideanReprojectionError(const Tracks& image_tracks,
+ const EuclideanReconstruction& reconstruction,
+ const CameraIntrinsics& intrinsics);
double ProjectiveReprojectionError(
- const Tracks &image_tracks,
- const ProjectiveReconstruction &reconstruction,
- const CameraIntrinsics &intrinsics);
+ const Tracks& image_tracks,
+ const ProjectiveReconstruction& reconstruction,
+ const CameraIntrinsics& intrinsics);
-void InvertIntrinsicsForTracks(const Tracks &raw_tracks,
- const CameraIntrinsics &camera_intrinsics,
- Tracks *calibrated_tracks);
+void InvertIntrinsicsForTracks(const Tracks& raw_tracks,
+ const CameraIntrinsics& camera_intrinsics,
+ Tracks* calibrated_tracks);
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/reconstruction.cc b/intern/libmv/libmv/simple_pipeline/reconstruction.cc
index 851eedb5bb1..584f7440caf 100644
--- a/intern/libmv/libmv/simple_pipeline/reconstruction.cc
+++ b/intern/libmv/libmv/simple_pipeline/reconstruction.cc
@@ -19,20 +19,21 @@
// IN THE SOFTWARE.
#include "libmv/simple_pipeline/reconstruction.h"
-#include "libmv/numeric/numeric.h"
#include "libmv/logging/logging.h"
+#include "libmv/numeric/numeric.h"
namespace libmv {
-EuclideanReconstruction::EuclideanReconstruction() {}
+EuclideanReconstruction::EuclideanReconstruction() {
+}
EuclideanReconstruction::EuclideanReconstruction(
- const EuclideanReconstruction &other) {
+ const EuclideanReconstruction& other) {
image_to_cameras_map_ = other.image_to_cameras_map_;
points_ = other.points_;
}
-EuclideanReconstruction &EuclideanReconstruction::operator=(
- const EuclideanReconstruction &other) {
+EuclideanReconstruction& EuclideanReconstruction::operator=(
+ const EuclideanReconstruction& other) {
if (&other != this) {
image_to_cameras_map_ = other.image_to_cameras_map_;
points_ = other.points_;
@@ -41,9 +42,9 @@ EuclideanReconstruction &EuclideanReconstruction::operator=(
}
void EuclideanReconstruction::InsertCamera(int image,
- const Mat3 &R,
- const Vec3 &t) {
- LG << "InsertCamera " << image << ":\nR:\n"<< R << "\nt:\n" << t;
+ const Mat3& R,
+ const Vec3& t) {
+ LG << "InsertCamera " << image << ":\nR:\n" << R << "\nt:\n" << t;
EuclideanCamera camera;
camera.image = image;
@@ -53,7 +54,7 @@ void EuclideanReconstruction::InsertCamera(int image,
image_to_cameras_map_.insert(make_pair(image, camera));
}
-void EuclideanReconstruction::InsertPoint(int track, const Vec3 &X) {
+void EuclideanReconstruction::InsertPoint(int track, const Vec3& X) {
LG << "InsertPoint " << track << ":\n" << X;
if (track >= points_.size()) {
points_.resize(track + 1);
@@ -62,13 +63,12 @@ void EuclideanReconstruction::InsertPoint(int track, const Vec3 &X) {
points_[track].X = X;
}
-EuclideanCamera *EuclideanReconstruction::CameraForImage(int image) {
- return const_cast<EuclideanCamera *>(
- static_cast<const EuclideanReconstruction *>(
- this)->CameraForImage(image));
+EuclideanCamera* EuclideanReconstruction::CameraForImage(int image) {
+ return const_cast<EuclideanCamera*>(
+ static_cast<const EuclideanReconstruction*>(this)->CameraForImage(image));
}
-const EuclideanCamera *EuclideanReconstruction::CameraForImage(
+const EuclideanCamera* EuclideanReconstruction::CameraForImage(
int image) const {
ImageToCameraMap::const_iterator it = image_to_cameras_map_.find(image);
if (it == image_to_cameras_map_.end()) {
@@ -86,16 +86,16 @@ vector<EuclideanCamera> EuclideanReconstruction::AllCameras() const {
return cameras;
}
-EuclideanPoint *EuclideanReconstruction::PointForTrack(int track) {
- return const_cast<EuclideanPoint *>(
- static_cast<const EuclideanReconstruction *>(this)->PointForTrack(track));
+EuclideanPoint* EuclideanReconstruction::PointForTrack(int track) {
+ return const_cast<EuclideanPoint*>(
+ static_cast<const EuclideanReconstruction*>(this)->PointForTrack(track));
}
-const EuclideanPoint *EuclideanReconstruction::PointForTrack(int track) const {
+const EuclideanPoint* EuclideanReconstruction::PointForTrack(int track) const {
if (track < 0 || track >= points_.size()) {
return NULL;
}
- const EuclideanPoint *point = &points_[track];
+ const EuclideanPoint* point = &points_[track];
if (point->track == -1) {
return NULL;
}
@@ -112,8 +112,8 @@ vector<EuclideanPoint> EuclideanReconstruction::AllPoints() const {
return points;
}
-void ProjectiveReconstruction::InsertCamera(int image, const Mat34 &P) {
- LG << "InsertCamera " << image << ":\nP:\n"<< P;
+void ProjectiveReconstruction::InsertCamera(int image, const Mat34& P) {
+ LG << "InsertCamera " << image << ":\nP:\n" << P;
ProjectiveCamera camera;
camera.image = image;
@@ -122,7 +122,7 @@ void ProjectiveReconstruction::InsertCamera(int image, const Mat34 &P) {
image_to_cameras_map_.insert(make_pair(image, camera));
}
-void ProjectiveReconstruction::InsertPoint(int track, const Vec4 &X) {
+void ProjectiveReconstruction::InsertPoint(int track, const Vec4& X) {
LG << "InsertPoint " << track << ":\n" << X;
if (track >= points_.size()) {
points_.resize(track + 1);
@@ -131,17 +131,17 @@ void ProjectiveReconstruction::InsertPoint(int track, const Vec4 &X) {
points_[track].X = X;
}
-ProjectiveCamera *ProjectiveReconstruction::CameraForImage(int image) {
- return const_cast<ProjectiveCamera *>(
- static_cast<const ProjectiveReconstruction *>(
- this)->CameraForImage(image));
+ProjectiveCamera* ProjectiveReconstruction::CameraForImage(int image) {
+ return const_cast<ProjectiveCamera*>(
+ static_cast<const ProjectiveReconstruction*>(this)->CameraForImage(
+ image));
}
-const ProjectiveCamera *ProjectiveReconstruction::CameraForImage(
+const ProjectiveCamera* ProjectiveReconstruction::CameraForImage(
int image) const {
ImageToCameraMap::const_iterator it = image_to_cameras_map_.find(image);
if (it == image_to_cameras_map_.end()) {
- return NULL;
+ return NULL;
}
return &it->second;
}
@@ -155,16 +155,17 @@ vector<ProjectiveCamera> ProjectiveReconstruction::AllCameras() const {
return cameras;
}
-ProjectivePoint *ProjectiveReconstruction::PointForTrack(int track) {
- return const_cast<ProjectivePoint *>(
- static_cast<const ProjectiveReconstruction *>(this)->PointForTrack(track));
+ProjectivePoint* ProjectiveReconstruction::PointForTrack(int track) {
+ return const_cast<ProjectivePoint*>(
+ static_cast<const ProjectiveReconstruction*>(this)->PointForTrack(track));
}
-const ProjectivePoint *ProjectiveReconstruction::PointForTrack(int track) const {
+const ProjectivePoint* ProjectiveReconstruction::PointForTrack(
+ int track) const {
if (track < 0 || track >= points_.size()) {
return NULL;
}
- const ProjectivePoint *point = &points_[track];
+ const ProjectivePoint* point = &points_[track];
if (point->track == -1) {
return NULL;
}
diff --git a/intern/libmv/libmv/simple_pipeline/reconstruction.h b/intern/libmv/libmv/simple_pipeline/reconstruction.h
index 544aeac042e..56b2ba34c91 100644
--- a/intern/libmv/libmv/simple_pipeline/reconstruction.h
+++ b/intern/libmv/libmv/simple_pipeline/reconstruction.h
@@ -21,14 +21,15 @@
#ifndef LIBMV_SIMPLE_PIPELINE_RECONSTRUCTION_H_
#define LIBMV_SIMPLE_PIPELINE_RECONSTRUCTION_H_
-#include "libmv/base/vector.h"
#include "libmv/base/map.h"
+#include "libmv/base/vector.h"
#include "libmv/numeric/numeric.h"
namespace libmv {
/*!
- A EuclideanCamera is the location and rotation of the camera viewing \a image.
+ A EuclideanCamera is the location and rotation of the camera viewing \a
+ image.
\a image identify which image from \link Tracks this camera represents.
\a R is a 3x3 matrix representing the rotation of the camera.
@@ -38,7 +39,7 @@ namespace libmv {
*/
struct EuclideanCamera {
EuclideanCamera() : image(-1) {}
- EuclideanCamera(const EuclideanCamera &c) : image(c.image), R(c.R), t(c.t) {}
+ EuclideanCamera(const EuclideanCamera& c) : image(c.image), R(c.R), t(c.t) {}
int image;
Mat3 R;
@@ -55,7 +56,7 @@ struct EuclideanCamera {
*/
struct EuclideanPoint {
EuclideanPoint() : track(-1) {}
- EuclideanPoint(const EuclideanPoint &p) : track(p.track), X(p.X) {}
+ EuclideanPoint(const EuclideanPoint& p) : track(p.track), X(p.X) {}
int track;
Vec3 X;
};
@@ -78,9 +79,9 @@ class EuclideanReconstruction {
EuclideanReconstruction();
/// Copy constructor.
- EuclideanReconstruction(const EuclideanReconstruction &other);
+ EuclideanReconstruction(const EuclideanReconstruction& other);
- EuclideanReconstruction &operator=(const EuclideanReconstruction &other);
+ EuclideanReconstruction& operator=(const EuclideanReconstruction& other);
/*!
Insert a camera into the set. If there is already a camera for the given
@@ -92,7 +93,7 @@ class EuclideanReconstruction {
\note You should use the same \a image identifier as in \link Tracks.
*/
- void InsertCamera(int image, const Mat3 &R, const Vec3 &t);
+ void InsertCamera(int image, const Mat3& R, const Vec3& t);
/*!
Insert a point into the reconstruction. If there is already a point for
@@ -104,18 +105,18 @@ class EuclideanReconstruction {
\note You should use the same \a track identifier as in \link Tracks.
*/
- void InsertPoint(int track, const Vec3 &X);
+ void InsertPoint(int track, const Vec3& X);
/// Returns a pointer to the camera corresponding to \a image.
- EuclideanCamera *CameraForImage(int image);
- const EuclideanCamera *CameraForImage(int image) const;
+ EuclideanCamera* CameraForImage(int image);
+ const EuclideanCamera* CameraForImage(int image) const;
/// Returns all cameras.
vector<EuclideanCamera> AllCameras() const;
/// Returns a pointer to the point corresponding to \a track.
- EuclideanPoint *PointForTrack(int track);
- const EuclideanPoint *PointForTrack(int track) const;
+ EuclideanPoint* PointForTrack(int track);
+ const EuclideanPoint* PointForTrack(int track) const;
/// Returns all points.
vector<EuclideanPoint> AllPoints() const;
@@ -139,7 +140,7 @@ class EuclideanReconstruction {
*/
struct ProjectiveCamera {
ProjectiveCamera() : image(-1) {}
- ProjectiveCamera(const ProjectiveCamera &c) : image(c.image), P(c.P) {}
+ ProjectiveCamera(const ProjectiveCamera& c) : image(c.image), P(c.P) {}
int image;
Mat34 P;
@@ -155,7 +156,7 @@ struct ProjectiveCamera {
*/
struct ProjectivePoint {
ProjectivePoint() : track(-1) {}
- ProjectivePoint(const ProjectivePoint &p) : track(p.track), X(p.X) {}
+ ProjectivePoint(const ProjectivePoint& p) : track(p.track), X(p.X) {}
int track;
Vec4 X;
};
@@ -184,7 +185,7 @@ class ProjectiveReconstruction {
\note You should use the same \a image identifier as in \link Tracks.
*/
- void InsertCamera(int image, const Mat34 &P);
+ void InsertCamera(int image, const Mat34& P);
/*!
Insert a point into the reconstruction. If there is already a point for
@@ -196,18 +197,18 @@ class ProjectiveReconstruction {
\note You should use the same \a track identifier as in \link Tracks.
*/
- void InsertPoint(int track, const Vec4 &X);
+ void InsertPoint(int track, const Vec4& X);
/// Returns a pointer to the camera corresponding to \a image.
- ProjectiveCamera *CameraForImage(int image);
- const ProjectiveCamera *CameraForImage(int image) const;
+ ProjectiveCamera* CameraForImage(int image);
+ const ProjectiveCamera* CameraForImage(int image) const;
/// Returns all cameras.
vector<ProjectiveCamera> AllCameras() const;
/// Returns a pointer to the point corresponding to \a track.
- ProjectivePoint *PointForTrack(int track);
- const ProjectivePoint *PointForTrack(int track) const;
+ ProjectivePoint* PointForTrack(int track);
+ const ProjectivePoint* PointForTrack(int track) const;
/// Returns all points.
vector<ProjectivePoint> AllPoints() const;
diff --git a/intern/libmv/libmv/simple_pipeline/reconstruction_scale.cc b/intern/libmv/libmv/simple_pipeline/reconstruction_scale.cc
index 40ac23be7a2..04fbb536d31 100644
--- a/intern/libmv/libmv/simple_pipeline/reconstruction_scale.cc
+++ b/intern/libmv/libmv/simple_pipeline/reconstruction_scale.cc
@@ -23,7 +23,7 @@
namespace libmv {
-void EuclideanScaleToUnity(EuclideanReconstruction *reconstruction) {
+void EuclideanScaleToUnity(EuclideanReconstruction* reconstruction) {
vector<EuclideanCamera> all_cameras = reconstruction->AllCameras();
vector<EuclideanPoint> all_points = reconstruction->AllPoints();
@@ -53,14 +53,14 @@ void EuclideanScaleToUnity(EuclideanReconstruction *reconstruction) {
// Rescale cameras positions.
for (int i = 0; i < all_cameras.size(); ++i) {
int image = all_cameras[i].image;
- EuclideanCamera *camera = reconstruction->CameraForImage(image);
+ EuclideanCamera* camera = reconstruction->CameraForImage(image);
camera->t = camera->t * scale_factor;
}
// Rescale points positions.
for (int i = 0; i < all_points.size(); ++i) {
int track = all_points[i].track;
- EuclideanPoint *point = reconstruction->PointForTrack(track);
+ EuclideanPoint* point = reconstruction->PointForTrack(track);
point->X = point->X * scale_factor;
}
}
diff --git a/intern/libmv/libmv/simple_pipeline/reconstruction_scale.h b/intern/libmv/libmv/simple_pipeline/reconstruction_scale.h
index f2349ff5146..c164878ee25 100644
--- a/intern/libmv/libmv/simple_pipeline/reconstruction_scale.h
+++ b/intern/libmv/libmv/simple_pipeline/reconstruction_scale.h
@@ -29,7 +29,7 @@ namespace libmv {
Scale euclidean reconstruction in a way variance of
camera centers equals to one.
*/
-void EuclideanScaleToUnity(EuclideanReconstruction *reconstruction);
+void EuclideanScaleToUnity(EuclideanReconstruction* reconstruction);
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/resect.cc b/intern/libmv/libmv/simple_pipeline/resect.cc
index e73fc44df2a..b5736767edd 100644
--- a/intern/libmv/libmv/simple_pipeline/resect.cc
+++ b/intern/libmv/libmv/simple_pipeline/resect.cc
@@ -25,17 +25,17 @@
#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
#include "libmv/multiview/euclidean_resection.h"
-#include "libmv/multiview/resection.h"
#include "libmv/multiview/projection.h"
-#include "libmv/numeric/numeric.h"
+#include "libmv/multiview/resection.h"
#include "libmv/numeric/levenberg_marquardt.h"
+#include "libmv/numeric/numeric.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"
namespace libmv {
namespace {
-Mat2X PointMatrixFromMarkers(const vector<Marker> &markers) {
+Mat2X PointMatrixFromMarkers(const vector<Marker>& markers) {
Mat2X points(2, markers.size());
for (int i = 0; i < markers.size(); ++i) {
points(0, i) = markers[i].x;
@@ -53,19 +53,19 @@ Mat2X PointMatrixFromMarkers(const vector<Marker> &markers) {
// axis to rotate around and the magnitude is the amount of the rotation.
struct EuclideanResectCostFunction {
public:
- typedef Vec FMatrixType;
+ typedef Vec FMatrixType;
typedef Vec6 XMatrixType;
- EuclideanResectCostFunction(const vector<Marker> &markers,
- const EuclideanReconstruction &reconstruction,
- const Mat3 &initial_R)
- : markers(markers),
- reconstruction(reconstruction),
- initial_R(initial_R) {}
+ EuclideanResectCostFunction(const vector<Marker>& markers,
+ const EuclideanReconstruction& reconstruction,
+ const Mat3& initial_R)
+ : markers(markers),
+ reconstruction(reconstruction),
+ initial_R(initial_R) {}
// dRt has dR (delta R) encoded as a euler vector in the first 3 parameters,
// followed by t in the next 3 parameters.
- Vec operator()(const Vec6 &dRt) const {
+ Vec operator()(const Vec6& dRt) const {
// Unpack R, t from dRt.
Mat3 R = RotationFromEulerVector(dRt.head<3>()) * initial_R;
Vec3 t = dRt.tail<3>();
@@ -74,25 +74,26 @@ struct EuclideanResectCostFunction {
Vec residuals(2 * markers.size());
residuals.setZero();
for (int i = 0; i < markers.size(); ++i) {
- const EuclideanPoint &point =
+ const EuclideanPoint& point =
*reconstruction.PointForTrack(markers[i].track);
Vec3 projected = R * point.X + t;
projected /= projected(2);
- residuals[2*i + 0] = projected(0) - markers[i].x;
- residuals[2*i + 1] = projected(1) - markers[i].y;
+ residuals[2 * i + 0] = projected(0) - markers[i].x;
+ residuals[2 * i + 1] = projected(1) - markers[i].y;
}
return residuals;
}
- const vector<Marker> &markers;
- const EuclideanReconstruction &reconstruction;
- const Mat3 &initial_R;
+ const vector<Marker>& markers;
+ const EuclideanReconstruction& reconstruction;
+ const Mat3& initial_R;
};
} // namespace
-bool EuclideanResect(const vector<Marker> &markers,
- EuclideanReconstruction *reconstruction, bool final_pass) {
+bool EuclideanResect(const vector<Marker>& markers,
+ EuclideanReconstruction* reconstruction,
+ bool final_pass) {
if (markers.size() < 5) {
return false;
}
@@ -106,9 +107,9 @@ bool EuclideanResect(const vector<Marker> &markers,
Mat3 R;
Vec3 t;
- if (0 || !euclidean_resection::EuclideanResection(
- points_2d, points_3d, &R, &t,
- euclidean_resection::RESECTION_EPNP)) {
+ if (0 ||
+ !euclidean_resection::EuclideanResection(
+ points_2d, points_3d, &R, &t, euclidean_resection::RESECTION_EPNP)) {
// printf("Resection for image %d failed\n", markers[0].image);
LG << "Resection for image " << markers[0].image << " failed;"
<< " trying fallback projective resection.";
@@ -116,7 +117,8 @@ bool EuclideanResect(const vector<Marker> &markers,
LG << "No fallback; failing resection for " << markers[0].image;
return false;
- if (!final_pass) return false;
+ if (!final_pass)
+ return false;
// Euclidean resection failed. Fall back to projective resection, which is
// less reliable but better conditioned when there are many points.
Mat34 P;
@@ -173,7 +175,9 @@ bool EuclideanResect(const vector<Marker> &markers,
t = dRt.tail<3>();
LG << "Resection for image " << markers[0].image << " got:\n"
- << "R:\n" << R << "\nt:\n" << t;
+ << "R:\n"
+ << R << "\nt:\n"
+ << t;
reconstruction->InsertCamera(markers[0].image, R, t);
return true;
}
@@ -186,15 +190,14 @@ namespace {
// freedom drift.
struct ProjectiveResectCostFunction {
public:
- typedef Vec FMatrixType;
+ typedef Vec FMatrixType;
typedef Vec12 XMatrixType;
- ProjectiveResectCostFunction(const vector<Marker> &markers,
- const ProjectiveReconstruction &reconstruction)
- : markers(markers),
- reconstruction(reconstruction) {}
+ ProjectiveResectCostFunction(const vector<Marker>& markers,
+ const ProjectiveReconstruction& reconstruction)
+ : markers(markers), reconstruction(reconstruction) {}
- Vec operator()(const Vec12 &vector_P) const {
+ Vec operator()(const Vec12& vector_P) const {
// Unpack P from vector_P.
Map<const Mat34> P(vector_P.data(), 3, 4);
@@ -202,24 +205,24 @@ struct ProjectiveResectCostFunction {
Vec residuals(2 * markers.size());
residuals.setZero();
for (int i = 0; i < markers.size(); ++i) {
- const ProjectivePoint &point =
+ const ProjectivePoint& point =
*reconstruction.PointForTrack(markers[i].track);
Vec3 projected = P * point.X;
projected /= projected(2);
- residuals[2*i + 0] = projected(0) - markers[i].x;
- residuals[2*i + 1] = projected(1) - markers[i].y;
+ residuals[2 * i + 0] = projected(0) - markers[i].x;
+ residuals[2 * i + 1] = projected(1) - markers[i].y;
}
return residuals;
}
- const vector<Marker> &markers;
- const ProjectiveReconstruction &reconstruction;
+ const vector<Marker>& markers;
+ const ProjectiveReconstruction& reconstruction;
};
} // namespace
-bool ProjectiveResect(const vector<Marker> &markers,
- ProjectiveReconstruction *reconstruction) {
+bool ProjectiveResect(const vector<Marker>& markers,
+ ProjectiveReconstruction* reconstruction) {
if (markers.size() < 5) {
return false;
}
@@ -263,7 +266,8 @@ bool ProjectiveResect(const vector<Marker> &markers,
P = Map<Mat34>(vector_P.data(), 3, 4);
LG << "Resection for image " << markers[0].image << " got:\n"
- << "P:\n" << P;
+ << "P:\n"
+ << P;
reconstruction->InsertCamera(markers[0].image, P);
return true;
}
diff --git a/intern/libmv/libmv/simple_pipeline/resect.h b/intern/libmv/libmv/simple_pipeline/resect.h
index f13d2e2d425..13c3d66bd37 100644
--- a/intern/libmv/libmv/simple_pipeline/resect.h
+++ b/intern/libmv/libmv/simple_pipeline/resect.h
@@ -22,8 +22,8 @@
#define LIBMV_SIMPLE_PIPELINE_RESECT_H
#include "libmv/base/vector.h"
-#include "libmv/simple_pipeline/tracks.h"
#include "libmv/simple_pipeline/reconstruction.h"
+#include "libmv/simple_pipeline/tracks.h"
namespace libmv {
@@ -51,8 +51,9 @@ namespace libmv {
\sa EuclideanIntersect, EuclideanReconstructTwoFrames
*/
-bool EuclideanResect(const vector<Marker> &markers,
- EuclideanReconstruction *reconstruction, bool final_pass);
+bool EuclideanResect(const vector<Marker>& markers,
+ EuclideanReconstruction* reconstruction,
+ bool final_pass);
/*!
Estimate the projective pose of a camera from 2D to 3D correspondences.
@@ -78,8 +79,8 @@ bool EuclideanResect(const vector<Marker> &markers,
\sa ProjectiveIntersect, ProjectiveReconstructTwoFrames
*/
-bool ProjectiveResect(const vector<Marker> &markers,
- ProjectiveReconstruction *reconstruction);
+bool ProjectiveResect(const vector<Marker>& markers,
+ ProjectiveReconstruction* reconstruction);
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/resect_test.cc b/intern/libmv/libmv/simple_pipeline/resect_test.cc
index 811edd282d8..ecf3f9b673d 100644
--- a/intern/libmv/libmv/simple_pipeline/resect_test.cc
+++ b/intern/libmv/libmv/simple_pipeline/resect_test.cc
@@ -153,7 +153,7 @@ TEST(EuclideanResection, Points4KnownImagePointsRandomTranslationRotation) {
// not precise enough with only 4 points.
//
// TODO(jmichot): Reenable this test when there is nonlinear refinement.
-#if 0
+# if 0
R_output.setIdentity();
T_output.setZero();
@@ -163,7 +163,7 @@ TEST(EuclideanResection, Points4KnownImagePointsRandomTranslationRotation) {
EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);*/
-#endif
+# endif
}
// TODO(jmichot): Reduce the code duplication here with the code above.
diff --git a/intern/libmv/libmv/simple_pipeline/tracks.cc b/intern/libmv/libmv/simple_pipeline/tracks.cc
index d5d009708ba..66243807a4b 100644
--- a/intern/libmv/libmv/simple_pipeline/tracks.cc
+++ b/intern/libmv/libmv/simple_pipeline/tracks.cc
@@ -21,31 +21,31 @@
#include "libmv/simple_pipeline/tracks.h"
#include <algorithm>
-#include <vector>
#include <iterator>
+#include <vector>
#include "libmv/numeric/numeric.h"
namespace libmv {
-Tracks::Tracks(const Tracks &other) {
+Tracks::Tracks(const Tracks& other) {
markers_ = other.markers_;
}
-Tracks::Tracks(const vector<Marker> &markers) : markers_(markers) {}
+Tracks::Tracks(const vector<Marker>& markers) : markers_(markers) {
+}
void Tracks::Insert(int image, int track, double x, double y, double weight) {
// TODO(keir): Wow, this is quadratic for repeated insertions. Fix this by
// adding a smarter data structure like a set<>.
for (int i = 0; i < markers_.size(); ++i) {
- if (markers_[i].image == image &&
- markers_[i].track == track) {
+ if (markers_[i].image == image && markers_[i].track == track) {
markers_[i].x = x;
markers_[i].y = y;
return;
}
}
- Marker marker = { image, track, x, y, weight };
+ Marker marker = {image, track, x, y, weight};
markers_.push_back(marker);
}
@@ -101,15 +101,17 @@ vector<Marker> Tracks::MarkersForTracksInBothImages(int image1,
std::sort(image2_tracks.begin(), image2_tracks.end());
std::vector<int> intersection;
- std::set_intersection(image1_tracks.begin(), image1_tracks.end(),
- image2_tracks.begin(), image2_tracks.end(),
+ std::set_intersection(image1_tracks.begin(),
+ image1_tracks.end(),
+ image2_tracks.begin(),
+ image2_tracks.end(),
std::back_inserter(intersection));
vector<Marker> markers;
for (int i = 0; i < markers_.size(); ++i) {
if ((markers_[i].image == image1 || markers_[i].image == image2) &&
- std::binary_search(intersection.begin(), intersection.end(),
- markers_[i].track)) {
+ std::binary_search(
+ intersection.begin(), intersection.end(), markers_[i].track)) {
markers.push_back(markers_[i]);
}
}
@@ -122,7 +124,7 @@ Marker Tracks::MarkerInImageForTrack(int image, int track) const {
return markers_[i];
}
}
- Marker null = { -1, -1, -1, -1, 0.0 };
+ Marker null = {-1, -1, -1, -1, 0.0};
return null;
}
@@ -168,12 +170,12 @@ int Tracks::NumMarkers() const {
return markers_.size();
}
-void CoordinatesForMarkersInImage(const vector<Marker> &markers,
+void CoordinatesForMarkersInImage(const vector<Marker>& markers,
int image,
- Mat *coordinates) {
+ Mat* coordinates) {
vector<Vec2> coords;
for (int i = 0; i < markers.size(); ++i) {
- const Marker &marker = markers[i];
+ const Marker& marker = markers[i];
if (markers[i].image == image) {
coords.push_back(Vec2(marker.x, marker.y));
}
diff --git a/intern/libmv/libmv/simple_pipeline/tracks.h b/intern/libmv/libmv/simple_pipeline/tracks.h
index 752d2790a1c..c3df3a223d8 100644
--- a/intern/libmv/libmv/simple_pipeline/tracks.h
+++ b/intern/libmv/libmv/simple_pipeline/tracks.h
@@ -36,7 +36,8 @@ namespace libmv {
\a weight is used by bundle adjustment and weight means how much the
track affects on a final solution.
- \note Markers are typically aggregated with the help of the \link Tracks class.
+ \note Markers are typically aggregated with the help of the \link Tracks
+ class.
\sa Tracks
*/
@@ -56,19 +57,20 @@ struct Marker {
images, which must get created before any 3D reconstruction can take place.
The container has several fast lookups for queries typically needed for
- structure from motion algorithms, such as \link MarkersForTracksInBothImages().
+ structure from motion algorithms, such as \link
+ MarkersForTracksInBothImages().
\sa Marker
*/
class Tracks {
public:
- Tracks() { }
+ Tracks() {}
// Copy constructor for a tracks object.
- Tracks(const Tracks &other);
+ Tracks(const Tracks& other);
/// Construct a new tracks object using the given markers to start.
- explicit Tracks(const vector<Marker> &markers);
+ explicit Tracks(const vector<Marker>& markers);
/*!
Inserts a marker into the set. If there is already a marker for the given
@@ -129,9 +131,9 @@ class Tracks {
vector<Marker> markers_;
};
-void CoordinatesForMarkersInImage(const vector<Marker> &markers,
+void CoordinatesForMarkersInImage(const vector<Marker>& markers,
int image,
- Mat *coordinates);
+ Mat* coordinates);
} // namespace libmv
diff --git a/intern/libmv/libmv/threading/threading.h b/intern/libmv/libmv/threading/threading.h
index f23bf6f172c..da625e02424 100644
--- a/intern/libmv/libmv/threading/threading.h
+++ b/intern/libmv/libmv/threading/threading.h
@@ -31,7 +31,7 @@
namespace libmv {
#if COMPILER_SUPPORTS_CXX11
-using mutex = std::mutex;
+using mutex = std::mutex;
using scoped_lock = std::unique_lock<std::mutex>;
using condition_variable = std::condition_variable;
#else
diff --git a/intern/libmv/libmv/tracking/brute_region_tracker.cc b/intern/libmv/libmv/tracking/brute_region_tracker.cc
index 85aecb7f633..7007fb9440b 100644
--- a/intern/libmv/libmv/tracking/brute_region_tracker.cc
+++ b/intern/libmv/libmv/tracking/brute_region_tracker.cc
@@ -25,31 +25,30 @@
#endif
#include "libmv/base/aligned_malloc.h"
-#include "libmv/image/image.h"
#include "libmv/image/convolve.h"
#include "libmv/image/correlation.h"
+#include "libmv/image/image.h"
#include "libmv/image/sample.h"
#include "libmv/logging/logging.h"
namespace libmv {
namespace {
-bool RegionIsInBounds(const FloatImage &image1,
- double x, double y,
+bool RegionIsInBounds(const FloatImage& image1,
+ double x,
+ double y,
int half_window_size) {
// Check the minimum coordinates.
int min_x = floor(x) - half_window_size - 1;
int min_y = floor(y) - half_window_size - 1;
- if (min_x < 0.0 ||
- min_y < 0.0) {
+ if (min_x < 0.0 || min_y < 0.0) {
return false;
}
// Check the maximum coordinates.
int max_x = ceil(x) + half_window_size + 1;
int max_y = ceil(y) + half_window_size + 1;
- if (max_x > image1.cols() ||
- max_y > image1.rows()) {
+ if (max_x > image1.cols() || max_y > image1.rows()) {
return false;
}
@@ -69,14 +68,15 @@ bool RegionIsInBounds(const FloatImage &image1,
// and "b", since the SSE load instructionst will pull in memory past the end
// of the arrays if their size is not a multiple of 16.
inline static __m128i SumOfAbsoluteDifferencesContiguousSSE(
- const unsigned char *a, // aligned
- const unsigned char *b, // not aligned
+ const unsigned char* a, // aligned
+ const unsigned char* b, // not aligned
unsigned int size,
__m128i sad) {
// Do the bulk of the work as 16-way integer operations.
for (unsigned int j = 0; j < size / 16; j++) {
- sad = _mm_add_epi32(sad, _mm_sad_epu8( _mm_load_si128 ((__m128i*)(a + 16 * j)),
- _mm_loadu_si128((__m128i*)(b + 16 * j))));
+ sad = _mm_add_epi32(sad,
+ _mm_sad_epu8(_mm_load_si128((__m128i*)(a + 16 * j)),
+ _mm_loadu_si128((__m128i*)(b + 16 * j))));
}
// Handle the trailing end.
// TODO(keir): Benchmark to verify that the below SSE is a win compared to a
@@ -90,32 +90,63 @@ inline static __m128i SumOfAbsoluteDifferencesContiguousSSE(
unsigned int remainder = size % 16u;
if (remainder) {
unsigned int j = size / 16;
- __m128i a_trail = _mm_load_si128 ((__m128i*)(a + 16 * j));
+ __m128i a_trail = _mm_load_si128((__m128i*)(a + 16 * j));
__m128i b_trail = _mm_loadu_si128((__m128i*)(b + 16 * j));
__m128i mask;
switch (remainder) {
-#define X 0xff
- case 1: mask = _mm_setr_epi8(X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break;
- case 2: mask = _mm_setr_epi8(X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break;
- case 3: mask = _mm_setr_epi8(X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break;
- case 4: mask = _mm_setr_epi8(X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break;
- case 5: mask = _mm_setr_epi8(X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break;
- case 6: mask = _mm_setr_epi8(X, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break;
- case 7: mask = _mm_setr_epi8(X, X, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0); break;
- case 8: mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0); break;
- case 9: mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0); break;
- case 10: mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, 0, 0, 0, 0, 0, 0); break;
- case 11: mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, 0, 0, 0, 0, 0); break;
- case 12: mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, X, 0, 0, 0, 0); break;
- case 13: mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 0, 0); break;
- case 14: mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 0); break;
- case 15: mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0); break;
+# define X 0xff
+ case 1:
+ mask = _mm_setr_epi8(X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case 2:
+ mask = _mm_setr_epi8(X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case 3:
+ mask = _mm_setr_epi8(X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case 4:
+ mask = _mm_setr_epi8(X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case 5:
+ mask = _mm_setr_epi8(X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case 6:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case 7:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case 8:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case 9:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0);
+ break;
+ case 10:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, 0, 0, 0, 0, 0, 0);
+ break;
+ case 11:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, 0, 0, 0, 0, 0);
+ break;
+ case 12:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, X, 0, 0, 0, 0);
+ break;
+ case 13:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 0, 0);
+ break;
+ case 14:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 0);
+ break;
+ case 15:
+ mask = _mm_setr_epi8(X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0);
+ break;
// To silence compiler warning.
default: mask = _mm_setzero_si128(); break;
-#undef X
+# undef X
}
- sad = _mm_add_epi32(sad, _mm_sad_epu8(_mm_and_si128(mask, a_trail),
- _mm_and_si128(mask, b_trail)));
+ sad = _mm_add_epi32(sad,
+ _mm_sad_epu8(_mm_and_si128(mask, a_trail),
+ _mm_and_si128(mask, b_trail)));
}
return sad;
}
@@ -124,13 +155,12 @@ inline static __m128i SumOfAbsoluteDifferencesContiguousSSE(
// Computes the sum of absolute differences between pattern and image. Pattern
// must be 16-byte aligned, and the stride must be a multiple of 16. The image
// does pointer does not have to be aligned.
-int SumOfAbsoluteDifferencesContiguousImage(
- const unsigned char *pattern,
- unsigned int pattern_width,
- unsigned int pattern_height,
- unsigned int pattern_stride,
- const unsigned char *image,
- unsigned int image_stride) {
+int SumOfAbsoluteDifferencesContiguousImage(const unsigned char* pattern,
+ unsigned int pattern_width,
+ unsigned int pattern_height,
+ unsigned int pattern_stride,
+ const unsigned char* image,
+ unsigned int image_stride) {
#ifdef __SSE2__
// TODO(keir): Add interleaved accumulation, where accumulation is done into
// two or more SSE registers that then get combined at the end. This reduces
@@ -145,8 +175,7 @@ int SumOfAbsoluteDifferencesContiguousImage(
sad);
}
return _mm_cvtsi128_si32(
- _mm_add_epi32(sad,
- _mm_shuffle_epi32(sad, _MM_SHUFFLE(3, 0, 1, 2))));
+ _mm_add_epi32(sad, _mm_shuffle_epi32(sad, _MM_SHUFFLE(3, 0, 1, 2))));
#else
int sad = 0;
for (int r = 0; r < pattern_height; ++r) {
@@ -161,12 +190,13 @@ int SumOfAbsoluteDifferencesContiguousImage(
// Sample a region of size width, height centered at x,y in image, converting
// from float to byte in the process. Samples from the first channel. Puts
// result into *pattern.
-void SampleRectangularPattern(const FloatImage &image,
- double x, double y,
+void SampleRectangularPattern(const FloatImage& image,
+ double x,
+ double y,
int width,
int height,
int pattern_stride,
- unsigned char *pattern) {
+ unsigned char* pattern) {
// There are two cases for width and height: even or odd. If it's odd, then
// the bounds [-width / 2, width / 2] works as expected. However, for even,
// this results in one extra access past the end. So use < instead of <= in
@@ -175,7 +205,7 @@ void SampleRectangularPattern(const FloatImage &image,
int end_height = (height / 2) + (height % 2);
for (int r = -height / 2; r < end_height; ++r) {
for (int c = -width / 2; c < end_width; ++c) {
- pattern[pattern_stride * (r + height / 2) + c + width / 2] =
+ pattern[pattern_stride * (r + height / 2) + c + width / 2] =
SampleLinear(image, y + r, x + c, 0) * 255.0;
}
}
@@ -195,30 +225,30 @@ inline int PadToAlignment(int x, int alignment) {
// is returned in *pattern_stride.
//
// NOTE: Caller must free *pattern with aligned_malloc() from above.
-void SampleSquarePattern(const FloatImage &image,
- double x, double y,
+void SampleSquarePattern(const FloatImage& image,
+ double x,
+ double y,
int half_width,
- unsigned char **pattern,
- int *pattern_stride) {
+ unsigned char** pattern,
+ int* pattern_stride) {
int width = 2 * half_width + 1;
// Allocate an aligned block with padding on the end so each row of the
// pattern starts on a 16-byte boundary.
*pattern_stride = PadToAlignment(width, 16);
int pattern_size_bytes = *pattern_stride * width;
- *pattern = static_cast<unsigned char *>(
- aligned_malloc(pattern_size_bytes, 16));
- SampleRectangularPattern(image, x, y, width, width,
- *pattern_stride,
- *pattern);
+ *pattern =
+ static_cast<unsigned char*>(aligned_malloc(pattern_size_bytes, 16));
+ SampleRectangularPattern(
+ image, x, y, width, width, *pattern_stride, *pattern);
}
// NOTE: Caller must free *image with aligned_malloc() from above.
-void FloatArrayToByteArrayWithPadding(const FloatImage &float_image,
- unsigned char **image,
- int *image_stride) {
+void FloatArrayToByteArrayWithPadding(const FloatImage& float_image,
+ unsigned char** image,
+ int* image_stride) {
// Allocate enough so that accessing 16 elements past the end is fine.
*image_stride = float_image.Width() + 16;
- *image = static_cast<unsigned char *>(
+ *image = static_cast<unsigned char*>(
aligned_malloc(*image_stride * float_image.Height(), 16));
for (int i = 0; i < float_image.Height(); ++i) {
for (int j = 0; j < float_image.Width(); ++j) {
@@ -235,10 +265,12 @@ void FloatArrayToByteArrayWithPadding(const FloatImage &float_image,
// values for every hypothesis looks like.
//
// TODO(keir): Priority queue for multiple hypothesis.
-bool BruteRegionTracker::Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const {
+bool BruteRegionTracker::Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const {
if (!RegionIsInBounds(image1, x1, y1, half_window_size)) {
LG << "Fell out of image1's window with x1=" << x1 << ", y1=" << y1
<< ", hw=" << half_window_size << ".";
@@ -252,28 +284,28 @@ bool BruteRegionTracker::Track(const FloatImage &image1,
BlurredImageAndDerivativesChannels(image2, 0.9, &image_and_gradient2);
// Sample the pattern to get it aligned to an image grid.
- unsigned char *pattern;
+ unsigned char* pattern;
int pattern_stride;
- SampleSquarePattern(image_and_gradient1, x1, y1, half_window_size,
- &pattern,
- &pattern_stride);
+ SampleSquarePattern(
+ image_and_gradient1, x1, y1, half_window_size, &pattern, &pattern_stride);
// Convert the search area directly to bytes without sampling.
- unsigned char *search_area;
+ unsigned char* search_area;
int search_area_stride;
- FloatArrayToByteArrayWithPadding(image_and_gradient2, &search_area,
- &search_area_stride);
+ FloatArrayToByteArrayWithPadding(
+ image_and_gradient2, &search_area, &search_area_stride);
// Try all possible locations inside the search area. Yes, everywhere.
int best_i = -1, best_j = -1, best_sad = INT_MAX;
for (int i = 0; i < image2.Height() - pattern_width; ++i) {
for (int j = 0; j < image2.Width() - pattern_width; ++j) {
- int sad = SumOfAbsoluteDifferencesContiguousImage(pattern,
- pattern_width,
- pattern_width,
- pattern_stride,
- search_area + search_area_stride * i + j,
- search_area_stride);
+ int sad = SumOfAbsoluteDifferencesContiguousImage(
+ pattern,
+ pattern_width,
+ pattern_width,
+ pattern_stride,
+ search_area + search_area_stride * i + j,
+ search_area_stride);
if (sad < best_sad) {
best_i = i;
best_j = j;
@@ -309,16 +341,23 @@ bool BruteRegionTracker::Track(const FloatImage &image1,
}
Array3Df image_and_gradient1_sampled, image_and_gradient2_sampled;
- SamplePattern(image_and_gradient1, x1, y1, half_window_size, 3,
+ SamplePattern(image_and_gradient1,
+ x1,
+ y1,
+ half_window_size,
+ 3,
&image_and_gradient1_sampled);
- SamplePattern(image_and_gradient2, *x2, *y2, half_window_size, 3,
+ SamplePattern(image_and_gradient2,
+ *x2,
+ *y2,
+ half_window_size,
+ 3,
&image_and_gradient2_sampled);
// Compute the Pearson product-moment correlation coefficient to check
// for sanity.
double correlation = PearsonProductMomentCorrelation(
- image_and_gradient1_sampled,
- image_and_gradient2_sampled);
+ image_and_gradient1_sampled, image_and_gradient2_sampled);
LG << "Final correlation: " << correlation;
diff --git a/intern/libmv/libmv/tracking/brute_region_tracker.h b/intern/libmv/libmv/tracking/brute_region_tracker.h
index a699c42ee92..183dc6df07b 100644
--- a/intern/libmv/libmv/tracking/brute_region_tracker.h
+++ b/intern/libmv/libmv/tracking/brute_region_tracker.h
@@ -27,17 +27,17 @@
namespace libmv {
struct BruteRegionTracker : public RegionTracker {
- BruteRegionTracker()
- : half_window_size(4),
- minimum_correlation(0.78) {}
+ BruteRegionTracker() : half_window_size(4), minimum_correlation(0.78) {}
virtual ~BruteRegionTracker() {}
// Tracker interface.
- virtual bool Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const;
+ virtual bool Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const;
// No point in creating getters or setters.
int half_window_size;
diff --git a/intern/libmv/libmv/tracking/hybrid_region_tracker.cc b/intern/libmv/libmv/tracking/hybrid_region_tracker.cc
index ea3b0f5bfc0..f0392643a6c 100644
--- a/intern/libmv/libmv/tracking/hybrid_region_tracker.cc
+++ b/intern/libmv/libmv/tracking/hybrid_region_tracker.cc
@@ -20,17 +20,19 @@
#include "libmv/tracking/hybrid_region_tracker.h"
-#include "libmv/image/image.h"
#include "libmv/image/convolve.h"
+#include "libmv/image/image.h"
#include "libmv/image/sample.h"
#include "libmv/logging/logging.h"
namespace libmv {
-bool HybridRegionTracker::Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const {
+bool HybridRegionTracker::Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const {
double x2_coarse = *x2;
double y2_coarse = *y2;
if (!coarse_tracker_->Track(image1, image2, x1, y1, &x2_coarse, &y2_coarse)) {
diff --git a/intern/libmv/libmv/tracking/hybrid_region_tracker.h b/intern/libmv/libmv/tracking/hybrid_region_tracker.h
index 967d2afd1e5..2730d2dbbf2 100644
--- a/intern/libmv/libmv/tracking/hybrid_region_tracker.h
+++ b/intern/libmv/libmv/tracking/hybrid_region_tracker.h
@@ -21,8 +21,8 @@
#ifndef LIBMV_REGION_TRACKING_HYBRID_REGION_TRACKER_H_
#define LIBMV_REGION_TRACKING_HYBRID_REGION_TRACKER_H_
-#include "libmv/image/image.h"
#include "libmv/base/scoped_ptr.h"
+#include "libmv/image/image.h"
#include "libmv/tracking/region_tracker.h"
namespace libmv {
@@ -30,18 +30,19 @@ namespace libmv {
// TODO(keir): Documentation!
class HybridRegionTracker : public RegionTracker {
public:
- HybridRegionTracker(RegionTracker *coarse_tracker,
- RegionTracker *fine_tracker)
- : coarse_tracker_(coarse_tracker),
- fine_tracker_(fine_tracker) {}
+ HybridRegionTracker(RegionTracker* coarse_tracker,
+ RegionTracker* fine_tracker)
+ : coarse_tracker_(coarse_tracker), fine_tracker_(fine_tracker) {}
virtual ~HybridRegionTracker() {}
// Tracker interface.
- virtual bool Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const;
+ virtual bool Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const;
scoped_ptr<RegionTracker> coarse_tracker_;
scoped_ptr<RegionTracker> fine_tracker_;
diff --git a/intern/libmv/libmv/tracking/kalman_filter.h b/intern/libmv/libmv/tracking/kalman_filter.h
index 9841f0e912c..b1312d0e027 100644
--- a/intern/libmv/libmv/tracking/kalman_filter.h
+++ b/intern/libmv/libmv/tracking/kalman_filter.h
@@ -19,13 +19,14 @@
// IN THE SOFTWARE.
#ifndef LIBMV_TRACKING_KALMAN_FILTER_H_
+#define LIBMV_TRACKING_KALMAN_FILTER_H_
#include "libmv/numeric/numeric.h"
namespace mv {
// A Kalman filter with order N and observation size K.
-template<typename T, int N, int K>
+template <typename T, int N, int K>
class KalmanFilter {
public:
struct State {
@@ -38,54 +39,47 @@ class KalmanFilter {
const T* observation_data,
const T* process_covariance_data,
const T* default_measurement_covariance_data)
- : state_transition_matrix_(
- Eigen::Matrix<T, N, N, Eigen::RowMajor>(state_transition_data)),
- observation_matrix_(
- Eigen::Matrix<T, K, N, Eigen::RowMajor>(observation_data)),
- process_covariance_(
- Eigen::Matrix<T, N, N, Eigen::RowMajor>(process_covariance_data)),
- default_measurement_covariance_(
- Eigen::Matrix<T, K, K, Eigen::RowMajor>(
- default_measurement_covariance_data)) {
- }
+ : state_transition_matrix_(
+ Eigen::Matrix<T, N, N, Eigen::RowMajor>(state_transition_data)),
+ observation_matrix_(
+ Eigen::Matrix<T, K, N, Eigen::RowMajor>(observation_data)),
+ process_covariance_(
+ Eigen::Matrix<T, N, N, Eigen::RowMajor>(process_covariance_data)),
+ default_measurement_covariance_(Eigen::Matrix<T, K, K, Eigen::RowMajor>(
+ default_measurement_covariance_data)) {}
- KalmanFilter(
- const Eigen::Matrix<T, N, N> &state_transition_matrix,
- const Eigen::Matrix<T, K, N> &observation_matrix,
- const Eigen::Matrix<T, N, N> &process_covariance,
- const Eigen::Matrix<T, K, K> &default_measurement_covariance)
- : state_transition_matrix_(state_transition_matrix),
- observation_matrix_(observation_matrix),
- process_covariance_(process_covariance),
- default_measurement_covariance_(default_measurement_covariance) {
- }
+ KalmanFilter(const Eigen::Matrix<T, N, N>& state_transition_matrix,
+ const Eigen::Matrix<T, K, N>& observation_matrix,
+ const Eigen::Matrix<T, N, N>& process_covariance,
+ const Eigen::Matrix<T, K, K>& default_measurement_covariance)
+ : state_transition_matrix_(state_transition_matrix),
+ observation_matrix_(observation_matrix),
+ process_covariance_(process_covariance),
+ default_measurement_covariance_(default_measurement_covariance) {}
// Advances the system according to the current state estimate.
- void Step(State *state) const {
+ void Step(State* state) const {
state->mean = state_transition_matrix_ * state->mean;
- state->covariance = state_transition_matrix_ *
- state->covariance *
- state_transition_matrix_.transpose() +
+ state->covariance = state_transition_matrix_ * state->covariance *
+ state_transition_matrix_.transpose() +
process_covariance_;
}
// Updates a state with a new measurement.
- void Update(const Eigen::Matrix<T, K, 1> &measurement_mean,
- const Eigen::Matrix<T, K, K> &measurement_covariance,
- State *state) const {
+ void Update(const Eigen::Matrix<T, K, 1>& measurement_mean,
+ const Eigen::Matrix<T, K, K>& measurement_covariance,
+ State* state) const {
// Calculate the innovation, which is a distribution over prediction error.
- Eigen::Matrix<T, K, 1> innovation_mean = measurement_mean -
- observation_matrix_ *
- state->mean;
+ Eigen::Matrix<T, K, 1> innovation_mean =
+ measurement_mean - observation_matrix_ * state->mean;
Eigen::Matrix<T, K, K> innovation_covariance =
- observation_matrix_ *
- state->covariance *
- observation_matrix_.transpose() +
+ observation_matrix_ * state->covariance *
+ observation_matrix_.transpose() +
measurement_covariance;
// Calculate the Kalman gain.
Eigen::Matrix<T, 6, 2> kalman_gain = state->covariance *
- observation_matrix_.transpose() *
+ observation_matrix_.transpose() *
innovation_covariance.inverse();
// Update the state mean and covariance.
@@ -95,8 +89,8 @@ class KalmanFilter {
state->covariance;
}
- void Update(State *state,
- const Eigen::Matrix<T, K, 1> &measurement_mean) const {
+ void Update(State* state,
+ const Eigen::Matrix<T, K, 1>& measurement_mean) const {
Update(state, measurement_mean, default_measurement_covariance_);
}
diff --git a/intern/libmv/libmv/tracking/klt_region_tracker.cc b/intern/libmv/libmv/tracking/klt_region_tracker.cc
index dbbf9f0b996..df1ded65489 100644
--- a/intern/libmv/libmv/tracking/klt_region_tracker.cc
+++ b/intern/libmv/libmv/tracking/klt_region_tracker.cc
@@ -20,10 +20,10 @@
#include "libmv/tracking/klt_region_tracker.h"
-#include "libmv/logging/logging.h"
-#include "libmv/image/image.h"
#include "libmv/image/convolve.h"
+#include "libmv/image/image.h"
#include "libmv/image/sample.h"
+#include "libmv/logging/logging.h"
namespace libmv {
@@ -33,16 +33,18 @@ namespace libmv {
// TODO(keir): The calls to SampleLinear() do boundary checking that should
// instead happen outside the loop. Since this is the innermost loop, the extra
// bounds checking hurts performance.
-static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
- const Array3Df &image_and_gradient2,
- double x1, double y1,
- double x2, double y2,
+static void ComputeTrackingEquation(const Array3Df& image_and_gradient1,
+ const Array3Df& image_and_gradient2,
+ double x1,
+ double y1,
+ double x2,
+ double y2,
int half_width,
- float *gxx,
- float *gxy,
- float *gyy,
- float *ex,
- float *ey) {
+ float* gxx,
+ float* gxy,
+ float* gyy,
+ float* ex,
+ float* ey) {
*gxx = *gxy = *gyy = 0;
*ex = *ey = 0;
for (int r = -half_width; r <= half_width; ++r) {
@@ -51,8 +53,8 @@ static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
float yy1 = y1 + r;
float xx2 = x2 + c;
float yy2 = y2 + r;
- float I = SampleLinear(image_and_gradient1, yy1, xx1, 0);
- float J = SampleLinear(image_and_gradient2, yy2, xx2, 0);
+ float I = SampleLinear(image_and_gradient1, yy1, xx1, 0);
+ float J = SampleLinear(image_and_gradient2, yy2, xx2, 0);
float gx = SampleLinear(image_and_gradient2, yy2, xx2, 1);
float gy = SampleLinear(image_and_gradient2, yy2, xx2, 2);
*gxx += gx * gx;
@@ -64,22 +66,21 @@ static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
}
}
-static bool RegionIsInBounds(const FloatImage &image1,
- double x, double y,
- int half_window_size) {
+static bool RegionIsInBounds(const FloatImage& image1,
+ double x,
+ double y,
+ int half_window_size) {
// Check the minimum coordinates.
int min_x = floor(x) - half_window_size - 1;
int min_y = floor(y) - half_window_size - 1;
- if (min_x < 0.0 ||
- min_y < 0.0) {
+ if (min_x < 0.0 || min_y < 0.0) {
return false;
}
// Check the maximum coordinates.
int max_x = ceil(x) + half_window_size + 1;
int max_y = ceil(y) + half_window_size + 1;
- if (max_x > image1.cols() ||
- max_y > image1.rows()) {
+ if (max_x > image1.cols() || max_y > image1.rows()) {
return false;
}
@@ -87,10 +88,12 @@ static bool RegionIsInBounds(const FloatImage &image1,
return true;
}
-bool KltRegionTracker::Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const {
+bool KltRegionTracker::Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const {
if (!RegionIsInBounds(image1, x1, y1, half_window_size)) {
LG << "Fell out of image1's window with x1=" << x1 << ", y1=" << y1
<< ", hw=" << half_window_size << ".";
@@ -116,10 +119,16 @@ bool KltRegionTracker::Track(const FloatImage &image1,
float gxx, gxy, gyy, ex, ey;
ComputeTrackingEquation(image_and_gradient1,
image_and_gradient2,
- x1, y1,
- *x2, *y2,
+ x1,
+ y1,
+ *x2,
+ *y2,
half_window_size,
- &gxx, &gxy, &gyy, &ex, &ey);
+ &gxx,
+ &gxy,
+ &gyy,
+ &ex,
+ &ey);
// Solve the tracking equation
//
diff --git a/intern/libmv/libmv/tracking/klt_region_tracker.h b/intern/libmv/libmv/tracking/klt_region_tracker.h
index 43977757084..07ed1b7155c 100644
--- a/intern/libmv/libmv/tracking/klt_region_tracker.h
+++ b/intern/libmv/libmv/tracking/klt_region_tracker.h
@@ -37,10 +37,12 @@ struct KltRegionTracker : public RegionTracker {
virtual ~KltRegionTracker() {}
// Tracker interface.
- virtual bool Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const;
+ virtual bool Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const;
// No point in creating getters or setters.
int half_window_size;
diff --git a/intern/libmv/libmv/tracking/pyramid_region_tracker.cc b/intern/libmv/libmv/tracking/pyramid_region_tracker.cc
index 4db501050f3..52764a535e0 100644
--- a/intern/libmv/libmv/tracking/pyramid_region_tracker.cc
+++ b/intern/libmv/libmv/tracking/pyramid_region_tracker.cc
@@ -29,8 +29,9 @@
namespace libmv {
-static void MakePyramid(const FloatImage &image, int num_levels,
- std::vector<FloatImage> *pyramid) {
+static void MakePyramid(const FloatImage& image,
+ int num_levels,
+ std::vector<FloatImage>* pyramid) {
pyramid->resize(num_levels);
(*pyramid)[0] = image;
for (int i = 1; i < num_levels; ++i) {
@@ -38,10 +39,12 @@ static void MakePyramid(const FloatImage &image, int num_levels,
}
}
-bool PyramidRegionTracker::Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const {
+bool PyramidRegionTracker::Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const {
// Shrink the guessed x and y location to match the coarsest level + 1 (which
// when gets corrected in the loop).
*x2 /= pow(2., num_levels_);
@@ -71,8 +74,8 @@ bool PyramidRegionTracker::Track(const FloatImage &image1,
// Track the point on this level with the base tracker.
LG << "Tracking on level " << i;
- bool succeeded = tracker_->Track(pyramid1[i], pyramid2[i], xx, yy,
- &x2_new, &y2_new);
+ bool succeeded =
+ tracker_->Track(pyramid1[i], pyramid2[i], xx, yy, &x2_new, &y2_new);
if (!succeeded) {
if (i == 0) {
diff --git a/intern/libmv/libmv/tracking/pyramid_region_tracker.h b/intern/libmv/libmv/tracking/pyramid_region_tracker.h
index 1f9675469f4..5fe21c95904 100644
--- a/intern/libmv/libmv/tracking/pyramid_region_tracker.h
+++ b/intern/libmv/libmv/tracking/pyramid_region_tracker.h
@@ -21,21 +21,24 @@
#ifndef LIBMV_CORRESPONDENCE_PYRAMID_TRACKER_H_
#define LIBMV_CORRESPONDENCE_PYRAMID_TRACKER_H_
-#include "libmv/image/image.h"
#include "libmv/base/scoped_ptr.h"
+#include "libmv/image/image.h"
#include "libmv/tracking/region_tracker.h"
namespace libmv {
class PyramidRegionTracker : public RegionTracker {
public:
- PyramidRegionTracker(RegionTracker *tracker, int num_levels)
+ PyramidRegionTracker(RegionTracker* tracker, int num_levels)
: tracker_(tracker), num_levels_(num_levels) {}
- virtual bool Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const;
+ virtual bool Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const;
+
private:
scoped_ptr<RegionTracker> tracker_;
int num_levels_;
diff --git a/intern/libmv/libmv/tracking/pyramid_region_tracker_test.cc b/intern/libmv/libmv/tracking/pyramid_region_tracker_test.cc
index d90a1012237..2fcf292e404 100644
--- a/intern/libmv/libmv/tracking/pyramid_region_tracker_test.cc
+++ b/intern/libmv/libmv/tracking/pyramid_region_tracker_test.cc
@@ -19,8 +19,8 @@
// IN THE SOFTWARE.
#include "libmv/tracking/pyramid_region_tracker.h"
-#include "libmv/tracking/klt_region_tracker.h"
#include "libmv/image/image.h"
+#include "libmv/tracking/klt_region_tracker.h"
#include "testing/testing.h"
namespace libmv {
@@ -55,8 +55,7 @@ TEST(PyramidKltRegionTracker, Track) {
KltRegionTracker tracker;
tracker.half_window_size = half_window_size;
- EXPECT_FALSE(tracker.Track(image1, image2, x1, y1,
- &x2_actual, &y2_actual));
+ EXPECT_FALSE(tracker.Track(image1, image2, x1, y1, &x2_actual, &y2_actual));
}
// Verify that it works with the pyramid tracker.
@@ -64,12 +63,11 @@ TEST(PyramidKltRegionTracker, Track) {
double x2_actual = x1;
double y2_actual = y1;
- KltRegionTracker *klt_tracker = new KltRegionTracker;
+ KltRegionTracker* klt_tracker = new KltRegionTracker;
klt_tracker->half_window_size = half_window_size;
PyramidRegionTracker tracker(klt_tracker, 3);
- EXPECT_TRUE(tracker.Track(image1, image2, x1, y1,
- &x2_actual, &y2_actual));
+ EXPECT_TRUE(tracker.Track(image1, image2, x1, y1, &x2_actual, &y2_actual));
EXPECT_NEAR(x2_actual, x2, 0.001);
EXPECT_NEAR(y2_actual, y2, 0.001);
diff --git a/intern/libmv/libmv/tracking/region_tracker.h b/intern/libmv/libmv/tracking/region_tracker.h
index 4f7574df1a3..e753ac8be6c 100644
--- a/intern/libmv/libmv/tracking/region_tracker.h
+++ b/intern/libmv/libmv/tracking/region_tracker.h
@@ -37,10 +37,12 @@ class RegionTracker {
image2. If no guess is available, (\a x1, \a y1) is a good start. Returns
true on success, false otherwise
*/
- virtual bool Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const = 0;
+ virtual bool Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const = 0;
};
} // namespace libmv
diff --git a/intern/libmv/libmv/tracking/retrack_region_tracker.cc b/intern/libmv/libmv/tracking/retrack_region_tracker.cc
index 4d230086d28..9152078053c 100644
--- a/intern/libmv/libmv/tracking/retrack_region_tracker.cc
+++ b/intern/libmv/libmv/tracking/retrack_region_tracker.cc
@@ -25,10 +25,12 @@
namespace libmv {
-bool RetrackRegionTracker::Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const {
+bool RetrackRegionTracker::Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const {
// Track forward, getting x2 and y2.
if (!tracker_->Track(image1, image2, x1, y1, x2, y2)) {
return false;
diff --git a/intern/libmv/libmv/tracking/retrack_region_tracker.h b/intern/libmv/libmv/tracking/retrack_region_tracker.h
index ab05f320834..504cf697349 100644
--- a/intern/libmv/libmv/tracking/retrack_region_tracker.h
+++ b/intern/libmv/libmv/tracking/retrack_region_tracker.h
@@ -21,8 +21,8 @@
#ifndef LIBMV_TRACKING_RETRACK_REGION_TRACKER_H_
#define LIBMV_TRACKING_RETRACK_REGION_TRACKER_H_
-#include "libmv/image/image.h"
#include "libmv/base/scoped_ptr.h"
+#include "libmv/image/image.h"
#include "libmv/tracking/region_tracker.h"
namespace libmv {
@@ -31,13 +31,16 @@ namespace libmv {
// track that doesn't track backwards to the starting point.
class RetrackRegionTracker : public RegionTracker {
public:
- RetrackRegionTracker(RegionTracker *tracker, double tolerance)
+ RetrackRegionTracker(RegionTracker* tracker, double tolerance)
: tracker_(tracker), tolerance_(tolerance) {}
- virtual bool Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const;
+ virtual bool Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const;
+
private:
scoped_ptr<RegionTracker> tracker_;
double tolerance_;
diff --git a/intern/libmv/libmv/tracking/track_region.cc b/intern/libmv/libmv/tracking/track_region.cc
index 895c9a1e23d..403b4088174 100644
--- a/intern/libmv/libmv/tracking/track_region.cc
+++ b/intern/libmv/libmv/tracking/track_region.cc
@@ -27,14 +27,14 @@
#include "libmv/tracking/track_region.h"
-#include <Eigen/SVD>
#include <Eigen/QR>
+#include <Eigen/SVD>
#include <iostream>
#include "ceres/ceres.h"
-#include "libmv/logging/logging.h"
+#include "libmv/image/convolve.h"
#include "libmv/image/image.h"
#include "libmv/image/sample.h"
-#include "libmv/image/convolve.h"
+#include "libmv/logging/logging.h"
#include "libmv/multiview/homography.h"
#include "libmv/numeric/numeric.h"
@@ -44,57 +44,45 @@
namespace ceres {
// A jet traits class to make it easier to work with mixed auto / numeric diff.
-template<typename T>
+template <typename T>
struct JetOps {
- static bool IsScalar() {
- return true;
- }
- static T GetScalar(const T& t) {
- return t;
- }
- static void SetScalar(const T& scalar, T* t) {
- *t = scalar;
- }
- static void ScaleDerivative(double scale_by, T *value) {
+ static bool IsScalar() { return true; }
+ static T GetScalar(const T& t) { return t; }
+ static void SetScalar(const T& scalar, T* t) { *t = scalar; }
+ static void ScaleDerivative(double scale_by, T* value) {
// For double, there is no derivative to scale.
- (void) scale_by; // Ignored.
- (void) value; // Ignored.
+ (void)scale_by; // Ignored.
+ (void)value; // Ignored.
}
};
-template<typename T, int N>
-struct JetOps<Jet<T, N> > {
- static bool IsScalar() {
- return false;
- }
- static T GetScalar(const Jet<T, N>& t) {
- return t.a;
- }
- static void SetScalar(const T& scalar, Jet<T, N>* t) {
- t->a = scalar;
- }
- static void ScaleDerivative(double scale_by, Jet<T, N> *value) {
+template <typename T, int N>
+struct JetOps<Jet<T, N>> {
+ static bool IsScalar() { return false; }
+ static T GetScalar(const Jet<T, N>& t) { return t.a; }
+ static void SetScalar(const T& scalar, Jet<T, N>* t) { t->a = scalar; }
+ static void ScaleDerivative(double scale_by, Jet<T, N>* value) {
value->v *= scale_by;
}
};
-template<typename FunctionType, int kNumArgs, typename ArgumentType>
+template <typename FunctionType, int kNumArgs, typename ArgumentType>
struct Chain {
- static ArgumentType Rule(const FunctionType &f,
+ static ArgumentType Rule(const FunctionType& f,
const FunctionType dfdx[kNumArgs],
const ArgumentType x[kNumArgs]) {
// In the default case of scalars, there's nothing to do since there are no
// derivatives to propagate.
- (void) dfdx; // Ignored.
- (void) x; // Ignored.
+ (void)dfdx; // Ignored.
+ (void)x; // Ignored.
return f;
}
};
// XXX Add documentation here!
-template<typename FunctionType, int kNumArgs, typename T, int N>
-struct Chain<FunctionType, kNumArgs, Jet<T, N> > {
- static Jet<T, N> Rule(const FunctionType &f,
+template <typename FunctionType, int kNumArgs, typename T, int N>
+struct Chain<FunctionType, kNumArgs, Jet<T, N>> {
+ static Jet<T, N> Rule(const FunctionType& f,
const FunctionType dfdx[kNumArgs],
const Jet<T, N> x[kNumArgs]) {
// x is itself a function of another variable ("z"); what this function
@@ -107,8 +95,8 @@ struct Chain<FunctionType, kNumArgs, Jet<T, N> > {
}
// Map the input gradient dfdx into an Eigen row vector.
- Eigen::Map<const Eigen::Matrix<FunctionType, 1, kNumArgs> >
- vector_dfdx(dfdx, 1, kNumArgs);
+ Eigen::Map<const Eigen::Matrix<FunctionType, 1, kNumArgs>> vector_dfdx(
+ dfdx, 1, kNumArgs);
// Now apply the chain rule to obtain df/dz. Combine the derivative with
// the scalar part to obtain f with full derivative information.
@@ -123,9 +111,9 @@ struct Chain<FunctionType, kNumArgs, Jet<T, N> > {
namespace libmv {
+using ceres::Chain;
using ceres::Jet;
using ceres::JetOps;
-using ceres::Chain;
TrackRegionOptions::TrackRegionOptions()
: mode(TRANSLATION),
@@ -144,17 +132,12 @@ TrackRegionOptions::TrackRegionOptions()
namespace {
// TODO(keir): Consider adding padding.
-template<typename T>
-bool InBounds(const FloatImage &image,
- const T &x,
- const T &y) {
- return 0.0 <= x && x < image.Width() &&
- 0.0 <= y && y < image.Height();
+template <typename T>
+bool InBounds(const FloatImage& image, const T& x, const T& y) {
+ return 0.0 <= x && x < image.Width() && 0.0 <= y && y < image.Height();
}
-bool AllInBounds(const FloatImage &image,
- const double *x,
- const double *y) {
+bool AllInBounds(const FloatImage& image, const double* x, const double* y) {
for (int i = 0; i < 4; ++i) {
if (!InBounds(image, x[i], y[i])) {
return false;
@@ -166,10 +149,10 @@ bool AllInBounds(const FloatImage &image,
// Sample the image at position (x, y) but use the gradient, if present, to
// propagate derivatives from x and y. This is needed to integrate the numeric
// image gradients with Ceres's autodiff framework.
-template<typename T>
-static T SampleWithDerivative(const FloatImage &image_and_gradient,
- const T &x,
- const T &y) {
+template <typename T>
+static T SampleWithDerivative(const FloatImage& image_and_gradient,
+ const T& x,
+ const T& y) {
float scalar_x = JetOps<T>::GetScalar(x);
float scalar_y = JetOps<T>::GetScalar(y);
@@ -184,18 +167,23 @@ static T SampleWithDerivative(const FloatImage &image_and_gradient,
// For the derivative case, sample the gradient as well.
SampleLinear(image_and_gradient, scalar_y, scalar_x, sample);
}
- T xy[2] = { x, y };
+ T xy[2] = {x, y};
return Chain<float, 2, T>::Rule(sample[0], sample + 1, xy);
}
-template<typename Warp>
+template <typename Warp>
class TerminationCheckingCallback : public ceres::IterationCallback {
public:
- TerminationCheckingCallback(const TrackRegionOptions &options,
+ TerminationCheckingCallback(const TrackRegionOptions& options,
const FloatImage& image2,
- const Warp &warp,
- const double *x1, const double *y1)
- : options_(options), image2_(image2), warp_(warp), x1_(x1), y1_(y1),
+ const Warp& warp,
+ const double* x1,
+ const double* y1)
+ : options_(options),
+ image2_(image2),
+ warp_(warp),
+ x1_(x1),
+ y1_(y1),
have_last_successful_step_(false) {}
virtual ceres::CallbackReturnType operator()(
@@ -229,7 +217,7 @@ class TerminationCheckingCallback : public ceres::IterationCallback {
for (int i = 0; i < 4; ++i) {
double dx = x2[i] - x2_last_successful_[i];
double dy = y2[i] - y2_last_successful_[i];
- double change_pixels = dx*dx + dy*dy;
+ double change_pixels = dx * dx + dy * dy;
if (change_pixels > max_change_pixels) {
max_change_pixels = change_pixels;
}
@@ -255,27 +243,27 @@ class TerminationCheckingCallback : public ceres::IterationCallback {
}
private:
- const TrackRegionOptions &options_;
- const FloatImage &image2_;
- const Warp &warp_;
- const double *x1_;
- const double *y1_;
+ const TrackRegionOptions& options_;
+ const FloatImage& image2_;
+ const Warp& warp_;
+ const double* x1_;
+ const double* y1_;
bool have_last_successful_step_;
double x2_last_successful_[4];
double y2_last_successful_[4];
};
-template<typename Warp>
+template <typename Warp>
class PixelDifferenceCostFunctor {
public:
- PixelDifferenceCostFunctor(const TrackRegionOptions &options,
- const FloatImage &image_and_gradient1,
- const FloatImage &image_and_gradient2,
- const Mat3 &canonical_to_image1,
+ PixelDifferenceCostFunctor(const TrackRegionOptions& options,
+ const FloatImage& image_and_gradient1,
+ const FloatImage& image_and_gradient2,
+ const Mat3& canonical_to_image1,
int num_samples_x,
int num_samples_y,
- const Warp &warp)
+ const Warp& warp)
: options_(options),
image_and_gradient1_(image_and_gradient1),
image_and_gradient2_(image_and_gradient2),
@@ -322,8 +310,8 @@ class PixelDifferenceCostFunctor {
src_mean_ /= num_samples;
}
- template<typename T>
- bool operator()(const T *warp_parameters, T *residuals) const {
+ template <typename T>
+ bool operator()(const T* warp_parameters, T* residuals) const {
if (options_.image1_mask != NULL) {
VLOG(2) << "Using a mask.";
}
@@ -333,8 +321,7 @@ class PixelDifferenceCostFunctor {
T dst_mean = T(1.0);
if (options_.use_normalized_intensities) {
- ComputeNormalizingCoefficient(warp_parameters,
- &dst_mean);
+ ComputeNormalizingCoefficient(warp_parameters, &dst_mean);
}
int cursor = 0;
@@ -374,9 +361,8 @@ class PixelDifferenceCostFunctor {
&image2_position[1]);
// Sample the destination, propagating derivatives.
- T dst_sample = SampleWithDerivative(image_and_gradient2_,
- image2_position[0],
- image2_position[1]);
+ T dst_sample = SampleWithDerivative(
+ image_and_gradient2_, image2_position[0], image2_position[1]);
// Sample the source. This is made complicated by ESM mode.
T src_sample;
@@ -386,8 +372,8 @@ class PixelDifferenceCostFunctor {
// better convergence. Copy the derivative of the warp parameters
// onto the jets for the image1 position. This is the ESM hack.
T image1_position_jet[2] = {
- image2_position[0], // Order is x, y. This matches the
- image2_position[1] // derivative order in the patch.
+ image2_position[0], // Order is x, y. This matches the
+ image2_position[1] // derivative order in the patch.
};
JetOps<T>::SetScalar(image1_position[0], image1_position_jet + 0);
JetOps<T>::SetScalar(image1_position[1], image1_position_jet + 1);
@@ -433,9 +419,9 @@ class PixelDifferenceCostFunctor {
}
// For normalized matching, the average and
- template<typename T>
- void ComputeNormalizingCoefficient(const T *warp_parameters,
- T *dst_mean) const {
+ template <typename T>
+ void ComputeNormalizingCoefficient(const T* warp_parameters,
+ T* dst_mean) const {
*dst_mean = T(0.0);
double num_samples = 0.0;
for (int r = 0; r < num_samples_y_; ++r) {
@@ -462,14 +448,12 @@ class PixelDifferenceCostFunctor {
&image2_position[0],
&image2_position[1]);
-
// Sample the destination, propagating derivatives.
// TODO(keir): This accumulation can, surprisingly, be done as a
// pre-pass by using integral images. This is complicated by the need
// to store the jets in the integral image, but it is possible.
- T dst_sample = SampleWithDerivative(image_and_gradient2_,
- image2_position[0],
- image2_position[1]);
+ T dst_sample = SampleWithDerivative(
+ image_and_gradient2_, image2_position[0], image2_position[1]);
// Weight the sample by the mask, if one is present.
if (options_.image1_mask != NULL) {
@@ -486,10 +470,10 @@ class PixelDifferenceCostFunctor {
// TODO(keir): Consider also computing the cost here.
double PearsonProductMomentCorrelationCoefficient(
- const double *warp_parameters) const {
+ const double* warp_parameters) const {
for (int i = 0; i < Warp::NUM_PARAMETERS; ++i) {
- VLOG(2) << "Correlation warp_parameters[" << i << "]: "
- << warp_parameters[i];
+ VLOG(2) << "Correlation warp_parameters[" << i
+ << "]: " << warp_parameters[i];
}
// The single-pass PMCC computation is somewhat numerically unstable, but
@@ -537,9 +521,9 @@ class PixelDifferenceCostFunctor {
}
sX += x;
sY += y;
- sXX += x*x;
- sYY += y*y;
- sXY += x*y;
+ sXX += x * x;
+ sYY += y * y;
+ sXY += x * y;
}
}
// Normalize.
@@ -549,25 +533,24 @@ class PixelDifferenceCostFunctor {
sYY /= num_samples;
sXY /= num_samples;
- double var_x = sXX - sX*sX;
- double var_y = sYY - sY*sY;
- double covariance_xy = sXY - sX*sY;
+ double var_x = sXX - sX * sX;
+ double var_y = sYY - sY * sY;
+ double covariance_xy = sXY - sX * sY;
double correlation = covariance_xy / sqrt(var_x * var_y);
- LG << "Covariance xy: " << covariance_xy
- << ", var 1: " << var_x << ", var 2: " << var_y
- << ", correlation: " << correlation;
+ LG << "Covariance xy: " << covariance_xy << ", var 1: " << var_x
+ << ", var 2: " << var_y << ", correlation: " << correlation;
return correlation;
}
private:
- const TrackRegionOptions &options_;
- const FloatImage &image_and_gradient1_;
- const FloatImage &image_and_gradient2_;
- const Mat3 &canonical_to_image1_;
+ const TrackRegionOptions& options_;
+ const FloatImage& image_and_gradient1_;
+ const FloatImage& image_and_gradient2_;
+ const Mat3& canonical_to_image1_;
int num_samples_x_;
int num_samples_y_;
- const Warp &warp_;
+ const Warp& warp_;
double src_mean_;
FloatImage pattern_and_gradient_;
@@ -579,15 +562,15 @@ class PixelDifferenceCostFunctor {
FloatImage pattern_mask_;
};
-template<typename Warp>
+template <typename Warp>
class WarpRegularizingCostFunctor {
public:
- WarpRegularizingCostFunctor(const TrackRegionOptions &options,
- const double *x1,
- const double *y1,
- const double *x2_original,
- const double *y2_original,
- const Warp &warp)
+ WarpRegularizingCostFunctor(const TrackRegionOptions& options,
+ const double* x1,
+ const double* y1,
+ const double* x2_original,
+ const double* y2_original,
+ const Warp& warp)
: options_(options),
x1_(x1),
y1_(y1),
@@ -606,11 +589,11 @@ class WarpRegularizingCostFunctor {
original_centroid_[1] /= 4;
}
- template<typename T>
- bool operator()(const T *warp_parameters, T *residuals) const {
- T dst_centroid[2] = { T(0.0), T(0.0) };
+ template <typename T>
+ bool operator()(const T* warp_parameters, T* residuals) const {
+ T dst_centroid[2] = {T(0.0), T(0.0)};
for (int i = 0; i < 4; ++i) {
- T image1_position[2] = { T(x1_[i]), T(y1_[i]) };
+ T image1_position[2] = {T(x1_[i]), T(y1_[i])};
T image2_position[2];
warp_.Forward(warp_parameters,
T(x1_[i]),
@@ -643,28 +626,30 @@ class WarpRegularizingCostFunctor {
return true;
}
- const TrackRegionOptions &options_;
- const double *x1_;
- const double *y1_;
- const double *x2_original_;
- const double *y2_original_;
+ const TrackRegionOptions& options_;
+ const double* x1_;
+ const double* y1_;
+ const double* x2_original_;
+ const double* y2_original_;
double original_centroid_[2];
- const Warp &warp_;
+ const Warp& warp_;
};
// Compute the warp from rectangular coordinates, where one corner is the
// origin, and the opposite corner is at (num_samples_x, num_samples_y).
-Mat3 ComputeCanonicalHomography(const double *x1,
- const double *y1,
+Mat3 ComputeCanonicalHomography(const double* x1,
+ const double* y1,
int num_samples_x,
int num_samples_y) {
Mat canonical(2, 4);
- canonical << 0, num_samples_x, num_samples_x, 0,
- 0, 0, num_samples_y, num_samples_y;
+ canonical << 0, num_samples_x, num_samples_x, 0, 0, 0, num_samples_y,
+ num_samples_y;
Mat xy1(2, 4);
+ // clang-format off
xy1 << x1[0], x1[1], x1[2], x1[3],
y1[0], y1[1], y1[2], y1[3];
+ // clang-format om
Mat3 H;
if (!Homography2DFromCorrespondencesLinear(canonical, xy1, &H, 1e-12)) {
@@ -675,7 +660,7 @@ Mat3 ComputeCanonicalHomography(const double *x1,
class Quad {
public:
- Quad(const double *x, const double *y) : x_(x), y_(y) {
+ Quad(const double* x, const double* y) : x_(x), y_(y) {
// Compute the centroid and store it.
centroid_ = Vec2(0.0, 0.0);
for (int i = 0; i < 4; ++i) {
@@ -685,9 +670,7 @@ class Quad {
}
// The centroid of the four points representing the quad.
- const Vec2& Centroid() const {
- return centroid_;
- }
+ const Vec2& Centroid() const { return centroid_; }
// The average magnitude of the four points relative to the centroid.
double Scale() const {
@@ -703,22 +686,24 @@ class Quad {
}
private:
- const double *x_;
- const double *y_;
+ const double* x_;
+ const double* y_;
Vec2 centroid_;
};
struct TranslationWarp {
- TranslationWarp(const double *x1, const double *y1,
- const double *x2, const double *y2) {
+ TranslationWarp(const double* x1,
+ const double* y1,
+ const double* x2,
+ const double* y2) {
Vec2 t = Quad(x2, y2).Centroid() - Quad(x1, y1).Centroid();
parameters[0] = t[0];
parameters[1] = t[1];
}
- template<typename T>
- void Forward(const T *warp_parameters,
- const T &x1, const T& y1, T *x2, T* y2) const {
+ template <typename T>
+ void Forward(
+ const T* warp_parameters, const T& x1, const T& y1, T* x2, T* y2) const {
*x2 = x1 + warp_parameters[0];
*y2 = y1 + warp_parameters[1];
}
@@ -729,8 +714,10 @@ struct TranslationWarp {
};
struct TranslationScaleWarp {
- TranslationScaleWarp(const double *x1, const double *y1,
- const double *x2, const double *y2)
+ TranslationScaleWarp(const double* x1,
+ const double* y1,
+ const double* x2,
+ const double* y2)
: q1(x1, y1) {
Quad q2(x2, y2);
@@ -746,9 +733,9 @@ struct TranslationScaleWarp {
// The strange way of parameterizing the translation and scaling is to make
// the knobs that the optimizer sees easy to adjust. This is less important
// for the scaling case than the rotation case.
- template<typename T>
- void Forward(const T *warp_parameters,
- const T &x1, const T& y1, T *x2, T* y2) const {
+ template <typename T>
+ void Forward(
+ const T* warp_parameters, const T& x1, const T& y1, T* x2, T* y2) const {
// Make the centroid of Q1 the origin.
const T x1_origin = x1 - q1.Centroid()(0);
const T y1_origin = y1 - q1.Centroid()(1);
@@ -775,15 +762,17 @@ struct TranslationScaleWarp {
};
// Assumes the given points are already zero-centroid and the same size.
-Mat2 OrthogonalProcrustes(const Mat2 &correlation_matrix) {
+Mat2 OrthogonalProcrustes(const Mat2& correlation_matrix) {
Eigen::JacobiSVD<Mat2> svd(correlation_matrix,
Eigen::ComputeFullU | Eigen::ComputeFullV);
return svd.matrixV() * svd.matrixU().transpose();
}
struct TranslationRotationWarp {
- TranslationRotationWarp(const double *x1, const double *y1,
- const double *x2, const double *y2)
+ TranslationRotationWarp(const double* x1,
+ const double* y1,
+ const double* x2,
+ const double* y2)
: q1(x1, y1) {
Quad q2(x2, y2);
@@ -816,9 +805,9 @@ struct TranslationRotationWarp {
//
// Instead, use the parameterization below that offers a parameterization
// that exposes the degrees of freedom in a way amenable to optimization.
- template<typename T>
- void Forward(const T *warp_parameters,
- const T &x1, const T& y1, T *x2, T* y2) const {
+ template <typename T>
+ void Forward(
+ const T* warp_parameters, const T& x1, const T& y1, T* x2, T* y2) const {
// Make the centroid of Q1 the origin.
const T x1_origin = x1 - q1.Centroid()(0);
const T y1_origin = y1 - q1.Centroid()(1);
@@ -847,8 +836,10 @@ struct TranslationRotationWarp {
};
struct TranslationRotationScaleWarp {
- TranslationRotationScaleWarp(const double *x1, const double *y1,
- const double *x2, const double *y2)
+ TranslationRotationScaleWarp(const double* x1,
+ const double* y1,
+ const double* x2,
+ const double* y2)
: q1(x1, y1) {
Quad q2(x2, y2);
@@ -884,9 +875,9 @@ struct TranslationRotationScaleWarp {
//
// Instead, use the parameterization below that offers a parameterization
// that exposes the degrees of freedom in a way amenable to optimization.
- template<typename T>
- void Forward(const T *warp_parameters,
- const T &x1, const T& y1, T *x2, T* y2) const {
+ template <typename T>
+ void Forward(
+ const T* warp_parameters, const T& x1, const T& y1, T* x2, T* y2) const {
// Make the centroid of Q1 the origin.
const T x1_origin = x1 - q1.Centroid()(0);
const T y1_origin = y1 - q1.Centroid()(1);
@@ -921,8 +912,10 @@ struct TranslationRotationScaleWarp {
};
struct AffineWarp {
- AffineWarp(const double *x1, const double *y1,
- const double *x2, const double *y2)
+ AffineWarp(const double* x1,
+ const double* y1,
+ const double* x2,
+ const double* y2)
: q1(x1, y1) {
Quad q2(x2, y2);
@@ -938,8 +931,8 @@ struct AffineWarp {
Vec2 v1 = q1.CornerRelativeToCentroid(i);
Vec2 v2 = q2.CornerRelativeToCentroid(i);
- Q1.row(2 * i + 0) << v1[0], v1[1], 0, 0;
- Q1.row(2 * i + 1) << 0, 0, v1[0], v1[1];
+ Q1.row(2 * i + 0) << v1[0], v1[1], 0, 0;
+ Q1.row(2 * i + 1) << 0, 0, v1[0], v1[1];
Q2(2 * i + 0) = v2[0];
Q2(2 * i + 1) = v2[1];
@@ -957,8 +950,8 @@ struct AffineWarp {
}
// See comments in other parameterizations about why the centroid is used.
- template<typename T>
- void Forward(const T *p, const T &x1, const T& y1, T *x2, T* y2) const {
+ template <typename T>
+ void Forward(const T* p, const T& x1, const T& y1, T* x2, T* y2) const {
// Make the centroid of Q1 the origin.
const T x1_origin = x1 - q1.Centroid()(0);
const T y1_origin = y1 - q1.Centroid()(1);
@@ -985,15 +978,21 @@ struct AffineWarp {
};
struct HomographyWarp {
- HomographyWarp(const double *x1, const double *y1,
- const double *x2, const double *y2) {
+ HomographyWarp(const double* x1,
+ const double* y1,
+ const double* x2,
+ const double* y2) {
Mat quad1(2, 4);
+ // clang-format off
quad1 << x1[0], x1[1], x1[2], x1[3],
y1[0], y1[1], y1[2], y1[3];
+ // clang-format on
Mat quad2(2, 4);
+ // clang-format off
quad2 << x2[0], x2[1], x2[2], x2[3],
y2[0], y2[1], y2[2], y2[3];
+ // clang-format on
Mat3 H;
if (!Homography2DFromCorrespondencesLinear(quad1, quad2, &H, 1e-12)) {
@@ -1014,13 +1013,12 @@ struct HomographyWarp {
}
}
- template<typename T>
- static void Forward(const T *p,
- const T &x1, const T& y1, T *x2, T* y2) {
+ template <typename T>
+ static void Forward(const T* p, const T& x1, const T& y1, T* x2, T* y2) {
// Homography warp with manual 3x3 matrix multiply.
- const T xx2 = (1.0 + p[0]) * x1 + p[1] * y1 + p[2];
- const T yy2 = p[3] * x1 + (1.0 + p[4]) * y1 + p[5];
- const T zz2 = p[6] * x1 + p[7] * y1 + 1.0;
+ const T xx2 = (1.0 + p[0]) * x1 + p[1] * y1 + p[2];
+ const T yy2 = p[3] * x1 + (1.0 + p[4]) * y1 + p[5];
+ const T zz2 = p[6] * x1 + p[7] * y1 + 1.0;
*x2 = xx2 / zz2;
*y2 = yy2 / zz2;
}
@@ -1036,11 +1034,14 @@ struct HomographyWarp {
//
// The idea is to take the maximum x or y distance. This may be oversampling.
// TODO(keir): Investigate the various choices; perhaps average is better?
-void PickSampling(const double *x1, const double *y1,
- const double *x2, const double *y2,
- int *num_samples_x, int *num_samples_y) {
- (void) x2; // Ignored.
- (void) y2; // Ignored.
+void PickSampling(const double* x1,
+ const double* y1,
+ const double* x2,
+ const double* y2,
+ int* num_samples_x,
+ int* num_samples_y) {
+ (void)x2; // Ignored.
+ (void)y2; // Ignored.
Vec2 a0(x1[0], y1[0]);
Vec2 a1(x1[1], y1[1]);
@@ -1053,18 +1054,10 @@ void PickSampling(const double *x1, const double *y1,
Vec2 b3(x1[3], y1[3]);
double x_dimensions[4] = {
- (a1 - a0).norm(),
- (a3 - a2).norm(),
- (b1 - b0).norm(),
- (b3 - b2).norm()
- };
+ (a1 - a0).norm(), (a3 - a2).norm(), (b1 - b0).norm(), (b3 - b2).norm()};
double y_dimensions[4] = {
- (a3 - a0).norm(),
- (a1 - a2).norm(),
- (b3 - b0).norm(),
- (b1 - b2).norm()
- };
+ (a3 - a0).norm(), (a1 - a2).norm(), (b3 - b0).norm(), (b1 - b2).norm()};
const double kScaleFactor = 1.0;
*num_samples_x = static_cast<int>(
kScaleFactor * *std::max_element(x_dimensions, x_dimensions + 4));
@@ -1074,17 +1067,18 @@ void PickSampling(const double *x1, const double *y1,
<< ", num_samples_y: " << *num_samples_y;
}
-bool SearchAreaTooBigForDescent(const FloatImage &image2,
- const double *x2, const double *y2) {
+bool SearchAreaTooBigForDescent(const FloatImage& image2,
+ const double* x2,
+ const double* y2) {
// TODO(keir): Check the bounds and enable only when it makes sense.
- (void) image2; // Ignored.
- (void) x2; // Ignored.
- (void) y2; // Ignored.
+ (void)image2; // Ignored.
+ (void)x2; // Ignored.
+ (void)y2; // Ignored.
return true;
}
-bool PointOnRightHalfPlane(const Vec2 &a, const Vec2 &b, double x, double y) {
+bool PointOnRightHalfPlane(const Vec2& a, const Vec2& b, double x, double y) {
Vec2 ba = b - a;
return ((Vec2(x, y) - b).transpose() * Vec2(-ba.y(), ba.x())) > 0;
}
@@ -1102,7 +1096,7 @@ bool PointOnRightHalfPlane(const Vec2 &a, const Vec2 &b, double x, double y) {
// y
//
// The implementation does up to four half-plane comparisons.
-bool PointInQuad(const double *xs, const double *ys, double x, double y) {
+bool PointInQuad(const double* xs, const double* ys, double x, double y) {
Vec2 a0(xs[0], ys[0]);
Vec2 a1(xs[1], ys[1]);
Vec2 a2(xs[2], ys[2]);
@@ -1116,24 +1110,27 @@ bool PointInQuad(const double *xs, const double *ys, double x, double y) {
// This makes it possible to map between Eigen float arrays and FloatImage
// without using comparisons.
-typedef Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> FloatArray;
+typedef Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
+ FloatArray;
// This creates a pattern in the frame of image2, from the pixel is image1,
// based on the initial guess represented by the two quads x1, y1, and x2, y2.
-template<typename Warp>
-void CreateBrutePattern(const double *x1, const double *y1,
- const double *x2, const double *y2,
- const FloatImage &image1,
- const FloatImage *image1_mask,
- FloatArray *pattern,
- FloatArray *mask,
- int *origin_x,
- int *origin_y) {
+template <typename Warp>
+void CreateBrutePattern(const double* x1,
+ const double* y1,
+ const double* x2,
+ const double* y2,
+ const FloatImage& image1,
+ const FloatImage* image1_mask,
+ FloatArray* pattern,
+ FloatArray* mask,
+ int* origin_x,
+ int* origin_y) {
// Get integer bounding box of quad2 in image2.
int min_x = static_cast<int>(floor(*std::min_element(x2, x2 + 4)));
int min_y = static_cast<int>(floor(*std::min_element(y2, y2 + 4)));
- int max_x = static_cast<int>(ceil (*std::max_element(x2, x2 + 4)));
- int max_y = static_cast<int>(ceil (*std::max_element(y2, y2 + 4)));
+ int max_x = static_cast<int>(ceil(*std::max_element(x2, x2 + 4)));
+ int max_y = static_cast<int>(ceil(*std::max_element(y2, y2 + 4)));
int w = max_x - min_x;
int h = max_y - min_y;
@@ -1154,9 +1151,8 @@ void CreateBrutePattern(const double *x1, const double *y1,
double dst_y = r;
double src_x;
double src_y;
- inverse_warp.Forward(inverse_warp.parameters,
- dst_x, dst_y,
- &src_x, &src_y);
+ inverse_warp.Forward(
+ inverse_warp.parameters, dst_x, dst_y, &src_x, &src_y);
if (PointInQuad(x1, y1, src_x, src_y)) {
(*pattern)(i, j) = SampleLinear(image1, src_y, src_x);
@@ -1191,24 +1187,32 @@ void CreateBrutePattern(const double *x1, const double *y1,
// pattern, when doing brute initialization. Unfortunately that implies a
// totally different warping interface, since access to more than a the source
// and current destination frame is necessary.
-template<typename Warp>
-bool BruteTranslationOnlyInitialize(const FloatImage &image1,
- const FloatImage *image1_mask,
- const FloatImage &image2,
+template <typename Warp>
+bool BruteTranslationOnlyInitialize(const FloatImage& image1,
+ const FloatImage* image1_mask,
+ const FloatImage& image2,
const int num_extra_points,
const bool use_normalized_intensities,
- const double *x1, const double *y1,
- double *x2, double *y2) {
+ const double* x1,
+ const double* y1,
+ double* x2,
+ double* y2) {
// Create the pattern to match in the space of image2, assuming our inital
// guess isn't too far from the template in image1. If there is no image1
// mask, then the resulting mask is binary.
FloatArray pattern;
FloatArray mask;
int origin_x = -1, origin_y = -1;
- CreateBrutePattern<Warp>(x1, y1, x2, y2,
- image1, image1_mask,
- &pattern, &mask,
- &origin_x, &origin_y);
+ CreateBrutePattern<Warp>(x1,
+ y1,
+ x2,
+ y2,
+ image1,
+ image1_mask,
+ &pattern,
+ &mask,
+ &origin_x,
+ &origin_y);
// For normalization, premultiply the pattern by the inverse pattern mean.
double mask_sum = 1.0;
@@ -1251,8 +1255,10 @@ bool BruteTranslationOnlyInitialize(const FloatImage &image1,
// instead, reducing the mean calculation to an O(1) operation.
double inverse_search_mean =
mask_sum / ((mask * search.block(r, c, h, w)).sum());
- sad = (mask * (pattern - (search.block(r, c, h, w) *
- inverse_search_mean))).abs().sum();
+ sad = (mask *
+ (pattern - (search.block(r, c, h, w) * inverse_search_mean)))
+ .abs()
+ .sum();
} else {
sad = (mask * (pattern - search.block(r, c, h, w))).abs().sum();
}
@@ -1274,9 +1280,8 @@ bool BruteTranslationOnlyInitialize(const FloatImage &image1,
<< "best_c: " << best_c << ", best_r: " << best_r << ", "
<< "origin_x: " << origin_x << ", origin_y: " << origin_y << ", "
<< "dc: " << (best_c - origin_x) << ", "
- << "dr: " << (best_r - origin_y)
- << ", tried " << ((image2.Height() - h) * (image2.Width() - w))
- << " shifts.";
+ << "dr: " << (best_r - origin_y) << ", tried "
+ << ((image2.Height() - h) * (image2.Width() - w)) << " shifts.";
// Apply the shift.
for (int i = 0; i < 4 + num_extra_points; ++i) {
@@ -1286,8 +1291,10 @@ bool BruteTranslationOnlyInitialize(const FloatImage &image1,
return true;
}
-void CopyQuad(double *src_x, double *src_y,
- double *dst_x, double *dst_y,
+void CopyQuad(double* src_x,
+ double* src_y,
+ double* dst_x,
+ double* dst_y,
int num_extra_points) {
for (int i = 0; i < 4 + num_extra_points; ++i) {
dst_x[i] = src_x[i];
@@ -1297,16 +1304,18 @@ void CopyQuad(double *src_x, double *src_y,
} // namespace
-template<typename Warp>
-void TemplatedTrackRegion(const FloatImage &image1,
- const FloatImage &image2,
- const double *x1, const double *y1,
- const TrackRegionOptions &options,
- double *x2, double *y2,
- TrackRegionResult *result) {
+template <typename Warp>
+void TemplatedTrackRegion(const FloatImage& image1,
+ const FloatImage& image2,
+ const double* x1,
+ const double* y1,
+ const TrackRegionOptions& options,
+ double* x2,
+ double* y2,
+ TrackRegionResult* result) {
for (int i = 0; i < 4 + options.num_extra_points; ++i) {
- LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); guess ("
- << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", "
+ LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); guess (" << x2[i]
+ << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", "
<< (y2[i] - y1[i]) << ").";
}
@@ -1322,9 +1331,14 @@ void TemplatedTrackRegion(const FloatImage &image1,
double y2_first_try[5];
CopyQuad(x2, y2, x2_first_try, y2_first_try, options.num_extra_points);
- TemplatedTrackRegion<Warp>(image1, image2,
- x1, y1, modified_options,
- x2_first_try, y2_first_try, result);
+ TemplatedTrackRegion<Warp>(image1,
+ image2,
+ x1,
+ y1,
+ modified_options,
+ x2_first_try,
+ y2_first_try,
+ result);
// Of the things that can happen in the first pass, don't try the brute
// pass (and second attempt) if the error is one of the terminations below.
@@ -1368,22 +1382,25 @@ void TemplatedTrackRegion(const FloatImage &image1,
// Prepare the image and gradient.
Array3Df image_and_gradient1;
Array3Df image_and_gradient2;
- BlurredImageAndDerivativesChannels(image1, options.sigma,
- &image_and_gradient1);
- BlurredImageAndDerivativesChannels(image2, options.sigma,
- &image_and_gradient2);
+ BlurredImageAndDerivativesChannels(
+ image1, options.sigma, &image_and_gradient1);
+ BlurredImageAndDerivativesChannels(
+ image2, options.sigma, &image_and_gradient2);
// Possibly do a brute-force translation-only initialization.
if (SearchAreaTooBigForDescent(image2, x2, y2) &&
options.use_brute_initialization) {
LG << "Running brute initialization...";
- bool found_any_alignment = BruteTranslationOnlyInitialize<Warp>(
- image_and_gradient1,
- options.image1_mask,
- image2,
- options.num_extra_points,
- options.use_normalized_intensities,
- x1, y1, x2, y2);
+ bool found_any_alignment =
+ BruteTranslationOnlyInitialize<Warp>(image_and_gradient1,
+ options.image1_mask,
+ image2,
+ options.num_extra_points,
+ options.use_normalized_intensities,
+ x1,
+ y1,
+ x2,
+ y2);
if (!found_any_alignment) {
LG << "Brute failed to find an alignment; pattern too small. "
<< "Failing entire track operation.";
@@ -1391,9 +1408,9 @@ void TemplatedTrackRegion(const FloatImage &image1,
return;
}
for (int i = 0; i < 4; ++i) {
- LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); brute ("
- << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i])
- << ", " << (y2[i] - y1[i]) << ").";
+ LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); brute (" << x2[i]
+ << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", "
+ << (y2[i] - y1[i]) << ").";
}
}
@@ -1408,14 +1425,13 @@ void TemplatedTrackRegion(const FloatImage &image1,
PickSampling(x1, y1, x2, y2, &num_samples_x, &num_samples_y);
// Compute the warp from rectangular coordinates.
- Mat3 canonical_homography = ComputeCanonicalHomography(x1, y1,
- num_samples_x,
- num_samples_y);
+ Mat3 canonical_homography =
+ ComputeCanonicalHomography(x1, y1, num_samples_x, num_samples_y);
ceres::Problem problem;
// Construct the warp cost function. AutoDiffCostFunction takes ownership.
- PixelDifferenceCostFunctor<Warp> *pixel_difference_cost_function =
+ PixelDifferenceCostFunctor<Warp>* pixel_difference_cost_function =
new PixelDifferenceCostFunctor<Warp>(options,
image_and_gradient1,
image_and_gradient2,
@@ -1424,28 +1440,24 @@ void TemplatedTrackRegion(const FloatImage &image1,
num_samples_y,
warp);
problem.AddResidualBlock(
- new ceres::AutoDiffCostFunction<
- PixelDifferenceCostFunctor<Warp>,
- ceres::DYNAMIC,
- Warp::NUM_PARAMETERS>(pixel_difference_cost_function,
- num_samples_x * num_samples_y),
- NULL,
- warp.parameters);
+ new ceres::AutoDiffCostFunction<PixelDifferenceCostFunctor<Warp>,
+ ceres::DYNAMIC,
+ Warp::NUM_PARAMETERS>(
+ pixel_difference_cost_function, num_samples_x * num_samples_y),
+ NULL,
+ warp.parameters);
// Construct the regularizing cost function
if (options.regularization_coefficient != 0.0) {
- WarpRegularizingCostFunctor<Warp> *regularizing_warp_cost_function =
- new WarpRegularizingCostFunctor<Warp>(options,
- x1, y2,
- x2_original,
- y2_original,
- warp);
+ WarpRegularizingCostFunctor<Warp>* regularizing_warp_cost_function =
+ new WarpRegularizingCostFunctor<Warp>(
+ options, x1, y2, x2_original, y2_original, warp);
problem.AddResidualBlock(
- new ceres::AutoDiffCostFunction<
- WarpRegularizingCostFunctor<Warp>,
- 8 /* num_residuals */,
- Warp::NUM_PARAMETERS>(regularizing_warp_cost_function),
+ new ceres::AutoDiffCostFunction<WarpRegularizingCostFunctor<Warp>,
+ 8 /* num_residuals */,
+ Warp::NUM_PARAMETERS>(
+ regularizing_warp_cost_function),
NULL,
warp.parameters);
}
@@ -1488,10 +1500,10 @@ void TemplatedTrackRegion(const FloatImage &image1,
return;
}
-#define HANDLE_TERMINATION(termination_enum) \
- if (summary.termination_type == ceres::termination_enum) { \
- result->termination = TrackRegionResult::termination_enum; \
- return; \
+#define HANDLE_TERMINATION(termination_enum) \
+ if (summary.termination_type == ceres::termination_enum) { \
+ result->termination = TrackRegionResult::termination_enum; \
+ return; \
}
// Avoid computing correlation for tracking failures.
@@ -1499,8 +1511,9 @@ void TemplatedTrackRegion(const FloatImage &image1,
// Otherwise, run a final correlation check.
if (options.minimum_correlation > 0.0) {
- result->correlation = pixel_difference_cost_function->
- PearsonProductMomentCorrelationCoefficient(warp.parameters);
+ result->correlation =
+ pixel_difference_cost_function
+ ->PearsonProductMomentCorrelationCoefficient(warp.parameters);
if (result->correlation < options.minimum_correlation) {
LG << "Failing with insufficient correlation.";
result->termination = TrackRegionResult::INSUFFICIENT_CORRELATION;
@@ -1523,36 +1536,39 @@ void TemplatedTrackRegion(const FloatImage &image1,
#undef HANDLE_TERMINATION
};
-void TrackRegion(const FloatImage &image1,
- const FloatImage &image2,
- const double *x1, const double *y1,
- const TrackRegionOptions &options,
- double *x2, double *y2,
- TrackRegionResult *result) {
+void TrackRegion(const FloatImage& image1,
+ const FloatImage& image2,
+ const double* x1,
+ const double* y1,
+ const TrackRegionOptions& options,
+ double* x2,
+ double* y2,
+ TrackRegionResult* result) {
// Enum is necessary due to templated nature of autodiff.
-#define HANDLE_MODE(mode_enum, mode_type) \
- if (options.mode == TrackRegionOptions::mode_enum) { \
- TemplatedTrackRegion<mode_type>(image1, image2, \
- x1, y1, \
- options, \
- x2, y2, \
- result); \
- return; \
+#define HANDLE_MODE(mode_enum, mode_type) \
+ if (options.mode == TrackRegionOptions::mode_enum) { \
+ TemplatedTrackRegion<mode_type>( \
+ image1, image2, x1, y1, options, x2, y2, result); \
+ return; \
}
- HANDLE_MODE(TRANSLATION, TranslationWarp);
- HANDLE_MODE(TRANSLATION_SCALE, TranslationScaleWarp);
- HANDLE_MODE(TRANSLATION_ROTATION, TranslationRotationWarp);
+ HANDLE_MODE(TRANSLATION, TranslationWarp);
+ HANDLE_MODE(TRANSLATION_SCALE, TranslationScaleWarp);
+ HANDLE_MODE(TRANSLATION_ROTATION, TranslationRotationWarp);
HANDLE_MODE(TRANSLATION_ROTATION_SCALE, TranslationRotationScaleWarp);
- HANDLE_MODE(AFFINE, AffineWarp);
- HANDLE_MODE(HOMOGRAPHY, HomographyWarp);
+ HANDLE_MODE(AFFINE, AffineWarp);
+ HANDLE_MODE(HOMOGRAPHY, HomographyWarp);
#undef HANDLE_MODE
}
-bool SamplePlanarPatch(const FloatImage &image,
- const double *xs, const double *ys,
- int num_samples_x, int num_samples_y,
- FloatImage *mask, FloatImage *patch,
- double *warped_position_x, double *warped_position_y) {
+bool SamplePlanarPatch(const FloatImage& image,
+ const double* xs,
+ const double* ys,
+ int num_samples_x,
+ int num_samples_y,
+ FloatImage* mask,
+ FloatImage* patch,
+ double* warped_position_x,
+ double* warped_position_y) {
// Bail early if the points are outside the image.
if (!AllInBounds(image, xs, ys)) {
LG << "Can't sample patch: out of bounds.";
@@ -1563,9 +1579,8 @@ bool SamplePlanarPatch(const FloatImage &image,
patch->Resize(num_samples_y, num_samples_x, image.Depth());
// Compute the warp from rectangular coordinates.
- Mat3 canonical_homography = ComputeCanonicalHomography(xs, ys,
- num_samples_x,
- num_samples_y);
+ Mat3 canonical_homography =
+ ComputeCanonicalHomography(xs, ys, num_samples_x, num_samples_y);
// Walk over the coordinates in the canonical space, sampling from the image
// in the original space and copying the result into the patch.
@@ -1573,12 +1588,11 @@ bool SamplePlanarPatch(const FloatImage &image,
for (int c = 0; c < num_samples_x; ++c) {
Vec3 image_position = canonical_homography * Vec3(c, r, 1);
image_position /= image_position(2);
- SampleLinear(image, image_position(1),
- image_position(0),
- &(*patch)(r, c, 0));
+ SampleLinear(
+ image, image_position(1), image_position(0), &(*patch)(r, c, 0));
if (mask) {
- float mask_value = SampleLinear(*mask, image_position(1),
- image_position(0), 0);
+ float mask_value =
+ SampleLinear(*mask, image_position(1), image_position(0), 0);
for (int d = 0; d < image.Depth(); d++)
(*patch)(r, c, d) *= mask_value;
diff --git a/intern/libmv/libmv/tracking/track_region.h b/intern/libmv/libmv/tracking/track_region.h
index 61dce22bcb8..7868e3b8b77 100644
--- a/intern/libmv/libmv/tracking/track_region.h
+++ b/intern/libmv/libmv/tracking/track_region.h
@@ -19,6 +19,7 @@
// IN THE SOFTWARE.
#ifndef LIBMV_TRACKING_TRACK_REGION_H_
+#define LIBMV_TRACKING_TRACK_REGION_H_
#include "libmv/image/image.h"
#include "libmv/image/sample.h"
@@ -107,7 +108,7 @@ struct TrackRegionOptions {
// If non-null, this is used as the pattern mask. It should match the size of
// image1, even though only values inside the image1 quad are examined. The
// values must be in the range 0.0 to 0.1.
- FloatImage *image1_mask;
+ FloatImage* image1_mask;
};
struct TrackRegionResult {
@@ -128,8 +129,7 @@ struct TrackRegionResult {
Termination termination;
bool is_usable() {
- return termination == CONVERGENCE ||
- termination == NO_CONVERGENCE;
+ return termination == CONVERGENCE || termination == NO_CONVERGENCE;
}
int num_iterations;
@@ -140,12 +140,14 @@ struct TrackRegionResult {
};
// Always needs 4 correspondences.
-void TrackRegion(const FloatImage &image1,
- const FloatImage &image2,
- const double *x1, const double *y1,
- const TrackRegionOptions &options,
- double *x2, double *y2,
- TrackRegionResult *result);
+void TrackRegion(const FloatImage& image1,
+ const FloatImage& image2,
+ const double* x1,
+ const double* y1,
+ const TrackRegionOptions& options,
+ double* x2,
+ double* y2,
+ TrackRegionResult* result);
// Sample a "canonical" version of the passed planar patch, using bilinear
// sampling. The passed corners must be within the image, and have at least two
@@ -156,11 +158,15 @@ void TrackRegion(const FloatImage &image1,
// the size of image.
// Warped coordinates of marker's position would be returned in
// warped_position_x and warped_position_y
-bool SamplePlanarPatch(const FloatImage &image,
- const double *xs, const double *ys,
- int num_samples_x, int num_samples_y,
- FloatImage *mask, FloatImage *patch,
- double *warped_position_x, double *warped_position_y);
+bool SamplePlanarPatch(const FloatImage& image,
+ const double* xs,
+ const double* ys,
+ int num_samples_x,
+ int num_samples_y,
+ FloatImage* mask,
+ FloatImage* patch,
+ double* warped_position_x,
+ double* warped_position_y);
} // namespace libmv
diff --git a/intern/libmv/libmv/tracking/trklt_region_tracker.cc b/intern/libmv/libmv/tracking/trklt_region_tracker.cc
index 05ef3d1d272..7ffa7555467 100644
--- a/intern/libmv/libmv/tracking/trklt_region_tracker.cc
+++ b/intern/libmv/libmv/tracking/trklt_region_tracker.cc
@@ -20,27 +20,29 @@
#include "libmv/tracking/trklt_region_tracker.h"
-#include "libmv/logging/logging.h"
-#include "libmv/numeric/numeric.h"
-#include "libmv/image/image.h"
#include "libmv/image/convolve.h"
+#include "libmv/image/image.h"
#include "libmv/image/sample.h"
+#include "libmv/logging/logging.h"
+#include "libmv/numeric/numeric.h"
namespace libmv {
// TODO(keir): Switch this to use the smarter LM loop like in ESM.
// Computes U and e from the Ud = e equation (number 14) from the paper.
-static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
- const Array3Df &image_and_gradient2,
- double x1, double y1,
- double x2, double y2,
+static void ComputeTrackingEquation(const Array3Df& image_and_gradient1,
+ const Array3Df& image_and_gradient2,
+ double x1,
+ double y1,
+ double x2,
+ double y2,
int half_width,
double lambda,
- Mat2f *U,
- Vec2f *e) {
+ Mat2f* U,
+ Vec2f* e) {
Mat2f A, B, C, D;
- A = B = C = D = Mat2f::Zero();
+ A = B = C = D = Mat2f::Zero();
Vec2f R, S, V, W;
R = S = V = W = Vec2f::Zero();
@@ -57,9 +59,9 @@ static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
Vec2f gI, gJ;
gI << SampleLinear(image_and_gradient1, yy1, xx1, 1),
- SampleLinear(image_and_gradient1, yy1, xx1, 2);
+ SampleLinear(image_and_gradient1, yy1, xx1, 2);
gJ << SampleLinear(image_and_gradient2, yy2, xx2, 1),
- SampleLinear(image_and_gradient2, yy2, xx2, 2);
+ SampleLinear(image_and_gradient2, yy2, xx2, 2);
// Equation 15 from the paper.
A += gI * gI.transpose();
@@ -77,26 +79,25 @@ static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
Mat2f Di = B.transpose().inverse();
// Equation 14 from the paper.
- *U = A*Di*C + lambda*Di*C - 0.5*B;
- *e = (A + lambda*Mat2f::Identity())*Di*(V - W) + 0.5*(S - R);
+ *U = A * Di * C + lambda * Di * C - 0.5 * B;
+ *e = (A + lambda * Mat2f::Identity()) * Di * (V - W) + 0.5 * (S - R);
}
-static bool RegionIsInBounds(const FloatImage &image1,
- double x, double y,
- int half_window_size) {
+static bool RegionIsInBounds(const FloatImage& image1,
+ double x,
+ double y,
+ int half_window_size) {
// Check the minimum coordinates.
int min_x = floor(x) - half_window_size - 1;
int min_y = floor(y) - half_window_size - 1;
- if (min_x < 0.0 ||
- min_y < 0.0) {
+ if (min_x < 0.0 || min_y < 0.0) {
return false;
}
// Check the maximum coordinates.
int max_x = ceil(x) + half_window_size + 1;
int max_y = ceil(y) + half_window_size + 1;
- if (max_x > image1.cols() ||
- max_y > image1.rows()) {
+ if (max_x > image1.cols() || max_y > image1.rows()) {
return false;
}
@@ -104,10 +105,12 @@ static bool RegionIsInBounds(const FloatImage &image1,
return true;
}
-bool TrkltRegionTracker::Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const {
+bool TrkltRegionTracker::Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const {
if (!RegionIsInBounds(image1, x1, y1, half_window_size)) {
LG << "Fell out of image1's window with x1=" << x1 << ", y1=" << y1
<< ", hw=" << half_window_size << ".";
@@ -134,11 +137,14 @@ bool TrkltRegionTracker::Track(const FloatImage &image1,
Vec2f e;
ComputeTrackingEquation(image_and_gradient1,
image_and_gradient2,
- x1, y1,
- *x2, *y2,
+ x1,
+ y1,
+ *x2,
+ *y2,
half_window_size,
lambda,
- &U, &e);
+ &U,
+ &e);
// Solve the linear system for the best update to x2 and y2.
d = U.lu().solve(e);
@@ -161,7 +167,6 @@ bool TrkltRegionTracker::Track(const FloatImage &image1,
LG << "x=" << *x2 << ", y=" << *y2 << ", dx=" << d[0] << ", dy=" << d[1]
<< ", det=" << determinant;
-
// If the update is small, then we probably found the target.
if (d.squaredNorm() < min_update_squared_distance) {
LG << "Successful track in " << i << " iterations.";
diff --git a/intern/libmv/libmv/tracking/trklt_region_tracker.h b/intern/libmv/libmv/tracking/trklt_region_tracker.h
index 26d0621aa02..a9cf5580f61 100644
--- a/intern/libmv/libmv/tracking/trklt_region_tracker.h
+++ b/intern/libmv/libmv/tracking/trklt_region_tracker.h
@@ -46,10 +46,12 @@ struct TrkltRegionTracker : public RegionTracker {
virtual ~TrkltRegionTracker() {}
// Tracker interface.
- virtual bool Track(const FloatImage &image1,
- const FloatImage &image2,
- double x1, double y1,
- double *x2, double *y2) const;
+ virtual bool Track(const FloatImage& image1,
+ const FloatImage& image2,
+ double x1,
+ double y1,
+ double* x2,
+ double* y2) const;
// No point in creating getters or setters.
int half_window_size;
diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
index 180f9f0a01c..3355e9075a0 100644
--- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
+++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
@@ -22,8 +22,6 @@
# XXX: This script is meant to be used from inside Blender!
# You should not directly use this script, rather use update_msg.py!
-import collections
-import copy
import datetime
import os
import re
diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py
index fd4488ecd73..b17c9eeebc5 100644
--- a/release/scripts/modules/bl_i18n_utils/utils.py
+++ b/release/scripts/modules/bl_i18n_utils/utils.py
@@ -21,12 +21,9 @@
# Some misc utilities...
import collections
-import copy
-import hashlib
import os
import re
import struct
-import sys
import tempfile
#import time
diff --git a/release/scripts/modules/bl_i18n_utils/utils_rtl.py b/release/scripts/modules/bl_i18n_utils/utils_rtl.py
index 2b6a56c5deb..8da1417c468 100755
--- a/release/scripts/modules/bl_i18n_utils/utils_rtl.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_rtl.py
@@ -32,7 +32,6 @@
# \", %s, %x12, %.4f, etc.), protecting them from ugly (evil) fribidi,
# which seems completely unaware of such things (as unicode is...).
-import sys
import ctypes
import re
@@ -89,7 +88,7 @@ def protect_format_seq(msg):
PDF = "\u202C"
LRO = "\u202D"
RLO = "\u202E"
- uctrl = {LRE, RLE, PDF, LRO, RLO}
+ # uctrl = {LRE, RLE, PDF, LRO, RLO}
# Most likely incomplete, but seems to cover current needs.
format_codes = set("tslfd")
digits = set(".0123456789")
diff --git a/release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py b/release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py
index b5127784c1e..0784a91d174 100644
--- a/release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py
+++ b/release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py
@@ -114,6 +114,7 @@ _km_hierarchy = [
('Custom Normals Modal Map', 'EMPTY', 'WINDOW', []),
('Bevel Modal Map', 'EMPTY', 'WINDOW', []),
('Paint Stroke Modal', 'EMPTY', 'WINDOW', []),
+ ('Sculpt Expand Modal', 'EMPTY', 'WINDOW', []),
('Paint Curve', 'EMPTY', 'WINDOW', []),
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
diff --git a/release/scripts/modules/bl_previews_utils/bl_previews_render.py b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
index 6e3d04e7fa2..979b47f7a14 100644
--- a/release/scripts/modules/bl_previews_utils/bl_previews_render.py
+++ b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
@@ -283,7 +283,8 @@ def do_previews(do_objects, do_collections, do_scenes, do_data_intern):
return cos
def preview_render_do(render_context, item_container, item_name, objects, offset_matrix=None):
- scene = bpy.data.scenes[render_context.scene, None]
+ # Unused.
+ # scene = bpy.data.scenes[render_context.scene, None]
if objects is not None:
camera = bpy.data.objects[render_context.camera, None]
light = bpy.data.objects[render_context.light, None] if render_context.light is not None else None
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 8afb09882fd..ddfd3d66e90 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -32,7 +32,6 @@ __all__ = (
import bpy
from bpy.props import (
- BoolProperty,
FloatVectorProperty,
EnumProperty,
)
@@ -50,7 +49,7 @@ def add_object_align_init(context, operator):
:rtype: :class:`mathutils.Matrix`
"""
- from mathutils import Matrix, Vector, Euler
+ from mathutils import Matrix, Vector
properties = operator.properties if operator is not None else None
space_data = context.space_data
@@ -113,7 +112,6 @@ def object_data_add(context, obdata, operator=None, name=None):
:return: the newly created object in the scene.
:rtype: :class:`bpy.types.Object`
"""
- scene = context.scene
layer = context.view_layer
layer_collection = context.layer_collection or layer.active_layer_collection
scene_collection = layer_collection.collection
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 5d89763f34b..ee9115b6643 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -19,7 +19,6 @@
# <pep8-80 compliant>
from _bpy import types as bpy_types
-import _bpy
StructRNA = bpy_types.bpy_struct
StructMetaPropGroup = bpy_types.bpy_struct_meta_idprop
@@ -900,6 +899,7 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
layout = self.layout
import os
+ import re
import bpy.utils
layout = self.layout
@@ -920,7 +920,11 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
(filter_path(f)))
])
- files.sort()
+ # Perform a "natural sort", so 20 comes after 3 (for example).
+ files.sort(
+ key=lambda file_path:
+ tuple(int(t) if t.isdigit() else t for t in re.split("(\d+)", file_path[0].lower())),
+ )
col = layout.column(align=True)
diff --git a/release/scripts/modules/console/complete_calltip.py b/release/scripts/modules/console/complete_calltip.py
index 611be00b633..4271003ae13 100644
--- a/release/scripts/modules/console/complete_calltip.py
+++ b/release/scripts/modules/console/complete_calltip.py
@@ -107,11 +107,7 @@ def get_argspec(func, strip_self=True, doc=None, source=None):
try:
func = func.__func__
except AttributeError:
- try:
- # py 2.X
- func = func.im_func
- except AttributeError:
- pass
+ pass
# is callable?
if not hasattr(func, '__call__'):
return ''
@@ -141,14 +137,10 @@ def get_argspec(func, strip_self=True, doc=None, source=None):
argspec = inspect.formatargspec(*inspect.getfullargspec(func))
except:
try:
- # py 2.X
- argspec = inspect.formatargspec(*inspect.getargspec(func))
+ argspec = inspect.formatargvalues(
+ *inspect.getargvalues(func))
except:
- try:
- argspec = inspect.formatargvalues(
- *inspect.getargvalues(func))
- except:
- argspec = ''
+ argspec = ''
if strip_self:
argspec = argspec.replace('self, ', '')
return argspec
diff --git a/release/scripts/modules/console_python.py b/release/scripts/modules/console_python.py
index 5106010b555..9e1b921774d 100644
--- a/release/scripts/modules/console_python.py
+++ b/release/scripts/modules/console_python.py
@@ -229,8 +229,6 @@ execute.hooks = []
def autocomplete(context):
- _readline_bypass()
-
from console import intellisense
sc = context.space_data
@@ -358,14 +356,3 @@ def banner(context):
sc.prompt = PROMPT
return {'FINISHED'}
-
-
-# workaround for readline crashing, see: T43491
-def _readline_bypass():
- if "rlcompleter" in sys.modules or "readline" in sys.modules:
- return
-
- # prevent 'rlcompleter' from loading the real 'readline' module.
- sys.modules["readline"] = None
- import rlcompleter
- del sys.modules["readline"]
diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py
index 964eff0e572..3bcc709ab72 100644
--- a/release/scripts/modules/rna_info.py
+++ b/release/scripts/modules/rna_info.py
@@ -622,8 +622,8 @@ def BuildRNAInfo():
yield (rna_sub_type_name, rna_sub_struct)
i += 1
- for (rna_type_name, rna_struct) in _bpy_types_iterator():
- # if not rna_type_name.startswith('__'):
+ for (_rna_type_name, rna_struct) in _bpy_types_iterator():
+ # if not _rna_type_name.startswith('__'):
identifier = rna_struct.identifier
diff --git a/release/scripts/presets/framerate/120.py b/release/scripts/presets/framerate/120.py
new file mode 100644
index 00000000000..53328907d2b
--- /dev/null
+++ b/release/scripts/presets/framerate/120.py
@@ -0,0 +1,3 @@
+import bpy
+bpy.context.scene.render.fps = 120
+bpy.context.scene.render.fps_base = 1
diff --git a/release/scripts/presets/framerate/240.py b/release/scripts/presets/framerate/240.py
new file mode 100644
index 00000000000..096af4e38ec
--- /dev/null
+++ b/release/scripts/presets/framerate/240.py
@@ -0,0 +1,3 @@
+import bpy
+bpy.context.scene.render.fps = 240
+bpy.context.scene.render.fps_base = 1
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 69582849308..949cfcae2b1 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -4470,6 +4470,15 @@ def km_sculpt(params):
{"properties": [("mode", 'INVERT')]}),
("sculpt.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
{"properties": [("mode", 'SMOOTH')]}),
+ # Expand
+ ("sculpt.expand", {"type": 'A', "value": 'PRESS', "shift": True},
+ {"properties": [("target", "MASK"), ("falloff_type", "GEODESIC"), ("invert", True)]}),
+ ("sculpt.expand", {"type": 'A', "value": 'PRESS', "shift": True, "alt": True},
+ {"properties": [("target", "MASK"), ("falloff_type", "NORMALS"), ("invert", False)]}),
+ ("sculpt.expand", {"type": 'W', "value": 'PRESS', "shift": True},
+ {"properties": [("target", "FACE_SETS"), ("falloff_type", "GEODESIC"), ("invert", False), ("use_modify_active", False)]}),
+ ("sculpt.expand", {"type": 'W', "value": 'PRESS', "shift": True, "alt": True},
+ {"properties": [("target", "FACE_SETS"), ("falloff_type", "BOUNDARY_FACE_SET"),("invert", False), ("use_modify_active", True)]}),
# Partial Visibility Show/hide
("sculpt.face_set_change_visibility", {"type": 'H', "value": 'PRESS'},
{"properties": [("mode", 'TOGGLE')]}),
@@ -4477,8 +4486,6 @@ def km_sculpt(params):
{"properties": [("mode", 'HIDE_ACTIVE')]}),
("sculpt.face_set_change_visibility", {"type": 'H', "value": 'PRESS', "alt": True},
{"properties": [("mode", 'SHOW_ALL')]}),
- ("sculpt.mask_expand", {"type": 'W', "value": 'PRESS', "shift": True},
- {"properties": [("use_normals", False), ("keep_previous_mask", False), ("invert", False), ("smooth_iterations", 0), ("create_face_set", True)]}),
("sculpt.face_set_edit", {"type": 'W', "value": 'PRESS', "ctrl": True},
{"properties": [("mode", 'GROW')]}),
("sculpt.face_set_edit", {"type": 'W', "value": 'PRESS', "ctrl": True, "alt": True},
@@ -4499,10 +4506,6 @@ def km_sculpt(params):
("paint.mask_lasso_gesture", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True}, None),
("wm.context_toggle", {"type": 'M', "value": 'PRESS', "ctrl": True},
{"properties": [("data_path", 'scene.tool_settings.sculpt.show_mask')]}),
- ("sculpt.mask_expand", {"type": 'A', "value": 'PRESS', "shift": True},
- {"properties": [("use_normals", False), ("keep_previous_mask", False), ("invert", True), ("smooth_iterations", 2), ("create_face_set", False)]}),
- ("sculpt.mask_expand", {"type": 'A', "value": 'PRESS', "shift": True, 'alt': True},
- {"properties": [("use_normals", True), ("keep_previous_mask", True), ("invert", False), ("smooth_iterations", 0), ("create_face_set", False)]}),
# Dynamic topology
("sculpt.dynamic_topology_toggle", {"type": 'D', "value": 'PRESS', "ctrl": True}, None),
("sculpt.dyntopo_detail_size_edit", {"type": 'D', "value": 'PRESS', "shift": True}, None),
@@ -5571,6 +5574,39 @@ def km_paint_stroke_modal(_params):
return keymap
+def km_sculpt_expand_modal(_params):
+ items = []
+ keymap = (
+ "Sculpt Expand Modal",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW', "modal": True},
+ {"items": items},
+ )
+
+ items.extend([
+ ("CANCEL", {"type": 'ESC', "value": 'PRESS', "any": True}, None),
+ ("CANCEL", {"type": 'RIGHTMOUSE', "value": 'PRESS', "any": True}, None),
+ ("CONFIRM", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ("INVERT", {"type": 'F', "value": 'PRESS', "any": True, "repeat" : False}, None),
+ ("PRESERVE", {"type": 'E', "value": 'PRESS', "any": True, "repeat" : False}, None),
+ ("GRADIENT", {"type": 'G', "value": 'PRESS', "any": True, "repeat" : False}, None),
+ ("RECURSION_STEP_GEODESIC", {"type": 'R', "value": 'PRESS', "repeat" : False}, None),
+ ("RECURSION_STEP_TOPOLOGY", {"type": 'R', "value": 'PRESS', "alt" : True ,"any": True, "repeat" : False}, None),
+ ("MOVE_TOGGLE", {"type": 'SPACE', "value": 'ANY', "any": True, "repeat" : False}, None),
+ ("FALLOFF_GEODESICS", {"type": 'ONE', "value": 'PRESS', "any": True, "repeat" : False}, None),
+ ("FALLOFF_TOPOLOGY", {"type": 'TWO', "value": 'PRESS', "any": True, "repeat" : False}, None),
+ ("FALLOFF_TOPOLOGY_DIAGONALS", {"type": 'THREE', "value": 'PRESS', "any": True, "repeat" : False}, None),
+ ("FALLOFF_SPHERICAL", {"type": 'FOUR', "value": 'PRESS', "any": True, "repeat" : False}, None),
+ ("SNAP_TOGGLE", {"type": 'LEFT_CTRL', "value": 'ANY', "repeat" : False}, None),
+ ("LOOP_COUNT_INCREASE", {"type": 'W', "value": 'PRESS', "any": True, "repeat" : True}, None),
+ ("LOOP_COUNT_DECREASE", {"type": 'Q', "value": 'PRESS', "any": True, "repeat" : True}, None),
+ ("BRUSH_GRADIENT_TOGGLE", {"type": 'B', "value": 'PRESS', "any": True, "repeat" : False}, None),
+ ("TEXTURE_DISTORTION_INCREASE", {"type": 'Y', "value": 'PRESS', "any": False, "repeat" : True}, None),
+ ("TEXTURE_DISTORTION_DECREASE", {"type": 'T', "value": 'PRESS', "any": False, "repeat" : True}, None),
+ ])
+ return keymap
+
+
+
# Fallback for gizmos that don't have custom a custom key-map.
def km_generic_gizmo(_params):
@@ -7085,6 +7121,7 @@ def generate_keymaps(params=None):
km_view3d_zoom_modal(params),
km_view3d_dolly_modal(params),
km_paint_stroke_modal(params),
+ km_sculpt_expand_modal(params),
# Gizmos.
km_generic_gizmo(params),
diff --git a/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py b/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py
index 9b0a260dc95..192ba2cf5b5 100644
--- a/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py
+++ b/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py
@@ -58,6 +58,7 @@ def load_handler(dummy):
# Grease pencil object
scene = bpy.data.scenes[0]
if scene:
+ scene.tool_settings.use_keyframe_insert_auto = True
for ob in scene.objects:
if ob.type == 'GPENCIL':
gpd = ob.data
diff --git a/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py b/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py
index bfad66ec6cd..c97c3466085 100644
--- a/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py
+++ b/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py
@@ -22,7 +22,6 @@ from bpy.app.handlers import persistent
@persistent
def load_handler(dummy):
- import os
from bpy import context
screen = context.screen
for area in screen.areas:
diff --git a/release/scripts/startup/bl_operators/console.py b/release/scripts/startup/bl_operators/console.py
index 231dade820d..cd6728d56b2 100644
--- a/release/scripts/startup/bl_operators/console.py
+++ b/release/scripts/startup/bl_operators/console.py
@@ -37,6 +37,7 @@ class ConsoleExec(Operator):
"""Execute the current console line as a python expression"""
bl_idname = "console.execute"
bl_label = "Console Execute"
+ bl_options = {'UNDO_GROUPED'}
interactive: BoolProperty(
options={'SKIP_SAVE'},
diff --git a/release/scripts/startup/bl_operators/geometry_nodes.py b/release/scripts/startup/bl_operators/geometry_nodes.py
index 9652f23aadb..c66f0ada955 100644
--- a/release/scripts/startup/bl_operators/geometry_nodes.py
+++ b/release/scripts/startup/bl_operators/geometry_nodes.py
@@ -19,7 +19,7 @@
import bpy
-def geometry_node_group_empty_new(context):
+def geometry_node_group_empty_new():
group = bpy.data.node_groups.new("Geometry Nodes", 'GeometryNodeTree')
group.inputs.new('NodeSocketGeometry', "Geometry")
group.outputs.new('NodeSocketGeometry', "Geometry")
@@ -85,7 +85,7 @@ class NewGeometryNodeTreeAssign(bpy.types.Operator):
if not modifier:
return {'CANCELLED'}
- group = geometry_node_group_empty_new(context)
+ group = geometry_node_group_empty_new()
modifier.node_group = group
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index 70b80f7198f..4a7700b03bb 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -19,7 +19,6 @@
# <pep8-80 compliant>
-import bpy
from bpy.types import Operator
from mathutils import Vector
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index 48312f958ef..a34ed019148 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -25,7 +25,6 @@ from bpy.props import (
BoolProperty,
EnumProperty,
FloatProperty,
- FloatVectorProperty,
IntProperty,
)
diff --git a/release/scripts/startup/bl_operators/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
index 4343717f264..1b801f77e07 100644
--- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py
+++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
@@ -18,7 +18,6 @@
# <pep8 compliant>
-import bpy
from bpy.types import Operator
from bpy.props import (
diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py
index 3442e189d14..ff5bcdb034f 100644
--- a/release/scripts/startup/bl_operators/view3d.py
+++ b/release/scripts/startup/bl_operators/view3d.py
@@ -169,7 +169,7 @@ class VIEW3D_OT_edit_mesh_extrude_manifold_normal(Operator):
obj = context.active_object
return (obj is not None and obj.mode == 'EDIT')
- def execute(self, context):
+ def execute(self, _context):
bpy.ops.mesh.extrude_manifold(
'INVOKE_REGION_WIN',
MESH_OT_extrude_region={
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index e8c62368239..e835e577953 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -42,7 +42,7 @@ class OBJECT_PT_constraints(ObjectConstraintPanel, Panel):
bl_label = "Object Constraints"
bl_options = {'HIDE_HEADER'}
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.operator_menu_enum("object.constraint_add", "type", text="Add Object Constraint")
@@ -56,7 +56,7 @@ class BONE_PT_constraints(BoneConstraintPanel, Panel):
bl_label = "Bone Constraints"
bl_options = {'HIDE_HEADER'}
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.operator_menu_enum("pose.constraint_add", "type", text="Add Bone Constraint")
@@ -122,7 +122,7 @@ class ConstraintButtonsPanel:
elif con.target.type in {'MESH', 'LATTICE'}:
col.prop_search(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
- def get_constraint(self, context):
+ def get_constraint(self, _context):
con = self.custom_data
self.layout.context_pointer_set("constraint", con)
return con
@@ -844,7 +844,7 @@ class ConstraintButtonsPanel:
self.draw_influence(layout, con)
- def draw_python_constraint(self, context):
+ def draw_python_constraint(self, _context):
layout = self.layout
layout.label(text="Blender 2.6 doesn't support python constraints yet")
@@ -976,7 +976,7 @@ class ConstraintButtonsSubPanel:
bl_label = ""
bl_options = {'DRAW_BOX'}
- def get_constraint(self, context):
+ def get_constraint(self, _context):
con = self.custom_data
self.layout.context_pointer_set("constraint", con)
return con
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index 170d7910339..f3e116ca321 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -255,17 +255,11 @@ class BONE_PT_display(BoneButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
- ob = context.object
bone = context.bone
- pchan = None
-
- if ob and bone:
- pchan = ob.pose.bones[bone.name]
- elif bone is None:
+ if bone is None:
bone = context.edit_bone
if bone:
-
col = layout.column()
col.prop(bone, "hide", text="Hide", toggle=False)
diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py
index 9db6eedb04c..69720a6c54b 100644
--- a/release/scripts/startup/bl_ui/properties_data_gpencil.py
+++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py
@@ -392,7 +392,6 @@ class DATA_PT_gpencil_display(DataButtonsPanel, Panel):
layout.use_property_decorate = False
gpd = context.gpencil
- gpl = gpd.layers.active
layout.prop(gpd, "edit_line_color", text="Edit Line Color")
diff --git a/release/scripts/startup/bl_ui/properties_data_hair.py b/release/scripts/startup/bl_ui/properties_data_hair.py
index 4964316ad0f..7f95fad9a9e 100644
--- a/release/scripts/startup/bl_ui/properties_data_hair.py
+++ b/release/scripts/startup/bl_ui/properties_data_hair.py
@@ -81,7 +81,7 @@ class HAIR_MT_add_attribute(Menu):
class HAIR_UL_attributes(UIList):
- def draw_item(self, context, layout, data, attribute, icon, active_data, active_propname, index):
+ def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
domain = attribute.bl_rna.properties['domain'].enum_items[attribute.domain]
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index d464a3ffc6b..39250559741 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -17,9 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
-import bpy
from bpy.types import Panel
-from bpy.app.translations import pgettext_iface as iface_
class ModifierButtonsPanel:
@@ -37,7 +35,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
ob = context.object
return ob and ob.type != 'GPENCIL'
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.operator_menu_enum("object.modifier_add", "type")
layout.template_modifiers()
@@ -51,7 +49,7 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
ob = context.object
return ob and ob.type == 'GPENCIL'
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.operator_menu_enum("object.gpencil_modifier_add", "type")
layout.template_grease_pencil_modifiers()
diff --git a/release/scripts/startup/bl_ui/properties_data_pointcloud.py b/release/scripts/startup/bl_ui/properties_data_pointcloud.py
index eca59ea4aaf..f0584c81c0c 100644
--- a/release/scripts/startup/bl_ui/properties_data_pointcloud.py
+++ b/release/scripts/startup/bl_ui/properties_data_pointcloud.py
@@ -83,7 +83,7 @@ class POINTCLOUD_MT_add_attribute(Menu):
class POINTCLOUD_UL_attributes(UIList):
- def draw_item(self, context, layout, data, attribute, icon, active_data, active_propname, index):
+ def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
split = layout.split(factor=0.75)
diff --git a/release/scripts/startup/bl_ui/properties_data_shaderfx.py b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
index a96fef018c7..576910697ad 100644
--- a/release/scripts/startup/bl_ui/properties_data_shaderfx.py
+++ b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
@@ -37,7 +37,7 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
# ob = context.object
# return ob and ob.type == 'GPENCIL'
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.operator_menu_enum("object.shaderfx_add", "type")
layout.template_shaderfx()
diff --git a/release/scripts/startup/bl_ui/properties_data_volume.py b/release/scripts/startup/bl_ui/properties_data_volume.py
index e7bf9adb876..70056b1d27c 100644
--- a/release/scripts/startup/bl_ui/properties_data_volume.py
+++ b/release/scripts/startup/bl_ui/properties_data_volume.py
@@ -84,7 +84,7 @@ class DATA_PT_volume_file(DataButtonsPanel, Panel):
class VOLUME_UL_grids(UIList):
- def draw_item(self, context, layout, data, grid, icon, active_data, active_propname, index):
+ def draw_item(self, _context, layout, _data, grid, _icon, _active_data, _active_propname, _index):
name = grid.name
data_type = grid.bl_rna.properties['data_type'].enum_items[grid.data_type]
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 0eb5d60457c..c23cc838e51 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -37,8 +37,6 @@ class AnnotationDrawingToolsPanel:
tool_settings = context.tool_settings
- is_clip_editor = context.space_data.type == 'CLIP_EDITOR'
-
col = layout.column(align=True)
col.label(text="Draw:")
@@ -337,7 +335,6 @@ class GPENCIL_MT_material_active(Menu):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
ob = context.active_object
- mat_active = ob.active_material
for slot in ob.material_slots:
mat = slot.material
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index 4d25b8ca309..09a1f40d3a9 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -26,7 +26,7 @@ from bpy.app.translations import contexts as i18n_contexts
# Use by both image & clip context menus.
-def draw_mask_context_menu(layout, context):
+def draw_mask_context_menu(layout, _context):
layout.operator_menu_enum("mask.handle_type_set", "type")
layout.operator("mask.switch_direction")
layout.operator("mask.cyclic_toggle")
diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py
index 69c557d336f..75c1f69f84f 100644
--- a/release/scripts/startup/bl_ui/properties_output.py
+++ b/release/scripts/startup/bl_ui/properties_output.py
@@ -80,7 +80,7 @@ class RENDER_PT_dimensions(RenderOutputButtonsPanel, Panel):
fps_rate = round(fps / fps_base, 2)
# TODO: Change the following to iterate over existing presets
- custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60})
+ custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60, 120, 240})
if custom_framerate is True:
fps_label_text = tip_("Custom (%.4g fps)") % fps_rate
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 91c58ba49cb..b248a70208f 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -617,7 +617,6 @@ def brush_settings(layout, context, brush, popover=False):
# use_persistent, set_persistent_base
if capabilities.has_persistence:
- ob = context.sculpt_object
layout.separator()
layout.prop(brush, "use_persistent")
layout.operator("sculpt.set_persistent_base")
@@ -1293,7 +1292,7 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
layout.template_curve_mapping(settings, "thickness_primitive_curve", brush=True)
-def brush_basic_gpencil_sculpt_settings(layout, context, brush, *, compact=False):
+def brush_basic_gpencil_sculpt_settings(layout, _context, brush, *, compact=False):
gp_settings = brush.gpencil_settings
tool = brush.gpencil_sculpt_tool
@@ -1328,7 +1327,6 @@ def brush_basic_gpencil_sculpt_settings(layout, context, brush, *, compact=False
def brush_basic_gpencil_weight_settings(layout, _context, brush, *, compact=False):
- gp_settings = brush.gpencil_settings
layout.prop(brush, "size", slider=True)
row = layout.row(align=True)
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 5d3417fad0f..d168d9ab6dd 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -19,7 +19,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Panel
from bl_ui.utils import PresetPanel
from .properties_physics_common import (
effector_weights_ui,
diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
index 8c39684583f..ad7d6008238 100644
--- a/release/scripts/startup/bl_ui/properties_view_layer.py
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -21,7 +21,7 @@ from bpy.types import Panel, UIList
class VIEWLAYER_UL_aov(UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
+ def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname):
row = layout.row()
split = row.split(factor=0.65)
icon = 'NONE' if item.is_valid else 'ERROR'
@@ -77,8 +77,6 @@ class VIEWLAYER_PT_eevee_layer_passes_data(ViewLayerButtonsPanel, Panel):
layout.use_property_split = True
layout.use_property_decorate = False
- scene = context.scene
- rd = scene.render
view_layer = context.view_layer
col = layout.column()
@@ -101,8 +99,6 @@ class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel):
view_layer = context.view_layer
view_layer_eevee = view_layer.eevee
- scene = context.scene
- scene_eevee = scene.eevee
col = layout.column(heading="Diffuse", align=True)
col.prop(view_layer, "use_pass_diffuse_direct", text="Light")
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 73cc674858c..9b5942cbaa9 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -375,7 +375,7 @@ class IMAGE_MT_uvs_split(Menu):
class IMAGE_MT_uvs_unwrap(Menu):
bl_label = "Unwrap"
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.operator("uv.unwrap")
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 43a5e17e50e..5c5a78f3942 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -19,10 +19,6 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
-from bpy.app.translations import (
- contexts as i18n_contexts,
- pgettext_iface as iface_,
-)
class OUTLINER_HT_header(Header):
@@ -257,7 +253,7 @@ class OUTLINER_MT_collection_new(Menu):
bl_label = "Collection"
@staticmethod
- def draw_without_context_menu(context, layout):
+ def draw_without_context_menu(_context, layout):
layout.operator("outliner.collection_new", text="New Collection").nested = True
layout.operator("outliner.id_paste", text="Paste Data-Blocks", icon='PASTEDOWN')
@@ -278,7 +274,6 @@ class OUTLINER_MT_object(Menu):
layout = self.layout
space = context.space_data
- obj = context.active_object
layout.operator("outliner.id_copy", text="Copy", icon='COPYDOWN')
layout.operator("outliner.id_paste", text="Paste", icon='PASTEDOWN')
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index e10f3383bc8..fa7082e139a 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -113,6 +113,10 @@ class SEQUENCER_HT_tool_header(Header):
# TODO: options popover.
def draw_tool_settings(self, context):
+ pass
+
+ # Currently unused.
+ '''
layout = self.layout
# Active Tool
@@ -120,6 +124,7 @@ class SEQUENCER_HT_tool_header(Header):
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.draw_active_tool_header(context, layout)
tool_mode = context.mode if tool is None else tool.mode
+ '''
class SEQUENCER_HT_header(Header):
@@ -129,8 +134,6 @@ class SEQUENCER_HT_header(Header):
layout = self.layout
st = context.space_data
- scene = context.scene
- sequencer_tool_settings = context.tool_settings.sequencer_tool_settings
show_region_tool_header = st.show_region_tool_header
@@ -336,8 +339,6 @@ class SEQUENCER_MT_view(Menu):
st = context.space_data
is_preview = st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}
is_sequencer_view = st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}
- scene = context.scene
- ed = scene.sequence_editor
if st.view_type == 'PREVIEW':
# Specifying the REGION_PREVIEW context is needed in preview-only
@@ -1904,7 +1905,6 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
if strip.proxy:
proxy = strip.proxy
- flow = layout.column_flow()
if ed.proxy_storage == 'PER_STRIP':
col = layout.column(heading="Custom Proxy")
col.prop(proxy, "use_proxy_custom_directory", text="Directory")
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py
index 12ec863327c..25f2a740f7c 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_common.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py
@@ -1022,7 +1022,7 @@ def activate_by_id(context, space_type, idname, *, as_fallback=False):
return True
-def activate_by_id_or_cycle(context, space_type, idname, *, offset=1, as_fallback=False):
+def activate_by_id_or_cycle(context, space_type, idname, *, offset=1, _as_fallback=False):
# Only cycle when the active tool is activated again.
cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 8e99c3af4c3..1e52142c85c 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -1096,7 +1096,7 @@ class _defs_edit_curve:
@ToolDef.from_fn
def draw():
- def draw_settings(context, layout, tool, *, extra=False):
+ def draw_settings(context, layout, _tool, *, extra=False):
# Tool settings initialize operator options.
tool_settings = context.tool_settings
cps = tool_settings.curve_paint_settings
@@ -1589,7 +1589,7 @@ class _defs_weight_paint:
@ToolDef.from_fn
def sample_weight():
- def draw_settings(context, layout, tool):
+ def draw_settings(context, layout, _tool):
if context.tool_settings.unified_paint_settings.use_unified_weight:
weight = context.tool_settings.unified_paint_settings.weight
elif context.tool_settings.weight_paint.brush:
@@ -1869,7 +1869,7 @@ class _defs_image_uv_sculpt:
class _defs_gpencil_paint:
@staticmethod
- def gpencil_primitive_toolbar(context, layout, tool, props):
+ def gpencil_primitive_toolbar(context, layout, _tool, props):
paint = context.tool_settings.gpencil_paint
brush = paint.brush
@@ -1907,7 +1907,7 @@ class _defs_gpencil_paint:
@ToolDef.from_fn
def cutter():
- def draw_settings(context, layout, tool):
+ def draw_settings(_context, layout, tool):
props = tool.operator_properties("gpencil.stroke_cutter")
row = layout.row()
row.use_property_split = False
@@ -2020,7 +2020,7 @@ class _defs_gpencil_paint:
@ToolDef.from_fn
def eyedropper():
- def draw_settings(context, layout, tool):
+ def draw_settings(_context, layout, tool):
props = tool.operator_properties("ui.eyedropper_gpencil_color")
row = layout.row()
row.use_property_split = False
@@ -2037,7 +2037,7 @@ class _defs_gpencil_paint:
@ToolDef.from_fn
def interpolate():
- def draw_settings(context, layout, tool):
+ def draw_settings(_context, layout, tool):
props = tool.operator_properties("gpencil.interpolate")
layout.prop(props, "layers")
layout.prop(props, "flip")
@@ -2201,7 +2201,7 @@ class _defs_gpencil_edit:
@ToolDef.from_fn
def transform_fill():
- def draw_settings(context, layout, tool):
+ def draw_settings(_context, layout, tool):
props = tool.operator_properties("gpencil.transform_fill")
row = layout.row()
row.use_property_split = False
@@ -2219,7 +2219,7 @@ class _defs_gpencil_edit:
@ToolDef.from_fn
def interpolate():
- def draw_settings(context, layout, tool):
+ def draw_settings(_context, layout, tool):
props = tool.operator_properties("gpencil.interpolate")
layout.prop(props, "layers")
layout.prop(props, "interpolate_selected_only")
@@ -2411,8 +2411,6 @@ class _defs_sequencer_generic:
@ToolDef.from_fn
def sample():
- def draw_settings(_context, layout, tool):
- props = tool.operator_properties("sequencer.sample")
return dict(
idname="builtin.sample",
label="Sample",
@@ -2421,7 +2419,6 @@ class _defs_sequencer_generic:
),
icon="ops.paint.weight_sample", # XXX, needs own icon.
keymap="Sequencer Tool: Sample",
- draw_settings=draw_settings,
)
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 45460a1a5de..7219922c379 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -244,7 +244,7 @@ class TOPBAR_MT_app(Menu):
class TOPBAR_MT_file_cleanup(Menu):
bl_label = "Clean Up"
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.separator()
@@ -475,7 +475,7 @@ class TOPBAR_MT_file_export(Menu):
bl_label = "Export"
bl_owner_use_filter = False
- def draw(self, context):
+ def draw(self, _context):
if bpy.app.build_options.collada:
self.layout.operator("wm.collada_export",
text="Collada (Default) (.dae)")
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 94a1e2bec4d..b214dc0c245 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -96,7 +96,7 @@ class USERPREF_MT_editor_menus(Menu):
class USERPREF_MT_view(Menu):
bl_label = "View"
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.menu("INFO_MT_area")
@@ -241,7 +241,7 @@ class USERPREF_PT_interface_translation(InterfacePanel, CenterAlignMixIn, Panel)
bl_translation_context = i18n_contexts.id_windowmanager
@classmethod
- def poll(cls, context):
+ def poll(cls, _context):
return bpy.app.build_options.international
def draw_centered(self, context, layout):
@@ -581,7 +581,7 @@ class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel):
bl_label = "Cycles Render Devices"
@classmethod
- def poll(cls, context):
+ def poll(cls, _context):
# No GPU rendering on macOS currently.
import sys
return bpy.app.build_options.cycles and sys.platform != "darwin"
@@ -642,7 +642,7 @@ class USERPREF_PT_system_video_sequencer(SystemPanel, CenterAlignMixIn, Panel):
def draw_centered(self, context, layout):
prefs = context.preferences
system = prefs.system
- edit = prefs.edit
+ # edit = prefs.edit
layout.prop(system, "memory_cache_limit")
@@ -2185,7 +2185,7 @@ class ExperimentalPanel:
url_prefix = "https://developer.blender.org/"
@classmethod
- def poll(cls, context):
+ def poll(cls, _context):
return bpy.app.version_cycle == 'alpha'
def _draw_items(self, context, items):
@@ -2260,7 +2260,7 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
bl_label = "Debugging"
@classmethod
- def poll(cls, context):
+ def poll(cls, _context):
# Unlike the other experimental panels, the debugging one is always visible
# even in beta or release.
return True
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 41a1831f46a..26e0c128f7c 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1068,7 +1068,7 @@ class VIEW3D_MT_snap(Menu):
class VIEW3D_MT_uv_map(Menu):
bl_label = "UV Mapping"
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.operator("uv.unwrap")
@@ -1822,7 +1822,7 @@ class VIEW3D_MT_select_edit_armature(Menu):
class VIEW3D_MT_paint_gpencil(Menu):
bl_label = "Paint"
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.operator("gpencil.vertex_color_set", text="Set Vertex Colors")
@@ -2238,7 +2238,7 @@ class VIEW3D_MT_object(Menu):
bl_context = "objectmode"
bl_label = "Object"
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.menu("VIEW3D_MT_transform_object")
@@ -2717,7 +2717,7 @@ class VIEW3D_MT_object_constraints(Menu):
class VIEW3D_MT_object_quick_effects(Menu):
bl_label = "Quick Effects"
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
layout.operator("object.quick_fur")
@@ -7009,10 +7009,9 @@ class VIEW3D_PT_gpencil_curve_edit(Panel):
bl_label = "Curve Editing"
def draw(self, context):
- gpd = context.gpencil_data
- settings = context.tool_settings.gpencil_sculpt
-
layout = self.layout
+
+ gpd = context.gpencil_data
col = layout.column(align=True)
col.prop(gpd, "edit_curve_resolution")
col.prop(gpd, "curve_edit_threshold")
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index ecf46ac2592..10010ab0b15 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -199,8 +199,6 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
ob = context.active_object
mesh = ob.data
- split = layout.split()
-
row = layout.row(align=True, heading="Transform")
row.prop(tool_settings, "use_transform_correct_face_attributes")
@@ -1353,8 +1351,6 @@ class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePenci
if context.mode == 'PAINT_GPENCIL':
brush = tool_settings.gpencil_paint.brush
if brush is not None:
- gp_settings = brush.gpencil_settings
-
col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
if brush.use_custom_icon:
@@ -1493,8 +1489,9 @@ class VIEW3D_PT_tools_grease_pencil_brush_stroke(Panel, View3DPanel):
brush = context.tool_settings.gpencil_paint.brush
return brush is not None and brush.gpencil_tool == 'DRAW'
- def draw(self, context):
- layout = self.layout
+ def draw(self, _context):
+ # layout = self.layout
+ pass
class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(Panel, View3DPanel):
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 2fce4bfc5b8..8666291cec8 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -235,12 +235,12 @@ typedef enum eAnimData_Recalc {
ADT_RECALC_ALL = (ADT_RECALC_DRIVERS | ADT_RECALC_ANIM),
} eAnimData_Recalc;
-bool BKE_animsys_store_rna_setting(struct PointerRNA *ptr,
- const char *rna_path,
- const int array_index,
- struct PathResolvedRNA *r_result);
-bool BKE_animsys_read_rna_setting(struct PathResolvedRNA *anim_rna, float *r_value);
-bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float value);
+bool BKE_animsys_rna_path_resolve(struct PointerRNA *ptr,
+ const char *rna_path,
+ const int array_index,
+ struct PathResolvedRNA *r_result);
+bool BKE_animsys_read_from_rna_path(struct PathResolvedRNA *anim_rna, float *r_value);
+bool BKE_animsys_write_to_rna_path(struct PathResolvedRNA *anim_rna, const float value);
/* Evaluation loop for evaluating animation data */
void BKE_animsys_evaluate_animdata(struct ID *id,
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index db44a771095..f5face2120e 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -27,6 +27,8 @@
extern "C" {
#endif
+struct AnimationEvalContext;
+struct bAction;
struct BMEditMesh;
struct Bone;
struct Depsgraph;
@@ -193,6 +195,12 @@ void BKE_pose_where_is_bone(struct Depsgraph *depsgraph,
bool do_extra);
void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
+/* Evaluate the action and apply it to the pose. If any pose bones are selected, only FCurves that
+ * relate to those bones are evaluated. */
+void BKE_pose_apply_action(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context);
+
/* get_objectspace_bone_matrix has to be removed still */
void get_objectspace_bone_matrix(struct Bone *bone,
float M_accumulatedMatrix[4][4],
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 17eb6e19292..66bfe620df7 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 9
+#define BLENDER_FILE_SUBVERSION 10
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index 3631feb5071..ec2262d4f60 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -59,6 +59,7 @@ enum {
CURVEMAP_SLOPE_POS_NEG = 2,
};
+void BKE_curvemapping_reset_view(struct CurveMapping *cumap);
void BKE_curvemap_reset(struct CurveMap *cuma, const struct rctf *clipr, int preset, int slope);
void BKE_curvemap_remove(struct CurveMap *cuma, const short flag);
bool BKE_curvemap_remove_point(struct CurveMap *cuma, struct CurveMapPoint *cmp);
diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h
index 1b1c4deeb8a..7d295929e77 100644
--- a/source/blender/blenkernel/BKE_cryptomatte.h
+++ b/source/blender/blenkernel/BKE_cryptomatte.h
@@ -31,21 +31,25 @@ extern "C" {
#endif
struct CryptomatteSession;
-struct ID;
-struct Main;
struct Material;
struct Object;
struct RenderResult;
struct CryptomatteSession *BKE_cryptomatte_init(void);
+struct CryptomatteSession *BKE_cryptomatte_init_from_render_result(
+ const struct RenderResult *render_result);
void BKE_cryptomatte_free(struct CryptomatteSession *session);
+void BKE_cryptomatte_add_layer(struct CryptomatteSession *session, const char *layer_name);
uint32_t BKE_cryptomatte_hash(const char *name, int name_len);
uint32_t BKE_cryptomatte_object_hash(struct CryptomatteSession *session,
+ const char *layer_name,
const struct Object *object);
uint32_t BKE_cryptomatte_material_hash(struct CryptomatteSession *session,
+ const char *layer_name,
const struct Material *material);
uint32_t BKE_cryptomatte_asset_hash(struct CryptomatteSession *session,
+ const char *layer_name,
const struct Object *object);
float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash);
@@ -53,11 +57,9 @@ char *BKE_cryptomatte_entries_to_matte_id(struct NodeCryptomatte *node_storage);
void BKE_cryptomatte_matte_id_to_entries(struct NodeCryptomatte *node_storage,
const char *matte_id);
-void BKE_cryptomatte_store_metadata(struct CryptomatteSession *session,
+void BKE_cryptomatte_store_metadata(const struct CryptomatteSession *session,
struct RenderResult *render_result,
- const ViewLayer *view_layer,
- eViewLayerCryptomatteFlags cryptomatte_layer,
- const char *cryptomatte_layer_name);
+ const ViewLayer *view_layer);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_cryptomatte.hh b/source/blender/blenkernel/BKE_cryptomatte.hh
index c1da0339359..f10b4c1f7c4 100644
--- a/source/blender/blenkernel/BKE_cryptomatte.hh
+++ b/source/blender/blenkernel/BKE_cryptomatte.hh
@@ -81,9 +81,26 @@ struct CryptomatteLayer {
static std::unique_ptr<CryptomatteLayer> read_from_manifest(blender::StringRefNull manifest);
uint32_t add_ID(const struct ID &id);
void add_hash(blender::StringRef name, CryptomatteHash cryptomatte_hash);
- std::string manifest();
+ std::string manifest() const;
std::optional<std::string> operator[](float encoded_hash) const;
};
+struct CryptomatteStampDataCallbackData {
+ struct CryptomatteSession *session;
+ blender::Map<std::string, std::string> hash_to_layer_name;
+
+ /**
+ * Extract the hash from a stamp data key.
+ *
+ * Cryptomatte keys are formatted as "cryptomatte/{layer_hash}/{attribute}".
+ */
+ static blender::StringRef extract_layer_hash(blender::StringRefNull key);
+
+ /* C type callback function (StampCallback). */
+ static void extract_layer_names(void *_data, const char *propname, char *propvalue, int len);
+ /* C type callback function (StampCallback). */
+ static void extract_layer_manifest(void *_data, const char *propname, char *propvalue, int len);
+};
+
} // namespace blender::bke::cryptomatte
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index b6116b32ca5..2c6e5ed3873 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -223,7 +223,7 @@ struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset);
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb) \
{ \
- ListBase *_lbarray[MAX_LIBARRAY]; \
+ ListBase *_lbarray[INDEX_ID_MAX]; \
int _i = set_listbasepointers((_bmain), _lbarray); \
while (_i--) { \
(_lb) = _lbarray[_i];
@@ -234,9 +234,13 @@ struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset);
((void)0)
/**
- * DO NOT use break statement with that macro,
- * use #FOREACH_MAIN_LISTBASE and #FOREACH_MAIN_LISTBASE_ID instead
- * if you need that kind of control flow. */
+ * Top level `foreach`-like macro allowing to loop over all IDs in a given #Main data-base.
+ *
+ * NOTE: Order tries to go from 'user IDs' to 'used IDs' (e.g. collections will be processed
+ * before objects, which will be processed before obdata types, etc.).
+ *
+ * WARNING: DO NOT use break statement with that macro, use #FOREACH_MAIN_LISTBASE and
+ * #FOREACH_MAIN_LISTBASE_ID instead if you need that kind of control flow. */
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id) \
{ \
ListBase *_lb; \
@@ -259,8 +263,8 @@ const char *BKE_main_blendfile_path_from_global(void);
struct ListBase *which_libbase(struct Main *bmain, short type);
-#define MAX_LIBARRAY 41
-int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
+//#define INDEX_ID_MAX 41
+int set_listbasepointers(struct Main *main, struct ListBase *lb[]);
#define MAIN_VERSION_ATLEAST(main, ver, subver) \
((main)->versionfile > (ver) || \
diff --git a/source/blender/blenkernel/BKE_mesh_mirror.h b/source/blender/blenkernel/BKE_mesh_mirror.h
index 2f792049a41..b5d0fec6bc1 100644
--- a/source/blender/blenkernel/BKE_mesh_mirror.h
+++ b/source/blender/blenkernel/BKE_mesh_mirror.h
@@ -46,7 +46,7 @@ void BKE_mesh_mirror_apply_mirror_on_axis(struct Main *bmain,
struct Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(struct MirrorModifierData *mmd,
struct Object *ob,
const struct Mesh *mesh,
- int axis);
+ const int axis);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index d675df6d868..655c53455cc 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -301,11 +301,11 @@ typedef struct bNodeType {
void (*free_self)(struct bNodeType *ntype);
/* **** execution callbacks **** */
- NodeInitExecFunction initexecfunc;
- NodeFreeExecFunction freeexecfunc;
- NodeExecFunction execfunc;
+ NodeInitExecFunction init_exec_fn;
+ NodeFreeExecFunction free_exec_fn;
+ NodeExecFunction exec_fn;
/* gpu */
- NodeGPUExecFunction gpufunc;
+ NodeGPUExecFunction gpu_fn;
/* Expands the bNode into nodes in a multi-function network, which will be evaluated later on. */
NodeExpandInMFNetworkFunction expand_in_mf_network;
@@ -829,10 +829,10 @@ void node_type_group_update(struct bNodeType *ntype,
struct bNode *node));
void node_type_exec(struct bNodeType *ntype,
- NodeInitExecFunction initexecfunc,
- NodeFreeExecFunction freeexecfunc,
- NodeExecFunction execfunc);
-void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc);
+ NodeInitExecFunction init_exec_fn,
+ NodeFreeExecFunction free_exec_fn,
+ NodeExecFunction exec_fn);
+void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpu_fn);
void node_type_internal_links(struct bNodeType *ntype,
void (*update_internal_links)(struct bNodeTree *, struct bNode *));
diff --git a/source/blender/blenkernel/BKE_node_ui_storage.hh b/source/blender/blenkernel/BKE_node_ui_storage.hh
index 231eb11d473..a49ff988272 100644
--- a/source/blender/blenkernel/BKE_node_ui_storage.hh
+++ b/source/blender/blenkernel/BKE_node_ui_storage.hh
@@ -16,6 +16,8 @@
#pragma once
+#include <mutex>
+
#include "BLI_hash.hh"
#include "BLI_map.hh"
#include "BLI_session_uuid.h"
@@ -82,6 +84,7 @@ struct NodeUIStorage {
struct NodeTreeUIStorage {
blender::Map<NodeTreeEvaluationContext, blender::Map<std::string, NodeUIStorage>> context_map;
+ std::mutex context_map_mutex;
};
const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C,
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index bca23f93b5c..3e5bf2570a6 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -473,10 +473,19 @@ typedef struct SculptSession {
struct MPropCol *vcol;
float *vmask;
- /* Mesh connectivity */
+ /* Mesh connectivity maps. */
+ /* Vertices to adjacent polys. */
struct MeshElemMap *pmap;
int *pmap_mem;
+ /* Edges to adjacent polys. */
+ struct MeshElemMap *epmap;
+ int *epmap_mem;
+
+ /* Vertices to adjacent edges. */
+ struct MeshElemMap *vemap;
+ int *vemap_mem;
+
/* Mesh Face Sets */
/* Total number of polys of the base mesh. */
int totfaces;
@@ -515,6 +524,7 @@ typedef struct SculptSession {
struct StrokeCache *cache;
struct FilterCache *filter_cache;
+ struct ExpandCache *expand_cache;
/* Cursor data and active vertex for tools */
SculptVertRef active_vertex_index;
diff --git a/source/blender/blenkernel/BKE_volume_to_mesh.hh b/source/blender/blenkernel/BKE_volume_to_mesh.hh
index 1ec8a8e84cd..1f6e89636c4 100644
--- a/source/blender/blenkernel/BKE_volume_to_mesh.hh
+++ b/source/blender/blenkernel/BKE_volume_to_mesh.hh
@@ -21,7 +21,6 @@
#endif
struct Mesh;
-struct VolumeGrid;
namespace blender::bke {
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 1e7986eedd9..c954d0670f0 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -77,6 +77,7 @@ set(SRC
intern/appdir.c
intern/armature.c
intern/armature_deform.c
+ intern/armature_pose.cc
intern/armature_update.c
intern/asset.cc
intern/attribute.c
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 06b8bd5f0f2..f9c2a4e53ad 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -2002,7 +2002,7 @@ void BKE_pose_blend_read_lib(BlendLibReader *reader, Object *ob, bPose *pose)
IDP_BlendReadLib(reader, pchan->prop);
- BLO_read_id_address(reader, arm->id.lib, &pchan->custom);
+ BLO_read_id_address(reader, ob->id.lib, &pchan->custom);
if (UNLIKELY(pchan->bone == NULL)) {
rebuild = true;
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 4d490f8f76a..9a890fd02be 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -376,59 +376,56 @@ static bool is_fcurve_evaluatable(FCurve *fcu)
return true;
}
-bool BKE_animsys_store_rna_setting(PointerRNA *ptr,
- /* typically 'fcu->rna_path', 'fcu->array_index' */
- const char *rna_path,
- const int array_index,
- PathResolvedRNA *r_result)
+bool BKE_animsys_rna_path_resolve(PointerRNA *ptr,
+ /* typically 'fcu->rna_path', 'fcu->array_index' */
+ const char *rna_path,
+ const int array_index,
+ PathResolvedRNA *r_result)
{
- bool success = false;
- const char *path = rna_path;
+ if (rna_path == NULL) {
+ return false;
+ }
- /* write value to setting */
- if (path) {
- /* get property to write to */
- if (RNA_path_resolve_property(ptr, path, &r_result->ptr, &r_result->prop)) {
- if ((ptr->owner_id == NULL) || RNA_property_animateable(&r_result->ptr, r_result->prop)) {
- int array_len = RNA_property_array_length(&r_result->ptr, r_result->prop);
-
- if (array_len && array_index >= array_len) {
- if (G.debug & G_DEBUG) {
- CLOG_WARN(&LOG,
- "Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d",
- (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
- path,
- array_index,
- array_len - 1);
- }
- }
- else {
- r_result->prop_index = array_len ? array_index : -1;
- success = true;
- }
- }
+ const char *path = rna_path;
+ if (!RNA_path_resolve_property(ptr, path, &r_result->ptr, &r_result->prop)) {
+ /* failed to get path */
+ /* XXX don't tag as failed yet though, as there are some legit situations (Action Constraint)
+ * where some channels will not exist, but shouldn't lock up Action */
+ if (G.debug & G_DEBUG) {
+ CLOG_WARN(&LOG,
+ "Animato: Invalid path. ID = '%s', '%s[%d]'",
+ (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
+ path,
+ array_index);
}
- else {
- /* failed to get path */
- /* XXX don't tag as failed yet though, as there are some legit situations (Action Constraint)
- * where some channels will not exist, but shouldn't lock up Action */
- if (G.debug & G_DEBUG) {
- CLOG_WARN(&LOG,
- "Animato: Invalid path. ID = '%s', '%s[%d]'",
- (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
- path,
- array_index);
- }
+ return false;
+ }
+
+ if (ptr->owner_id != NULL && !RNA_property_animateable(&r_result->ptr, r_result->prop)) {
+ return false;
+ }
+
+ int array_len = RNA_property_array_length(&r_result->ptr, r_result->prop);
+ if (array_len && array_index >= array_len) {
+ if (G.debug & G_DEBUG) {
+ CLOG_WARN(&LOG,
+ "Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d",
+ (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
+ path,
+ array_index,
+ array_len - 1);
}
+ return false;
}
- return success;
+ r_result->prop_index = array_len ? array_index : -1;
+ return true;
}
/* less than 1.0 evaluates to false, use epsilon to avoid float error */
#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON)))
-bool BKE_animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value)
+bool BKE_animsys_read_from_rna_path(PathResolvedRNA *anim_rna, float *r_value)
{
PropertyRNA *prop = anim_rna->prop;
PointerRNA *ptr = &anim_rna->ptr;
@@ -491,7 +488,7 @@ bool BKE_animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value)
}
/* Write the given value to a setting using RNA, and return success */
-bool BKE_animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float value)
+bool BKE_animsys_write_to_rna_path(PathResolvedRNA *anim_rna, const float value)
{
PropertyRNA *prop = anim_rna->prop;
PointerRNA *ptr = &anim_rna->ptr;
@@ -502,7 +499,7 @@ bool BKE_animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float value)
/* Check whether value is new. Otherwise we skip all the updates. */
float old_value;
- if (!BKE_animsys_read_rna_setting(anim_rna, &old_value)) {
+ if (!BKE_animsys_read_from_rna_path(anim_rna, &old_value)) {
return false;
}
if (old_value == value) {
@@ -591,8 +588,8 @@ static void animsys_write_orig_anim_rna(PointerRNA *ptr,
}
PathResolvedRNA orig_anim_rna;
/* TODO(sergey): Should be possible to cache resolved path in dependency graph somehow. */
- if (BKE_animsys_store_rna_setting(&ptr_orig, rna_path, array_index, &orig_anim_rna)) {
- BKE_animsys_write_rna_setting(&orig_anim_rna, value);
+ if (BKE_animsys_rna_path_resolve(&ptr_orig, rna_path, array_index, &orig_anim_rna)) {
+ BKE_animsys_write_to_rna_path(&orig_anim_rna, value);
}
}
@@ -614,9 +611,9 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr,
}
PathResolvedRNA anim_rna;
- if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ if (BKE_animsys_rna_path_resolve(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
- BKE_animsys_write_rna_setting(&anim_rna, curval);
+ BKE_animsys_write_to_rna_path(&anim_rna, curval);
if (flush_to_original) {
animsys_write_orig_anim_rna(ptr, fcu->rna_path, fcu->array_index, curval);
}
@@ -666,9 +663,9 @@ static void animsys_evaluate_drivers(PointerRNA *ptr,
* NOTE: for 'layering' option later on, we should check if we should remove old value
* before adding new to only be done when drivers only changed. */
PathResolvedRNA anim_rna;
- if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ if (BKE_animsys_rna_path_resolve(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
- ok = BKE_animsys_write_rna_setting(&anim_rna, curval);
+ ok = BKE_animsys_write_to_rna_path(&anim_rna, curval);
}
/* set error-flag if evaluation failed */
@@ -747,19 +744,19 @@ void animsys_evaluate_action_group(PointerRNA *ptr,
/* check if this curve should be skipped */
if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0 && !BKE_fcurve_is_empty(fcu)) {
PathResolvedRNA anim_rna;
- if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ if (BKE_animsys_rna_path_resolve(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
- BKE_animsys_write_rna_setting(&anim_rna, curval);
+ BKE_animsys_write_to_rna_path(&anim_rna, curval);
}
}
}
}
/* Evaluate Action (F-Curve Bag) */
-static void animsys_evaluate_action_ex(PointerRNA *ptr,
- bAction *act,
- const AnimationEvalContext *anim_eval_context,
- const bool flush_to_original)
+void animsys_evaluate_action(PointerRNA *ptr,
+ bAction *act,
+ const AnimationEvalContext *anim_eval_context,
+ const bool flush_to_original)
{
/* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */
if (act == NULL) {
@@ -772,14 +769,6 @@ static void animsys_evaluate_action_ex(PointerRNA *ptr,
animsys_evaluate_fcurves(ptr, &act->curves, anim_eval_context, flush_to_original);
}
-void animsys_evaluate_action(PointerRNA *ptr,
- bAction *act,
- const AnimationEvalContext *anim_eval_context,
- const bool flush_to_original)
-{
- animsys_evaluate_action_ex(ptr, act, anim_eval_context, flush_to_original);
-}
-
/* ***************************************** */
/* NLA System - Evaluation */
@@ -2008,7 +1997,7 @@ void nladata_flush_channels(PointerRNA *ptr,
if (nec->is_array) {
rna.prop_index = i;
}
- BKE_animsys_write_rna_setting(&rna, value);
+ BKE_animsys_write_to_rna_path(&rna, value);
if (flush_to_original) {
animsys_write_orig_anim_rna(ptr, nec->rna_path, rna.prop_index, value);
}
@@ -2769,8 +2758,8 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
/* for each override, simply execute... */
for (aor = adt->overrides.first; aor; aor = aor->next) {
PathResolvedRNA anim_rna;
- if (BKE_animsys_store_rna_setting(ptr, aor->rna_path, aor->array_index, &anim_rna)) {
- BKE_animsys_write_rna_setting(&anim_rna, aor->value);
+ if (BKE_animsys_rna_path_resolve(ptr, aor->rna_path, aor->array_index, &anim_rna)) {
+ BKE_animsys_write_to_rna_path(&anim_rna, aor->value);
}
}
}
@@ -2850,7 +2839,7 @@ void BKE_animsys_evaluate_animdata(ID *id,
}
/* evaluate Active Action only */
else if (adt->action) {
- animsys_evaluate_action_ex(&id_ptr, adt->action, anim_eval_context, flush_to_original);
+ animsys_evaluate_action(&id_ptr, adt->action, anim_eval_context, flush_to_original);
}
}
@@ -3100,13 +3089,13 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCu
// printf("\told val = %f\n", fcu->curval);
PathResolvedRNA anim_rna;
- if (BKE_animsys_store_rna_setting(&id_ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ if (BKE_animsys_rna_path_resolve(&id_ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
/* Evaluate driver, and write results to COW-domain destination */
const float ctime = DEG_get_ctime(depsgraph);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
depsgraph, ctime);
const float curval = calculate_fcurve(&anim_rna, fcu, &anim_eval_context);
- ok = BKE_animsys_write_rna_setting(&anim_rna, curval);
+ ok = BKE_animsys_write_to_rna_path(&anim_rna, curval);
/* Flush results & status codes to original data for UI (T59984) */
if (ok && DEG_is_active(depsgraph)) {
diff --git a/source/blender/blenkernel/intern/armature_pose.cc b/source/blender/blenkernel/intern/armature_pose.cc
new file mode 100644
index 00000000000..bb371b16c42
--- /dev/null
+++ b/source/blender/blenkernel/intern/armature_pose.cc
@@ -0,0 +1,133 @@
+/*
+ * 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) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Defines and code for core node types
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BKE_animsys.h"
+#include "BKE_armature.h"
+
+#include "BLI_set.hh"
+
+#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+
+#include "RNA_access.h"
+
+namespace {
+using BoneNameSet = blender::Set<std::string>;
+
+// Forward declarations.
+BoneNameSet pose_apply_find_selected_bones(const bPose *pose);
+void pose_apply_disable_fcurves_for_unselected_bones(bAction *action,
+ const BoneNameSet &selected_bone_names);
+void pose_apply_restore_fcurves(bAction *action);
+} // namespace
+
+void BKE_pose_apply_action(struct Object *ob,
+ struct bAction *action,
+ struct AnimationEvalContext *anim_eval_context)
+{
+ bPose *pose = ob->pose;
+ if (pose == nullptr) {
+ return;
+ }
+
+ const BoneNameSet selected_bone_names = pose_apply_find_selected_bones(pose);
+ const bool limit_to_selected_bones = !selected_bone_names.is_empty();
+
+ if (limit_to_selected_bones) {
+ /* Mute all FCurves that are not associated with selected bones. This separates the concept of
+ * bone selection from the FCurve evaluation code. */
+ pose_apply_disable_fcurves_for_unselected_bones(action, selected_bone_names);
+ }
+
+ /* Apply the Action. */
+ PointerRNA pose_owner_ptr;
+ RNA_id_pointer_create(&ob->id, &pose_owner_ptr);
+ animsys_evaluate_action(&pose_owner_ptr, action, anim_eval_context, false);
+
+ if (limit_to_selected_bones) {
+ pose_apply_restore_fcurves(action);
+ }
+}
+
+namespace {
+BoneNameSet pose_apply_find_selected_bones(const bPose *pose)
+{
+ BoneNameSet selected_bone_names;
+ bool all_bones_selected = true;
+ bool no_bones_selected = true;
+
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
+ const bool is_selected = (pchan->bone->flag & BONE_SELECTED) != 0 &&
+ (pchan->bone->flag & BONE_HIDDEN_P) == 0;
+ all_bones_selected &= is_selected;
+ no_bones_selected &= !is_selected;
+
+ if (is_selected) {
+ /* Bone names are unique, so no need to check for duplicates. */
+ selected_bone_names.add_new(pchan->name);
+ }
+ }
+
+ /* If no bones are selected, act as if all are. */
+ if (all_bones_selected || no_bones_selected) {
+ return BoneNameSet(); /* An empty set means "ignore bone selection". */
+ }
+ return selected_bone_names;
+}
+
+void pose_apply_restore_fcurves(bAction *action)
+{
+ /* TODO(Sybren): Restore the FCurve flags, instead of just erasing the 'disabled' flag. */
+ LISTBASE_FOREACH (FCurve *, fcu, &action->curves) {
+ fcu->flag &= ~FCURVE_DISABLED;
+ }
+}
+
+void pose_apply_disable_fcurves_for_unselected_bones(bAction *action,
+ const BoneNameSet &selected_bone_names)
+{
+ LISTBASE_FOREACH (FCurve *, fcu, &action->curves) {
+ if (!fcu->rna_path || !strstr(fcu->rna_path, "pose.bones[")) {
+ continue;
+ }
+
+ /* Get bone name, and check if this bone is selected. */
+ char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
+ if (!bone_name) {
+ continue;
+ }
+ const bool is_selected = selected_bone_names.contains(bone_name);
+ MEM_freeN(bone_name);
+ if (is_selected) {
+ continue;
+ }
+
+ fcu->flag |= FCURVE_DISABLED;
+ }
+}
+
+} // namespace
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 8974190d0e3..61dc0903cc8 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -31,6 +31,7 @@
#include "BLI_color.hh"
#include "BLI_float2.hh"
#include "BLI_span.hh"
+#include "BLI_threads.h"
#include "CLG_log.h"
@@ -712,11 +713,13 @@ struct CustomDataAccessInfo {
class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
using AsReadAttribute = ReadAttributePtr (*)(const void *data, const int domain_size);
using AsWriteAttribute = WriteAttributePtr (*)(void *data, const int domain_size);
+ using UpdateOnRead = void (*)(const GeometryComponent &component);
using UpdateOnWrite = void (*)(GeometryComponent &component);
const CustomDataType stored_type_;
const CustomDataAccessInfo custom_data_access_;
const AsReadAttribute as_read_attribute_;
const AsWriteAttribute as_write_attribute_;
+ const UpdateOnRead update_on_read_;
const UpdateOnWrite update_on_write_;
public:
@@ -730,6 +733,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
const CustomDataAccessInfo custom_data_access,
const AsReadAttribute as_read_attribute,
const AsWriteAttribute as_write_attribute,
+ const UpdateOnRead update_on_read,
const UpdateOnWrite update_on_write)
: BuiltinAttributeProvider(
std::move(attribute_name), domain, attribute_type, creatable, writable, deletable),
@@ -737,6 +741,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
custom_data_access_(custom_data_access),
as_read_attribute_(as_read_attribute),
as_write_attribute_(as_write_attribute),
+ update_on_read_(update_on_read),
update_on_write_(update_on_write)
{
}
@@ -747,6 +752,11 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
if (custom_data == nullptr) {
return {};
}
+
+ if (update_on_read_ != nullptr) {
+ update_on_read_(component);
+ }
+
const int domain_size = component.attribute_domain_size(domain_);
const void *data = CustomData_get_layer(custom_data, stored_type_);
if (data == nullptr) {
@@ -1350,6 +1360,43 @@ static WriteAttributePtr make_material_index_write_attribute(void *data, const i
ATTR_DOMAIN_POLYGON, MutableSpan<MPoly>((MPoly *)data, domain_size));
}
+static float3 get_vertex_normal(const MVert &vert)
+{
+ float3 result;
+ normal_short_to_float_v3(result, vert.no);
+ return result;
+}
+
+static ReadAttributePtr make_vertex_normal_read_attribute(const void *data, const int domain_size)
+{
+ return std::make_unique<DerivedArrayReadAttribute<MVert, float3, get_vertex_normal>>(
+ ATTR_DOMAIN_POINT, Span<MVert>((const MVert *)data, domain_size));
+}
+
+static void update_vertex_normals_when_dirty(const GeometryComponent &component)
+{
+ const Mesh *mesh = get_mesh_from_component_for_read(component);
+ if (mesh == nullptr) {
+ return;
+ }
+
+ /* Since normals are derived data, `const` write access to them is okay. However, ensure that
+ * two threads don't use write normals to a mesh at the same time. Note that this relies on
+ * the idempotence of the operation; calculating the normals just fills the #MVert struct
+ * rather than allocating new memory. */
+ if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
+ ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
+ BLI_mutex_lock(mesh_eval_mutex);
+
+ /* Check again to avoid a second thread needlessly recalculating the same normals. */
+ if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
+ BKE_mesh_calc_normals(const_cast<Mesh *>(mesh));
+ }
+
+ BLI_mutex_unlock(mesh_eval_mutex);
+ }
+}
+
static float2 get_loop_uv(const MLoopUV &uv)
{
return float2(uv.uv);
@@ -1459,6 +1506,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
point_access,
make_vertex_position_read_attribute,
make_vertex_position_write_attribute,
+ nullptr,
tag_normals_dirty_when_writing_position);
static BuiltinCustomDataLayerProvider material_index("material_index",
@@ -1471,8 +1519,22 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
polygon_access,
make_material_index_read_attribute,
make_material_index_write_attribute,
+ nullptr,
nullptr);
+ static BuiltinCustomDataLayerProvider vertex_normal("vertex_normal",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_FLOAT3,
+ CD_MVERT,
+ BuiltinAttributeProvider::NonCreatable,
+ BuiltinAttributeProvider::Readonly,
+ BuiltinAttributeProvider::NonDeletable,
+ point_access,
+ make_vertex_normal_read_attribute,
+ nullptr,
+ update_vertex_normals_when_dirty,
+ nullptr);
+
static NamedLegacyCustomDataProvider uvs(ATTR_DOMAIN_CORNER,
CD_PROP_FLOAT2,
CD_MLOOPUV,
@@ -1493,7 +1555,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static CustomDataAttributeProvider edge_custom_data(ATTR_DOMAIN_EDGE, edge_access);
static CustomDataAttributeProvider polygon_custom_data(ATTR_DOMAIN_POLYGON, polygon_access);
- return ComponentAttributeProviders({&position, &material_index},
+ return ComponentAttributeProviders({&position, &material_index, &vertex_normal},
{&uvs,
&vertex_colors,
&corner_custom_data,
@@ -1541,6 +1603,7 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud()
point_access,
make_array_read_attribute<float3, ATTR_DOMAIN_POINT>,
make_array_write_attribute<float3, ATTR_DOMAIN_POINT>,
+ nullptr,
nullptr);
static BuiltinCustomDataLayerProvider radius(
"radius",
@@ -1553,6 +1616,7 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud()
point_access,
make_array_read_attribute<float, ATTR_DOMAIN_POINT>,
make_array_write_attribute<float, ATTR_DOMAIN_POINT>,
+ nullptr,
nullptr);
static CustomDataAttributeProvider point_custom_data(ATTR_DOMAIN_POINT, point_access);
return ComponentAttributeProviders({&position, &radius}, {&point_custom_data});
@@ -1886,7 +1950,7 @@ OutputAttributePtr GeometryComponent::attribute_try_get_for_output(const StringR
if (!attribute) {
this->attribute_try_create(attribute_name, domain, data_type);
attribute = this->attribute_try_get_for_write(attribute_name);
- if (default_value != nullptr) {
+ if (attribute && default_value != nullptr) {
void *data = attribute->get_span_for_write_only().data();
cpp_type->fill_initialized(default_value, data, attribute->size());
attribute->apply_span();
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 32710c4fa60..101f4b7caf6 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -865,7 +865,7 @@ bool BKE_blendfile_write_partial(Main *bmain_src,
ReportList *reports)
{
Main *bmain_dst = MEM_callocN(sizeof(Main), "copybuffer");
- ListBase *lbarray_dst[MAX_LIBARRAY], *lbarray_src[MAX_LIBARRAY];
+ ListBase *lbarray_dst[INDEX_ID_MAX], *lbarray_src[INDEX_ID_MAX];
int a, retval;
void *path_list_backup = NULL;
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 2ad0ac950d0..47427beccba 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -783,7 +783,7 @@ void BKE_bpath_traverse_main(Main *bmain,
const int flag,
void *bpath_user_data)
{
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(bmain, lbarray);
while (a--) {
BKE_bpath_traverse_id_list(bmain, lbarray[a], visit_cb, flag, bpath_user_data);
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 3eb9fb6161d..44d9bd6b2d2 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -965,6 +965,12 @@ void BKE_curvemapping_changed_all(CurveMapping *cumap)
cumap->cur = cur;
}
+/* Reset the view for current curve. */
+void BKE_curvemapping_reset_view(CurveMapping *cumap)
+{
+ cumap->curr = cumap->clipr;
+}
+
/* table should be verified */
float BKE_curvemap_evaluateF(const CurveMapping *cumap, const CurveMap *cuma, float value)
{
diff --git a/source/blender/blenkernel/intern/cryptomatte.cc b/source/blender/blenkernel/intern/cryptomatte.cc
index 42158dced96..9d9cace3a35 100644
--- a/source/blender/blenkernel/intern/cryptomatte.cc
+++ b/source/blender/blenkernel/intern/cryptomatte.cc
@@ -37,6 +37,8 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "RE_pipeline.h"
+
#include "MEM_guardedalloc.h"
#include <cctype>
@@ -47,13 +49,13 @@
#include <string_view>
struct CryptomatteSession {
- blender::bke::cryptomatte::CryptomatteLayer objects;
- blender::bke::cryptomatte::CryptomatteLayer assets;
- blender::bke::cryptomatte::CryptomatteLayer materials;
+ blender::Map<std::string, blender::bke::cryptomatte::CryptomatteLayer> layers;
CryptomatteSession();
CryptomatteSession(const Main *bmain);
+ CryptomatteSession(StampData *stamp_data);
+ blender::bke::cryptomatte::CryptomatteLayer &add_layer(std::string layer_name);
std::optional<std::string> operator[](float encoded_hash) const;
#ifdef WITH_CXX_GUARDEDALLOC
@@ -67,21 +69,50 @@ CryptomatteSession::CryptomatteSession()
CryptomatteSession::CryptomatteSession(const Main *bmain)
{
- LISTBASE_FOREACH (ID *, id, &bmain->objects) {
- objects.add_ID(*id);
+ if (!BLI_listbase_is_empty(&bmain->objects)) {
+ blender::bke::cryptomatte::CryptomatteLayer &objects = add_layer("CryptoObject");
+ LISTBASE_FOREACH (ID *, id, &bmain->objects) {
+ objects.add_ID(*id);
+ }
}
- LISTBASE_FOREACH (ID *, id, &bmain->materials) {
- materials.add_ID(*id);
+ if (!BLI_listbase_is_empty(&bmain->materials)) {
+ blender::bke::cryptomatte::CryptomatteLayer &materials = add_layer("CryptoMaterial");
+ LISTBASE_FOREACH (ID *, id, &bmain->materials) {
+ materials.add_ID(*id);
+ }
}
}
+CryptomatteSession::CryptomatteSession(StampData *stamp_data)
+{
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData callback_data;
+ callback_data.session = this;
+ BKE_stamp_info_callback(
+ &callback_data,
+ stamp_data,
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_names,
+ false);
+ BKE_stamp_info_callback(
+ &callback_data,
+ stamp_data,
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_manifest,
+ false);
+}
+
+blender::bke::cryptomatte::CryptomatteLayer &CryptomatteSession::add_layer(std::string layer_name)
+{
+ return layers.lookup_or_add_default(layer_name);
+}
+
std::optional<std::string> CryptomatteSession::operator[](float encoded_hash) const
{
- std::optional<std::string> result = objects[encoded_hash];
- if (result) {
- return result;
+ for (const blender::bke::cryptomatte::CryptomatteLayer &layer : layers.values()) {
+ std::optional<std::string> result = layer[encoded_hash];
+ if (result) {
+ return result;
+ }
}
- return materials[encoded_hash];
+ return std::nullopt;
}
CryptomatteSession *BKE_cryptomatte_init(void)
@@ -90,6 +121,18 @@ CryptomatteSession *BKE_cryptomatte_init(void)
return session;
}
+struct CryptomatteSession *BKE_cryptomatte_init_from_render_result(
+ const struct RenderResult *render_result)
+{
+ CryptomatteSession *session = new CryptomatteSession(render_result->stamp_data);
+ return session;
+}
+
+void BKE_cryptomatte_add_layer(struct CryptomatteSession *session, const char *layer_name)
+{
+ session->add_layer(layer_name);
+}
+
void BKE_cryptomatte_free(CryptomatteSession *session)
{
BLI_assert(session != nullptr);
@@ -102,26 +145,36 @@ uint32_t BKE_cryptomatte_hash(const char *name, const int name_len)
return hash.hash;
}
-uint32_t BKE_cryptomatte_object_hash(CryptomatteSession *session, const Object *object)
+uint32_t BKE_cryptomatte_object_hash(CryptomatteSession *session,
+ const char *layer_name,
+ const Object *object)
{
- return session->objects.add_ID(object->id);
+ blender::bke::cryptomatte::CryptomatteLayer *layer = session->layers.lookup_ptr(layer_name);
+ BLI_assert(layer);
+ return layer->add_ID(object->id);
}
-uint32_t BKE_cryptomatte_material_hash(CryptomatteSession *session, const Material *material)
+uint32_t BKE_cryptomatte_material_hash(CryptomatteSession *session,
+ const char *layer_name,
+ const Material *material)
{
if (material == nullptr) {
return 0.0f;
}
- return session->materials.add_ID(material->id);
+ blender::bke::cryptomatte::CryptomatteLayer *layer = session->layers.lookup_ptr(layer_name);
+ BLI_assert(layer);
+ return layer->add_ID(material->id);
}
-uint32_t BKE_cryptomatte_asset_hash(CryptomatteSession *session, const Object *object)
+uint32_t BKE_cryptomatte_asset_hash(CryptomatteSession *session,
+ const char *layer_name,
+ const Object *object)
{
const Object *asset_object = object;
while (asset_object->parent != nullptr) {
asset_object = asset_object->parent;
}
- return session->assets.add_ID(asset_object->id);
+ return BKE_cryptomatte_object_hash(session, layer_name, asset_object);
}
float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash)
@@ -131,22 +184,30 @@ float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash)
char *BKE_cryptomatte_entries_to_matte_id(NodeCryptomatte *node_storage)
{
- DynStr *matte_id = BLI_dynstr_new();
+ std::stringstream ss;
+ ss.precision(9);
+
bool first = true;
LISTBASE_FOREACH (CryptomatteEntry *, entry, &node_storage->entries) {
if (!first) {
- BLI_dynstr_append(matte_id, ",");
+ ss << ',';
}
- if (BLI_strnlen(entry->name, sizeof(entry->name)) != 0) {
- BLI_dynstr_nappend(matte_id, entry->name, sizeof(entry->name));
+ blender::StringRef entry_name(entry->name, BLI_strnlen(entry->name, sizeof(entry->name)));
+ if (!entry_name.is_empty()) {
+ ss << entry_name;
}
else {
- BLI_dynstr_appendf(matte_id, "<%.9g>", entry->encoded_hash);
+ ss << '<' << std::scientific << entry->encoded_hash << '>';
}
first = false;
}
- char *result = BLI_dynstr_get_cstring(matte_id);
- BLI_dynstr_free(matte_id);
+
+ /* Convert result to C string. */
+ const std::string result_string = ss.str();
+ const char *c_str = result_string.c_str();
+ size_t result_len = result_string.size() + 1;
+ char *result = static_cast<char *>(MEM_mallocN(sizeof(char) * result_len, __func__));
+ memcpy(result, c_str, result_len);
return result;
}
@@ -213,37 +274,23 @@ static void add_render_result_meta_data(RenderResult *render_result,
value.data());
}
-void BKE_cryptomatte_store_metadata(struct CryptomatteSession *session,
+void BKE_cryptomatte_store_metadata(const struct CryptomatteSession *session,
RenderResult *render_result,
- const ViewLayer *view_layer,
- eViewLayerCryptomatteFlags cryptomatte_layer,
- const char *cryptomatte_layer_name)
-{
- /* Create Manifest. */
- blender::bke::cryptomatte::CryptomatteLayer *layer = nullptr;
- switch (cryptomatte_layer) {
- case VIEW_LAYER_CRYPTOMATTE_OBJECT:
- layer = &session->objects;
- break;
- case VIEW_LAYER_CRYPTOMATTE_MATERIAL:
- layer = &session->materials;
- break;
- case VIEW_LAYER_CRYPTOMATTE_ASSET:
- layer = &session->assets;
- break;
- default:
- BLI_assert(!"Incorrect cryptomatte layer");
- break;
- }
+ const ViewLayer *view_layer)
+{
+ for (const blender::Map<std::string, blender::bke::cryptomatte::CryptomatteLayer>::Item item :
+ session->layers.items()) {
+ const blender::StringRefNull layer_name(item.key);
+ const blender::bke::cryptomatte::CryptomatteLayer &layer = item.value;
- const std::string manifest = layer->manifest();
- const std::string name = cryptomatte_determine_name(view_layer, cryptomatte_layer_name);
+ const std::string manifest = layer.manifest();
+ const std::string name = cryptomatte_determine_name(view_layer, layer_name);
- /* Store the meta data into the render result. */
- add_render_result_meta_data(render_result, name, "name", name);
- add_render_result_meta_data(render_result, name, "hash", "MurmurHash3_32");
- add_render_result_meta_data(render_result, name, "conversion", "uint32_to_float32");
- add_render_result_meta_data(render_result, name, "manifest", manifest);
+ add_render_result_meta_data(render_result, name, "name", name);
+ add_render_result_meta_data(render_result, name, "hash", "MurmurHash3_32");
+ add_render_result_meta_data(render_result, name, "conversion", "uint32_to_float32");
+ add_render_result_meta_data(render_result, name, "manifest", manifest);
+ }
}
namespace blender::bke::cryptomatte {
@@ -253,6 +300,9 @@ constexpr StringRef WHITESPACES = " \t\n\v\f\r";
static constexpr blender::StringRef skip_whitespaces_(blender::StringRef ref)
{
size_t skip = ref.find_first_not_of(WHITESPACES);
+ if (skip == blender::StringRef::not_found) {
+ return ref;
+ }
return ref.drop_prefix(skip);
}
@@ -450,7 +500,7 @@ std::unique_ptr<CryptomatteLayer> CryptomatteLayer::read_from_manifest(
blender::StringRefNull manifest)
{
std::unique_ptr<CryptomatteLayer> layer = std::make_unique<CryptomatteLayer>();
- blender::bke::cryptomatte::manifest::from_manifest(*layer.get(), manifest);
+ blender::bke::cryptomatte::manifest::from_manifest(*layer, manifest);
return layer;
}
@@ -481,9 +531,70 @@ std::optional<std::string> CryptomatteLayer::operator[](float encoded_hash) cons
return std::nullopt;
}
-std::string CryptomatteLayer::manifest()
+std::string CryptomatteLayer::manifest() const
{
return blender::bke::cryptomatte::manifest::to_manifest(this);
}
+blender::StringRef CryptomatteStampDataCallbackData::extract_layer_hash(blender::StringRefNull key)
+{
+ BLI_assert(key.startswith("cryptomatte/"));
+
+ size_t start_index = key.find_first_of('/');
+ size_t end_index = key.find_last_of('/');
+ if (start_index == blender::StringRef::not_found) {
+ return "";
+ }
+ if (end_index == blender::StringRef::not_found) {
+ return "";
+ }
+ if (end_index <= start_index) {
+ return "";
+ }
+ return key.substr(start_index + 1, end_index - start_index - 1);
+}
+
+void CryptomatteStampDataCallbackData::extract_layer_names(void *_data,
+ const char *propname,
+ char *propvalue,
+ int UNUSED(len))
+{
+ CryptomatteStampDataCallbackData *data = static_cast<CryptomatteStampDataCallbackData *>(_data);
+
+ blender::StringRefNull key(propname);
+ if (!key.startswith("cryptomatte/")) {
+ return;
+ }
+ if (!key.endswith("/name")) {
+ return;
+ }
+ blender::StringRef layer_hash = extract_layer_hash(key);
+ data->hash_to_layer_name.add(layer_hash, propvalue);
+}
+
+/* C type callback function (StampCallback). */
+void CryptomatteStampDataCallbackData::extract_layer_manifest(void *_data,
+ const char *propname,
+ char *propvalue,
+ int UNUSED(len))
+{
+ CryptomatteStampDataCallbackData *data = static_cast<CryptomatteStampDataCallbackData *>(_data);
+
+ blender::StringRefNull key(propname);
+ if (!key.startswith("cryptomatte/")) {
+ return;
+ }
+ if (!key.endswith("/manifest")) {
+ return;
+ }
+ blender::StringRef layer_hash = extract_layer_hash(key);
+ if (!data->hash_to_layer_name.contains(layer_hash)) {
+ return;
+ }
+
+ blender::StringRef layer_name = data->hash_to_layer_name.lookup(layer_hash);
+ blender::bke::cryptomatte::CryptomatteLayer &layer = data->session->add_layer(layer_name);
+ blender::bke::cryptomatte::manifest::from_manifest(layer, propvalue);
+}
+
} // namespace blender::bke::cryptomatte
diff --git a/source/blender/blenkernel/intern/cryptomatte_test.cc b/source/blender/blenkernel/intern/cryptomatte_test.cc
index 4a25f5f7d87..5481b97913c 100644
--- a/source/blender/blenkernel/intern/cryptomatte_test.cc
+++ b/source/blender/blenkernel/intern/cryptomatte_test.cc
@@ -17,7 +17,15 @@
*/
#include "testing/testing.h"
+#include "BKE_cryptomatte.h"
#include "BKE_cryptomatte.hh"
+#include "BKE_image.h"
+
+#include "DNA_node_types.h"
+
+#include "RE_pipeline.h"
+
+#include "MEM_guardedalloc.h"
namespace blender::bke::cryptomatte::tests {
@@ -41,7 +49,7 @@ TEST(cryptomatte, extract_layer_name)
ASSERT_EQ("", BKE_cryptomatte_extract_layer_name(""));
}
-TEST(cryptomatte, cryptomatte_layer)
+TEST(cryptomatte, layer)
{
blender::bke::cryptomatte::CryptomatteLayer layer;
ASSERT_EQ("{}", layer.manifest());
@@ -53,7 +61,7 @@ TEST(cryptomatte, cryptomatte_layer)
ASSERT_EQ("{\"Object\":\"0000007b\",\"Object2\":\"0758946e\"}", layer.manifest());
}
-TEST(cryptomatte, cryptomatte_layer_quoted)
+TEST(cryptomatte, layer_quoted)
{
blender::bke::cryptomatte::CryptomatteLayer layer;
layer.add_hash("\"Object\"", 123);
@@ -66,7 +74,7 @@ static void test_cryptomatte_manifest(std::string expected, std::string manifest
blender::bke::cryptomatte::CryptomatteLayer::read_from_manifest(manifest)->manifest());
}
-TEST(cryptomatte, cryptomatte_layer_from_manifest)
+TEST(cryptomatte, layer_from_manifest)
{
test_cryptomatte_manifest("{}", "{}");
test_cryptomatte_manifest("{\"Object\":\"12345678\"}", "{\"Object\": \"12345678\"}");
@@ -82,4 +90,103 @@ TEST(cryptomatte, cryptomatte_layer_from_manifest)
"{\"Object\\\"01\\\"\":\"12345678\",\"Object\":\"12345678\", \"Object2\":\"87654321\"}");
}
+TEST(cryptomatte, extract_layer_hash_from_metadata_key)
+{
+ EXPECT_EQ("eb4c67b",
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_hash(
+ "cryptomatte/eb4c67b/conversion"));
+ EXPECT_EQ("qwerty",
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_hash(
+ "cryptomatte/qwerty/name"));
+ /* Check if undefined behaviors are handled. */
+ EXPECT_EQ("",
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_hash(
+ "cryptomatte/name"));
+ EXPECT_EQ("",
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_hash(
+ "cryptomatte/"));
+}
+
+static void validate_cryptomatte_session_from_stamp_data(void *UNUSED(data),
+ const char *propname,
+ char *propvalue,
+ int UNUSED(len))
+{
+ blender::StringRefNull prop_name(propname);
+ if (!prop_name.startswith("cryptomatte/")) {
+ return;
+ }
+
+ if (prop_name == "cryptomatte/87f095e/name") {
+ EXPECT_STREQ("viewlayername.layer1", propvalue);
+ }
+ else if (prop_name == "cryptomatte/87f095e/hash") {
+ EXPECT_STREQ("MurmurHash3_32", propvalue);
+ }
+ else if (prop_name == "cryptomatte/87f095e/conversion") {
+ EXPECT_STREQ("uint32_to_float32", propvalue);
+ }
+ else if (prop_name == "cryptomatte/87f095e/manifest") {
+ EXPECT_STREQ("{\"Object\":\"12345678\"}", propvalue);
+ }
+
+ else if (prop_name == "cryptomatte/c42daa7/name") {
+ EXPECT_STREQ("viewlayername.layer2", propvalue);
+ }
+ else if (prop_name == "cryptomatte/c42daa7/hash") {
+ EXPECT_STREQ("MurmurHash3_32", propvalue);
+ }
+ else if (prop_name == "cryptomatte/c42daa7/conversion") {
+ EXPECT_STREQ("uint32_to_float32", propvalue);
+ }
+ else if (prop_name == "cryptomatte/c42daa7/manifest") {
+ EXPECT_STREQ("{\"Object2\":\"87654321\"}", propvalue);
+ }
+
+ else {
+ EXPECT_EQ("Unhandled", std::string(propname) + ": " + propvalue);
+ }
+}
+
+TEST(cryptomatte, session_from_stamp_data)
+{
+ /* Create CryptomatteSession from stamp data. */
+ RenderResult *render_result = static_cast<RenderResult *>(
+ MEM_callocN(sizeof(RenderResult), __func__));
+ BKE_render_result_stamp_data(render_result, "cryptomatte/qwerty/name", "layer1");
+ BKE_render_result_stamp_data(
+ render_result, "cryptomatte/qwerty/manifest", "{\"Object\":\"12345678\"}");
+ BKE_render_result_stamp_data(render_result, "cryptomatte/uiop/name", "layer2");
+ BKE_render_result_stamp_data(
+ render_result, "cryptomatte/uiop/manifest", "{\"Object2\":\"87654321\"}");
+ CryptomatteSession *session = BKE_cryptomatte_init_from_render_result(render_result);
+ EXPECT_NE(session, nullptr);
+ RE_FreeRenderResult(render_result);
+
+ /* Create StampData from CryptomatteSession. */
+ ViewLayer view_layer;
+ BLI_strncpy(view_layer.name, "viewlayername", sizeof(view_layer.name));
+ RenderResult *render_result2 = static_cast<RenderResult *>(
+ MEM_callocN(sizeof(RenderResult), __func__));
+ BKE_cryptomatte_store_metadata(session, render_result2, &view_layer);
+
+ /* Validate StampData. */
+ BKE_stamp_info_callback(
+ nullptr, render_result2->stamp_data, validate_cryptomatte_session_from_stamp_data, false);
+
+ RE_FreeRenderResult(render_result2);
+ BKE_cryptomatte_free(session);
+}
+
+TEST(cryptomatte, T86026)
+{
+ NodeCryptomatte storage = {{0.0f}};
+ CryptomatteEntry entry = {nullptr};
+ BLI_addtail(&storage.entries, &entry);
+ entry.encoded_hash = 4.76190593e-07;
+ char *matte_id = BKE_cryptomatte_entries_to_matte_id(&storage);
+ EXPECT_STREQ("<4.761905927e-07>", matte_id);
+ MEM_freeN(matte_id);
+}
+
} // namespace blender::bke::cryptomatte::tests
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 1a260c5d48e..6c4c3231667 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -378,7 +378,8 @@ static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups,
/* Don't copy attributes that are stored directly in the mesh data structs. */
Map<std::string, AttributeKind> attributes;
- gather_attribute_info(attributes, component_types, set_groups, {"position", "material_index"});
+ gather_attribute_info(
+ attributes, component_types, set_groups, {"position", "material_index", "vertex_normal"});
join_attributes(
set_groups, component_types, attributes, static_cast<GeometryComponent &>(dst_component));
}
diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c
index 1889d1c4eb0..fee70922570 100644
--- a/source/blender/blenkernel/intern/idtype.c
+++ b/source/blender/blenkernel/intern/idtype.c
@@ -63,7 +63,7 @@ bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v)
(key_a->offset_in_ID != key_b->offset_in_ID) || (key_a->cache_v != key_b->cache_v);
}
-static IDTypeInfo *id_types[MAX_LIBARRAY] = {NULL};
+static IDTypeInfo *id_types[INDEX_ID_MAX] = {NULL};
static void id_type_init(void)
{
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 54c2f5f5565..a511c1f9c4c 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -916,7 +916,7 @@ void BKE_main_id_tag_idcode(struct Main *mainvar,
*/
void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value)
{
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int a;
a = set_listbasepointers(mainvar, lbarray);
@@ -949,7 +949,7 @@ void BKE_main_id_flag_listbase(ListBase *lb, const int flag, const bool value)
*/
void BKE_main_id_flag_all(Main *bmain, const int flag, const bool value)
{
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int a;
a = set_listbasepointers(bmain, lbarray);
while (a--) {
@@ -1870,7 +1870,7 @@ void BKE_library_make_local(Main *bmain,
const bool untagged_only,
const bool set_fake)
{
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
LinkNode *todo_ids = NULL;
LinkNode *copied_ids = NULL;
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index 7c5032c97f4..1d7f89e1e8d 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -240,7 +240,7 @@ void BKE_id_free_us(Main *bmain, void *idv) /* test users */
static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
{
const int tag = LIB_TAG_DOIT;
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
Link dummy_link = {0};
int base_count, i;
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index eaf1e2d46e6..acd0c10040c 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -46,7 +46,7 @@ enum {
typedef struct LibraryForeachIDData {
Main *bmain;
/**
- * 'Real' ID, the one that might be in bmain, only differs from self_id when the later is a
+ * 'Real' ID, the one that might be in `bmain`, only differs from self_id when the later is a
* private one.
*/
ID *owner_id;
@@ -137,7 +137,7 @@ void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void
bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp)
{
- /* Needed e.g. for callbacks handling relationships... This call shall be absolutely readonly. */
+ /* Needed e.g. for callbacks handling relationships. This call shall be absolutely read-only. */
ID *id = *id_pp;
const int flag = data->flag;
@@ -215,7 +215,7 @@ static void library_foreach_ID_link(Main *bmain,
data.self_id;
/* inherit_data is non-NULL when this function is called for some sub-data ID
- * (like root nodetree of a material).
+ * (like root node-tree of a material).
* In that case, we do not want to generate those 'generic flags' from our current sub-data ID
* (the node tree), but re-use those generated for the 'owner' ID (the material). */
if (inherit_data == NULL) {
@@ -440,7 +440,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
typedef struct IDUsersIter {
ID *id;
- ListBase *lb_array[MAX_LIBARRAY];
+ ListBase *lb_array[INDEX_ID_MAX];
int lb_idx;
ID *curr_id;
@@ -514,7 +514,7 @@ int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
{
IDUsersIter iter;
- ListBase *lb_array[MAX_LIBARRAY];
+ ListBase *lb_array[INDEX_ID_MAX];
ID *id = idv;
int i = set_listbasepointers(bmain, lb_array);
bool is_defined = false;
@@ -567,7 +567,7 @@ bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, bool *is_used_linked)
{
IDUsersIter iter;
- ListBase *lb_array[MAX_LIBARRAY];
+ ListBase *lb_array[INDEX_ID_MAX];
ID *id = idv;
int i = set_listbasepointers(bmain, lb_array);
bool is_defined = false;
@@ -632,7 +632,7 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
if (ELEM(GS(id->name), ID_WM, ID_WS, ID_SCE, ID_SCR, ID_LI)) {
/* Some 'root' ID types are never unused (even though they may not have actual users), unless
- * their actual usercount is set to 0. */
+ * their actual user-count is set to 0. */
return;
}
@@ -683,7 +683,7 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
*
* By default only tag IDs with `0` user count.
* If `do_tag_recursive` is set, it will check dependencies to detect all IDs that are not actually
- * used in current file, including 'archipelagoes` (i.e. set of IDs referencing each other in
+ * used in current file, including 'archipelagos` (i.e. set of IDs referencing each other in
* loops, but without any 'external' valid usages.
*
* Valid usages here are defined as ref-counting usages, which are not towards embedded or
@@ -700,7 +700,7 @@ void BKE_lib_query_unused_ids_tag(Main *bmain,
const bool do_tag_recursive,
int *r_num_tagged)
{
- /* First loop, to only check for immediatly unused IDs (those with 0 user count).
+ /* First loop, to only check for immediately unused IDs (those with 0 user count).
* NOTE: It also takes care of clearing given tag for used IDs. */
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
@@ -805,7 +805,7 @@ void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
*/
void BKE_library_indirectly_used_data_tag_clear(Main *bmain)
{
- ListBase *lb_array[MAX_LIBARRAY];
+ ListBase *lb_array[INDEX_ID_MAX];
bool do_loop = true;
while (do_loop) {
diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c
index 6f94b3355fa..d1f34ad8ce9 100644
--- a/source/blender/blenkernel/intern/main.c
+++ b/source/blender/blenkernel/intern/main.c
@@ -53,7 +53,7 @@ Main *BKE_main_new(void)
void BKE_main_free(Main *mainvar)
{
/* also call when reading a file, erase all, etc */
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int a;
/* Since we are removing whole main, no need to bother 'properly'
@@ -532,18 +532,17 @@ ListBase *which_libbase(Main *bmain, short type)
}
/**
- * puts into array *lb pointers to all the #ListBase structs in main,
- * and returns the number of them as the function result. This is useful for
- * generic traversal of all the blocks in a Main (by traversing all the
- * lists in turn), without worrying about block types.
+ * Put the pointers to all the #ListBase structs in given `bmain` into the `*lb[INDEX_ID_MAX]`
+ * array, and return the number of those for convenience.
*
- * \note #MAX_LIBARRAY define should match this code */
-int set_listbasepointers(Main *bmain, ListBase **lb)
+ * This is useful for generic traversal of all the blocks in a #Main (by traversing all the lists
+ * in turn), without worrying about block types.
+ *
+ * \note The order of each ID type #ListBase in the array is determined by the `INDEX_ID_<IDTYPE>`
+ * enum definitions in `DNA_ID.h`. See also the #FOREACH_MAIN_ID_BEGIN macro in `BKE_main.h`
+ */
+int set_listbasepointers(Main *bmain, ListBase *lb[INDEX_ID_MAX])
{
- /* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last.
- * This is important because freeing data decreases user-counts of other data-blocks,
- * if this data is its self freed it can crash. */
-
/* Libraries may be accessed from pretty much any other ID. */
lb[INDEX_ID_LI] = &(bmain->libraries);
@@ -606,5 +605,5 @@ int set_listbasepointers(Main *bmain, ListBase **lb)
lb[INDEX_ID_NULL] = NULL;
- return (MAX_LIBARRAY - 1);
+ return (INDEX_ID_MAX - 1);
}
diff --git a/source/blender/blenkernel/intern/main_idmap.c b/source/blender/blenkernel/intern/main_idmap.c
index 21f5e9c6fb2..1d362db4432 100644
--- a/source/blender/blenkernel/intern/main_idmap.c
+++ b/source/blender/blenkernel/intern/main_idmap.c
@@ -66,7 +66,7 @@ struct IDNameLib_TypeMap {
* Opaque structure, external API users only see this.
*/
struct IDNameLib_Map {
- struct IDNameLib_TypeMap type_maps[MAX_LIBARRAY];
+ struct IDNameLib_TypeMap type_maps[INDEX_ID_MAX];
struct GHash *uuid_map;
struct Main *bmain;
struct GSet *valid_id_pointers;
@@ -77,7 +77,7 @@ static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id
short id_type)
{
if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) {
- for (int i = 0; i < MAX_LIBARRAY; i++) {
+ for (int i = 0; i < INDEX_ID_MAX; i++) {
if (id_map->type_maps[i].id_type == id_type) {
return &id_map->type_maps[i];
}
@@ -108,13 +108,13 @@ struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
id_map->idmap_types = idmap_types;
int index = 0;
- while (index < MAX_LIBARRAY) {
+ while (index < INDEX_ID_MAX) {
struct IDNameLib_TypeMap *type_map = &id_map->type_maps[index];
type_map->map = NULL;
type_map->id_type = BKE_idtype_idcode_iter_step(&index);
BLI_assert(type_map->id_type != 0);
}
- BLI_assert(index == MAX_LIBARRAY);
+ BLI_assert(index == INDEX_ID_MAX);
if (idmap_types & MAIN_IDMAP_TYPE_UUID) {
ID *id;
@@ -231,7 +231,7 @@ void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map)
{
if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) {
struct IDNameLib_TypeMap *type_map = id_map->type_maps;
- for (int i = 0; i < MAX_LIBARRAY; i++, type_map++) {
+ for (int i = 0; i < INDEX_ID_MAX; i++, type_map++) {
if (type_map->map) {
BLI_ghash_free(type_map->map, NULL, NULL);
type_map->map = NULL;
diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
index 299b1ff1c71..a179d39a9d2 100644
--- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
@@ -32,6 +32,7 @@
#include "BLI_alloca.h"
#include "BLI_float2.hh"
+#include "BLI_float4x4.hh"
#include "BLI_math.h"
#include "BLI_mesh_boolean.hh"
#include "BLI_mesh_intersect.hh"
@@ -50,12 +51,12 @@ constexpr int estimated_max_facelen = 100; /* Used for initial size of some Vect
* so this is a hack to clean up such matrices.
* Would be better to change the transformation code itself.
*/
-static void clean_obmat(float cleaned[4][4], const float mat[4][4])
+static void clean_obmat(float4x4 &cleaned, const float4x4 &mat)
{
const float fuzz = 1e-6f;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
- float f = mat[i][j];
+ float f = mat.values[i][j];
if (fabsf(f) <= fuzz) {
f = 0.0f;
}
@@ -65,17 +66,11 @@ static void clean_obmat(float cleaned[4][4], const float mat[4][4])
else if (fabsf(f + 1.0f) <= fuzz) {
f = -1.0f;
}
- cleaned[i][j] = f;
+ cleaned.values[i][j] = f;
}
}
}
-/* Need to wrap this in a class to use it in an Array. */
-class TransMat {
- public:
- float mat[4][4];
-};
-
/* `MeshesToIMeshInfo` keeps track of information used when combining a number
* of `Mesh`es into a single `IMesh` for doing boolean on.
* Mostly this means keeping track of the index offsets for various mesh elements. */
@@ -97,7 +92,7 @@ class MeshesToIMeshInfo {
Array<Face *> mesh_to_imesh_face;
/* Transformation matrix to transform a coordinate in the corresponding
* Mesh to the local space of the first Mesh. */
- Array<TransMat> to_obj0;
+ Array<float4x4> to_obj0;
/* Total number of input mesh vertices. */
int tot_meshes_verts;
/* Total number of input mesh edges. */
@@ -242,7 +237,7 @@ const MEdge *MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index,
* All allocation of memory for the IMesh comes from `arena`.
*/
static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
- const float (*obmats[])[4][4],
+ Span<const float4x4 *> obmats,
IMeshArena &arena,
MeshesToIMeshInfo *r_info)
{
@@ -271,7 +266,7 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
r_info->mesh_vert_offset = Array<int>(nmeshes);
r_info->mesh_edge_offset = Array<int>(nmeshes);
r_info->mesh_poly_offset = Array<int>(nmeshes);
- r_info->to_obj0 = Array<TransMat>(nmeshes);
+ r_info->to_obj0 = Array<float4x4>(nmeshes);
int v = 0;
int e = 0;
int f = 0;
@@ -286,15 +281,15 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
* of object 0, we multiply each object's `obmat` by the inverse of
* object 0's `obmat`. Exact Boolean works better if these matrices
* are 'cleaned' -- see the comment for the `clean_obmat` function, above. */
- float obj0_mat[4][4];
- float inv_obj0_mat[4][4];
+ float4x4 obj0_mat;
+ float4x4 inv_obj0_mat;
if (obmats[0] == nullptr) {
- unit_m4(obj0_mat);
- unit_m4(inv_obj0_mat);
+ unit_m4(obj0_mat.values);
+ unit_m4(inv_obj0_mat.values);
}
else {
clean_obmat(obj0_mat, *obmats[0]);
- invert_m4_m4(inv_obj0_mat, obj0_mat);
+ invert_m4_m4(inv_obj0_mat.values, obj0_mat.values);
}
/* For each input `Mesh`, make `Vert`s and `Face`s for the corresponding
@@ -303,13 +298,13 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
* When making `Face`s, we also put in the original indices for `MEdge`s that
* make up the `MPoly`s using the same scheme. */
for (int mi : meshes.index_range()) {
- float objn_to_obj0_mat[4][4];
+ float4x4 objn_to_obj0_mat;
const Mesh *me = meshes[mi];
if (mi == 0) {
r_info->mesh_vert_offset[mi] = 0;
r_info->mesh_edge_offset[mi] = 0;
r_info->mesh_poly_offset[mi] = 0;
- unit_m4(r_info->to_obj0[0].mat);
+ unit_m4(r_info->to_obj0[0].values);
}
else {
r_info->mesh_vert_offset[mi] = v;
@@ -317,23 +312,22 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
r_info->mesh_poly_offset[mi] = f;
/* Get matrix that transforms a coordinate in objects[mi]'s local space
* to object[0]'s local space.*/
- float objn_mat[4][4];
+ float4x4 objn_mat;
if (obmats[mi] == nullptr) {
- unit_m4(objn_mat);
+ unit_m4(objn_mat.values);
}
else {
clean_obmat(objn_mat, *obmats[mi]);
}
- mul_m4_m4m4(objn_to_obj0_mat, inv_obj0_mat, objn_mat);
- copy_m4_m4(r_info->to_obj0[mi].mat, objn_to_obj0_mat);
+ objn_to_obj0_mat = inv_obj0_mat * objn_mat;
+ r_info->to_obj0[mi] = objn_to_obj0_mat;
}
for (int vi = 0; vi < me->totvert; ++vi) {
- float co[3];
- copy_v3_v3(co, me->mvert[vi].co);
+ float3 co = me->mvert[vi].co;
if (mi > 0) {
- mul_m4_v3(objn_to_obj0_mat, co);
+ co = objn_to_obj0_mat * co;
}
- r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(mpq3(co[0], co[1], co[2]), v);
+ r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(mpq3(co.x, co.y, co.z), v);
++v;
}
for (const MPoly &poly : Span(me->mpoly, me->totpoly)) {
@@ -534,7 +528,7 @@ static int fill_orig_loops(const Face *f,
static void get_poly2d_cos(const Mesh *me,
const MPoly *mp,
float (*cos_2d)[2],
- const TransMat &trans_mat,
+ const float4x4 &trans_mat,
float r_axis_mat[3][3])
{
int n = mp->totloop;
@@ -546,9 +540,8 @@ static void get_poly2d_cos(const Mesh *me,
MLoop *ml = &me->mloop[mp->loopstart];
const MVert *mverts = me->mvert;
for (int i = 0; i < n; ++i) {
- float co[3];
- copy_v3_v3(co, mverts[ml->v].co);
- mul_m4_v3(trans_mat.mat, co);
+ float3 co = mverts[ml->v].co;
+ co = trans_mat * co;
mul_v2_m3v3(cos_2d[i], r_axis_mat, co);
++ml;
}
@@ -618,6 +611,9 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
* A non bmesh version could have the benefit of not copying data into src_blocks_ofs -
* using the contiguous data instead. TODO: add to the custom data API. */
int target_layer_type_index = CustomData_get_named_layer(target_cd, ty, name);
+ if (!CustomData_layer_has_interp(source_cd, source_layer_i)) {
+ continue;
+ }
int source_layer_type_index = source_layer_i - source_cd->typemap[ty];
BLI_assert(target_layer_type_index != -1 && source_layer_type_index >= 0);
for (int j = 0; j < orig_mp->totloop; ++j) {
@@ -763,23 +759,23 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
* Do Exact Boolean directly, without a round trip through #BMesh.
* The Mesh operands are in `meshes`, with corresponding transforms in in `obmats`.
*/
-static Mesh *direct_mesh_boolean(const Mesh **meshes,
- const float (*obmats[])[4][4],
- const int meshes_len,
+static Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
+ Span<const float4x4 *> obmats,
const bool use_self,
const BoolOpType boolean_mode)
{
const int dbg_level = 0;
+ BLI_assert(meshes.size() == obmats.size());
+ const int meshes_len = meshes.size();
if (meshes_len <= 0) {
return nullptr;
}
if (dbg_level > 0) {
std::cout << "\nDIRECT_MESH_INTERSECT, nmeshes = " << meshes_len << "\n";
}
- Span<const Mesh *> mesh_span(meshes, meshes_len);
MeshesToIMeshInfo mim;
IMeshArena arena;
- IMesh m_in = meshes_to_imesh(mesh_span, obmats, arena, &mim);
+ IMesh m_in = meshes_to_imesh(meshes, obmats, arena, &mim);
std::function<int(int)> shape_fn = [&mim](int f) {
for (int mi = 0; mi < mim.mesh_poly_offset.size() - 1; ++mi) {
if (f < mim.mesh_poly_offset[mi + 1]) {
@@ -814,10 +810,10 @@ Mesh *BKE_mesh_boolean(const Mesh **meshes,
const bool use_self,
const int boolean_mode)
{
+ const blender::float4x4 **transforms = (const blender::float4x4 **)obmats;
return blender::meshintersect::direct_mesh_boolean(
- meshes,
- obmats,
- meshes_len,
+ blender::Span(meshes, meshes_len),
+ blender::Span(transforms, meshes_len),
use_self,
static_cast<blender::meshintersect::BoolOpType>(boolean_mode));
}
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 7bd7fb4a29b..6b46ae3430b 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -372,7 +372,8 @@ static ID *node_owner_get(Main *bmain, ID *id)
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
return id;
}
- BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0);
+ /* TODO: Sort this NO_MAIN or not for embedded node trees. See T86119. */
+ // BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0);
ListBase *lists[] = {&bmain->materials,
&bmain->lights,
@@ -3554,7 +3555,8 @@ void nodeSetActive(bNodeTree *ntree, bNode *node)
tnode->flag &= ~NODE_ACTIVE_ID;
}
}
- if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
+ if ((node->typeinfo->nclass == NODE_CLASS_TEXTURE) ||
+ (node->typeinfo->type == GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE)) {
tnode->flag &= ~NODE_ACTIVE_TEXTURE;
}
}
@@ -3563,7 +3565,8 @@ void nodeSetActive(bNodeTree *ntree, bNode *node)
if (node->id) {
node->flag |= NODE_ACTIVE_ID;
}
- if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
+ if ((node->typeinfo->nclass == NODE_CLASS_TEXTURE) ||
+ (node->typeinfo->type == GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE)) {
node->flag |= NODE_ACTIVE_TEXTURE;
}
}
@@ -4479,18 +4482,18 @@ void node_type_group_update(struct bNodeType *ntype,
}
void node_type_exec(struct bNodeType *ntype,
- NodeInitExecFunction initexecfunc,
- NodeFreeExecFunction freeexecfunc,
- NodeExecFunction execfunc)
+ NodeInitExecFunction init_exec_fn,
+ NodeFreeExecFunction free_exec_fn,
+ NodeExecFunction exec_fn)
{
- ntype->initexecfunc = initexecfunc;
- ntype->freeexecfunc = freeexecfunc;
- ntype->execfunc = execfunc;
+ ntype->init_exec_fn = init_exec_fn;
+ ntype->free_exec_fn = free_exec_fn;
+ ntype->exec_fn = exec_fn;
}
-void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc)
+void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpu_fn)
{
- ntype->gpufunc = gpufunc;
+ ntype->gpu_fn = gpu_fn;
}
void node_type_internal_links(bNodeType *ntype,
diff --git a/source/blender/blenkernel/intern/node_ui_storage.cc b/source/blender/blenkernel/intern/node_ui_storage.cc
index ea492c4d36a..97f52dd3727 100644
--- a/source/blender/blenkernel/intern/node_ui_storage.cc
+++ b/source/blender/blenkernel/intern/node_ui_storage.cc
@@ -16,6 +16,8 @@
#include "CLG_log.h"
+#include <mutex>
+
#include "BLI_map.hh"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
@@ -33,10 +35,20 @@ using blender::Map;
using blender::StringRef;
using blender::Vector;
+/* Use a global mutex because otherwise it would have to be stored directly in the
+ * bNodeTree struct in DNA. This could change if the node tree had a runtime struct. */
+static std::mutex global_ui_storage_mutex;
+
static void ui_storage_ensure(bNodeTree &ntree)
{
+ /* As an optimization, only acquire a lock if the UI storage doesn't exist,
+ * because it only needs to be allocated once for every node tree. */
if (ntree.ui_storage == nullptr) {
- ntree.ui_storage = new NodeTreeUIStorage();
+ std::lock_guard<std::mutex> lock(global_ui_storage_mutex);
+ /* Check again-- another thread may have allocated the storage while this one waited. */
+ if (ntree.ui_storage == nullptr) {
+ ntree.ui_storage = new NodeTreeUIStorage();
+ }
}
}
@@ -50,8 +62,12 @@ const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C
}
const Object *active_object = CTX_data_active_object(C);
+ if (active_object == nullptr) {
+ return nullptr;
+ }
+
const ModifierData *active_modifier = BKE_object_active_modifier(active_object);
- if (active_object == nullptr || active_modifier == nullptr) {
+ if (active_modifier == nullptr) {
return nullptr;
}
@@ -74,6 +90,7 @@ void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree,
{
NodeTreeUIStorage *ui_storage = ntree.ui_storage;
if (ui_storage != nullptr) {
+ std::lock_guard<std::mutex> lock(ui_storage->context_map_mutex);
ui_storage->context_map.remove(context);
}
}
@@ -109,13 +126,14 @@ static void node_error_message_log(bNodeTree &ntree,
}
}
-static NodeUIStorage &find_node_ui_storage(bNodeTree &ntree,
- const NodeTreeEvaluationContext &context,
- const bNode &node)
+static NodeUIStorage &node_ui_storage_ensure(bNodeTree &ntree,
+ const NodeTreeEvaluationContext &context,
+ const bNode &node)
{
ui_storage_ensure(ntree);
NodeTreeUIStorage &ui_storage = *ntree.ui_storage;
+ std::lock_guard<std::mutex> lock(ui_storage.context_map_mutex);
Map<std::string, NodeUIStorage> &node_tree_ui_storage =
ui_storage.context_map.lookup_or_add_default(context);
@@ -133,7 +151,7 @@ void BKE_nodetree_error_message_add(bNodeTree &ntree,
{
node_error_message_log(ntree, node, message, type);
- NodeUIStorage &node_ui_storage = find_node_ui_storage(ntree, context, node);
+ NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ntree, context, node);
node_ui_storage.warnings.append({type, std::move(message)});
}
@@ -142,6 +160,6 @@ void BKE_nodetree_attribute_hint_add(bNodeTree &ntree,
const bNode &node,
const StringRef attribute_name)
{
- NodeUIStorage &node_ui_storage = find_node_ui_storage(ntree, context, node);
+ NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ntree, context, node);
node_ui_storage.attribute_name_hints.add_as(attribute_name);
}
diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c
index 05873d20f7f..b9497d389e7 100644
--- a/source/blender/blenkernel/intern/outliner_treehash.c
+++ b/source/blender/blenkernel/intern/outliner_treehash.c
@@ -101,7 +101,7 @@ static unsigned int tse_hash(const void *ptr)
unsigned int u_int;
} hash;
- BLI_assert(tse->type || !tse->nr);
+ BLI_assert((tse->type != TSE_SOME_ID) || !tse->nr);
hash.h_pair[0] = tse->type;
hash.h_pair[1] = tse->nr;
@@ -193,7 +193,7 @@ static TseGroup *BKE_outliner_treehash_lookup_group(GHash *th, short type, short
{
TreeStoreElem tse_template;
tse_template.type = type;
- tse_template.nr = type ? nr : 0; /* we're picky! :) */
+ tse_template.nr = (type == TSE_SOME_ID) ? 0 : nr; /* we're picky! :) */
tse_template.id = id;
BLI_assert(th);
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 0a2441bbf74..a374c3252b9 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1423,6 +1423,12 @@ static void sculptsession_free_pbvh(Object *object)
MEM_SAFE_FREE(ss->pmap);
MEM_SAFE_FREE(ss->pmap_mem);
+ MEM_SAFE_FREE(ss->epmap);
+ MEM_SAFE_FREE(ss->epmap_mem);
+
+ MEM_SAFE_FREE(ss->vemap);
+ MEM_SAFE_FREE(ss->vemap_mem);
+
MEM_SAFE_FREE(ss->persistent_base);
MEM_SAFE_FREE(ss->preview_vert_index_list);
@@ -1472,6 +1478,13 @@ void BKE_sculptsession_free(Object *ob)
MEM_SAFE_FREE(ss->pmap);
MEM_SAFE_FREE(ss->pmap_mem);
+
+ MEM_SAFE_FREE(ss->epmap);
+ MEM_SAFE_FREE(ss->epmap_mem);
+
+ MEM_SAFE_FREE(ss->vemap);
+ MEM_SAFE_FREE(ss->vemap_mem);
+
if (ss->bm_log) {
BM_log_free(ss->bm_log);
}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 8b911143668..623f3a349d8 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -1681,6 +1681,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
sfile->op = NULL;
sfile->previews_timer = NULL;
sfile->tags = 0;
+ sfile->runtime = NULL;
BLO_read_data_address(reader, &sfile->params);
BLO_read_data_address(reader, &sfile->asset_params);
}
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index 5bffcd4d9e7..4cc2d101b02 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -514,7 +514,7 @@ static void studiolight_create_matcap_gputexture(StudioLightImage *sli)
ImBuf *ibuf = sli->ibuf;
float *gpu_matcap_3components = MEM_callocN(sizeof(float[3]) * ibuf->x * ibuf->y, __func__);
- float(*offset4)[4] = (float(*)[4])ibuf->rect_float;
+ const float(*offset4)[4] = (const float(*)[4])ibuf->rect_float;
float(*offset3)[3] = (float(*)[3])gpu_matcap_3components;
for (int i = 0; i < ibuf->x * ibuf->y; i++, offset4++, offset3++) {
copy_v3_v3(*offset3, *offset4);
diff --git a/source/blender/blenlib/BLI_multi_value_map.hh b/source/blender/blenlib/BLI_multi_value_map.hh
index 018f080e633..4113085a1e3 100644
--- a/source/blender/blenlib/BLI_multi_value_map.hh
+++ b/source/blender/blenlib/BLI_multi_value_map.hh
@@ -104,6 +104,22 @@ template<typename Key, typename Value> class MultiValueMap {
}
/**
+ * Get a mutable span to all the values that are stored for the given key.
+ */
+ MutableSpan<Value> lookup(const Key &key)
+ {
+ return this->lookup_as(key);
+ }
+ template<typename ForwardKey> MutableSpan<Value> lookup_as(const ForwardKey &key)
+ {
+ Vector<Value> *vector = map_.lookup_ptr_as(key);
+ if (vector != nullptr) {
+ return vector->as_mutable_span();
+ }
+ return {};
+ }
+
+ /**
* Note: This signature will change when the implementation changes.
*/
typename MapType::ItemIterator items() const
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index bb00755e901..287334a34ee 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -377,7 +377,7 @@ int BLI_exists(const char *path)
struct stat st;
BLI_assert(!BLI_path_is_rel(path));
if (stat(path, &st)) {
- return (0);
+ return 0;
}
#endif
return (st.st_mode);
diff --git a/source/blender/blenlib/intern/string_search.cc b/source/blender/blenlib/intern/string_search.cc
index a09aa7a4bc2..44baff1f5e3 100644
--- a/source/blender/blenlib/intern/string_search.cc
+++ b/source/blender/blenlib/intern/string_search.cc
@@ -395,6 +395,7 @@ void extract_normalized_words(StringRef str,
struct SearchItem {
blender::Span<blender::StringRef> normalized_words;
+ int length;
void *user_data;
};
@@ -416,8 +417,10 @@ void BLI_string_search_add(StringSearch *search, const char *str, void *user_dat
{
using namespace blender;
Vector<StringRef, 64> words;
- string_search::extract_normalized_words(str, search->allocator, words);
- search->items.append({search->allocator.construct_array_copy(words.as_span()), user_data});
+ StringRef str_ref{str};
+ string_search::extract_normalized_words(str_ref, search->allocator, words);
+ search->items.append(
+ {search->allocator.construct_array_copy(words.as_span()), (int)str_ref.size(), user_data});
}
/**
@@ -453,7 +456,15 @@ int BLI_string_search_query(StringSearch *search, const char *query, void ***r_d
* score. Results with the same score are in the order they have been added to the search. */
Vector<int> sorted_result_indices;
for (const int score : found_scores) {
- Span<int> indices = result_indices_by_score.lookup(score);
+ MutableSpan<int> indices = result_indices_by_score.lookup(score);
+ if (score == found_scores[0]) {
+ /* Sort items with best score by length. Shorter items are more likely the ones you are
+ * looking for. This also ensures that exact matches will be at the top, even if the query is
+ * a substring of another item. */
+ std::sort(indices.begin(), indices.end(), [&](int a, int b) {
+ return search->items[a].length < search->items[b].length;
+ });
+ }
sorted_result_indices.extend(indices);
}
diff --git a/source/blender/blenlib/intern/string_utils.c b/source/blender/blenlib/intern/string_utils.c
index dbeb75570fb..dbe5c96260b 100644
--- a/source/blender/blenlib/intern/string_utils.c
+++ b/source/blender/blenlib/intern/string_utils.c
@@ -333,11 +333,6 @@ bool BLI_uniquename_cb(UniquenameCheckCallback unique_check,
return false;
}
-/* little helper macro for BLI_uniquename */
-#ifndef GIVE_STRADDR
-# define GIVE_STRADDR(data, offset) (((char *)data) + offset)
-#endif
-
/**
* Generic function to set a unique name. It is only designed to be used in situations
* where the name is part of the struct.
@@ -353,7 +348,7 @@ static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name,
for (link = list->first; link; link = link->next) {
if (link != vlink) {
- if (STREQ(GIVE_STRADDR(link, name_offs), name)) {
+ if (STREQ(POINTER_OFFSET((const char *)link, name_offs), name)) {
return true;
}
}
@@ -403,7 +398,7 @@ bool BLI_uniquename(
}
return BLI_uniquename_cb(
- uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
+ uniquename_unique_check, &data, defname, delim, POINTER_OFFSET(vlink, name_offs), name_len);
}
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/blenlib/tests/BLI_multi_value_map_test.cc b/source/blender/blenlib/tests/BLI_multi_value_map_test.cc
index 7501fbe0d87..a910f2935d4 100644
--- a/source/blender/blenlib/tests/BLI_multi_value_map_test.cc
+++ b/source/blender/blenlib/tests/BLI_multi_value_map_test.cc
@@ -29,6 +29,27 @@ TEST(multi_value_map, LookupExistant)
EXPECT_EQ(map.lookup(3)[0], 6);
}
+TEST(multi_value_map, LookupMutable)
+{
+ MultiValueMap<int, int> map;
+ map.add(1, 2);
+ map.add(4, 5);
+ map.add(4, 6);
+ map.add(6, 7);
+
+ MutableSpan<int> span = map.lookup(4);
+ EXPECT_EQ(span.size(), 2);
+ span[0] = 10;
+ span[1] = 20;
+
+ map.add(4, 5);
+ MutableSpan<int> new_span = map.lookup(4);
+ EXPECT_EQ(new_span.size(), 3);
+ EXPECT_EQ(new_span[0], 10);
+ EXPECT_EQ(new_span[1], 20);
+ EXPECT_EQ(new_span[2], 5);
+}
+
TEST(multi_value_map, AddMultiple)
{
MultiValueMap<int, int> map;
diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c
index 7261db5d3a6..f3fc1453461 100644
--- a/source/blender/blenloader/intern/blend_validate.c
+++ b/source/blender/blenloader/intern/blend_validate.c
@@ -60,7 +60,7 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports)
blo_split_main(&mainlist, bmain);
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int i = set_listbasepointers(bmain, lbarray);
while (i--) {
for (ID *id = lbarray[i]->first; id != NULL; id = id->next) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index c0293c1f8f2..2200f7c291b 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -449,7 +449,7 @@ static void oldnewmap_free(OldNewMap *onm)
static void add_main_to_main(Main *mainvar, Main *from)
{
- ListBase *lbarray[MAX_LIBARRAY], *fromarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX], *fromarray[INDEX_ID_MAX];
int a;
set_listbasepointers(mainvar, lbarray);
@@ -517,7 +517,7 @@ void blo_split_main(ListBase *mainlist, Main *main)
lib_main_array[i] = libmain;
}
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
i = set_listbasepointers(main, lbarray);
while (i--) {
ID *id = lbarray[i]->first;
@@ -1965,7 +1965,7 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
/* undo file support: add all library pointers in lookup */
void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd)
{
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
LISTBASE_FOREACH (Main *, ptr, old_mainlist) {
int i = set_listbasepointers(ptr, lbarray);
@@ -4543,7 +4543,7 @@ void BLO_main_expander(BLOExpandDoitCallback expand_doit_func)
*/
void BLO_expand_main(void *fdhandle, Main *mainvar)
{
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
FileData *fd = fdhandle;
ID *id;
int a;
@@ -4713,7 +4713,7 @@ static void add_loose_object_data_to_scene(Main *mainvar,
}
/* Loop over all ID types, instancing object-data for ID types that have support for it. */
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int i = set_listbasepointers(mainvar, lbarray);
while (i--) {
const short idcode = BKE_idtype_idcode_from_index(i);
@@ -4979,7 +4979,7 @@ static bool library_link_idcode_needs_tag_check(const short idcode, const int fl
*/
static void library_link_clear_tag(Main *mainvar, const int flag)
{
- for (int i = 0; i < MAX_LIBARRAY; i++) {
+ for (int i = 0; i < INDEX_ID_MAX; i++) {
const short idcode = BKE_idtype_idcode_from_index(i);
BLI_assert(idcode != -1);
if (library_link_idcode_needs_tag_check(idcode, flag)) {
@@ -5068,8 +5068,8 @@ static void split_main_newid(Main *mainptr, Main *main_newid)
BLI_strncpy(main_newid->name, mainptr->name, sizeof(main_newid->name));
main_newid->curlib = mainptr->curlib;
- ListBase *lbarray[MAX_LIBARRAY];
- ListBase *lbarray_newid[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
+ ListBase *lbarray_newid[INDEX_ID_MAX];
int i = set_listbasepointers(mainptr, lbarray);
set_listbasepointers(main_newid, lbarray_newid);
while (i--) {
@@ -5227,7 +5227,7 @@ void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)
static int has_linked_ids_to_read(Main *mainvar)
{
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(mainvar, lbarray);
while (a--) {
@@ -5295,7 +5295,7 @@ static void read_library_linked_ids(FileData *basefd,
{
GHash *loaded_ids = BLI_ghash_str_new(__func__);
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(mainvar, lbarray);
while (a--) {
@@ -5344,7 +5344,7 @@ static void read_library_clear_weak_links(FileData *basefd, ListBase *mainlist,
{
/* Any remaining weak links at this point have been lost, silently drop
* those by setting them to NULL pointers. */
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(mainvar, lbarray);
while (a--) {
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index d86ddc5b646..289092f7f19 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1141,7 +1141,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 276, 5)) {
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int a;
/* Important to clear all non-persistent flags from older versions here,
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index ef2e196094e..1ecaee10e6a 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -3684,7 +3684,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
if (!MAIN_VERSION_ATLEAST(bmain, 280, 48)) {
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
/* Those are not currently used, but are accessible through RNA API and were not
- * properly initialized previously. This is mere copy of BKE_init_scene() code. */
+ * properly initialized previously. This is mere copy of #scene_init_data code. */
if (scene->r.im_format.view_settings.look[0] == '\0') {
BKE_color_managed_display_settings_init(&scene->r.im_format.display_settings);
BKE_color_managed_view_settings_init_render(
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 2f3e2ae09a7..f1245a31c70 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -69,6 +69,8 @@
#include "SEQ_proxy.h"
#include "SEQ_render.h"
#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
+#include "SEQ_transform.h"
#include "BLO_readfile.h"
#include "readfile.h"
@@ -332,6 +334,37 @@ static void seq_convert_transform_crop_lb_2(const Scene *scene,
}
}
+static void seq_update_meta_disp_range(Editing *ed)
+{
+ if (ed == NULL) {
+ return;
+ }
+
+ LISTBASE_FOREACH_BACKWARD (MetaStack *, ms, &ed->metastack) {
+ /* Update ms->disp_range from meta. */
+ if (ms->disp_range[0] == ms->disp_range[1]) {
+ copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
+ }
+
+ /* Update meta strip endpoints. */
+ SEQ_transform_set_left_handle_frame(ms->parseq, ms->disp_range[0]);
+ SEQ_transform_set_right_handle_frame(ms->parseq, ms->disp_range[1]);
+ SEQ_transform_fix_single_image_seq_offsets(ms->parseq);
+
+ /* Recalculate effects using meta strip. */
+ LISTBASE_FOREACH (Sequence *, seq, ms->oldbasep) {
+ if (seq->seq2) {
+ seq->start = seq->startdisp = max_ii(seq->seq1->startdisp, seq->seq2->startdisp);
+ seq->enddisp = min_ii(seq->seq1->enddisp, seq->seq2->enddisp);
+ }
+ }
+
+ /* Ensure that active seqbase points to active meta strip seqbase. */
+ MetaStack *active_ms = SEQ_meta_stack_active_get(ed);
+ SEQ_seqbase_active_set(ed, &active_ms->parseq->seqbase);
+ }
+}
+
void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
{
if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) {
@@ -606,6 +639,10 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
*/
{
/* Keep this block, even when empty. */
+
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ seq_update_meta_disp_range(SEQ_editing_get(scene, false));
+ }
}
}
@@ -1762,6 +1799,24 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
FOREACH_NODETREE_END;
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 293, 10)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_GEOMETRY) {
+ version_node_socket_name(ntree, GEO_NODE_ATTRIBUTE_PROXIMITY, "Location", "Position");
+ }
+ }
+ FOREACH_NODETREE_END;
+
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ /* Fix old scene with too many samples that were not being used.
+ * Now they are properly used and might produce a huge slowdown.
+ * So we clamp to what the old max actual was. */
+ if (scene->eevee.volumetric_shadow_samples > 32) {
+ scene->eevee.volumetric_shadow_samples = 32;
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 0a4f2fde93f..6fbd4b77487 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -768,7 +768,7 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef)
/* Keep it last of write_foodata functions. */
static void write_libraries(WriteData *wd, Main *main)
{
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
ID *id;
int a, tot;
bool found_one;
@@ -954,7 +954,7 @@ static bool write_file_handle(Main *mainvar,
* if needed, without duplicating whole code. */
Main *bmain = mainvar;
do {
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(bmain, lbarray);
while (a--) {
ID *id = lbarray[a]->first;
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 49204d2a2b0..5c43720f635 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -46,7 +46,7 @@ static void recount_totsels(BMesh *bm)
int *tots[3];
int i;
- /* recount (tot * sel) variables */
+ /* Recount total selection variables. */
bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
tots[0] = &bm->totvertsel;
tots[1] = &bm->totedgesel;
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 7d980299771..535df52c1e1 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -924,7 +924,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
len = 2 * dia * sinf(phid / 2.0f);
- /* length of one segment in shortest parallen */
+ /* Length of one segment in shortest parallel. */
vec[0] = dia * sinf(phid);
vec[1] = 0.0f;
vec[2] = dia * cosf(phid);
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index a17724895f1..6cdf3278908 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -6445,7 +6445,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
if (bmv) {
BLI_array_append(vv, bmv);
BLI_array_append(ee, bme); /* TODO: Maybe better edge here. */
- if (corner3special && v->ebev && !v->ebev->is_seam && k != vm->seg) {
+ if (corner3special && v->ebev && !bv->any_seam && k != vm->seg) {
BLI_array_append(vv_fix, bmv);
}
}
@@ -6474,7 +6474,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
if (bmv) {
BLI_array_append(vv, bmv);
BLI_array_append(ee, bme);
- if (corner3special && v->ebev && !v->ebev->is_seam && k != 0) {
+ if (corner3special && v->ebev && !bv->any_seam && k != 0) {
BLI_array_append(vv_fix, bmv);
}
}
diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h
index ba66d7f0dfe..4aae5471858 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -113,11 +113,11 @@ extern "C" {
*
* When the chunk-order is determined, the first few chunks will be checked if they can be scheduled.
* Chunks can have three states:
- * - [@ref ChunkExecutionState.COM_ES_NOT_SCHEDULED]:
+ * - [@ref eChunkExecutionState.NOT_SCHEDULED]:
* Chunk is not yet scheduled, or dependencies are not met.
- * - [@ref ChunkExecutionState.COM_ES_SCHEDULED]:
+ * - [@ref eChunkExecutionState.SCHEDULED]:
* All dependencies are met, chunk is scheduled, but not finished.
- * - [@ref ChunkExecutionState.COM_ES_EXECUTED]:
+ * - [@ref eChunkExecutionState.EXECUTED]:
* Chunk is finished.
*
* \see ExecutionGroup.execute
diff --git a/source/blender/compositor/intern/COM_CPUDevice.cpp b/source/blender/compositor/intern/COM_CPUDevice.cpp
index 7ea12866148..b520a437008 100644
--- a/source/blender/compositor/intern/COM_CPUDevice.cpp
+++ b/source/blender/compositor/intern/COM_CPUDevice.cpp
@@ -24,8 +24,8 @@ CPUDevice::CPUDevice(int thread_id) : m_thread_id(thread_id)
void CPUDevice::execute(WorkPackage *work)
{
- const unsigned int chunkNumber = work->getChunkNumber();
- ExecutionGroup *executionGroup = work->getExecutionGroup();
+ const unsigned int chunkNumber = work->chunk_number;
+ ExecutionGroup *executionGroup = work->execution_group;
rcti rect;
executionGroup->determineChunkRect(&rect, chunkNumber);
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 08035940667..7d897d29576 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -115,9 +115,9 @@
#include "COM_ViewerNode.h"
#include "COM_ZCombineNode.h"
-bool Converter::is_fast_node(bNode *b_node)
+bool COM_bnode_is_fast_node(const bNode &b_node)
{
- return !ELEM(b_node->type,
+ return !ELEM(b_node.type,
CMP_NODE_BLUR,
CMP_NODE_VECBLUR,
CMP_NODE_BILATERALBLUR,
@@ -132,7 +132,7 @@ bool Converter::is_fast_node(bNode *b_node)
CMP_NODE_DENOISE);
}
-Node *Converter::convert(bNode *b_node)
+Node *COM_convert_bnode(bNode *b_node)
{
Node *node = nullptr;
@@ -419,36 +419,37 @@ Node *Converter::convert(bNode *b_node)
return node;
}
-NodeOperation *Converter::convertDataType(NodeOperationOutput *from, NodeOperationInput *to)
+/* TODO(jbakker): make this an std::optional<NodeOperation>. */
+NodeOperation *COM_convert_data_type(const NodeOperationOutput &from, const NodeOperationInput &to)
{
- DataType fromDatatype = from->getDataType();
- DataType toDatatype = to->getDataType();
+ const DataType src_data_type = from.getDataType();
+ const DataType dst_data_type = to.getDataType();
- if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_COLOR) {
+ if (src_data_type == COM_DT_VALUE && dst_data_type == COM_DT_COLOR) {
return new ConvertValueToColorOperation();
}
- if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_VECTOR) {
+ if (src_data_type == COM_DT_VALUE && dst_data_type == COM_DT_VECTOR) {
return new ConvertValueToVectorOperation();
}
- if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VALUE) {
+ if (src_data_type == COM_DT_COLOR && dst_data_type == COM_DT_VALUE) {
return new ConvertColorToValueOperation();
}
- if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VECTOR) {
+ if (src_data_type == COM_DT_COLOR && dst_data_type == COM_DT_VECTOR) {
return new ConvertColorToVectorOperation();
}
- if (fromDatatype == COM_DT_VECTOR && toDatatype == COM_DT_VALUE) {
+ if (src_data_type == COM_DT_VECTOR && dst_data_type == COM_DT_VALUE) {
return new ConvertVectorToValueOperation();
}
- if (fromDatatype == COM_DT_VECTOR && toDatatype == COM_DT_COLOR) {
+ if (src_data_type == COM_DT_VECTOR && dst_data_type == COM_DT_COLOR) {
return new ConvertVectorToColorOperation();
}
return nullptr;
}
-void Converter::convertResolution(NodeOperationBuilder &builder,
- NodeOperationOutput *fromSocket,
- NodeOperationInput *toSocket)
+void COM_convert_resolution(NodeOperationBuilder &builder,
+ NodeOperationOutput *fromSocket,
+ NodeOperationInput *toSocket)
{
InputResizeMode mode = toSocket->getResizeMode();
diff --git a/source/blender/compositor/intern/COM_Converter.h b/source/blender/compositor/intern/COM_Converter.h
index fe3b8b75ccc..59be34bf0e3 100644
--- a/source/blender/compositor/intern/COM_Converter.h
+++ b/source/blender/compositor/intern/COM_Converter.h
@@ -31,56 +31,37 @@ class NodeOperationOutput;
class NodeOperationBuilder;
/**
- * \brief Conversion methods for the compositor
+ * \brief Wraps a bNode in its Node instance.
+ *
+ * For all nodetypes a wrapper class is created.
+ *
+ * \note When adding a new node to blender, this method needs to be changed to return the correct
+ * Node instance.
+ *
+ * \see Node
*/
-class Converter {
- public:
- /**
- * \brief Convert/wraps a bNode in its Node instance.
- *
- * For all nodetypes a wrapper class is created.
- *
- * \note When adding a new node to blender, this method needs to be changed to return the correct
- * Node instance.
- *
- * \see Node
- */
- static Node *convert(bNode *b_node);
-
- /**
- * \brief True if the node is considered 'fast'.
- *
- * Slow nodes will be skipped if fast execution is required.
- */
- static bool is_fast_node(bNode *b_node);
+Node *COM_convert_bnode(bNode *b_node);
- /**
- * \brief This method will add a datetype conversion rule when the to-socket does not support the
- * from-socket actual data type.
- *
- * \note this method is called when conversion is needed.
- *
- * \param link: the NodeLink what needs conversion
- * \param system: the ExecutionSystem to add the conversion to.
- * \see NodeLink - a link between two sockets
- */
- static NodeOperation *convertDataType(NodeOperationOutput *from, NodeOperationInput *to);
+/**
+ * \brief True if the node is considered 'fast'.
+ *
+ * Slow nodes will be skipped if fast execution is required.
+ */
+bool COM_bnode_is_fast_node(const bNode &b_node);
- /**
- * \brief This method will add a resolution rule based on the settings of the NodeInput.
- *
- * \note Conversion logic is implemented in this method
- * \see InputSocketResizeMode for the possible conversions.
- *
- * \param link: the NodeLink what needs conversion
- * \param system: the ExecutionSystem to add the conversion to.
- * \see NodeLink - a link between two sockets
- */
- static void convertResolution(NodeOperationBuilder &builder,
- NodeOperationOutput *fromSocket,
- NodeOperationInput *toSocket);
+/**
+ * \brief This function will add a datetype conversion rule when the to-socket does not support the
+ * from-socket actual data type.
+ */
+NodeOperation *COM_convert_data_type(const NodeOperationOutput &from,
+ const NodeOperationInput &to);
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:Converter")
-#endif
-};
+/**
+ * \brief This function will add a resolution rule based on the settings of the NodeInput.
+ *
+ * \note Conversion logic is implemented in this function.
+ * \see InputSocketResizeMode for the possible conversions.
+ */
+void COM_convert_resolution(NodeOperationBuilder &builder,
+ NodeOperationOutput *fromSocket,
+ NodeOperationInput *toSocket);
diff --git a/source/blender/compositor/intern/COM_Device.h b/source/blender/compositor/intern/COM_Device.h
index bb95f1e953c..0b0f0f5c1c6 100644
--- a/source/blender/compositor/intern/COM_Device.h
+++ b/source/blender/compositor/intern/COM_Device.h
@@ -55,7 +55,7 @@ class Device {
* \brief execute a WorkPackage
* \param work: the WorkPackage to execute
*/
- virtual void execute(WorkPackage *work) = 0;
+ virtual void execute(struct WorkPackage *work) = 0;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:Device")
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
index 9c21c91c370..37623228183 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
@@ -43,20 +43,19 @@
ExecutionGroup::ExecutionGroup()
{
- this->m_isOutput = false;
+ this->m_is_output = false;
this->m_complex = false;
- this->m_chunkExecutionStates = nullptr;
this->m_bTree = nullptr;
this->m_height = 0;
this->m_width = 0;
- this->m_cachedMaxReadBufferOffset = 0;
- this->m_numberOfXChunks = 0;
- this->m_numberOfYChunks = 0;
- this->m_numberOfChunks = 0;
+ this->m_max_read_buffer_offset = 0;
+ this->m_x_chunks_len = 0;
+ this->m_y_chunks_len = 0;
+ this->m_chunks_len = 0;
this->m_initialized = false;
this->m_openCL = false;
this->m_singleThreaded = false;
- this->m_chunksFinished = 0;
+ this->m_chunks_finished = 0;
BLI_rcti_init(&this->m_viewerBorder, 0, 0, 0, 0);
this->m_executionStartTime = 0;
}
@@ -108,7 +107,7 @@ bool ExecutionGroup::addOperation(NodeOperation *operation)
m_initialized = true;
}
- m_operations.push_back(operation);
+ m_operations.append(operation);
return true;
}
@@ -121,45 +120,36 @@ NodeOperation *ExecutionGroup::getOutputOperation() const
void ExecutionGroup::initExecution()
{
- if (this->m_chunkExecutionStates != nullptr) {
- MEM_freeN(this->m_chunkExecutionStates);
- }
- unsigned int index;
+ m_chunk_execution_states.clear();
determineNumberOfChunks();
- this->m_chunkExecutionStates = nullptr;
- if (this->m_numberOfChunks != 0) {
- this->m_chunkExecutionStates = (ChunkExecutionState *)MEM_mallocN(
- sizeof(ChunkExecutionState) * this->m_numberOfChunks, __func__);
- for (index = 0; index < this->m_numberOfChunks; index++) {
- this->m_chunkExecutionStates[index] = COM_ES_NOT_SCHEDULED;
+ if (this->m_chunks_len != 0) {
+ m_chunk_execution_states.resize(this->m_chunks_len);
+ for (int index = 0; index < this->m_chunks_len; index++) {
+ m_chunk_execution_states[index] = eChunkExecutionState::NOT_SCHEDULED;
}
}
- unsigned int maxNumber = 0;
+ unsigned int max_offset = 0;
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
+ for (NodeOperation *operation : m_operations) {
if (operation->isReadBufferOperation()) {
- ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
- this->m_cachedReadOperations.push_back(readOperation);
- maxNumber = max(maxNumber, readOperation->getOffset());
+ ReadBufferOperation *readOperation = static_cast<ReadBufferOperation *>(operation);
+ this->m_read_operations.append(readOperation);
+ max_offset = MAX2(max_offset, readOperation->getOffset());
}
}
- maxNumber++;
- this->m_cachedMaxReadBufferOffset = maxNumber;
+ max_offset++;
+ this->m_max_read_buffer_offset = max_offset;
}
void ExecutionGroup::deinitExecution()
{
- if (this->m_chunkExecutionStates != nullptr) {
- MEM_freeN(this->m_chunkExecutionStates);
- this->m_chunkExecutionStates = nullptr;
- }
- this->m_numberOfChunks = 0;
- this->m_numberOfXChunks = 0;
- this->m_numberOfYChunks = 0;
- this->m_cachedReadOperations.clear();
+ m_chunk_execution_states.clear();
+ this->m_chunks_len = 0;
+ this->m_x_chunks_len = 0;
+ this->m_y_chunks_len = 0;
+ this->m_read_operations.clear();
this->m_bTree = nullptr;
}
void ExecutionGroup::determineResolution(unsigned int resolution[2])
@@ -174,17 +164,17 @@ void ExecutionGroup::determineResolution(unsigned int resolution[2])
void ExecutionGroup::determineNumberOfChunks()
{
if (this->m_singleThreaded) {
- this->m_numberOfXChunks = 1;
- this->m_numberOfYChunks = 1;
- this->m_numberOfChunks = 1;
+ this->m_x_chunks_len = 1;
+ this->m_y_chunks_len = 1;
+ this->m_chunks_len = 1;
}
else {
const float chunkSizef = this->m_chunkSize;
const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
- this->m_numberOfXChunks = ceil(border_width / chunkSizef);
- this->m_numberOfYChunks = ceil(border_height / chunkSizef);
- this->m_numberOfChunks = this->m_numberOfXChunks * this->m_numberOfYChunks;
+ this->m_x_chunks_len = ceil(border_width / chunkSizef);
+ this->m_y_chunks_len = ceil(border_height / chunkSizef);
+ this->m_chunks_len = this->m_x_chunks_len * this->m_y_chunks_len;
}
}
@@ -202,20 +192,20 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
if (bTree->test_break && bTree->test_break(bTree->tbh)) {
return;
} /** \note Early break out for blur and preview nodes. */
- if (this->m_numberOfChunks == 0) {
+ if (this->m_chunks_len == 0) {
return;
} /** \note Early break out. */
unsigned int chunkNumber;
this->m_executionStartTime = PIL_check_seconds_timer();
- this->m_chunksFinished = 0;
+ this->m_chunks_finished = 0;
this->m_bTree = bTree;
unsigned int index;
- unsigned int *chunkOrder = (unsigned int *)MEM_mallocN(
- sizeof(unsigned int) * this->m_numberOfChunks, __func__);
+ unsigned int *chunkOrder = (unsigned int *)MEM_mallocN(sizeof(unsigned int) * this->m_chunks_len,
+ __func__);
- for (chunkNumber = 0; chunkNumber < this->m_numberOfChunks; chunkNumber++) {
+ for (chunkNumber = 0; chunkNumber < this->m_chunks_len; chunkNumber++) {
chunkOrder[chunkNumber] = chunkNumber;
}
NodeOperation *operation = this->getOutputOperation();
@@ -235,9 +225,9 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
switch (chunkorder) {
case COM_TO_RANDOM:
- for (index = 0; index < 2 * this->m_numberOfChunks; index++) {
- int index1 = rand() % this->m_numberOfChunks;
- int index2 = rand() % this->m_numberOfChunks;
+ for (index = 0; index < 2 * this->m_chunks_len; index++) {
+ int index1 = rand() % this->m_chunks_len;
+ int index2 = rand() % this->m_chunks_len;
int s = chunkOrder[index1];
chunkOrder[index1] = chunkOrder[index2];
chunkOrder[index2] = s;
@@ -247,9 +237,9 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
ChunkOrderHotspot *hotspots[1];
hotspots[0] = new ChunkOrderHotspot(border_width * centerX, border_height * centerY, 0.0f);
rcti rect;
- ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(
- sizeof(ChunkOrder) * this->m_numberOfChunks, __func__);
- for (index = 0; index < this->m_numberOfChunks; index++) {
+ ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(sizeof(ChunkOrder) * this->m_chunks_len,
+ __func__);
+ for (index = 0; index < this->m_chunks_len; index++) {
determineChunkRect(&rect, index);
chunkOrders[index].number = index;
chunkOrders[index].x = rect.xmin - this->m_viewerBorder.xmin;
@@ -257,8 +247,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
chunkOrders[index].update_distance(hotspots, 1);
}
- std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks - 1]);
- for (index = 0; index < this->m_numberOfChunks; index++) {
+ std::sort(&chunkOrders[0], &chunkOrders[this->m_chunks_len - 1]);
+ for (index = 0; index < this->m_chunks_len; index++) {
chunkOrder[index] = chunkOrders[index].number;
}
@@ -275,7 +265,7 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
unsigned int bx = mx + 2 * tx;
unsigned int by = my + 2 * ty;
- float addition = this->m_numberOfChunks / COM_RULE_OF_THIRDS_DIVIDER;
+ float addition = this->m_chunks_len / COM_RULE_OF_THIRDS_DIVIDER;
hotspots[0] = new ChunkOrderHotspot(mx, my, addition * 0);
hotspots[1] = new ChunkOrderHotspot(tx, my, addition * 1);
hotspots[2] = new ChunkOrderHotspot(bx, my, addition * 2);
@@ -286,9 +276,9 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
hotspots[7] = new ChunkOrderHotspot(mx, ty, addition * 7);
hotspots[8] = new ChunkOrderHotspot(mx, by, addition * 8);
rcti rect;
- ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(
- sizeof(ChunkOrder) * this->m_numberOfChunks, __func__);
- for (index = 0; index < this->m_numberOfChunks; index++) {
+ ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(sizeof(ChunkOrder) * this->m_chunks_len,
+ __func__);
+ for (index = 0; index < this->m_chunks_len; index++) {
determineChunkRect(&rect, index);
chunkOrders[index].number = index;
chunkOrders[index].x = rect.xmin - this->m_viewerBorder.xmin;
@@ -296,9 +286,9 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
chunkOrders[index].update_distance(hotspots, 9);
}
- std::sort(&chunkOrders[0], &chunkOrders[this->m_numberOfChunks]);
+ std::sort(&chunkOrders[0], &chunkOrders[this->m_chunks_len]);
- for (index = 0; index < this->m_numberOfChunks; index++) {
+ for (index = 0; index < this->m_chunks_len; index++) {
chunkOrder[index] = chunkOrders[index].number;
}
@@ -332,31 +322,35 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
finished = true;
int numberEvaluated = 0;
- for (index = startIndex;
- index < this->m_numberOfChunks && numberEvaluated < maxNumberEvaluated;
+ for (index = startIndex; index < this->m_chunks_len && numberEvaluated < maxNumberEvaluated;
index++) {
chunkNumber = chunkOrder[index];
- int yChunk = chunkNumber / this->m_numberOfXChunks;
- int xChunk = chunkNumber - (yChunk * this->m_numberOfXChunks);
- const ChunkExecutionState state = this->m_chunkExecutionStates[chunkNumber];
- if (state == COM_ES_NOT_SCHEDULED) {
- scheduleChunkWhenPossible(graph, xChunk, yChunk);
- finished = false;
- startEvaluated = true;
- numberEvaluated++;
-
- if (bTree->update_draw) {
- bTree->update_draw(bTree->udh);
+ int yChunk = chunkNumber / this->m_x_chunks_len;
+ int xChunk = chunkNumber - (yChunk * this->m_x_chunks_len);
+ switch (m_chunk_execution_states[chunkNumber]) {
+ case eChunkExecutionState::NOT_SCHEDULED: {
+ scheduleChunkWhenPossible(graph, xChunk, yChunk);
+ finished = false;
+ startEvaluated = true;
+ numberEvaluated++;
+
+ if (bTree->update_draw) {
+ bTree->update_draw(bTree->udh);
+ }
+ break;
}
- }
- else if (state == COM_ES_SCHEDULED) {
- finished = false;
- startEvaluated = true;
- numberEvaluated++;
- }
- else if (state == COM_ES_EXECUTED && !startEvaluated) {
- startIndex = index + 1;
- }
+ case eChunkExecutionState::SCHEDULED: {
+ finished = false;
+ startEvaluated = true;
+ numberEvaluated++;
+ break;
+ }
+ case eChunkExecutionState::EXECUTED: {
+ if (!startEvaluated) {
+ startIndex = index + 1;
+ }
+ }
+ };
}
WorkScheduler::finish();
@@ -374,17 +368,14 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
MemoryBuffer **ExecutionGroup::getInputBuffersOpenCL(int chunkNumber)
{
rcti rect;
- vector<MemoryProxy *> memoryproxies;
- unsigned int index;
+ std::vector<MemoryProxy *> memoryproxies;
determineChunkRect(&rect, chunkNumber);
this->determineDependingMemoryProxies(&memoryproxies);
MemoryBuffer **memoryBuffers = (MemoryBuffer **)MEM_callocN(
- sizeof(MemoryBuffer *) * this->m_cachedMaxReadBufferOffset, __func__);
+ sizeof(MemoryBuffer *) * this->m_max_read_buffer_offset, __func__);
rcti output;
- for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
- ReadBufferOperation *readOperation =
- (ReadBufferOperation *)this->m_cachedReadOperations[index];
+ for (ReadBufferOperation *readOperation : m_read_operations) {
MemoryProxy *memoryProxy = readOperation->getMemoryProxy();
this->determineDependingAreaOfInterest(&rect, readOperation, &output);
MemoryBuffer *memoryBuffer = memoryProxy->getExecutor()->constructConsolidatedMemoryBuffer(
@@ -405,13 +396,13 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem
void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers)
{
- if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED) {
- this->m_chunkExecutionStates[chunkNumber] = COM_ES_EXECUTED;
+ if (this->m_chunk_execution_states[chunkNumber] == eChunkExecutionState::SCHEDULED) {
+ this->m_chunk_execution_states[chunkNumber] = eChunkExecutionState::EXECUTED;
}
- atomic_add_and_fetch_u(&this->m_chunksFinished, 1);
+ atomic_add_and_fetch_u(&this->m_chunks_finished, 1);
if (memoryBuffers) {
- for (unsigned int index = 0; index < this->m_cachedMaxReadBufferOffset; index++) {
+ for (unsigned int index = 0; index < this->m_max_read_buffer_offset; index++) {
MemoryBuffer *buffer = memoryBuffers[index];
if (buffer) {
if (buffer->isTemporarily()) {
@@ -424,16 +415,16 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memo
}
if (this->m_bTree) {
// status report is only performed for top level Execution Groups.
- float progress = this->m_chunksFinished;
- progress /= this->m_numberOfChunks;
+ float progress = this->m_chunks_finished;
+ progress /= this->m_chunks_len;
this->m_bTree->progress(this->m_bTree->prh, progress);
char buf[128];
BLI_snprintf(buf,
sizeof(buf),
TIP_("Compositing | Tile %u-%u"),
- this->m_chunksFinished,
- this->m_numberOfChunks);
+ this->m_chunks_finished,
+ this->m_chunks_len);
this->m_bTree->stats_draw(this->m_bTree->sdh, buf);
}
}
@@ -452,20 +443,20 @@ inline void ExecutionGroup::determineChunkRect(rcti *rect,
else {
const unsigned int minx = xChunk * this->m_chunkSize + this->m_viewerBorder.xmin;
const unsigned int miny = yChunk * this->m_chunkSize + this->m_viewerBorder.ymin;
- const unsigned int width = min((unsigned int)this->m_viewerBorder.xmax, this->m_width);
- const unsigned int height = min((unsigned int)this->m_viewerBorder.ymax, this->m_height);
+ const unsigned int width = MIN2((unsigned int)this->m_viewerBorder.xmax, this->m_width);
+ const unsigned int height = MIN2((unsigned int)this->m_viewerBorder.ymax, this->m_height);
BLI_rcti_init(rect,
- min(minx, this->m_width),
- min(minx + this->m_chunkSize, width),
- min(miny, this->m_height),
- min(miny + this->m_chunkSize, height));
+ MIN2(minx, this->m_width),
+ MIN2(minx + this->m_chunkSize, width),
+ MIN2(miny, this->m_height),
+ MIN2(miny + this->m_chunkSize, height));
}
}
void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int chunkNumber) const
{
- const unsigned int yChunk = chunkNumber / this->m_numberOfXChunks;
- const unsigned int xChunk = chunkNumber - (yChunk * this->m_numberOfXChunks);
+ const unsigned int yChunk = chunkNumber / this->m_x_chunks_len;
+ const unsigned int xChunk = chunkNumber - (yChunk * this->m_x_chunks_len);
determineChunkRect(rect, xChunk, yChunk);
}
@@ -500,8 +491,8 @@ bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area
int maxychunk = (maxy + (int)m_chunkSize - 1) / (int)m_chunkSize;
minxchunk = max_ii(minxchunk, 0);
minychunk = max_ii(minychunk, 0);
- maxxchunk = min_ii(maxxchunk, (int)m_numberOfXChunks);
- maxychunk = min_ii(maxychunk, (int)m_numberOfYChunks);
+ maxxchunk = min_ii(maxxchunk, (int)m_x_chunks_len);
+ maxychunk = min_ii(maxychunk, (int)m_y_chunks_len);
bool result = true;
for (indexx = minxchunk; indexx < maxxchunk; indexx++) {
@@ -517,8 +508,8 @@ bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area
bool ExecutionGroup::scheduleChunk(unsigned int chunkNumber)
{
- if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_NOT_SCHEDULED) {
- this->m_chunkExecutionStates[chunkNumber] = COM_ES_SCHEDULED;
+ if (this->m_chunk_execution_states[chunkNumber] == eChunkExecutionState::NOT_SCHEDULED) {
+ this->m_chunk_execution_states[chunkNumber] = eChunkExecutionState::SCHEDULED;
WorkScheduler::schedule(this, chunkNumber);
return true;
}
@@ -527,25 +518,25 @@ bool ExecutionGroup::scheduleChunk(unsigned int chunkNumber)
bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *graph, int xChunk, int yChunk)
{
- if (xChunk < 0 || xChunk >= (int)this->m_numberOfXChunks) {
+ if (xChunk < 0 || xChunk >= (int)this->m_x_chunks_len) {
return true;
}
- if (yChunk < 0 || yChunk >= (int)this->m_numberOfYChunks) {
+ if (yChunk < 0 || yChunk >= (int)this->m_y_chunks_len) {
return true;
}
- int chunkNumber = yChunk * this->m_numberOfXChunks + xChunk;
+ int chunkNumber = yChunk * this->m_x_chunks_len + xChunk;
// chunk is already executed
- if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_EXECUTED) {
+ if (this->m_chunk_execution_states[chunkNumber] == eChunkExecutionState::EXECUTED) {
return true;
}
// chunk is scheduled, but not executed
- if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED) {
+ if (this->m_chunk_execution_states[chunkNumber] == eChunkExecutionState::SCHEDULED) {
return false;
}
// chunk is nor executed nor scheduled.
- vector<MemoryProxy *> memoryProxies;
+ std::vector<MemoryProxy *> memoryProxies;
this->determineDependingMemoryProxies(&memoryProxies);
rcti rect;
@@ -554,9 +545,8 @@ bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *graph, int xChun
bool canBeExecuted = true;
rcti area;
- for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
- ReadBufferOperation *readOperation =
- (ReadBufferOperation *)this->m_cachedReadOperations[index];
+ for (index = 0; index < m_read_operations.size(); index++) {
+ ReadBufferOperation *readOperation = m_read_operations[index];
BLI_rcti_init(&area, 0, 0, 0, 0);
MemoryProxy *memoryProxy = memoryProxies[index];
determineDependingAreaOfInterest(&rect, readOperation, &area);
@@ -586,12 +576,9 @@ void ExecutionGroup::determineDependingAreaOfInterest(rcti *input,
this->getOutputOperation()->determineDependingAreaOfInterest(input, readOperation, output);
}
-void ExecutionGroup::determineDependingMemoryProxies(vector<MemoryProxy *> *memoryProxies)
+void ExecutionGroup::determineDependingMemoryProxies(std::vector<MemoryProxy *> *memoryProxies)
{
- unsigned int index;
- for (index = 0; index < this->m_cachedReadOperations.size(); index++) {
- ReadBufferOperation *readOperation =
- (ReadBufferOperation *)this->m_cachedReadOperations[index];
+ for (ReadBufferOperation *readOperation : m_read_operations) {
memoryProxies->push_back(readOperation->getMemoryProxy());
}
}
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h
index dd079415d09..f73f4473b5d 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.h
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.h
@@ -23,6 +23,8 @@
#endif
#include "BLI_rect.h"
+#include "BLI_vector.hh"
+
#include "COM_CompositorContext.h"
#include "COM_Device.h"
#include "COM_MemoryProxy.h"
@@ -30,8 +32,6 @@
#include "COM_NodeOperation.h"
#include <vector>
-using std::vector;
-
class ExecutionSystem;
class MemoryProxy;
class ReadBufferOperation;
@@ -41,20 +41,20 @@ class Device;
* \brief the execution state of a chunk in an ExecutionGroup
* \ingroup Execution
*/
-typedef enum ChunkExecutionState {
+enum class eChunkExecutionState {
/**
* \brief chunk is not yet scheduled
*/
- COM_ES_NOT_SCHEDULED = 0,
+ NOT_SCHEDULED = 0,
/**
* \brief chunk is scheduled, but not yet executed
*/
- COM_ES_SCHEDULED = 1,
+ SCHEDULED = 1,
/**
* \brief chunk is executed.
*/
- COM_ES_EXECUTED = 2,
-} ChunkExecutionState;
+ EXECUTED = 2,
+};
/**
* \brief Class ExecutionGroup is a group of Operations that are executed as one.
@@ -63,23 +63,20 @@ typedef enum ChunkExecutionState {
* \ingroup Execution
*/
class ExecutionGroup {
- public:
- typedef std::vector<NodeOperation *> Operations;
-
private:
// fields
/**
* \brief list of operations in this ExecutionGroup
*/
- Operations m_operations;
+ blender::Vector<NodeOperation *> m_operations;
/**
* \brief is this ExecutionGroup an input ExecutionGroup
* an input execution group is a group that is at the end of the calculation
* (the output is important for the user).
*/
- int m_isOutput;
+ bool m_is_output;
/**
* \brief Width of the output
@@ -100,17 +97,17 @@ class ExecutionGroup {
/**
* \brief number of chunks in the x-axis
*/
- unsigned int m_numberOfXChunks;
+ unsigned int m_x_chunks_len;
/**
* \brief number of chunks in the y-axis
*/
- unsigned int m_numberOfYChunks;
+ unsigned int m_y_chunks_len;
/**
* \brief total number of chunks
*/
- unsigned int m_numberOfChunks;
+ unsigned int m_chunks_len;
/**
* \brief contains this ExecutionGroup a complex NodeOperation.
@@ -131,12 +128,12 @@ class ExecutionGroup {
* \brief what is the maximum number field of all ReadBufferOperation in this ExecutionGroup.
* \note this is used to construct the MemoryBuffers that will be passed during execution.
*/
- unsigned int m_cachedMaxReadBufferOffset;
+ unsigned int m_max_read_buffer_offset;
/**
- * \brief a cached vector of all read operations in the execution group.
+ * \brief All read operations of this execution group.
*/
- Operations m_cachedReadOperations;
+ blender::Vector<ReadBufferOperation *> m_read_operations;
/**
* \brief reference to the original bNodeTree,
@@ -148,15 +145,15 @@ class ExecutionGroup {
/**
* \brief total number of chunks that have been calculated for this ExecutionGroup
*/
- unsigned int m_chunksFinished;
+ unsigned int m_chunks_finished;
/**
- * \brief the chunkExecutionStates holds per chunk the execution state. this state can be
- * - COM_ES_NOT_SCHEDULED: not scheduled
- * - COM_ES_SCHEDULED: scheduled
- * - COM_ES_EXECUTED: executed
+ * \brief m_chunk_execution_states holds per chunk the execution state. this state can be
+ * - eChunkExecutionState::NOT_SCHEDULED: not scheduled
+ * - eChunkExecutionState::SCHEDULED: scheduled
+ * - eChunkExecutionState::EXECUTED: executed
*/
- ChunkExecutionState *m_chunkExecutionStates;
+ blender::Vector<eChunkExecutionState> m_chunk_execution_states;
/**
* \brief indicator when this ExecutionGroup has valid Operations in its vector for Execution
@@ -272,18 +269,18 @@ class ExecutionGroup {
* \note ViewerOperation, CompositeOperation, PreviewOperation.
* \see NodeOperation.isOutputOperation
*/
- int isOutputExecutionGroup() const
+ bool isOutputExecutionGroup() const
{
- return this->m_isOutput;
+ return this->m_is_output;
}
/**
* \brief set whether this ExecutionGroup is an output
* \param isOutput:
*/
- void setOutputExecutionGroup(int isOutput)
+ void setOutputExecutionGroup(bool is_output)
{
- this->m_isOutput = isOutput;
+ this->m_is_output = is_output;
}
/**
@@ -405,7 +402,7 @@ class ExecutionGroup {
* \note the area of the MemoryProxy.creator that has to be executed.
* \param memoryProxies: result
*/
- void determineDependingMemoryProxies(vector<MemoryProxy *> *memoryProxies);
+ void determineDependingMemoryProxies(std::vector<MemoryProxy *> *memoryProxies);
/**
* \brief Determine the rect (minx, maxx, miny, maxy) of a chunk.
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
index 4c0c7d2103e..6691e5feb5f 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
@@ -121,7 +121,8 @@ ExecutionSystem::~ExecutionSystem()
this->m_groups.clear();
}
-void ExecutionSystem::set_operations(const Operations &operations, const Groups &groups)
+void ExecutionSystem::set_operations(const blender::Vector<NodeOperation *> &operations,
+ const blender::Vector<ExecutionGroup *> &groups)
{
m_operations = operations;
m_groups = groups;
@@ -135,10 +136,7 @@ void ExecutionSystem::execute()
DebugInfo::execute_started(this);
unsigned int order = 0;
- for (vector<NodeOperation *>::iterator iter = this->m_operations.begin();
- iter != this->m_operations.end();
- ++iter) {
- NodeOperation *operation = *iter;
+ for (NodeOperation *operation : m_operations) {
if (operation->isReadBufferOperation()) {
ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
readOperation->setOffset(order);
@@ -179,10 +177,10 @@ void ExecutionSystem::execute()
WorkScheduler::start(this->m_context);
- executeGroups(COM_PRIORITY_HIGH);
+ execute_groups(COM_PRIORITY_HIGH);
if (!this->getContext().isFastCalculation()) {
- executeGroups(COM_PRIORITY_MEDIUM);
- executeGroups(COM_PRIORITY_LOW);
+ execute_groups(COM_PRIORITY_MEDIUM);
+ execute_groups(COM_PRIORITY_LOW);
}
WorkScheduler::finish();
@@ -199,37 +197,23 @@ void ExecutionSystem::execute()
}
}
-void ExecutionSystem::executeGroups(CompositorPriority priority)
+void ExecutionSystem::execute_groups(CompositorPriority priority)
{
- unsigned int index;
- vector<ExecutionGroup *> executionGroups;
- this->findOutputExecutionGroup(&executionGroups, priority);
-
- for (index = 0; index < executionGroups.size(); index++) {
- ExecutionGroup *group = executionGroups[index];
+ blender::Vector<ExecutionGroup *> execution_groups = find_output_execution_groups(priority);
+ for (ExecutionGroup *group : execution_groups) {
group->execute(this);
}
}
-void ExecutionSystem::findOutputExecutionGroup(vector<ExecutionGroup *> *result,
- CompositorPriority priority) const
+blender::Vector<ExecutionGroup *> ExecutionSystem::find_output_execution_groups(
+ CompositorPriority priority) const
{
- unsigned int index;
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *group = this->m_groups[index];
- if (group->isOutputExecutionGroup() && group->getRenderPriotrity() == priority) {
- result->push_back(group);
- }
- }
-}
+ blender::Vector<ExecutionGroup *> result;
-void ExecutionSystem::findOutputExecutionGroup(vector<ExecutionGroup *> *result) const
-{
- unsigned int index;
- for (index = 0; index < this->m_groups.size(); index++) {
- ExecutionGroup *group = this->m_groups[index];
- if (group->isOutputExecutionGroup()) {
- result->push_back(group);
+ for (ExecutionGroup *group : m_groups) {
+ if (group->isOutputExecutionGroup() && group->getRenderPriotrity() == priority) {
+ result.append(group);
}
}
+ return result;
}
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index 44b47787b06..9a51baf55d7 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -21,12 +21,16 @@ class ExecutionGroup;
#pragma once
#include "BKE_text.h"
+
#include "COM_ExecutionGroup.h"
#include "COM_Node.h"
#include "COM_NodeOperation.h"
+
#include "DNA_color_types.h"
#include "DNA_node_types.h"
+#include "BLI_vector.hh"
+
/**
* \page execution Execution model
* In order to get to an efficient model for execution, several steps are being done. these steps
@@ -79,7 +83,7 @@ class ExecutionGroup;
* - [@ref InputSocketResizeMode.COM_SC_NO_RESIZE]:
* Bottom left of the images are aligned.
*
- * \see Converter.convertDataType Datatype conversions
+ * \see COM_convert_data_type Datatype conversions
* \see Converter.convertResolution Image size conversions
*
* \section EM_Step4 Step4: group operations in executions groups
@@ -113,9 +117,6 @@ class ExecutionGroup;
* \brief the ExecutionSystem contains the whole compositor tree.
*/
class ExecutionSystem {
- public:
- typedef std::vector<NodeOperation *> Operations;
- typedef std::vector<ExecutionGroup *> Groups;
private:
/**
@@ -126,24 +127,19 @@ class ExecutionSystem {
/**
* \brief vector of operations
*/
- Operations m_operations;
+ blender::Vector<NodeOperation *> m_operations;
/**
* \brief vector of groups
*/
- Groups m_groups;
+ blender::Vector<ExecutionGroup *> m_groups;
private: // methods
/**
* find all execution group with output nodes
*/
- void findOutputExecutionGroup(vector<ExecutionGroup *> *result,
- CompositorPriority priority) const;
-
- /**
- * find all execution group with output nodes
- */
- void findOutputExecutionGroup(vector<ExecutionGroup *> *result) const;
+ blender::Vector<ExecutionGroup *> find_output_execution_groups(
+ CompositorPriority priority) const;
public:
/**
@@ -167,7 +163,8 @@ class ExecutionSystem {
*/
~ExecutionSystem();
- void set_operations(const Operations &operations, const Groups &groups);
+ void set_operations(const blender::Vector<NodeOperation *> &operations,
+ const blender::Vector<ExecutionGroup *> &groups);
/**
* \brief execute this system
@@ -186,7 +183,7 @@ class ExecutionSystem {
}
private:
- void executeGroups(CompositorPriority priority);
+ void execute_groups(CompositorPriority priority);
/* allow the DebugInfo class to look at internals */
friend class DebugInfo;
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index a13db6bb09e..17a73efeab2 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -20,9 +20,6 @@
#include "MEM_guardedalloc.h"
-using std::max;
-using std::min;
-
static unsigned int determine_num_channels(DataType datatype)
{
switch (datatype) {
@@ -156,10 +153,10 @@ void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer)
return;
}
unsigned int otherY;
- unsigned int minX = max(this->m_rect.xmin, otherBuffer->m_rect.xmin);
- unsigned int maxX = min(this->m_rect.xmax, otherBuffer->m_rect.xmax);
- unsigned int minY = max(this->m_rect.ymin, otherBuffer->m_rect.ymin);
- unsigned int maxY = min(this->m_rect.ymax, otherBuffer->m_rect.ymax);
+ unsigned int minX = MAX2(this->m_rect.xmin, otherBuffer->m_rect.xmin);
+ unsigned int maxX = MIN2(this->m_rect.xmax, otherBuffer->m_rect.xmax);
+ unsigned int minY = MAX2(this->m_rect.ymin, otherBuffer->m_rect.ymin);
+ unsigned int maxY = MIN2(this->m_rect.ymax, otherBuffer->m_rect.ymax);
int offset;
int otherOffset;
diff --git a/source/blender/compositor/intern/COM_MetaData.cpp b/source/blender/compositor/intern/COM_MetaData.cpp
index 4bc4571face..a6306f6c657 100644
--- a/source/blender/compositor/intern/COM_MetaData.cpp
+++ b/source/blender/compositor/intern/COM_MetaData.cpp
@@ -18,7 +18,6 @@
#include "COM_MetaData.h"
-#include "BKE_cryptomatte.hh"
#include "BKE_image.h"
#include "RE_pipeline.h"
@@ -69,3 +68,39 @@ void MetaData::addToRenderResult(RenderResult *render_result) const
BKE_render_result_stamp_data(render_result, entry.key.c_str(), entry.value.c_str());
}
}
+
+void MetaDataExtractCallbackData::addMetaData(blender::StringRef key, blender::StringRefNull value)
+{
+ if (!meta_data) {
+ meta_data = std::make_unique<MetaData>();
+ }
+ meta_data->add(key, value);
+}
+
+void MetaDataExtractCallbackData::setCryptomatteKeys(blender::StringRef cryptomatte_layer_name)
+{
+ manifest_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
+ "manifest");
+ hash_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
+ "hash");
+ conversion_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
+ "conversion");
+}
+
+void MetaDataExtractCallbackData::extract_cryptomatte_meta_data(void *_data,
+ const char *propname,
+ char *propvalue,
+ int UNUSED(len))
+{
+ MetaDataExtractCallbackData *data = static_cast<MetaDataExtractCallbackData *>(_data);
+ blender::StringRefNull key(propname);
+ if (key == data->hash_key) {
+ data->addMetaData(META_DATA_KEY_CRYPTOMATTE_HASH, propvalue);
+ }
+ else if (key == data->conversion_key) {
+ data->addMetaData(META_DATA_KEY_CRYPTOMATTE_CONVERSION, propvalue);
+ }
+ else if (key == data->manifest_key) {
+ data->addMetaData(META_DATA_KEY_CRYPTOMATTE_MANIFEST, propvalue);
+ }
+} \ No newline at end of file
diff --git a/source/blender/compositor/intern/COM_MetaData.h b/source/blender/compositor/intern/COM_MetaData.h
index c1e34df2791..fa3de895b4e 100644
--- a/source/blender/compositor/intern/COM_MetaData.h
+++ b/source/blender/compositor/intern/COM_MetaData.h
@@ -20,13 +20,13 @@
#include <string>
+#include "BKE_cryptomatte.hh"
#include "BLI_map.hh"
#include "MEM_guardedalloc.h"
/* Forward declarations. */
struct RenderResult;
-struct StampData;
/* Cryptomatte includes hash in its meta data keys. The hash is generated from the render
* layer/pass name. Compositing happens without the knowledge of the original layer and pass. The
@@ -54,3 +54,18 @@ class MetaData {
MEM_CXX_CLASS_ALLOC_FUNCS("COM:MetaData")
#endif
};
+
+struct MetaDataExtractCallbackData {
+ std::unique_ptr<MetaData> meta_data;
+ std::string hash_key;
+ std::string conversion_key;
+ std::string manifest_key;
+
+ void addMetaData(blender::StringRef key, blender::StringRefNull value);
+ void setCryptomatteKeys(blender::StringRef cryptomatte_layer_name);
+ /* C type callback function (StampCallback). */
+ static void extract_cryptomatte_meta_data(void *_data,
+ const char *propname,
+ char *propvalue,
+ int UNUSED(len));
+};
diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp
index b604b8ced88..421a762d9b5 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.cpp
+++ b/source/blender/compositor/intern/COM_NodeGraph.cpp
@@ -90,7 +90,7 @@ void NodeGraph::add_node(Node *node,
void NodeGraph::add_link(NodeOutput *fromSocket, NodeInput *toSocket)
{
- m_links.push_back(Link(fromSocket, toSocket));
+ m_links.append(Link(fromSocket, toSocket));
/* register with the input */
toSocket->setLink(fromSocket);
@@ -132,7 +132,7 @@ void NodeGraph::add_bNode(const CompositorContext &context,
}
/* replace slow nodes with proxies for fast execution */
- if (context.isFastCalculation() && !Converter::is_fast_node(b_node)) {
+ if (context.isFastCalculation() && !COM_bnode_is_fast_node(*b_node)) {
add_proxies_skip(b_ntree, b_node, key, is_active_group);
return;
}
@@ -146,7 +146,7 @@ void NodeGraph::add_bNode(const CompositorContext &context,
}
else {
/* regular nodes, handled in Converter */
- Node *node = Converter::convert(b_node);
+ Node *node = COM_convert_bnode(b_node);
if (node) {
add_node(node, b_ntree, key, is_active_group);
}
diff --git a/source/blender/compositor/intern/COM_NodeGraph.h b/source/blender/compositor/intern/COM_NodeGraph.h
index 7252d546fce..990e3a30831 100644
--- a/source/blender/compositor/intern/COM_NodeGraph.h
+++ b/source/blender/compositor/intern/COM_NodeGraph.h
@@ -18,6 +18,8 @@
#pragma once
+#include "BLI_vector.hh"
+
#include <map>
#include <set>
#include <vector>
@@ -39,33 +41,21 @@ class NodeOutput;
*/
class NodeGraph {
public:
- class Link {
- private:
- NodeOutput *m_from;
- NodeInput *m_to;
-
- public:
- Link(NodeOutput *from, NodeInput *to) : m_from(from), m_to(to)
- {
- }
+ struct Link {
+ NodeOutput *from;
+ NodeInput *to;
- NodeOutput *getFromSocket() const
- {
- return m_from;
- }
- NodeInput *getToSocket() const
+ Link(NodeOutput *from, NodeInput *to) : from(from), to(to)
{
- return m_to;
}
};
typedef std::vector<Node *> Nodes;
typedef Nodes::iterator NodeIterator;
- typedef std::vector<Link> Links;
private:
Nodes m_nodes;
- Links m_links;
+ blender::Vector<Link> m_links;
public:
NodeGraph();
@@ -75,7 +65,7 @@ class NodeGraph {
{
return m_nodes;
}
- const Links &links() const
+ const blender::Vector<Link> &links() const
{
return m_links;
}
diff --git a/source/blender/compositor/intern/COM_NodeOperation.cpp b/source/blender/compositor/intern/COM_NodeOperation.cpp
index 1a30806f28c..ce7d3a6389e 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperation.cpp
@@ -182,10 +182,10 @@ bool NodeOperation::determineDependingAreaOfInterest(rcti *input,
first = false;
}
else {
- output->xmin = min(output->xmin, tempOutput.xmin);
- output->ymin = min(output->ymin, tempOutput.ymin);
- output->xmax = max(output->xmax, tempOutput.xmax);
- output->ymax = max(output->ymax, tempOutput.ymax);
+ output->xmin = MIN2(output->xmin, tempOutput.xmin);
+ output->ymin = MIN2(output->ymin, tempOutput.ymin);
+ output->xmax = MAX2(output->xmax, tempOutput.xmax);
+ output->ymax = MAX2(output->ymax, tempOutput.ymax);
}
}
}
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 0ce7c1389bd..f26279e2869 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -33,10 +33,6 @@
#include "clew.h"
-using std::list;
-using std::max;
-using std::min;
-
class OpenCLDevice;
class ReadBufferOperation;
class WriteBufferOperation;
@@ -239,8 +235,8 @@ class NodeOperation : public SocketReader {
MemoryBuffer * /*outputMemoryBuffer*/,
cl_mem /*clOutputBuffer*/,
MemoryBuffer ** /*inputMemoryBuffers*/,
- list<cl_mem> * /*clMemToCleanUp*/,
- list<cl_kernel> * /*clKernelsToCleanUp*/)
+ std::list<cl_mem> * /*clMemToCleanUp*/,
+ std::list<cl_kernel> * /*clKernelsToCleanUp*/)
{
}
virtual void deinitExecution();
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
index 35a3314db3b..688b693080f 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
@@ -72,11 +72,9 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
inverse_input_map[it->second].push_back(it->first);
}
- for (NodeGraph::Links::const_iterator it = m_graph.links().begin(); it != m_graph.links().end();
- ++it) {
- const NodeGraph::Link &link = *it;
- NodeOutput *from = link.getFromSocket();
- NodeInput *to = link.getToSocket();
+ for (const NodeGraph::Link &link : m_graph.links()) {
+ NodeOutput *from = link.from;
+ NodeInput *to = link.to;
NodeOperationOutput *op_from = find_operation_output(m_output_map, from);
const OpInputs &op_to_list = find_operation_inputs(inverse_input_map, to);
@@ -125,7 +123,7 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
void NodeOperationBuilder::addOperation(NodeOperation *operation)
{
- m_operations.push_back(operation);
+ m_operations.append(operation);
}
void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket,
@@ -288,7 +286,7 @@ void NodeOperationBuilder::add_datatype_conversions()
}
for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
const Link &link = *it;
- NodeOperation *converter = Converter::convertDataType(link.from(), link.to());
+ NodeOperation *converter = COM_convert_data_type(*link.from(), *link.to());
if (converter) {
addOperation(converter);
@@ -306,8 +304,7 @@ void NodeOperationBuilder::add_operation_input_constants()
*/
using Inputs = std::vector<NodeOperationInput *>;
Inputs pending_inputs;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
+ for (NodeOperation *op : m_operations) {
for (int k = 0; k < op->getNumberOfInputSockets(); ++k) {
NodeOperationInput *input = op->getInputSocket(k);
if (!input->isConnected()) {
@@ -408,9 +405,7 @@ void NodeOperationBuilder::resolve_proxies()
void NodeOperationBuilder::determineResolutions()
{
/* determine all resolutions of the operations (Width/Height) */
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
+ for (NodeOperation *op : m_operations) {
if (op->isOutputOperation(m_context->isRendering()) && !op->isPreviewOperation()) {
unsigned int resolution[2] = {0, 0};
unsigned int preferredResolution[2] = {0, 0};
@@ -419,9 +414,7 @@ void NodeOperationBuilder::determineResolutions()
}
}
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
+ for (NodeOperation *op : m_operations) {
if (op->isOutputOperation(m_context->isRendering()) && op->isPreviewOperation()) {
unsigned int resolution[2] = {0, 0};
unsigned int preferredResolution[2] = {0, 0};
@@ -446,7 +439,7 @@ void NodeOperationBuilder::determineResolutions()
}
for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
const Link &link = *it;
- Converter::convertResolution(*this, link.from(), link.to());
+ COM_convert_resolution(*this, link.from(), link.to());
}
}
}
@@ -575,16 +568,14 @@ void NodeOperationBuilder::add_complex_operation_buffers()
/* note: complex ops and get cached here first, since adding operations
* will invalidate iterators over the main m_operations
*/
- Operations complex_ops;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- if ((*it)->isComplex()) {
- complex_ops.push_back(*it);
+ blender::Vector<NodeOperation *> complex_ops;
+ for (NodeOperation *operation : m_operations) {
+ if (operation->isComplex()) {
+ complex_ops.append(operation);
}
}
- for (Operations::const_iterator it = complex_ops.begin(); it != complex_ops.end(); ++it) {
- NodeOperation *op = *it;
-
+ for (NodeOperation *op : complex_ops) {
DebugInfo::operation_read_write_buffer(op);
for (int index = 0; index < op->getNumberOfInputSockets(); index++) {
@@ -624,9 +615,7 @@ static void find_reachable_operations_recursive(Tags &reachable, NodeOperation *
void NodeOperationBuilder::prune_operations()
{
Tags reachable;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
+ for (NodeOperation *op : m_operations) {
/* output operations are primary executed operations */
if (op->isOutputOperation(m_context->isRendering())) {
find_reachable_operations_recursive(reachable, op);
@@ -634,12 +623,10 @@ void NodeOperationBuilder::prune_operations()
}
/* delete unreachable operations */
- Operations reachable_ops;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
+ blender::Vector<NodeOperation *> reachable_ops;
+ for (NodeOperation *op : m_operations) {
if (reachable.find(op) != reachable.end()) {
- reachable_ops.push_back(op);
+ reachable_ops.append(op);
}
else {
delete op;
@@ -650,7 +637,7 @@ void NodeOperationBuilder::prune_operations()
}
/* topological (depth-first) sorting of operations */
-static void sort_operations_recursive(NodeOperationBuilder::Operations &sorted,
+static void sort_operations_recursive(blender::Vector<NodeOperation *> &sorted,
Tags &visited,
NodeOperation *op)
{
@@ -666,17 +653,17 @@ static void sort_operations_recursive(NodeOperationBuilder::Operations &sorted,
}
}
- sorted.push_back(op);
+ sorted.append(op);
}
void NodeOperationBuilder::sort_operations()
{
- Operations sorted;
+ blender::Vector<NodeOperation *> sorted;
sorted.reserve(m_operations.size());
Tags visited;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- sort_operations_recursive(sorted, visited, *it);
+ for (NodeOperation *operation : m_operations) {
+ sort_operations_recursive(sorted, visited, operation);
}
m_operations = sorted;
@@ -705,7 +692,7 @@ static void add_group_operations_recursive(Tags &visited, NodeOperation *op, Exe
ExecutionGroup *NodeOperationBuilder::make_group(NodeOperation *op)
{
ExecutionGroup *group = new ExecutionGroup();
- m_groups.push_back(group);
+ m_groups.append(group);
Tags visited;
add_group_operations_recursive(visited, op, group);
@@ -715,9 +702,7 @@ ExecutionGroup *NodeOperationBuilder::make_group(NodeOperation *op)
void NodeOperationBuilder::group_operations()
{
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
+ for (NodeOperation *op : m_operations) {
if (op->isOutputOperation(m_context->isRendering())) {
ExecutionGroup *group = make_group(op);
group->setOutputExecutionGroup(true);
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.h b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
index 5dd4022b127..b502a12d9b1 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.h
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
@@ -24,8 +24,6 @@
#include "COM_NodeGraph.h"
-using std::vector;
-
class CompositorContext;
class Node;
@@ -64,9 +62,7 @@ class NodeOperationBuilder {
}
};
- typedef std::vector<NodeOperation *> Operations;
typedef std::vector<Link> Links;
- typedef std::vector<ExecutionGroup *> Groups;
typedef std::map<NodeOperationInput *, NodeInput *> InputSocketMap;
typedef std::map<NodeOutput *, NodeOperationOutput *> OutputSocketMap;
@@ -78,9 +74,9 @@ class NodeOperationBuilder {
const CompositorContext *m_context;
NodeGraph m_graph;
- Operations m_operations;
+ blender::Vector<NodeOperation *> m_operations;
Links m_links;
- Groups m_groups;
+ blender::Vector<ExecutionGroup *> m_groups;
/** Maps operation inputs to node inputs */
InputSocketMap m_input_map;
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
index acfe800e433..34450366aec 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
@@ -61,8 +61,8 @@ void OpenCLDevice::deinitialize()
void OpenCLDevice::execute(WorkPackage *work)
{
- const unsigned int chunkNumber = work->getChunkNumber();
- ExecutionGroup *executionGroup = work->getExecutionGroup();
+ const unsigned int chunkNumber = work->chunk_number;
+ ExecutionGroup *executionGroup = work->execution_group;
rcti rect;
executionGroup->determineChunkRect(&rect, chunkNumber);
@@ -79,7 +79,7 @@ void OpenCLDevice::execute(WorkPackage *work)
cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
int parameterIndex,
int offsetIndex,
- list<cl_mem> *cleanup,
+ std::list<cl_mem> *cleanup,
MemoryBuffer **inputMemoryBuffers,
SocketReader *reader)
{
@@ -111,7 +111,7 @@ const cl_image_format *OpenCLDevice::determineImageFormat(MemoryBuffer *memoryBu
cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
int parameterIndex,
int offsetIndex,
- list<cl_mem> *cleanup,
+ std::list<cl_mem> *cleanup,
MemoryBuffer **inputMemoryBuffers,
ReadBufferOperation *reader)
{
@@ -258,7 +258,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel,
}
cl_kernel OpenCLDevice::COM_clCreateKernel(const char *kernelname,
- list<cl_kernel> *clKernelsToCleanUp)
+ std::list<cl_kernel> *clKernelsToCleanUp)
{
cl_int error;
cl_kernel kernel = clCreateKernel(this->m_program, kernelname, &error);
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h
index d502f5aa34b..e4fd397b4e8 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.h
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.h
@@ -25,8 +25,6 @@ class OpenCLDevice;
#include "COM_WorkScheduler.h"
#include "clew.h"
-using std::list;
-
/**
* \brief device representing an GPU OpenCL device.
* an instance of this class represents a single cl_device
@@ -107,13 +105,13 @@ class OpenCLDevice : public Device {
cl_mem COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
int parameterIndex,
int offsetIndex,
- list<cl_mem> *cleanup,
+ std::list<cl_mem> *cleanup,
MemoryBuffer **inputMemoryBuffers,
SocketReader *reader);
cl_mem COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel,
int parameterIndex,
int offsetIndex,
- list<cl_mem> *cleanup,
+ std::list<cl_mem> *cleanup,
MemoryBuffer **inputMemoryBuffers,
ReadBufferOperation *reader);
void COM_clAttachMemoryBufferOffsetToKernelParameter(cl_kernel kernel,
@@ -130,5 +128,5 @@ class OpenCLDevice : public Device {
MemoryBuffer *outputMemoryBuffer,
int offsetIndex,
NodeOperation *operation);
- cl_kernel COM_clCreateKernel(const char *kernelname, list<cl_kernel> *clKernelsToCleanUp);
+ cl_kernel COM_clCreateKernel(const char *kernelname, std::list<cl_kernel> *clKernelsToCleanUp);
};
diff --git a/source/blender/compositor/intern/COM_WorkPackage.cpp b/source/blender/compositor/intern/COM_WorkPackage.cpp
index 795f8d88d50..60684f2c45c 100644
--- a/source/blender/compositor/intern/COM_WorkPackage.cpp
+++ b/source/blender/compositor/intern/COM_WorkPackage.cpp
@@ -18,8 +18,8 @@
#include "COM_WorkPackage.h"
-WorkPackage::WorkPackage(ExecutionGroup *group, unsigned int chunkNumber)
+WorkPackage::WorkPackage(ExecutionGroup *execution_group, unsigned int chunk_number)
{
- this->m_executionGroup = group;
- this->m_chunkNumber = chunkNumber;
+ this->execution_group = execution_group;
+ this->chunk_number = chunk_number;
}
diff --git a/source/blender/compositor/intern/COM_WorkPackage.h b/source/blender/compositor/intern/COM_WorkPackage.h
index f4370aa41be..db5eb3d3072 100644
--- a/source/blender/compositor/intern/COM_WorkPackage.h
+++ b/source/blender/compositor/intern/COM_WorkPackage.h
@@ -16,8 +16,6 @@
* Copyright 2011, Blender Foundation.
*/
-class WorkPackage;
-
#pragma once
class ExecutionGroup;
@@ -27,41 +25,23 @@ class ExecutionGroup;
* \brief contains data about work that can be scheduled
* \see WorkScheduler
*/
-class WorkPackage {
- private:
+struct WorkPackage {
/**
* \brief executionGroup with the operations-setup to be evaluated
*/
- ExecutionGroup *m_executionGroup;
+ ExecutionGroup *execution_group;
/**
* \brief number of the chunk to be executed
*/
- unsigned int m_chunkNumber;
+ unsigned int chunk_number;
- public:
/**
* constructor
* \param group: the ExecutionGroup
- * \param chunkNumber: the number of the chunk
- */
- WorkPackage(ExecutionGroup *group, unsigned int chunkNumber);
-
- /**
- * \brief get the ExecutionGroup
- */
- ExecutionGroup *getExecutionGroup() const
- {
- return this->m_executionGroup;
- }
-
- /**
- * \brief get the number of the chunk
+ * \param chunk_number: the number of the chunk
*/
- unsigned int getChunkNumber() const
- {
- return this->m_chunkNumber;
- }
+ WorkPackage(ExecutionGroup *group, unsigned int chunk_number);
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:WorkPackage")
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index 9ca704afdea..a70b6ba4abe 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -48,7 +48,7 @@ static ThreadLocal(CPUDevice *) g_thread_device;
static struct {
/** \brief list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
*/
- vector<CPUDevice *> cpu_devices;
+ std::vector<CPUDevice *> cpu_devices;
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
/** \brief list of all thread for every CPUDevice in cpudevices a thread exists. */
@@ -62,7 +62,7 @@ static struct {
cl_program opencl_program;
/** \brief list of all OpenCLDevices. for every OpenCL GPU device an instance of OpenCLDevice is
* created. */
- vector<OpenCLDevice *> gpu_devices;
+ std::vector<OpenCLDevice *> gpu_devices;
/** \brief list of all thread for every GPUDevice in cpudevices a thread exists. */
ListBase gpu_threads;
/** \brief all scheduled work for the GPU. */
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index 596a448e6a0..69729e018d7 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -34,12 +34,12 @@ ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter,
- RenderLayer *rl,
+ RenderLayer *render_layer,
+ RenderPass *render_pass,
Image *image,
ImageUser *user,
int framenumber,
int outputsocketIndex,
- int passindex,
int view,
DataType datatype) const
{
@@ -47,19 +47,18 @@ NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter,
MultilayerBaseOperation *operation = nullptr;
switch (datatype) {
case COM_DT_VALUE:
- operation = new MultilayerValueOperation(passindex, view);
+ operation = new MultilayerValueOperation(render_layer, render_pass, view);
break;
case COM_DT_VECTOR:
- operation = new MultilayerVectorOperation(passindex, view);
+ operation = new MultilayerVectorOperation(render_layer, render_pass, view);
break;
case COM_DT_COLOR:
- operation = new MultilayerColorOperation(passindex, view);
+ operation = new MultilayerColorOperation(render_layer, render_pass, view);
break;
default:
break;
}
operation->setImage(image);
- operation->setRenderLayer(rl);
operation->setImageUser(user);
operation->setFramenumber(framenumber);
@@ -128,16 +127,15 @@ void ImageNode::convertToOperations(NodeConverter &converter,
}
if (rpass) {
- int passindex = BLI_findindex(&rl->passes, rpass);
switch (rpass->channels) {
case 1:
operation = doMultilayerCheck(converter,
rl,
+ rpass,
image,
imageuser,
framenumber,
index,
- passindex,
view,
COM_DT_VALUE);
break;
@@ -146,22 +144,22 @@ void ImageNode::convertToOperations(NodeConverter &converter,
case 3:
operation = doMultilayerCheck(converter,
rl,
+ rpass,
image,
imageuser,
framenumber,
index,
- passindex,
view,
COM_DT_VECTOR);
break;
case 4:
operation = doMultilayerCheck(converter,
rl,
+ rpass,
image,
imageuser,
framenumber,
index,
- passindex,
view,
COM_DT_COLOR);
break;
diff --git a/source/blender/compositor/nodes/COM_ImageNode.h b/source/blender/compositor/nodes/COM_ImageNode.h
index 1a811fe855d..b99fc07f105 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.h
+++ b/source/blender/compositor/nodes/COM_ImageNode.h
@@ -24,6 +24,7 @@
#include "DNA_node_types.h"
#include "RE_engine.h"
+#include "RE_pipeline.h"
/**
* \brief ImageNode
@@ -32,12 +33,12 @@
class ImageNode : public Node {
private:
NodeOperation *doMultilayerCheck(NodeConverter &converter,
- RenderLayer *rl,
+ RenderLayer *render_layer,
+ RenderPass *render_pass,
Image *image,
ImageUser *user,
int framenumber,
int outputsocketIndex,
- int passindex,
int view,
DataType datatype) const;
diff --git a/source/blender/compositor/nodes/COM_SwitchViewNode.cpp b/source/blender/compositor/nodes/COM_SwitchViewNode.cpp
index e4a946e2e9d..e534ebfac9a 100644
--- a/source/blender/compositor/nodes/COM_SwitchViewNode.cpp
+++ b/source/blender/compositor/nodes/COM_SwitchViewNode.cpp
@@ -33,7 +33,7 @@ void SwitchViewNode::convertToOperations(NodeConverter &converter,
/* get the internal index of the socket with a matching name */
int nr = BLI_findstringindex(&bnode->inputs, viewName, offsetof(bNodeSocket, name));
- nr = max(nr, 0);
+ nr = MAX2(nr, 0);
result = converter.addInputProxy(getInputSocket(nr), false);
converter.mapOutputSocket(getOutputSocket(0), result);
diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp
index f7b7816e1a1..a8ad2a11790 100644
--- a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp
@@ -62,7 +62,7 @@ void BokehBlurOperation::initExecution()
int width = this->m_inputBokehProgram->getWidth();
int height = this->m_inputBokehProgram->getHeight();
- float dimension = min(width, height);
+ float dimension = MIN2(width, height);
this->m_bokehMidX = width / 2.0f;
this->m_bokehMidY = height / 2.0f;
@@ -84,7 +84,7 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
int bufferwidth = inputBuffer->getWidth();
int bufferstartx = inputBuffer->getRect()->xmin;
int bufferstarty = inputBuffer->getRect()->ymin;
- const float max_dim = max(this->getWidth(), this->getHeight());
+ const float max_dim = MAX2(this->getWidth(), this->getHeight());
int pixelSize = this->m_size * max_dim / 100.0f;
zero_v4(color_accum);
@@ -99,10 +99,10 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
int maxy = y + pixelSize;
int minx = x - pixelSize;
int maxx = x + pixelSize;
- miny = max(miny, inputBuffer->getRect()->ymin);
- minx = max(minx, inputBuffer->getRect()->xmin);
- maxy = min(maxy, inputBuffer->getRect()->ymax);
- maxx = min(maxx, inputBuffer->getRect()->xmax);
+ miny = MAX2(miny, inputBuffer->getRect()->ymin);
+ minx = MAX2(minx, inputBuffer->getRect()->xmin);
+ maxy = MIN2(maxy, inputBuffer->getRect()->ymax);
+ maxx = MIN2(maxx, inputBuffer->getRect()->xmax);
int step = getStep();
int offsetadd = getOffsetAdd() * COM_NUM_CHANNELS_COLOR;
@@ -144,7 +144,7 @@ bool BokehBlurOperation::determineDependingAreaOfInterest(rcti *input,
{
rcti newInput;
rcti bokehInput;
- const float max_dim = max(this->getWidth(), this->getHeight());
+ const float max_dim = MAX2(this->getWidth(), this->getHeight());
if (this->m_sizeavailable) {
newInput.xmax = input->xmax + (this->m_size * max_dim / 100.0f);
@@ -193,14 +193,14 @@ void BokehBlurOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> * /*clKernelsToCleanUp*/)
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel kernel = device->COM_clCreateKernel("bokehBlurKernel", nullptr);
if (!this->m_sizeavailable) {
updateSize();
}
- const float max_dim = max(this->getWidth(), this->getHeight());
+ const float max_dim = MAX2(this->getWidth(), this->getHeight());
cl_int radius = this->m_size * max_dim / 100.0f;
cl_int step = this->getStep();
@@ -235,7 +235,7 @@ void BokehBlurOperation::determineResolution(unsigned int resolution[2],
{
NodeOperation::determineResolution(resolution, preferredResolution);
if (this->m_extend_bounds) {
- const float max_dim = max(resolution[0], resolution[1]);
+ const float max_dim = MAX2(resolution[0], resolution[1]);
resolution[0] += 2 * this->m_size * max_dim / 100.0f;
resolution[1] += 2 * this->m_size * max_dim / 100.0f;
}
diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.h b/source/blender/compositor/operations/COM_BokehBlurOperation.h
index 335574a381d..a2e320dfdad 100644
--- a/source/blender/compositor/operations/COM_BokehBlurOperation.h
+++ b/source/blender/compositor/operations/COM_BokehBlurOperation.h
@@ -67,8 +67,8 @@ class BokehBlurOperation : public NodeOperation, public QualityStepHelper {
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> *clKernelsToCleanUp);
void setExtendBounds(bool extend_bounds)
{
diff --git a/source/blender/compositor/operations/COM_BoxMaskOperation.cpp b/source/blender/compositor/operations/COM_BoxMaskOperation.cpp
index 662b08bdee9..bb10f3425e2 100644
--- a/source/blender/compositor/operations/COM_BoxMaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_BoxMaskOperation.cpp
@@ -64,7 +64,7 @@ void BoxMaskOperation::executePixelSampled(float output[4], float x, float y, Pi
switch (this->m_maskType) {
case CMP_NODE_MASKTYPE_ADD:
if (inside) {
- output[0] = max(inputMask[0], inputValue[0]);
+ output[0] = MAX2(inputMask[0], inputValue[0]);
}
else {
output[0] = inputMask[0];
diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp b/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp
index a2c6fd47771..15375589888 100644
--- a/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp
+++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp
@@ -95,7 +95,7 @@ void ChannelMatteOperation::executePixelSampled(float output[4],
this->m_inputImageProgram->readSampled(inColor, x, y, sampler);
/* matte operation */
- alpha = inColor[this->m_ids[0]] - max(inColor[this->m_ids[1]], inColor[this->m_ids[2]]);
+ alpha = inColor[this->m_ids[0]] - MAX2(inColor[this->m_ids[1]], inColor[this->m_ids[2]]);
/* flip because 0.0 is transparent, not 1.0 */
alpha = 1.0f - alpha;
@@ -116,5 +116,5 @@ void ChannelMatteOperation::executePixelSampled(float output[4],
*/
/* Don't make something that was more transparent less transparent. */
- output[0] = min(alpha, inColor[3]);
+ output[0] = MIN2(alpha, inColor[3]);
}
diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.h b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
index 24a5e03a1bf..9a0b888b5a2 100644
--- a/source/blender/compositor/operations/COM_ChannelMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
@@ -38,12 +38,12 @@ class ChannelMatteOperation : public NodeOperation {
float m_limit_range;
/** ids to use for the operations (max and simple)
- * alpha = in[ids[0]] - max(in[ids[1]], in[ids[2]])
+ * alpha = in[ids[0]] - MAX2(in[ids[1]], in[ids[2]])
* the simple operation is using:
* alpha = in[ids[0]] - in[ids[1]]
* but to use the same formula and operation for both we do:
* ids[2] = ids[1]
- * alpha = in[ids[0]] - max(in[ids[1]], in[ids[2]])
+ * alpha = in[ids[0]] - MAX2(in[ids[1]], in[ids[2]])
*/
int m_ids[3];
diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp
index f9eaaf6f7a0..44eef1e19cd 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp
+++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp
@@ -59,7 +59,7 @@ void ColorBalanceASCCDLOperation::executePixelSampled(float output[4],
this->m_inputColorOperation->readSampled(inputColor, x, y, sampler);
float fac = value[0];
- fac = min(1.0f, fac);
+ fac = MIN2(1.0f, fac);
const float mfac = 1.0f - fac;
output[0] = mfac * inputColor[0] +
diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp
index df44e87a86a..934b7e51aee 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp
+++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp
@@ -64,7 +64,7 @@ void ColorBalanceLGGOperation::executePixelSampled(float output[4],
this->m_inputColorOperation->readSampled(inputColor, x, y, sampler);
float fac = value[0];
- fac = min(1.0f, fac);
+ fac = MIN2(1.0f, fac);
const float mfac = 1.0f - fac;
output[0] = mfac * inputColor[0] +
diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp
index 60343c28662..02c109e8acd 100644
--- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp
+++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp
@@ -66,7 +66,7 @@ void ColorCorrectionOperation::executePixelSampled(float output[4],
float r, g, b;
float value = inputMask[0];
- value = min(1.0f, value);
+ value = MIN2(1.0f, value);
const float mvalue = 1.0f - value;
float levelShadows = 0.0;
diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.cpp b/source/blender/compositor/operations/COM_ColorSpillOperation.cpp
index 050792d8dab..8139d71c637 100644
--- a/source/blender/compositor/operations/COM_ColorSpillOperation.cpp
+++ b/source/blender/compositor/operations/COM_ColorSpillOperation.cpp
@@ -90,7 +90,7 @@ void ColorSpillOperation::executePixelSampled(float output[4],
float input[4];
this->m_inputFacReader->readSampled(fac, x, y, sampler);
this->m_inputImageReader->readSampled(input, x, y, sampler);
- float rfac = min(1.0f, fac[0]);
+ float rfac = MIN2(1.0f, fac[0]);
float map;
switch (this->m_spillMethod) {
diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp
index fe395ecae9e..abf423cc48a 100644
--- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp
@@ -63,13 +63,13 @@ void ConvertDepthToRadiusOperation::initExecution()
(this->getHeight() / (float)this->getWidth()) :
(this->getWidth() / (float)this->getHeight());
this->m_aperture = 0.5f * (this->m_cam_lens / (this->m_aspect * cam_sensor)) / this->m_fStop;
- const float minsz = min(getWidth(), getHeight());
+ const float minsz = MIN2(getWidth(), getHeight());
this->m_dof_sp = minsz /
((cam_sensor / 2.0f) /
- this->m_cam_lens); // <- == aspect * min(img->x, img->y) / tan(0.5f * fov);
+ this->m_cam_lens); // <- == aspect * MIN2(img->x, img->y) / tan(0.5f * fov);
if (this->m_blurPostOperation) {
- m_blurPostOperation->setSigma(min(m_aperture * 128.0f, this->m_maxRadius));
+ m_blurPostOperation->setSigma(MIN2(m_aperture * 128.0f, this->m_maxRadius));
}
}
diff --git a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp
index 1c2570cd251..a5f2ae404e3 100644
--- a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp
@@ -92,8 +92,8 @@ void ConvolutionEdgeFilterOperation::executePixel(float output[4], int x, int y,
output[3] = in2[3];
/* Make sure we don't return negative color. */
- output[0] = max(output[0], 0.0f);
- output[1] = max(output[1], 0.0f);
- output[2] = max(output[2], 0.0f);
- output[3] = max(output[3], 0.0f);
+ output[0] = MAX2(output[0], 0.0f);
+ output[1] = MAX2(output[1], 0.0f);
+ output[2] = MAX2(output[2], 0.0f);
+ output[3] = MAX2(output[3], 0.0f);
}
diff --git a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp
index 7e35f6fb4f6..425e87ffa7e 100644
--- a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp
@@ -105,10 +105,10 @@ void ConvolutionFilterOperation::executePixel(float output[4], int x, int y, voi
output[3] = output[3] * value[0] + in2[3] * mval;
/* Make sure we don't return negative color. */
- output[0] = max(output[0], 0.0f);
- output[1] = max(output[1], 0.0f);
- output[2] = max(output[2], 0.0f);
- output[3] = max(output[3], 0.0f);
+ output[0] = MAX2(output[0], 0.0f);
+ output[1] = MAX2(output[1], 0.0f);
+ output[2] = MAX2(output[2], 0.0f);
+ output[3] = MAX2(output[3], 0.0f);
}
bool ConvolutionFilterOperation::determineDependingAreaOfInterest(
diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp
index 408f588871e..9364557169c 100644
--- a/source/blender/compositor/operations/COM_CropOperation.cpp
+++ b/source/blender/compositor/operations/COM_CropOperation.cpp
@@ -54,10 +54,10 @@ void CropBaseOperation::updateArea()
local_settings.y2 = height - 1;
}
- this->m_xmax = max(local_settings.x1, local_settings.x2) + 1;
- this->m_xmin = min(local_settings.x1, local_settings.x2);
- this->m_ymax = max(local_settings.y1, local_settings.y2) + 1;
- this->m_ymin = min(local_settings.y1, local_settings.y2);
+ this->m_xmax = MAX2(local_settings.x1, local_settings.x2) + 1;
+ this->m_xmin = MIN2(local_settings.x1, local_settings.x2);
+ this->m_ymax = MAX2(local_settings.y1, local_settings.y2) + 1;
+ this->m_ymin = MIN2(local_settings.y1, local_settings.y2);
}
else {
this->m_xmax = 0;
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
index b2dfb558028..fbe9fe8ea27 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
@@ -41,7 +41,7 @@ void DilateErodeThresholdOperation::initExecution()
}
else {
if (this->m_inset * 2 > this->m_distance) {
- this->m_scope = max(this->m_inset * 2 - this->m_distance, this->m_distance);
+ this->m_scope = MAX2(this->m_inset * 2 - this->m_distance, this->m_distance);
}
else {
this->m_scope = this->m_distance;
@@ -71,10 +71,10 @@ void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y,
MemoryBuffer *inputBuffer = (MemoryBuffer *)data;
float *buffer = inputBuffer->getBuffer();
rcti *rect = inputBuffer->getRect();
- const int minx = max(x - this->m_scope, rect->xmin);
- const int miny = max(y - this->m_scope, rect->ymin);
- const int maxx = min(x + this->m_scope, rect->xmax);
- const int maxy = min(y + this->m_scope, rect->ymax);
+ const int minx = MAX2(x - this->m_scope, rect->xmin);
+ const int miny = MAX2(y - this->m_scope, rect->ymin);
+ const int maxx = MIN2(x + this->m_scope, rect->xmax);
+ const int maxy = MIN2(y + this->m_scope, rect->ymax);
const int bufferWidth = BLI_rcti_size_x(rect);
int offset;
@@ -87,7 +87,7 @@ void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y,
if (buffer[offset] < sw) {
const float dx = xi - x;
const float dis = dx * dx + dy * dy;
- mindist = min(mindist, dis);
+ mindist = MIN2(mindist, dis);
}
offset++;
}
@@ -102,7 +102,7 @@ void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y,
if (buffer[offset] > sw) {
const float dx = xi - x;
const float dis = dx * dx + dy * dy;
- mindist = min(mindist, dis);
+ mindist = MIN2(mindist, dis);
}
offset++;
}
@@ -191,10 +191,10 @@ void DilateDistanceOperation::executePixel(float output[4], int x, int y, void *
MemoryBuffer *inputBuffer = (MemoryBuffer *)data;
float *buffer = inputBuffer->getBuffer();
rcti *rect = inputBuffer->getRect();
- const int minx = max(x - this->m_scope, rect->xmin);
- const int miny = max(y - this->m_scope, rect->ymin);
- const int maxx = min(x + this->m_scope, rect->xmax);
- const int maxy = min(y + this->m_scope, rect->ymax);
+ const int minx = MAX2(x - this->m_scope, rect->xmin);
+ const int miny = MAX2(y - this->m_scope, rect->ymin);
+ const int maxx = MIN2(x + this->m_scope, rect->xmax);
+ const int maxy = MIN2(y + this->m_scope, rect->ymax);
const int bufferWidth = BLI_rcti_size_x(rect);
int offset;
@@ -207,7 +207,7 @@ void DilateDistanceOperation::executePixel(float output[4], int x, int y, void *
const float dx = xi - x;
const float dis = dx * dx + dy * dy;
if (dis <= mindist) {
- value = max(buffer[offset], value);
+ value = MAX2(buffer[offset], value);
}
offset++;
}
@@ -238,8 +238,8 @@ void DilateDistanceOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> * /*clKernelsToCleanUp*/)
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel dilateKernel = device->COM_clCreateKernel("dilateKernel", nullptr);
@@ -270,10 +270,10 @@ void ErodeDistanceOperation::executePixel(float output[4], int x, int y, void *d
MemoryBuffer *inputBuffer = (MemoryBuffer *)data;
float *buffer = inputBuffer->getBuffer();
rcti *rect = inputBuffer->getRect();
- const int minx = max(x - this->m_scope, rect->xmin);
- const int miny = max(y - this->m_scope, rect->ymin);
- const int maxx = min(x + this->m_scope, rect->xmax);
- const int maxy = min(y + this->m_scope, rect->ymax);
+ const int minx = MAX2(x - this->m_scope, rect->xmin);
+ const int miny = MAX2(y - this->m_scope, rect->ymin);
+ const int maxx = MIN2(x + this->m_scope, rect->xmax);
+ const int maxy = MIN2(y + this->m_scope, rect->ymax);
const int bufferWidth = BLI_rcti_size_x(rect);
int offset;
@@ -286,7 +286,7 @@ void ErodeDistanceOperation::executePixel(float output[4], int x, int y, void *d
const float dx = xi - x;
const float dis = dx * dx + dy * dy;
if (dis <= mindist) {
- value = min(buffer[offset], value);
+ value = MIN2(buffer[offset], value);
}
offset++;
}
@@ -298,8 +298,8 @@ void ErodeDistanceOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> * /*clKernelsToCleanUp*/)
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel erodeKernel = device->COM_clCreateKernel("erodeKernel", nullptr);
@@ -360,10 +360,10 @@ void *DilateStepOperation::initializeTileData(rcti *rect)
int half_window = this->m_iterations;
int window = half_window * 2 + 1;
- int xmin = max(0, rect->xmin - half_window);
- int ymin = max(0, rect->ymin - half_window);
- int xmax = min(width, rect->xmax + half_window);
- int ymax = min(height, rect->ymax + half_window);
+ int xmin = MAX2(0, rect->xmin - half_window);
+ int ymin = MAX2(0, rect->ymin - half_window);
+ int xmax = MIN2(width, rect->xmax + half_window);
+ int ymax = MIN2(height, rect->ymax + half_window);
int bwidth = rect->xmax - rect->xmin;
int bheight = rect->ymax - rect->ymin;
@@ -378,7 +378,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect)
// single row or column of input values, padded with FLT_MAX's to
// simplify the logic.
float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp");
- float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window),
+ float *buf = (float *)MEM_mallocN(sizeof(float) * (MAX2(bwidth, bheight) + 5 * half_window),
"dilate erode buf");
// The following is based on the van Herk/Gil-Werman algorithm for morphology operations.
@@ -396,13 +396,13 @@ void *DilateStepOperation::initializeTileData(rcti *rect)
temp[window - 1] = buf[start];
for (x = 1; x < window; x++) {
- temp[window - 1 - x] = max(temp[window - x], buf[start - x]);
- temp[window - 1 + x] = max(temp[window + x - 2], buf[start + x]);
+ temp[window - 1 - x] = MAX2(temp[window - x], buf[start - x]);
+ temp[window - 1 + x] = MAX2(temp[window + x - 2], buf[start + x]);
}
start = half_window + (i - 1) * window + 1;
- for (x = -min(0, start); x < window - max(0, start + window - bwidth); x++) {
- rectf[bwidth * (y - ymin) + (start + x)] = max(temp[x], temp[x + window - 1]);
+ for (x = -MIN2(0, start); x < window - MAX2(0, start + window - bwidth); x++) {
+ rectf[bwidth * (y - ymin) + (start + x)] = MAX2(temp[x], temp[x + window - 1]);
}
}
}
@@ -421,13 +421,14 @@ void *DilateStepOperation::initializeTileData(rcti *rect)
temp[window - 1] = buf[start];
for (y = 1; y < window; y++) {
- temp[window - 1 - y] = max(temp[window - y], buf[start - y]);
- temp[window - 1 + y] = max(temp[window + y - 2], buf[start + y]);
+ temp[window - 1 - y] = MAX2(temp[window - y], buf[start - y]);
+ temp[window - 1 + y] = MAX2(temp[window + y - 2], buf[start + y]);
}
start = half_window + (i - 1) * window + 1;
- for (y = -min(0, start); y < window - max(0, start + window - bheight); y++) {
- rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = max(temp[y], temp[y + window - 1]);
+ for (y = -MIN2(0, start); y < window - MAX2(0, start + window - bheight); y++) {
+ rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = MAX2(temp[y],
+ temp[y + window - 1]);
}
}
}
@@ -489,10 +490,10 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
int half_window = this->m_iterations;
int window = half_window * 2 + 1;
- int xmin = max(0, rect->xmin - half_window);
- int ymin = max(0, rect->ymin - half_window);
- int xmax = min(width, rect->xmax + half_window);
- int ymax = min(height, rect->ymax + half_window);
+ int xmin = MAX2(0, rect->xmin - half_window);
+ int ymin = MAX2(0, rect->ymin - half_window);
+ int xmax = MIN2(width, rect->xmax + half_window);
+ int ymax = MIN2(height, rect->ymax + half_window);
int bwidth = rect->xmax - rect->xmin;
int bheight = rect->ymax - rect->ymin;
@@ -507,7 +508,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
// single row or column of input values, padded with FLT_MAX's to
// simplify the logic.
float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp");
- float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window),
+ float *buf = (float *)MEM_mallocN(sizeof(float) * (MAX2(bwidth, bheight) + 5 * half_window),
"dilate erode buf");
// The following is based on the van Herk/Gil-Werman algorithm for morphology operations.
@@ -525,13 +526,13 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
temp[window - 1] = buf[start];
for (x = 1; x < window; x++) {
- temp[window - 1 - x] = min(temp[window - x], buf[start - x]);
- temp[window - 1 + x] = min(temp[window + x - 2], buf[start + x]);
+ temp[window - 1 - x] = MIN2(temp[window - x], buf[start - x]);
+ temp[window - 1 + x] = MIN2(temp[window + x - 2], buf[start + x]);
}
start = half_window + (i - 1) * window + 1;
- for (x = -min(0, start); x < window - max(0, start + window - bwidth); x++) {
- rectf[bwidth * (y - ymin) + (start + x)] = min(temp[x], temp[x + window - 1]);
+ for (x = -MIN2(0, start); x < window - MAX2(0, start + window - bwidth); x++) {
+ rectf[bwidth * (y - ymin) + (start + x)] = MIN2(temp[x], temp[x + window - 1]);
}
}
}
@@ -550,13 +551,14 @@ void *ErodeStepOperation::initializeTileData(rcti *rect)
temp[window - 1] = buf[start];
for (y = 1; y < window; y++) {
- temp[window - 1 - y] = min(temp[window - y], buf[start - y]);
- temp[window - 1 + y] = min(temp[window + y - 2], buf[start + y]);
+ temp[window - 1 - y] = MIN2(temp[window - y], buf[start - y]);
+ temp[window - 1 + y] = MIN2(temp[window + y - 2], buf[start + y]);
}
start = half_window + (i - 1) * window + 1;
- for (y = -min(0, start); y < window - max(0, start + window - bheight); y++) {
- rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = min(temp[y], temp[y + window - 1]);
+ for (y = -MIN2(0, start); y < window - MAX2(0, start + window - bheight); y++) {
+ rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = MIN2(temp[y],
+ temp[y + window - 1]);
}
}
}
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.h b/source/blender/compositor/operations/COM_DilateErodeOperation.h
index 2af5c8990ee..35f9be89220 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.h
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.h
@@ -115,8 +115,8 @@ class DilateDistanceOperation : public NodeOperation {
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> *clKernelsToCleanUp);
};
class ErodeDistanceOperation : public DilateDistanceOperation {
public:
@@ -131,8 +131,8 @@ class ErodeDistanceOperation : public DilateDistanceOperation {
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> *clKernelsToCleanUp);
};
class DilateStepOperation : public NodeOperation {
diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
index c0b9c9b6f1d..3f0cd4ef255 100644
--- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
@@ -100,8 +100,8 @@ void DirectionalBlurOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> * /*clKernelsToCleanUp*/)
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel directionalBlurKernel = device->COM_clCreateKernel("directionalBlurKernel", nullptr);
diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.h b/source/blender/compositor/operations/COM_DirectionalBlurOperation.h
index fdb7b82779e..0c220f0e239 100644
--- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.h
+++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.h
@@ -61,6 +61,6 @@ class DirectionalBlurOperation : public NodeOperation, public QualityStepHelper
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> *clKernelsToCleanUp);
};
diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp b/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp
index 38541f91fc8..a6985a40625 100644
--- a/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp
@@ -73,7 +73,7 @@ void EllipseMaskOperation::executePixelSampled(float output[4],
switch (this->m_maskType) {
case CMP_NODE_MASKTYPE_ADD:
if (inside) {
- output[0] = max(inputMask[0], inputValue[0]);
+ output[0] = MAX2(inputMask[0], inputValue[0]);
}
else {
output[0] = inputMask[0];
diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp
index 157c595afcb..b3c1b6b4413 100644
--- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp
@@ -209,7 +209,7 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src,
(void)0
// intermediate buffers
- sz = max(src_width, src_height);
+ sz = MAX2(src_width, src_height);
X = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss X buf");
Y = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss Y buf");
W = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss W buf");
diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
index d489c64953e..ca3173001cb 100644
--- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
@@ -256,7 +256,7 @@ void GaussianBlurReferenceOperation::initExecution()
void GaussianBlurReferenceOperation::updateGauss()
{
int i;
- int x = max(m_filtersizex, m_filtersizey);
+ int x = MAX2(m_filtersizex, m_filtersizey);
m_maintabs = (float **)MEM_mallocN(x * sizeof(float *), "gauss array");
for (i = 0; i < x; i++) {
m_maintabs[i] = make_gausstab(i + 1, i + 1);
@@ -333,7 +333,7 @@ void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y,
void GaussianBlurReferenceOperation::deinitExecution()
{
int x, i;
- x = max(this->m_filtersizex, this->m_filtersizey);
+ x = MAX2(this->m_filtersizex, this->m_filtersizey);
for (i = 0; i < x; i++) {
MEM_freeN(this->m_maintabs[i]);
}
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp
index 90333f7dd79..596d439658c 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp
@@ -122,8 +122,8 @@ void GaussianXBlurOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> * /*clKernelsToCleanUp*/)
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel gaussianXBlurOperationKernel = device->COM_clCreateKernel(
"gaussianXBlurOperationKernel", nullptr);
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
index b2bcd79e716..78ea6aa3cc2 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h
@@ -42,8 +42,8 @@ class GaussianXBlurOperation : public BlurBaseOperation {
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> *clKernelsToCleanUp);
/**
* \brief initialize the execution
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp
index c5b3cf24239..55c1551ca42 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp
@@ -122,8 +122,8 @@ void GaussianYBlurOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> * /*clKernelsToCleanUp*/)
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel gaussianYBlurOperationKernel = device->COM_clCreateKernel(
"gaussianYBlurOperationKernel", nullptr);
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
index d921780876a..8e7440b6fe4 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h
@@ -42,8 +42,8 @@ class GaussianYBlurOperation : public BlurBaseOperation {
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> *clKernelsToCleanUp);
/**
* \brief initialize the execution
diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp
index 1a1922f828c..cfa4b99cd70 100644
--- a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp
@@ -54,9 +54,9 @@ void GlareThresholdOperation::executePixelSampled(float output[4],
output[1] -= threshold;
output[2] -= threshold;
- output[0] = max(output[0], 0.0f);
- output[1] = max(output[1], 0.0f);
- output[2] = max(output[2], 0.0f);
+ output[0] = MAX2(output[0], 0.0f);
+ output[1] = MAX2(output[1], 0.0f);
+ output[2] = MAX2(output[2], 0.0f);
}
else {
zero_v3(output);
diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp
index 72bf86facfb..c9cc8ebc045 100644
--- a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp
@@ -50,7 +50,7 @@ void KeyingBlurOperation::executePixel(float output[4], int x, int y, void *data
float average = 0.0f;
if (this->m_axis == 0) {
- const int start = max(0, x - this->m_size + 1), end = min(bufferWidth, x + this->m_size);
+ const int start = MAX2(0, x - this->m_size + 1), end = MIN2(bufferWidth, x + this->m_size);
for (int cx = start; cx < end; cx++) {
int bufferIndex = (y * bufferWidth + cx);
average += buffer[bufferIndex];
@@ -58,8 +58,8 @@ void KeyingBlurOperation::executePixel(float output[4], int x, int y, void *data
}
}
else {
- const int start = max(0, y - this->m_size + 1),
- end = min(inputBuffer->getHeight(), y + this->m_size);
+ const int start = MAX2(0, y - this->m_size + 1),
+ end = MIN2(inputBuffer->getHeight(), y + this->m_size);
for (int cy = start; cy < end; cy++) {
int bufferIndex = (cy * bufferWidth + x);
average += buffer[bufferIndex];
diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp b/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp
index b9bb316462d..f4d0d6c6a00 100644
--- a/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp
+++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp
@@ -63,8 +63,8 @@ void KeyingDespillOperation::executePixelSampled(float output[4],
const int other_1 = (screen_primary_channel + 1) % 3;
const int other_2 = (screen_primary_channel + 2) % 3;
- const int min_channel = min(other_1, other_2);
- const int max_channel = max(other_1, other_2);
+ const int min_channel = MIN2(other_1, other_2);
+ const int max_channel = MAX2(other_1, other_2);
float average_value, amount;
diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp
index 9ef4217d300..94e65181207 100644
--- a/source/blender/compositor/operations/COM_KeyingOperation.cpp
+++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp
@@ -30,8 +30,8 @@ static float get_pixel_saturation(const float pixelColor[4],
const int other_1 = (primary_channel + 1) % 3;
const int other_2 = (primary_channel + 2) % 3;
- const int min_channel = min(other_1, other_2);
- const int max_channel = max(other_1, other_2);
+ const int min_channel = MIN2(other_1, other_2);
+ const int max_channel = MAX2(other_1, other_2);
const float val = screen_balance * pixelColor[min_channel] +
(1.0f - screen_balance) * pixelColor[max_channel];
diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp
index 096930d0a83..2bd7493625e 100644
--- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp
+++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp
@@ -54,7 +54,7 @@ void LuminanceMatteOperation::executePixelSampled(float output[4],
float alpha;
/* one line thread-friend algorithm:
- * output[0] = min(inputValue[3], min(1.0f, max(0.0f, ((luminance - low) / (high - low))));
+ * output[0] = MIN2(inputValue[3], MIN2(1.0f, MAX2(0.0f, ((luminance - low) / (high - low))));
*/
/* test range */
diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h
index eba14d10373..67e6b64315c 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.h
+++ b/source/blender/compositor/operations/COM_MaskOperation.h
@@ -84,7 +84,7 @@ class MaskOperation : public NodeOperation {
void setMotionBlurSamples(int samples)
{
- this->m_rasterMaskHandleTot = min(max(1, samples), CMP_NODE_MASK_MBLUR_SAMPLES_MAX);
+ this->m_rasterMaskHandleTot = MIN2(MAX2(1, samples), CMP_NODE_MASK_MBLUR_SAMPLES_MAX);
}
void setMotionBlurShutter(float shutter)
{
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cpp b/source/blender/compositor/operations/COM_MathBaseOperation.cpp
index dbec6dd1874..692c1e70462 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.cpp
@@ -351,7 +351,7 @@ void MathMinimumOperation::executePixelSampled(float output[4],
this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler);
this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler);
- output[0] = min(inputValue1[0], inputValue2[0]);
+ output[0] = MIN2(inputValue1[0], inputValue2[0]);
clampIfNeeded(output);
}
@@ -367,7 +367,7 @@ void MathMaximumOperation::executePixelSampled(float output[4],
this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler);
this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler);
- output[0] = max(inputValue1[0], inputValue2[0]);
+ output[0] = MAX2(inputValue1[0], inputValue2[0]);
clampIfNeeded(output);
}
diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp
index 76a66727a75..11df0900345 100644
--- a/source/blender/compositor/operations/COM_MixOperation.cpp
+++ b/source/blender/compositor/operations/COM_MixOperation.cpp
@@ -523,9 +523,9 @@ void MixGlareOperation::executePixelSampled(float output[4],
inputColor1[2] = 0.0f;
}
- output[0] = mf * max(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f);
- output[1] = mf * max(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f);
- output[2] = mf * max(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f);
+ output[0] = mf * MAX2(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f);
+ output[1] = mf * MAX2(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f);
+ output[2] = mf * MAX2(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f);
output[3] = inputColor1[3];
clampIfNeeded(output);
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
index 023538ee5b1..60936ee1939 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
@@ -21,10 +21,14 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-MultilayerBaseOperation::MultilayerBaseOperation(int passindex, int view)
+MultilayerBaseOperation::MultilayerBaseOperation(RenderLayer *render_layer,
+ RenderPass *render_pass,
+ int view)
{
- this->m_passId = passindex;
+ this->m_passId = BLI_findindex(&render_layer->passes, render_pass);
this->m_view = view;
+ this->m_renderLayer = render_layer;
+ this->m_renderPass = render_pass;
}
ImBuf *MultilayerBaseOperation::getImBuf()
@@ -45,6 +49,32 @@ ImBuf *MultilayerBaseOperation::getImBuf()
return nullptr;
}
+std::unique_ptr<MetaData> MultilayerColorOperation::getMetaData() const
+{
+ BLI_assert(this->m_buffer);
+ MetaDataExtractCallbackData callback_data = {nullptr};
+ RenderResult *render_result = this->m_image->rr;
+ if (render_result && render_result->stamp_data) {
+ RenderLayer *render_layer = this->m_renderLayer;
+ RenderPass *render_pass = this->m_renderPass;
+ std::string full_layer_name =
+ std::string(render_layer->name,
+ BLI_strnlen(render_layer->name, sizeof(render_layer->name))) +
+ "." +
+ std::string(render_pass->name, BLI_strnlen(render_pass->name, sizeof(render_pass->name)));
+ blender::StringRef cryptomatte_layer_name =
+ blender::bke::cryptomatte::BKE_cryptomatte_extract_layer_name(full_layer_name);
+ callback_data.setCryptomatteKeys(cryptomatte_layer_name);
+
+ BKE_stamp_info_callback(&callback_data,
+ render_result->stamp_data,
+ MetaDataExtractCallbackData::extract_cryptomatte_meta_data,
+ false);
+ }
+
+ return std::move(callback_data.meta_data);
+}
+
void MultilayerColorOperation::executePixelSampled(float output[4],
float x,
float y,
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.h b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
index adfcc975ade..f5176b0a4db 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.h
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
@@ -24,34 +24,34 @@ class MultilayerBaseOperation : public BaseImageOperation {
private:
int m_passId;
int m_view;
- RenderLayer *m_renderlayer;
protected:
+ RenderLayer *m_renderLayer;
+ RenderPass *m_renderPass;
ImBuf *getImBuf();
public:
/**
* Constructor
*/
- MultilayerBaseOperation(int passindex, int view);
- void setRenderLayer(RenderLayer *renderlayer)
- {
- this->m_renderlayer = renderlayer;
- }
+ MultilayerBaseOperation(RenderLayer *render_layer, RenderPass *render_pass, int view);
};
class MultilayerColorOperation : public MultilayerBaseOperation {
public:
- MultilayerColorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view)
+ MultilayerColorOperation(RenderLayer *render_layer, RenderPass *render_pass, int view)
+ : MultilayerBaseOperation(render_layer, render_pass, view)
{
this->addOutputSocket(COM_DT_COLOR);
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ std::unique_ptr<MetaData> getMetaData() const override;
};
class MultilayerValueOperation : public MultilayerBaseOperation {
public:
- MultilayerValueOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view)
+ MultilayerValueOperation(RenderLayer *render_layer, RenderPass *render_pass, int view)
+ : MultilayerBaseOperation(render_layer, render_pass, view)
{
this->addOutputSocket(COM_DT_VALUE);
}
@@ -60,7 +60,8 @@ class MultilayerValueOperation : public MultilayerBaseOperation {
class MultilayerVectorOperation : public MultilayerBaseOperation {
public:
- MultilayerVectorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view)
+ MultilayerVectorOperation(RenderLayer *render_layer, RenderPass *render_pass, int view)
+ : MultilayerBaseOperation(render_layer, render_pass, view)
{
this->addOutputSocket(COM_DT_VECTOR);
}
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
index 19d49bc2ae7..bb1b312ffec 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
@@ -26,7 +26,6 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
-#include "BKE_cryptomatte.hh"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
index 4f4116d6faa..73de60f4c34 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -20,7 +20,6 @@
#include "COM_MetaData.h"
-#include "BKE_cryptomatte.hh"
#include "BKE_image.h"
#include "BKE_scene.h"
@@ -217,74 +216,32 @@ void RenderLayersProg::determineResolution(unsigned int resolution[2],
}
}
-struct CallbackData {
- std::unique_ptr<MetaData> meta_data;
- std::string hash_key;
- std::string conversion_key;
- std::string manifest_key;
-
- void addMetaData(blender::StringRef key, blender::StringRefNull value)
- {
- if (!meta_data) {
- meta_data = std::make_unique<MetaData>();
- }
- meta_data->add(key, value);
- }
-
- void setCryptomatteKeys(blender::StringRef cryptomatte_layer_name)
- {
- manifest_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
- "manifest");
- hash_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name,
- "hash");
- conversion_key = blender::bke::cryptomatte::BKE_cryptomatte_meta_data_key(
- cryptomatte_layer_name, "conversion");
- }
-};
-
-/* C type callback function (StampCallback). */
-static void extract_cryptomatte_meta_data(void *_data,
- const char *propname,
- char *propvalue,
- int UNUSED(len))
-{
- CallbackData *data = static_cast<CallbackData *>(_data);
- blender::StringRefNull key(propname);
- if (key == data->hash_key) {
- data->addMetaData(META_DATA_KEY_CRYPTOMATTE_HASH, propvalue);
- }
- else if (key == data->conversion_key) {
- data->addMetaData(META_DATA_KEY_CRYPTOMATTE_CONVERSION, propvalue);
- }
- else if (key == data->manifest_key) {
- data->addMetaData(META_DATA_KEY_CRYPTOMATTE_MANIFEST, propvalue);
- }
-}
-
std::unique_ptr<MetaData> RenderLayersProg::getMetaData() const
{
Scene *scene = this->getScene();
Render *re = (scene) ? RE_GetSceneRender(scene) : nullptr;
- RenderResult *rr = nullptr;
- CallbackData callback_data = {nullptr};
+ RenderResult *render_result = nullptr;
+ MetaDataExtractCallbackData callback_data = {nullptr};
if (re) {
- rr = RE_AcquireResultRead(re);
+ render_result = RE_AcquireResultRead(re);
}
- if (rr && rr->stamp_data) {
+ if (render_result && render_result->stamp_data) {
ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, getLayerId());
if (view_layer) {
std::string full_layer_name = std::string(
view_layer->name,
BLI_strnlen(view_layer->name, sizeof(view_layer->name))) +
"." + m_passName;
- blender::StringRef cryptomatte_layer_name = blender::bke::cryptomatte::BKE_cryptomatte_extract_layer_name(
- full_layer_name);
+ blender::StringRef cryptomatte_layer_name =
+ blender::bke::cryptomatte::BKE_cryptomatte_extract_layer_name(full_layer_name);
callback_data.setCryptomatteKeys(cryptomatte_layer_name);
- BKE_stamp_info_callback(
- &callback_data, rr->stamp_data, extract_cryptomatte_meta_data, false);
+ BKE_stamp_info_callback(&callback_data,
+ render_result->stamp_data,
+ MetaDataExtractCallbackData::extract_cryptomatte_meta_data,
+ false);
}
}
diff --git a/source/blender/compositor/operations/COM_RotateOperation.cpp b/source/blender/compositor/operations/COM_RotateOperation.cpp
index 7a21e960c13..9a1f54a6e10 100644
--- a/source/blender/compositor/operations/COM_RotateOperation.cpp
+++ b/source/blender/compositor/operations/COM_RotateOperation.cpp
@@ -93,10 +93,10 @@ bool RotateOperation::determineDependingAreaOfInterest(rcti *input,
const float y2 = this->m_centerY + (-this->m_sine * dxmax + this->m_cosine * dymin);
const float y3 = this->m_centerY + (-this->m_sine * dxmin + this->m_cosine * dymax);
const float y4 = this->m_centerY + (-this->m_sine * dxmax + this->m_cosine * dymax);
- const float minx = min(x1, min(x2, min(x3, x4)));
- const float maxx = max(x1, max(x2, max(x3, x4)));
- const float miny = min(y1, min(y2, min(y3, y4)));
- const float maxy = max(y1, max(y2, max(y3, y4)));
+ const float minx = MIN2(x1, MIN2(x2, MIN2(x3, x4)));
+ const float maxx = MAX2(x1, MAX2(x2, MAX2(x3, x4)));
+ const float miny = MIN2(y1, MIN2(y2, MIN2(y3, y4)));
+ const float maxy = MAX2(y1, MAX2(y2, MAX2(y3, y4)));
newInput.xmax = ceil(maxx) + 1;
newInput.xmin = floor(minx) - 1;
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
index 7cfa4de7a61..28811d479a5 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
@@ -33,7 +33,7 @@ void SunBeamsOperation::initExecution()
/* convert to pixels */
this->m_source_px[0] = this->m_data.source[0] * this->getWidth();
this->m_source_px[1] = this->m_data.source[1] * this->getHeight();
- this->m_ray_length_px = this->m_data.ray_length * max(this->getWidth(), this->getHeight());
+ this->m_ray_length_px = this->m_data.ray_length * MAX2(this->getWidth(), this->getHeight());
}
/**
diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cpp b/source/blender/compositor/operations/COM_TonemapOperation.cpp
index cb0fc747dcb..4c1d285a69f 100644
--- a/source/blender/compositor/operations/COM_TonemapOperation.cpp
+++ b/source/blender/compositor/operations/COM_TonemapOperation.cpp
@@ -51,9 +51,9 @@ void TonemapOperation::executePixel(float output[4], int x, int y, void *data)
output[2] /= ((db == 0.0f) ? 1.0f : db);
const float igm = avg->igm;
if (igm != 0.0f) {
- output[0] = powf(max(output[0], 0.0f), igm);
- output[1] = powf(max(output[1], 0.0f), igm);
- output[2] = powf(max(output[2], 0.0f), igm);
+ output[0] = powf(MAX2(output[0], 0.0f), igm);
+ output[1] = powf(MAX2(output[1], 0.0f), igm);
+ output[2] = powf(MAX2(output[2], 0.0f), igm);
}
}
void PhotoreceptorTonemapOperation::executePixel(float output[4], int x, int y, void *data)
diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
index 414b5bd980a..909a2f73d25 100644
--- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
@@ -74,7 +74,7 @@ void *VariableSizeBokehBlurOperation::initializeTileData(rcti *rect)
this->determineDependingAreaOfInterest(
rect, (ReadBufferOperation *)this->m_inputSizeProgram, &rect2);
- const float max_dim = max(m_width, m_height);
+ const float max_dim = MAX2(m_width, m_height);
const float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f;
data->maxBlurScalar = (int)(data->size->getMaximumValue(&rect2) * scalar);
@@ -102,7 +102,7 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y,
float multiplier_accum[4];
float color_accum[4];
- const float max_dim = max(m_width, m_height);
+ const float max_dim = MAX2(m_width, m_height);
const float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f;
int maxBlurScalar = tileData->maxBlurScalar;
@@ -120,10 +120,10 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y,
int maxx = search[2];
int maxy = search[3];
#else
- int minx = max(x - maxBlurScalar, 0);
- int miny = max(y - maxBlurScalar, 0);
- int maxx = min(x + maxBlurScalar, (int)m_width);
- int maxy = min(y + maxBlurScalar, (int)m_height);
+ int minx = MAX2(x - maxBlurScalar, 0);
+ int miny = MAX2(y - maxBlurScalar, 0);
+ int maxx = MIN2(x + maxBlurScalar, (int)m_width);
+ int maxy = MIN2(y + maxBlurScalar, (int)m_height);
#endif
{
inputSizeBuffer->readNoCheck(tempSize, x, y);
@@ -145,7 +145,7 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y,
int offsetColorNxNy = offsetValueNxNy * COM_NUM_CHANNELS_COLOR;
for (int nx = minx; nx < maxx; nx += addXStepValue) {
if (nx != x || ny != y) {
- float size = min(inputSizeFloatBuffer[offsetValueNxNy] * scalar, size_center);
+ float size = MIN2(inputSizeFloatBuffer[offsetValueNxNy] * scalar, size_center);
if (size > this->m_threshold) {
float dx = nx - x;
if (size > fabsf(dx) && size > fabsf(dy)) {
@@ -185,8 +185,8 @@ void VariableSizeBokehBlurOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> * /*clKernelsToCleanUp*/)
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> * /*clKernelsToCleanUp*/)
{
cl_kernel defocusKernel = device->COM_clCreateKernel("defocusKernel", nullptr);
@@ -197,7 +197,7 @@ void VariableSizeBokehBlurOperation::executeOpenCL(OpenCLDevice *device,
MemoryBuffer *sizeMemoryBuffer = this->m_inputSizeProgram->getInputMemoryBuffer(
inputMemoryBuffers);
- const float max_dim = max(m_width, m_height);
+ const float max_dim = MAX2(m_width, m_height);
cl_float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f;
maxBlur = (cl_int)min_ff(sizeMemoryBuffer->getMaximumValue() * scalar, (float)this->m_maxBlur);
@@ -235,7 +235,7 @@ bool VariableSizeBokehBlurOperation::determineDependingAreaOfInterest(
rcti newInput;
rcti bokehInput;
- const float max_dim = max(m_width, m_height);
+ const float max_dim = MAX2(m_width, m_height);
const float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f;
int maxBlurScalar = this->m_maxBlur * scalar;
diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h
index 258b5d385c0..fe927f791fa 100644
--- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h
+++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h
@@ -80,8 +80,8 @@ class VariableSizeBokehBlurOperation : public NodeOperation, public QualityStepH
MemoryBuffer *outputMemoryBuffer,
cl_mem clOutputBuffer,
MemoryBuffer **inputMemoryBuffers,
- list<cl_mem> *clMemToCleanUp,
- list<cl_kernel> *clKernelsToCleanUp);
+ std::list<cl_mem> *clMemToCleanUp,
+ std::list<cl_kernel> *clKernelsToCleanUp);
};
#ifdef COM_DEFOCUS_SEARCH
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
index 9fb995bf463..8d38dbfe180 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
@@ -143,9 +143,9 @@ void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device,
}
// STEP 2
- list<cl_mem> *clMemToCleanUp = new list<cl_mem>();
+ std::list<cl_mem> *clMemToCleanUp = new std::list<cl_mem>();
clMemToCleanUp->push_back(clOutputBuffer);
- list<cl_kernel> *clKernelsToCleanUp = new list<cl_kernel>();
+ std::list<cl_kernel> *clKernelsToCleanUp = new std::list<cl_kernel>();
this->m_input->executeOpenCL(device,
outputBuffer,
diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.cpp b/source/blender/compositor/operations/COM_ZCombineOperation.cpp
index 22a37a4583e..26d3f2c7dc4 100644
--- a/source/blender/compositor/operations/COM_ZCombineOperation.cpp
+++ b/source/blender/compositor/operations/COM_ZCombineOperation.cpp
@@ -83,7 +83,7 @@ void ZCombineAlphaOperation::executePixelSampled(float output[4],
output[0] = fac * color1[0] + ifac * color2[0];
output[1] = fac * color1[1] + ifac * color2[1];
output[2] = fac * color1[2] + ifac * color2[2];
- output[3] = max(color1[3], color2[3]);
+ output[3] = MAX2(color1[3], color2[3]);
}
void ZCombineOperation::deinitExecution()
@@ -149,7 +149,7 @@ void ZCombineMaskAlphaOperation::executePixelSampled(float output[4],
output[0] = color1[0] * mfac + color2[0] * fac;
output[1] = color1[1] * mfac + color2[1] * fac;
output[2] = color1[2] * mfac + color2[2] * fac;
- output[3] = max(color1[3], color2[3]);
+ output[3] = MAX2(color1[3], color2[3]);
}
void ZCombineMaskOperation::deinitExecution()
diff --git a/source/blender/datatoc/datatoc_icon.c b/source/blender/datatoc/datatoc_icon.c
index 4a9c5875c17..f4f510891e0 100644
--- a/source/blender/datatoc/datatoc_icon.c
+++ b/source/blender/datatoc/datatoc_icon.c
@@ -72,6 +72,27 @@ static void endian_switch_uint32(unsigned int *val)
*val = ((tval >> 24)) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | ((tval << 24));
}
+static const char *path_slash_rfind(const char *string)
+{
+ const char *const lfslash = strrchr(string, '/');
+ const char *const lbslash = strrchr(string, '\\');
+
+ if (!lfslash) {
+ return lbslash;
+ }
+ if (!lbslash) {
+ return lfslash;
+ }
+
+ return (lfslash > lbslash) ? lfslash : lbslash;
+}
+
+static const char *path_basename(const char *path)
+{
+ const char *const filename = path_slash_rfind(path);
+ return filename ? filename + 1 : path;
+}
+
/* -------------------------------------------------------------------- */
/* Write a PNG from RGBA pixels */
@@ -183,6 +204,71 @@ struct IconHead {
unsigned int canvas_w, canvas_h;
};
+struct IconInfo {
+ struct IconHead head;
+ char *file_name;
+};
+
+struct IconMergeContext {
+ /* Information about all icons read from disk.
+ * Is used for sanity checks like prevention of two files defining icon for
+ * the same position on canvas. */
+ int num_read_icons;
+ struct IconInfo *read_icons;
+};
+
+static void icon_merge_context_init(struct IconMergeContext *context)
+{
+ context->num_read_icons = 0;
+ context->read_icons = NULL;
+}
+
+/* Get icon information from the context which matches given icon head.
+ * Is used to check whether icon is re-defined, and to provide useful information about which
+ * files are conflicting. */
+static struct IconInfo *icon_merge_context_info_for_icon_head(struct IconMergeContext *context,
+ struct IconHead *icon_head)
+{
+ if (context->read_icons == NULL) {
+ return NULL;
+ }
+
+ for (int i = 0; i < context->num_read_icons; i++) {
+ struct IconInfo *read_icon_info = &context->read_icons[i];
+ const struct IconHead *read_icon_head = &read_icon_info->head;
+ if (read_icon_head->orig_x == icon_head->orig_x &&
+ read_icon_head->orig_y == icon_head->orig_y) {
+ return read_icon_info;
+ }
+ }
+
+ return NULL;
+}
+
+static void icon_merge_context_register_icon(struct IconMergeContext *context,
+ const char *file_name,
+ struct IconHead *icon_head)
+{
+ context->read_icons = realloc(context->read_icons,
+ sizeof(struct IconInfo) * (context->num_read_icons + 1));
+
+ struct IconInfo *icon_info = &context->read_icons[context->num_read_icons];
+ icon_info->head = *icon_head;
+ icon_info->file_name = strdup(path_basename(file_name));
+
+ context->num_read_icons++;
+}
+
+static void icon_merge_context_free(struct IconMergeContext *context)
+{
+ if (context->read_icons != NULL) {
+ for (int i = 0; i < context->num_read_icons; i++) {
+ free(context->read_icons[i].file_name);
+ }
+ free(context->read_icons);
+ }
+}
+
static bool icon_decode_head(FILE *f_src, struct IconHead *r_head)
{
if (fread(r_head, 1, sizeof(*r_head), f_src) == sizeof(*r_head)) {
@@ -247,7 +333,8 @@ static bool icon_read(const char *file_src, struct IconHead *r_head, unsigned in
return success;
}
-static bool icon_merge(const char *file_src,
+static bool icon_merge(struct IconMergeContext *context,
+ const char *file_src,
unsigned int **r_pixels_canvas,
unsigned int *r_canvas_w,
unsigned int *r_canvas_h)
@@ -265,6 +352,15 @@ static bool icon_merge(const char *file_src,
return false;
}
+ struct IconInfo *read_icon_info = icon_merge_context_info_for_icon_head(context, &head);
+ if (read_icon_info != NULL) {
+ printf(
+ "Conflicting icon files %s and %s\n", path_basename(file_src), read_icon_info->file_name);
+ free(pixels);
+ return false;
+ }
+ icon_merge_context_register_icon(context, file_src, &head);
+
if (*r_canvas_w == 0) {
/* init once */
*r_canvas_w = head.canvas_w;
@@ -315,9 +411,13 @@ static bool icondir_to_png(const char *path_src, const char *file_dst)
int path_str_len;
int found = 0, fail = 0;
+ struct IconMergeContext context;
+
unsigned int *pixels_canvas = NULL;
unsigned int canvas_w = 0, canvas_h = 0;
+ icon_merge_context_init(&context);
+
errno = 0;
dir = opendir(path_src);
if (dir == NULL) {
@@ -335,7 +435,7 @@ static bool icondir_to_png(const char *path_src, const char *file_dst)
strcpy(filename, fname->d_name);
- if (icon_merge(filepath, &pixels_canvas, &canvas_w, &canvas_h)) {
+ if (icon_merge(&context, filepath, &pixels_canvas, &canvas_w, &canvas_h)) {
found++;
}
else {
@@ -344,6 +444,8 @@ static bool icondir_to_png(const char *path_src, const char *file_dst)
}
}
+ icon_merge_context_free(&context);
+
closedir(dir);
if (found == 0) {
@@ -359,7 +461,7 @@ static bool icondir_to_png(const char *path_src, const char *file_dst)
free(pixels_canvas);
- return true;
+ return (fail == 0);
}
/* -------------------------------------------------------------------- */
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index 14c91834739..df8c8215d2f 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -33,9 +33,7 @@
#include "MEM_guardedalloc.h"
-#include "DNA_ID.h" /* for ID_Type */
-
-#include "BKE_main.h" /* for MAX_LIBARRAY */
+#include "DNA_ID.h" /* for ID_Type and INDEX_ID_MAX */
#include "BLI_threads.h" /* for SpinLock */
@@ -111,10 +109,10 @@ struct Depsgraph {
bool need_update;
/* Indicates which ID types were updated. */
- char id_type_updated[MAX_LIBARRAY];
+ char id_type_updated[INDEX_ID_MAX];
/* Indicates type of IDs present in the depsgraph. */
- char id_type_exist[MAX_LIBARRAY];
+ char id_type_exist[INDEX_ID_MAX];
/* Quick-Access Temp Data ............. */
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index 34465c12914..ed002321729 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -86,7 +86,7 @@ void verify_id_properties_freed(DEGObjectIterData *data)
const Object *dupli_object = data->dupli_object_current->ob;
Object *temp_dupli_object = &data->temp_dupli_object;
if (temp_dupli_object->id.properties == nullptr) {
- // No ID properties in temp datablock -- no leak is possible.
+ // No ID properties in temp data-block -- no leak is possible.
return;
}
if (temp_dupli_object->id.properties == dupli_object->id.properties) {
@@ -435,7 +435,7 @@ static void DEG_iterator_ids_step(BLI_Iterator *iter, deg::IDNode *id_node, bool
if (only_updated && !(id_cow->recalc & ID_RECALC_ALL)) {
bNodeTree *ntree = ntreeFromID(id_cow);
- /* Nodetree is considered part of the datablock. */
+ /* Node-tree is considered part of the data-block. */
if (!(ntree && (ntree->id.recalc & ID_RECALC_ALL))) {
iter->skip = true;
return;
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index c60ec4351bc..2051ee3657a 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -253,7 +253,7 @@ void depsgraph_update_editors_tag(Main *bmain, Depsgraph *graph, ID *id)
{
/* NOTE: We handle this immediately, without delaying anything, to be
* sure we don't cause threading issues with OpenGL. */
- /* TODO(sergey): Make sure this works for CoW-ed datablocks as well. */
+ /* TODO(sergey): Make sure this works for CoW-ed data-blocks as well. */
DEGEditorUpdateContext update_ctx = {nullptr};
update_ctx.bmain = bmain;
update_ctx.depsgraph = (::Depsgraph *)graph;
@@ -306,7 +306,7 @@ void depsgraph_tag_component(Depsgraph *graph,
/* This is a tag compatibility with legacy code.
*
* Mainly, old code was tagging object with ID_RECALC_GEOMETRY tag to inform
- * that object's data datablock changed. Now API expects that ID is given
+ * that object's data data-block changed. Now API expects that ID is given
* explicitly, but not all areas are aware of this yet. */
void deg_graph_id_tag_legacy_compat(
Main *bmain, Depsgraph *depsgraph, ID *id, IDRecalcFlag tag, eUpdateSource update_source)
@@ -667,7 +667,7 @@ void graph_id_tag_update(
IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(&current_flag));
graph_id_tag_update_single_flag(bmain, graph, id, id_node, tag, update_source);
}
- /* Special case for nested node tree datablocks. */
+ /* Special case for nested node tree data-blocks. */
id_tag_update_ntree_special(bmain, graph, id, flag, update_source);
/* Direct update tags means that something outside of simulated/cached
* physics did change and that cache is to be invalidated.
@@ -777,12 +777,12 @@ void DEG_graph_time_tag_update(struct Depsgraph *depsgraph)
deg_graph->tag_time_source();
}
-/* Mark a particular datablock type as having changing. */
+/* Mark a particular data-block type as having changing. */
void DEG_graph_id_type_tag(Depsgraph *depsgraph, short id_type)
{
if (id_type == ID_NT) {
- /* Stupid workaround so parent datablocks of nested nodetree get looped
- * over when we loop over tagged datablock types. */
+ /* Stupid workaround so parent data-blocks of nested node-tree get looped
+ * over when we loop over tagged data-block types. */
DEG_graph_id_type_tag(depsgraph, ID_MA);
DEG_graph_id_type_tag(depsgraph, ID_TE);
DEG_graph_id_type_tag(depsgraph, ID_LA);
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc
index 3c0df93f4b9..c1d2dd8b6cc 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc
@@ -59,14 +59,14 @@ void animated_property_store_cb(ID *id, FCurve *fcurve, void *data_v)
/* Resolve path to the property. */
PathResolvedRNA resolved_rna;
- if (!BKE_animsys_store_rna_setting(
+ if (!BKE_animsys_rna_path_resolve(
&data->id_pointer_rna, fcurve->rna_path, fcurve->array_index, &resolved_rna)) {
return;
}
/* Read property value. */
float value;
- if (!BKE_animsys_read_rna_setting(&resolved_rna, &value)) {
+ if (!BKE_animsys_read_from_rna_path(&resolved_rna, &value)) {
return;
}
@@ -127,15 +127,15 @@ void AnimationBackup::restore_to_id(ID *id)
* NOTE: Do it again (after storing), since the sub-data pointers might be
* changed after copy-on-write. */
PathResolvedRNA resolved_rna;
- if (!BKE_animsys_store_rna_setting(&id_pointer_rna,
- value_backup.rna_path.c_str(),
- value_backup.array_index,
- &resolved_rna)) {
+ if (!BKE_animsys_rna_path_resolve(&id_pointer_rna,
+ value_backup.rna_path.c_str(),
+ value_backup.array_index,
+ &resolved_rna)) {
return;
}
/* Write property value. */
- if (!BKE_animsys_write_rna_setting(&resolved_rna, value_backup.value)) {
+ if (!BKE_animsys_write_to_rna_path(&resolved_rna, value_backup.value)) {
return;
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c
index c95279fc078..0cb2d55d1eb 100644
--- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c
+++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c
@@ -124,8 +124,20 @@ void EEVEE_cryptomatte_renderpasses_init(EEVEE_Data *vedata)
if (!DRW_state_is_image_render()) {
return;
}
- if (eevee_cryptomatte_active_layers(view_layer) != 0) {
- g_data->cryptomatte_session = BKE_cryptomatte_init();
+ const eViewLayerCryptomatteFlags active_layers = eevee_cryptomatte_active_layers(view_layer);
+ if (active_layers) {
+ struct CryptomatteSession *session = BKE_cryptomatte_init();
+ if ((active_layers & VIEW_LAYER_CRYPTOMATTE_OBJECT) != 0) {
+ BKE_cryptomatte_add_layer(session, "CryptoObject");
+ }
+ if ((active_layers & VIEW_LAYER_CRYPTOMATTE_MATERIAL) != 0) {
+ BKE_cryptomatte_add_layer(session, "CryptoMaterial");
+ }
+ if ((active_layers & VIEW_LAYER_CRYPTOMATTE_ASSET) != 0) {
+ BKE_cryptomatte_add_layer(session, "CryptoAsset");
+ }
+ g_data->cryptomatte_session = session;
+
g_data->render_passes |= EEVEE_RENDER_PASS_CRYPTOMATTE | EEVEE_RENDER_PASS_VOLUME_LIGHT;
g_data->cryptomatte_accurate_mode = (view_layer->cryptomatte_flag &
VIEW_LAYER_CRYPTOMATTE_ACCURATE) != 0;
@@ -208,20 +220,22 @@ static DRWShadingGroup *eevee_cryptomatte_shading_group_create(EEVEE_Data *vedat
EEVEE_PassList *psl = vedata->psl;
int layer_offset = 0;
if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_OBJECT) != 0) {
- uint32_t cryptomatte_hash = BKE_cryptomatte_object_hash(g_data->cryptomatte_session, ob);
+ uint32_t cryptomatte_hash = BKE_cryptomatte_object_hash(
+ g_data->cryptomatte_session, "CryptoObject", ob);
float cryptomatte_color_value = BKE_cryptomatte_hash_to_float(cryptomatte_hash);
cryptohash[layer_offset] = cryptomatte_color_value;
layer_offset++;
}
if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_MATERIAL) != 0) {
- uint32_t cryptomatte_hash = BKE_cryptomatte_material_hash(g_data->cryptomatte_session,
- material);
+ uint32_t cryptomatte_hash = BKE_cryptomatte_material_hash(
+ g_data->cryptomatte_session, "CryptoMaterial", material);
float cryptomatte_color_value = BKE_cryptomatte_hash_to_float(cryptomatte_hash);
cryptohash[layer_offset] = cryptomatte_color_value;
layer_offset++;
}
if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_ASSET) != 0) {
- uint32_t cryptomatte_hash = BKE_cryptomatte_asset_hash(g_data->cryptomatte_session, ob);
+ uint32_t cryptomatte_hash = BKE_cryptomatte_asset_hash(
+ g_data->cryptomatte_session, "CryptoAsset", ob);
float cryptomatte_color_value = BKE_cryptomatte_hash_to_float(cryptomatte_hash);
cryptohash[layer_offset] = cryptomatte_color_value;
layer_offset++;
@@ -693,30 +707,9 @@ void EEVEE_cryptomatte_store_metadata(EEVEE_Data *vedata, RenderResult *render_r
EEVEE_PrivateData *g_data = vedata->stl->g_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
const ViewLayer *view_layer = draw_ctx->view_layer;
- const eViewLayerCryptomatteFlags cryptomatte_layers = view_layer->cryptomatte_flag &
- VIEW_LAYER_CRYPTOMATTE_ALL;
BLI_assert(g_data->cryptomatte_session);
- if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_OBJECT) != 0) {
- BKE_cryptomatte_store_metadata(g_data->cryptomatte_session,
- render_result,
- view_layer,
- VIEW_LAYER_CRYPTOMATTE_OBJECT,
- "CryptoObject");
- }
- if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_MATERIAL) != 0) {
- BKE_cryptomatte_store_metadata(g_data->cryptomatte_session,
- render_result,
- view_layer,
- VIEW_LAYER_CRYPTOMATTE_MATERIAL,
- "CryptoMaterial");
- }
- if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_ASSET) != 0) {
- BKE_cryptomatte_store_metadata(g_data->cryptomatte_session,
- render_result,
- view_layer,
- VIEW_LAYER_CRYPTOMATTE_ASSET,
- "CryptoAsset");
- }
+
+ BKE_cryptomatte_store_metadata(g_data->cryptomatte_session, render_result, view_layer);
}
/** \} */
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
index 33d45d61d42..5f8e0106337 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -273,9 +273,12 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
float minimal_overblur = 1.0f / sqrtf(sample_count);
float user_overblur = scene_eval->eevee.bokeh_overblur / 100.0f;
- effects->dof_coc_params[1] *= minimal_overblur + user_overblur;
+ minimal_overblur *= effects->dof_coc_params[1];
+ user_overblur *= effects->dof_coc_params[1];
+
+ effects->dof_coc_params[1] = minimal_overblur + user_overblur;
/* Avoid dilating the shape. Over-blur only soften. */
- effects->dof_jitter_radius -= effects->dof_coc_params[1];
+ effects->dof_jitter_radius -= minimal_overblur + user_overblur * 0.5f;
}
}
else {
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 145fddf62a0..37ecdb20651 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -196,7 +196,7 @@ static uint eevee_lightcache_memsize_get(LightCache *lcache)
return size;
}
-static bool eevee_lightcache_version_check(LightCache *lcache)
+static bool eevee_lightcache_version_check(const LightCache *lcache)
{
switch (lcache->type) {
case LIGHTCACHE_TYPE_STATIC:
@@ -313,7 +313,14 @@ static bool EEVEE_lightcache_validate(const LightCache *light_cache,
const int grid_len,
const int irr_size[3])
{
- if (light_cache && !(light_cache->flag & LIGHTCACHE_INVALID)) {
+ if (light_cache == NULL) {
+ return false;
+ }
+ if (!eevee_lightcache_version_check(light_cache)) {
+ return false;
+ }
+
+ if (!(light_cache->flag & LIGHTCACHE_INVALID)) {
/* See if we need the same amount of texture space. */
if ((irr_size[0] == light_cache->grid_tx.tex_size[0]) &&
(irr_size[1] == light_cache->grid_tx.tex_size[1]) &&
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index ae01aee5dae..7fd39007263 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -208,12 +208,14 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
DRW_shgroup_stencil_mask(shgrp, sss_id);
{
+ eGPUSamplerState state = GPU_SAMPLER_DEFAULT;
+
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_subsurface_first_pass_sh_get(),
psl->sss_blur_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_texture_ref_ex(grp, "sssIrradiance", &effects->sss_irradiance, state);
+ DRW_shgroup_uniform_texture_ref_ex(grp, "sssRadius", &effects->sss_radius, state);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
@@ -223,9 +225,9 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
grp = DRW_shgroup_create(EEVEE_shaders_subsurface_second_pass_sh_get(), psl->sss_resolve_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
- DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_texture_ref_ex(grp, "sssIrradiance", &effects->sss_blur, state);
+ DRW_shgroup_uniform_texture_ref_ex(grp, "sssAlbedo", &effects->sss_albedo, state);
+ DRW_shgroup_uniform_texture_ref_ex(grp, "sssRadius", &effects->sss_radius, state);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index bc2895ef3df..5f0fde134d1 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -135,6 +135,60 @@ void accumulate_light(vec3 light, float fac, inout vec4 accum)
accum += vec4(light, 1.0) * min(fac, (1.0 - accum.a));
}
+/* Same thing as Cycles without the comments to make it shorter. */
+vec3 ensure_valid_reflection(vec3 Ng, vec3 I, vec3 N)
+{
+ vec3 R = -reflect(I, N);
+
+ /* Reflection rays may always be at least as shallow as the incoming ray. */
+ float threshold = min(0.9 * dot(Ng, I), 0.025);
+ if (dot(Ng, R) >= threshold) {
+ return N;
+ }
+
+ float NdotNg = dot(N, Ng);
+ vec3 X = normalize(N - NdotNg * Ng);
+
+ float Ix = dot(I, X), Iz = dot(I, Ng);
+ float Ix2 = sqr(Ix), Iz2 = sqr(Iz);
+ float a = Ix2 + Iz2;
+
+ float b = sqrt(Ix2 * (a - sqr(threshold)));
+ float c = Iz * threshold + a;
+
+ float fac = 0.5 / a;
+ float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c);
+ bool valid1 = (N1_z2 > 1e-5) && (N1_z2 <= (1.0 + 1e-5));
+ bool valid2 = (N2_z2 > 1e-5) && (N2_z2 <= (1.0 + 1e-5));
+
+ vec2 N_new;
+ if (valid1 && valid2) {
+ /* If both are possible, do the expensive reflection-based check. */
+ vec2 N1 = vec2(sqrt(1.0 - N1_z2), sqrt(N1_z2));
+ vec2 N2 = vec2(sqrt(1.0 - N2_z2), sqrt(N2_z2));
+
+ float R1 = 2.0 * (N1.x * Ix + N1.y * Iz) * N1.y - Iz;
+ float R2 = 2.0 * (N2.x * Ix + N2.y * Iz) * N2.y - Iz;
+
+ valid1 = (R1 >= 1e-5);
+ valid2 = (R2 >= 1e-5);
+ if (valid1 && valid2) {
+ N_new = (R1 < R2) ? N1 : N2;
+ }
+ else {
+ N_new = (R1 > R2) ? N1 : N2;
+ }
+ }
+ else if (valid1 || valid2) {
+ float Nz2 = valid1 ? N1_z2 : N2_z2;
+ N_new = vec2(sqrt(1.0 - Nz2), sqrt(Nz2));
+ }
+ else {
+ return Ng;
+ }
+ return N_new.x * X + N_new.y * Ng;
+}
+
/* ----------- Cone angle Approximation --------- */
/* Return a fitted cone angle given the input roughness */
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
index 5c10a7f451f..00d265a48b0 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
@@ -3,6 +3,7 @@
#pragma BLENDER_REQUIRE(lights_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
+#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl)
struct ClosureInputGlossy {
vec3 N; /** Shading normal. */
@@ -39,6 +40,10 @@ ClosureEvalGlossy closure_Glossy_eval_init(inout ClosureInputGlossy cl_in,
cl_in.roughness = clamp(cl_in.roughness, 1e-8, 0.9999);
cl_out.radiance = vec3(0.0);
+#ifndef STEP_RESOLVE /* SSR */
+ cl_in.N = ensure_valid_reflection(cl_common.Ng, cl_common.V, cl_in.N);
+#endif
+
float NV = dot(cl_in.N, cl_common.V);
vec2 lut_uv = lut_coords(NV, cl_in.roughness);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
index a4b29d68ac4..ecff28dcd38 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
@@ -80,25 +80,24 @@ void do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 vP, float a2, vec4 rand)
vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH);
vec3 R = reflect(-V, H);
+ const float bad_ray_threshold = 0.01;
+
+ vec3 vNg = safe_normalize(cross(dFdx(vP), dFdy(vP)));
+
/* If ray is bad (i.e. going below the surface) regenerate. */
- /* This threshold is a bit higher than 0 to improve self intersection cases. */
- const float bad_ray_threshold = 0.085;
- if (dot(R, N) <= bad_ray_threshold) {
+ if (dot(R, vNg) < bad_ray_threshold) {
H = sample_ggx(rand.xzw * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH);
R = reflect(-V, H);
}
-
- if (dot(R, N) <= bad_ray_threshold) {
+ if (dot(R, vNg) < bad_ray_threshold) {
H = sample_ggx(rand.xzw * vec3(1.0, 1.0, -1.0), a2, N, T, B, NH);
R = reflect(-V, H);
}
-
- if (dot(R, N) <= bad_ray_threshold) {
+ if (dot(R, vNg) < bad_ray_threshold) {
H = sample_ggx(rand.xzw * vec3(1.0, -1.0, 1.0), a2, N, T, B, NH);
R = reflect(-V, H);
}
-
- if (dot(R, N) <= bad_ray_threshold) {
+ if (dot(R, vNg) < bad_ray_threshold) {
/* Not worth tracing. */
return;
}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
index 2a53a4f119f..1964adf3059 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -26,7 +26,7 @@ void main(void)
vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO precompute */
vec2 uvs = gl_FragCoord.xy * pixel_size;
vec3 sss_irradiance = texture(sssIrradiance, uvs).rgb;
- float sss_radius = texture(sssRadius, uvs).r;
+ float sss_radius = texture(sssRadius, uvs).r * radii_max_radius.w;
float depth = texture(depthBuffer, uvs).r;
float depth_view = get_view_z_from_depth(depth);
@@ -43,8 +43,7 @@ void main(void)
/* Compute kernel bounds in 2D. */
float homcoord = ProjectionMatrix[2][3] * depth_view + ProjectionMatrix[3][3];
vec2 scale = vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * sss_radius / homcoord;
- vec2 finalStep = scale * radii_max_radius.w;
- finalStep *= 0.5; /* samples range -1..1 */
+ vec2 finalStep = scale * 0.5; /* samples range -1..1 */
/* Center sample */
vec3 accum = sss_irradiance * kernel[0].rgb;
@@ -55,15 +54,18 @@ void main(void)
vec3 color = texture(sssIrradiance, sample_uv).rgb;
float sample_depth = texture(depthBuffer, sample_uv).r;
sample_depth = get_view_z_from_depth(sample_depth);
- /* Depth correction factor. */
- float depth_delta = depth_view - sample_depth;
- float s = clamp(1.0 - exp(-(depth_delta * depth_delta) / (2.0 * sss_radius)), 0.0, 1.0);
+ /* Depth correction factor. See Real Time Realistic Skin Translucency 2010
+ * by Jimenez, eqs. 2 and 9, and D9740.
+ * Coefficient -2 follows from gaussian_profile() from gpu_material.c and
+ * from the definition of finalStep. */
+ float depth_delta = (depth_view - sample_depth) / sss_radius;
+ float s = exp(-2.0 * sqr(depth_delta));
/* Out of view samples. */
if (any(lessThan(sample_uv, vec2(0.0))) || any(greaterThan(sample_uv, vec2(1.0)))) {
- s = 1.0;
+ s = 0.0;
}
/* Mix with first sample in failure case and apply kernel color. */
- accum += kernel[i].rgb * mix(color, sss_irradiance, s);
+ accum += kernel[i].rgb * mix(sss_irradiance, color, s);
}
#if defined(FIRST_PASS)
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
index de384146b80..c9b5d0dea36 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
@@ -304,5 +304,8 @@ vec3 probe_evaluate_grid(GridData gd, vec3 P, vec3 N, vec3 localpos)
vec3 probe_evaluate_world_diff(vec3 N)
{
+ if (prbNumRenderGrid == 0) {
+ return vec3(0);
+ }
return irradiance_from_cell_get(0, N);
}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
index 9b852a57ec4..b1e3a40e8d2 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
@@ -98,7 +98,7 @@ vec3 light_volume(LightData ld, vec4 l_vector)
return tint * lum;
}
-#define VOLUMETRIC_SHADOW_MAX_STEP 32.0
+#define VOLUMETRIC_SHADOW_MAX_STEP 128.0
vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction)
{
@@ -115,10 +115,10 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D v
#if defined(VOLUME_SHADOW)
/* Heterogeneous volume shadows */
float dd = l_vector.w / volShadowSteps;
- vec3 L = l_vector.xyz * l_vector.w;
+ vec3 L = l_vector.xyz / volShadowSteps;
vec3 shadow = vec3(1.0);
- for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volShadowSteps - 0.1); s += 1.0) {
- vec3 pos = ray_wpos + L * (s / volShadowSteps);
+ for (float s = 1.0; s < VOLUMETRIC_SHADOW_MAX_STEP && s <= volShadowSteps; s += 1.0) {
+ vec3 pos = ray_wpos + L * s;
vec3 s_extinction = participating_media_extinction(pos, volume_extinction);
shadow *= exp(-s_extinction * dd);
}
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 66ba558c4f4..739723b3af0 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -970,8 +970,15 @@ GPUVertBuf *DRW_cache_object_pos_vertbuf_get(Object *ob)
int DRW_cache_object_material_count_get(struct Object *ob)
{
+ short type = ob->type;
+
Mesh *me = BKE_object_get_evaluated_mesh(ob);
- short type = (me != NULL) ? OB_MESH : ob->type;
+ if (me != NULL && type != OB_POINTCLOUD) {
+ /* Some object types (e.g. curves) can have a Curve in ob->data, but will be rendered as mesh.
+ * For point clouds this never happens. Ideally this check would happen at another level and we
+ * would just have to care about ob->data here. */
+ type = OB_MESH;
+ }
switch (type) {
case OB_MESH:
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index f540ff09032..84bc0327aa2 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -46,10 +46,10 @@
struct DupliObject;
struct Object;
-/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
+/** Use draw manager to call GPU_select, see: #DRW_draw_select_loop */
#define USE_GPU_SELECT
-/* Use drawcall batching using instanced rendering. */
+/** Use draw-call batching using instanced rendering. */
#define USE_BATCHING 1
// #define DRW_DEBUG_CULLING
diff --git a/source/blender/draw/intern/draw_manager_profiling.c b/source/blender/draw/intern/draw_manager_profiling.c
index 98a6b2bff00..9bfc8d98fe4 100644
--- a/source/blender/draw/intern/draw_manager_profiling.c
+++ b/source/blender/draw/intern/draw_manager_profiling.c
@@ -151,7 +151,6 @@ void DRW_stats_group_end(void)
void DRW_stats_query_start(const char *name)
{
GPU_debug_group_begin(name);
- drw_stats_timer_start_ex(name, false);
drw_stats_timer_start_ex(name, true);
}
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 38820e05869..711ec0a9d22 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -2544,7 +2544,7 @@ static bool animchannels_find_poll(bContext *C)
}
/* find_invoke() - Get initial channels */
-static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
@@ -2557,7 +2557,7 @@ static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *
RNA_string_set(op->ptr, "query", ac.ads->searchstr);
/* defer to popup */
- return WM_operator_props_popup(C, op, evt);
+ return WM_operator_props_popup(C, op, event);
}
/* find_exec() - Called to set the value */
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index b344e67f62d..1809daa3fcb 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -305,6 +305,7 @@ static void fmodifier_frame_range_draw(const bContext *C, Panel *panel)
PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
FModifier *fcm = (FModifier *)ptr->data;
uiLayoutSetActive(layout, fcm->flag & FMODIFIER_FLAG_RANGERESTRICT);
@@ -478,6 +479,7 @@ static void fn_generator_panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, ptr, "function_type", 0, "", ICON_NONE);
uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "use_additive", 0, NULL, ICON_NONE);
@@ -698,6 +700,7 @@ static void envelope_panel_draw(const bContext *C, Panel *panel)
FMod_Envelope *env = (FMod_Envelope *)fcm->data;
uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
/* General settings. */
col = uiLayoutColumn(layout, true);
@@ -792,6 +795,7 @@ static void limits_panel_draw(const bContext *C, Panel *panel)
PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
/* Minimums. */
col = uiLayoutColumn(layout, false);
@@ -853,6 +857,7 @@ static void stepped_panel_draw(const bContext *C, Panel *panel)
PointerRNA *ptr = fmodifier_get_pointers(C, panel, NULL);
uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
/* Stepping Settings. */
col = uiLayoutColumn(layout, false);
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index bb5bcd4083e..66ca38ce218 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -552,9 +552,12 @@ static void separated_armature_fix_links(Main *bmain, Object *origArm, Object *n
}
}
-/* Helper function for armature separating - remove certain bones from the given armature
- * sel: remove selected bones from the armature, otherwise the unselected bones are removed
- * (ob is not in edit-mode)
+/**
+ * Helper function for armature separating - remove certain bones from the given armature.
+ *
+ * \param ob: Armature object (must not be is not in edit-mode).
+ * \param is_select: remove selected bones from the armature,
+ * otherwise the unselected bones are removed.
*/
static void separate_armature_bones(Main *bmain, Object *ob, const bool is_select)
{
@@ -621,7 +624,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
bool ok = false;
/* set wait cursor in case this takes a while */
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
@@ -706,7 +709,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
MEM_freeN(bases);
/* Recalculate/redraw + cleanup */
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
if (ok) {
BKE_report(op->reports, RPT_INFO, "Separated bones");
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 78bce8679bb..e65871c0896 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -476,9 +476,9 @@ static int pose_clear_paths_exec(bContext *C, wmOperator *op)
}
/* operator callback/wrapper */
-static int pose_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+static int pose_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
+ if ((event->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
RNA_boolean_set(op->ptr, "only_selected", true);
}
return pose_clear_paths_exec(C, op);
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 45f623f3a9d..dd90f9f2cc3 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -1321,10 +1321,10 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
}
/* specially handle events for searching */
-static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, ushort event, char ascii)
+static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, ushort event_type, char ascii)
{
/* try doing some form of string manipulation first */
- switch (event) {
+ switch (event_type) {
case EVT_BACKSPACEKEY:
if (pld->searchstr[0] && pld->search_cursor) {
short len = strlen(pld->searchstr);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 0593cedb5a1..33ef6a5d026 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1359,7 +1359,7 @@ static int separate_exec(bContext *C, wmOperator *op)
int error_generic;
} status = {0};
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
@@ -1426,7 +1426,7 @@ static int separate_exec(bContext *C, wmOperator *op)
status.changed++;
}
MEM_freeN(bases);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
if (status.unselected == bases_len) {
BKE_report(op->reports, RPT_ERROR, "No point was selected");
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index c8bd38d58fe..e9817f82090 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -2093,7 +2093,7 @@ static void annotation_draw_apply_event(
p->mval[1] = (float)event->mval[1] - y;
/* Key to toggle stabilization. */
- if (event->shift > 0 && p->paintmode == GP_PAINTMODE_DRAW) {
+ if (event->shift && p->paintmode == GP_PAINTMODE_DRAW) {
/* Using permanent stabilization, shift will deactivate the flag. */
if (p->flags & GP_PAINTFLAG_USE_STABILIZER) {
if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
@@ -2108,7 +2108,7 @@ static void annotation_draw_apply_event(
}
}
/* verify key status for straight lines */
- else if ((event->ctrl > 0) || (event->alt > 0)) {
+ else if (event->ctrl || event->alt) {
if (p->straight[0] == 0) {
int dx = abs((int)(p->mval[0] - p->mvalo[0]));
int dy = abs((int)(p->mval[1] - p->mvalo[1]));
@@ -2348,7 +2348,7 @@ static int annotation_draw_invoke(bContext *C, wmOperator *op, const wmEvent *ev
p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP;
annotation_draw_toggle_stabilizer_cursor(p, true);
}
- else if (event->shift > 0) {
+ else if (event->shift) {
p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
annotation_draw_toggle_stabilizer_cursor(p, true);
}
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index c76c2e55d2b..fd2758c8a08 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -1420,7 +1420,7 @@ void GPENCIL_OT_layer_merge(wmOperatorType *ot)
/* ********************** Change Layer ***************************** */
-static int gpencil_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
+static int gpencil_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
uiPopupMenu *pup;
uiLayout *layout;
@@ -1676,7 +1676,7 @@ void GPENCIL_OT_stroke_arrange(wmOperatorType *ot)
/* identifiers */
ot->name = "Arrange Stroke";
ot->idname = "GPENCIL_OT_stroke_arrange";
- ot->description = "Arrange selected strokes up/down in the drawing order of the active layer";
+ ot->description = "Arrange selected strokes up/down in the display order of the active layer";
/* callbacks */
ot->exec = gpencil_stroke_arrange_exec;
diff --git a/source/blender/editors/gpencil/gpencil_edit_curve.c b/source/blender/editors/gpencil/gpencil_edit_curve.c
index 0f9a8c93df9..e766a410889 100644
--- a/source/blender/editors/gpencil/gpencil_edit_curve.c
+++ b/source/blender/editors/gpencil/gpencil_edit_curve.c
@@ -131,7 +131,7 @@ void GPENCIL_OT_stroke_enter_editcurve_mode(wmOperatorType *ot)
"Error Threshold",
"Threshold on the maximum deviation from the actual stroke",
FLT_MIN,
- 10.f);
+ 10.0f);
RNA_def_property_ui_range(prop, FLT_MIN, 10.0f, 0.1f, 5);
}
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 406daf9f92e..85130e89ad1 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -55,6 +55,7 @@
#include "BKE_screen.h"
#include "ED_gpencil.h"
+#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_view3d.h"
@@ -542,12 +543,18 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4])
if (gpl == tgpf->gpl) {
if ((gpl->actframe == NULL) || (gpl->actframe->framenum != tgpf->active_cfra)) {
short add_frame_mode;
- if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
- add_frame_mode = GP_GETFRAME_ADD_COPY;
+ if (IS_AUTOKEY_ON(tgpf->scene)) {
+ if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
+ add_frame_mode = GP_GETFRAME_ADD_COPY;
+ }
+ else {
+ add_frame_mode = GP_GETFRAME_ADD_NEW;
+ }
}
else {
- add_frame_mode = GP_GETFRAME_ADD_NEW;
+ add_frame_mode = GP_GETFRAME_USE_PREV;
}
+
BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, add_frame_mode);
}
}
@@ -1456,7 +1463,10 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
tgpf->done = true;
/* Get frame or create a new one. */
- tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW);
+ tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl,
+ tgpf->active_cfra,
+ IS_AUTOKEY_ON(tgpf->scene) ? GP_GETFRAME_ADD_NEW :
+ GP_GETFRAME_USE_PREV);
/* Set frame as selected. */
tgpf->gpf->flag |= GP_FRAME_SELECT;
@@ -2064,6 +2074,12 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
estate = OPERATOR_CANCELLED;
break;
case LEFTMOUSE:
+ if (!IS_AUTOKEY_ON(tgpf->scene) && (!is_multiedit) && (tgpf->gpl->actframe == NULL)) {
+ BKE_report(op->reports, RPT_INFO, "No available frame for creating stroke");
+ estate = OPERATOR_CANCELLED;
+ break;
+ }
+
/* first time the event is not enabled to show help lines. */
if ((tgpf->oldkey != -1) || (!help_lines)) {
ARegion *region = BKE_area_find_region_xy(
@@ -2088,17 +2104,24 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
gpencil_stroke_convertcoords_tpoint(
tgpf->scene, tgpf->region, tgpf->ob, &point2D, NULL, &pt->x);
+ /* Hash of selected frames.*/
+ GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64);
+
/* If not multiframe and there is no frame in CFRA for the active layer, create
- * a new frame before to make the hash function can find something. */
+ * a new frame. */
if (!is_multiedit) {
tgpf->gpf = BKE_gpencil_layer_frame_get(
- tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW);
+ tgpf->gpl,
+ tgpf->active_cfra,
+ IS_AUTOKEY_ON(tgpf->scene) ? GP_GETFRAME_ADD_NEW : GP_GETFRAME_USE_PREV);
tgpf->gpf->flag |= GP_FRAME_SELECT;
- }
- /* Hash of selected frames.*/
- GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64);
- BKE_gpencil_frame_selected_hash(tgpf->gpd, frame_list);
+ BLI_ghash_insert(
+ frame_list, POINTER_FROM_INT(tgpf->active_cfra), tgpf->gpl->actframe);
+ }
+ else {
+ BKE_gpencil_frame_selected_hash(tgpf->gpd, frame_list);
+ }
/* Loop all frames. */
wmWindow *win = CTX_wm_window(C);
diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c
index 7e6b42f284b..b7ed77801c0 100644
--- a/source/blender/editors/gpencil/gpencil_mesh.c
+++ b/source/blender/editors/gpencil/gpencil_mesh.c
@@ -251,7 +251,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
gpd->draw_mode = (project_type == GP_REPROJECT_KEEP) ? GP_DRAWMODE_3D : GP_DRAWMODE_2D;
/* Set cursor to indicate working. */
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
GP_SpaceConversion gsc = {NULL};
SnapObjectContext *sctx = NULL;
@@ -385,7 +385,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
/* Reset cursor. */
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
/* done */
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 974f51ff90b..1217a3a7e8f 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -67,6 +67,7 @@
#include "ED_clip.h"
#include "ED_gpencil.h"
+#include "ED_keyframing.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -2155,6 +2156,10 @@ static void gpencil_paint_initstroke(tGPsdata *p,
continue;
}
+ if (!IS_AUTOKEY_ON(scene) && (gpl->actframe == NULL)) {
+ continue;
+ }
+
/* Add a new frame if needed (and based off the active frame,
* as we need some existing strokes to erase)
*
@@ -2164,7 +2169,8 @@ static void gpencil_paint_initstroke(tGPsdata *p,
*/
if (gpl->actframe && gpl->actframe->strokes.first) {
if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
- gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+ short frame_mode = IS_AUTOKEY_ON(scene) ? GP_GETFRAME_ADD_COPY : GP_GETFRAME_USE_PREV;
+ gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, frame_mode);
}
has_layer_to_erase = true;
break;
@@ -2187,11 +2193,16 @@ static void gpencil_paint_initstroke(tGPsdata *p,
/* Drawing Modes - Add a new frame if needed on the active layer */
short add_frame_mode;
- if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
- add_frame_mode = GP_GETFRAME_ADD_COPY;
+ if (IS_AUTOKEY_ON(scene)) {
+ if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
+ add_frame_mode = GP_GETFRAME_ADD_COPY;
+ }
+ else {
+ add_frame_mode = GP_GETFRAME_ADD_NEW;
+ }
}
else {
- add_frame_mode = GP_GETFRAME_ADD_NEW;
+ add_frame_mode = GP_GETFRAME_USE_PREV;
}
bool need_tag = p->gpl->actframe == NULL;
@@ -2206,6 +2217,10 @@ static void gpencil_paint_initstroke(tGPsdata *p,
if (G.debug & G_DEBUG) {
printf("Error: No frame created (gpencil_paint_init)\n");
}
+ if (!IS_AUTOKEY_ON(scene)) {
+ BKE_report(p->reports, RPT_INFO, "No available frame for creating stroke");
+ }
+
return;
}
p->gpf->flag |= GP_FRAME_PAINT;
@@ -2469,6 +2484,8 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
return 0;
}
+ p->reports = op->reports;
+
/* init painting data */
gpencil_paint_initstroke(p, paintmode, CTX_data_ensure_evaluated_depsgraph(C));
if (p->status == GP_STATUS_ERROR) {
@@ -2483,8 +2500,6 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
p->keymodifier = -1;
}
- p->reports = op->reports;
-
/* everything is now setup ok */
return 1;
}
@@ -2835,7 +2850,7 @@ static void gpencil_draw_apply_event(bContext *C,
/* verify direction for straight lines and guides */
if ((is_speed_guide) ||
- ((event->alt > 0) && (RNA_boolean_get(op->ptr, "disable_straight") == false))) {
+ (event->alt && (RNA_boolean_get(op->ptr, "disable_straight") == false))) {
if (p->straight == 0) {
int dx = (int)fabsf(p->mval[0] - p->mvali[0]);
int dy = (int)fabsf(p->mval[1] - p->mvali[1]);
@@ -2876,13 +2891,13 @@ static void gpencil_draw_apply_event(bContext *C,
/* special eraser modes */
if (p->paintmode == GP_PAINTMODE_ERASER) {
- if (event->shift > 0) {
+ if (event->shift) {
p->flags |= GP_PAINTFLAG_HARD_ERASER;
}
else {
p->flags &= ~GP_PAINTFLAG_HARD_ERASER;
}
- if (event->alt > 0) {
+ if (event->alt) {
p->flags |= GP_PAINTFLAG_STROKE_ERASER;
}
else {
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 12d399f32ca..b29ef2e7ee2 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -71,6 +71,7 @@
#include "RNA_enum_types.h"
#include "ED_gpencil.h"
+#include "ED_keyframing.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_space_api.h"
@@ -1253,9 +1254,18 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
tGPDprimitive *tgpi = NULL;
+ if (!IS_AUTOKEY_ON(scene)) {
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
+ if ((gpl == NULL) || (gpl->actframe == NULL)) {
+ BKE_report(op->reports, RPT_INFO, "No available frame for creating stroke");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
/* initialize operator runtime data */
gpencil_primitive_init(C, op);
tgpi = op->customdata;
@@ -1310,11 +1320,16 @@ static void gpencil_primitive_interaction_end(bContext *C,
/* insert keyframes as required... */
short add_frame_mode;
- if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
- add_frame_mode = GP_GETFRAME_ADD_COPY;
+ if (IS_AUTOKEY_ON(tgpi->scene)) {
+ if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
+ add_frame_mode = GP_GETFRAME_ADD_COPY;
+ }
+ else {
+ add_frame_mode = GP_GETFRAME_ADD_NEW;
+ }
}
else {
- add_frame_mode = GP_GETFRAME_ADD_NEW;
+ add_frame_mode = GP_GETFRAME_USE_PREV;
}
bool need_tag = tgpi->gpl->actframe == NULL;
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index 0d3ab9011d6..9666aca5254 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -73,6 +73,7 @@
#include "UI_view2d.h"
#include "ED_gpencil.h"
+#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -1019,7 +1020,11 @@ static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
if (gpl == NULL) {
gpl = CTX_data_active_gpencil_layer(C);
}
- bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(
+ gpl, CFRA, IS_AUTOKEY_ON(scene) ? GP_GETFRAME_ADD_NEW : GP_GETFRAME_USE_PREV);
+ if (gpf == NULL) {
+ continue;
+ }
/* Make a new stroke */
new_stroke = BKE_gpencil_stroke_duplicate(gps, true, true);
@@ -1334,6 +1339,10 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso
/* go through each layer, and ensure that we've got a valid frame to use */
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ if (!IS_AUTOKEY_ON(scene) && (gpl->actframe == NULL)) {
+ continue;
+ }
+
/* only editable and visible layers are considered */
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
@@ -1343,7 +1352,7 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso
* - This is useful when animating as it saves that "uh-oh" moment when you realize you've
* spent too much time editing the wrong frame.
*/
- if (gpf->framenum != cfra) {
+ if ((IS_AUTOKEY_ON(scene)) && (gpf->framenum != cfra)) {
BKE_gpencil_frame_addcopy(gpl, cfra);
/* Need tag to recalculate evaluated data to avoid crashes. */
DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c
index 677451eaabc..6bd0540a9d4 100644
--- a/source/blender/editors/gpencil/gpencil_uv.c
+++ b/source/blender/editors/gpencil/gpencil_uv.c
@@ -44,6 +44,7 @@
#include "ED_numinput.h"
#include "ED_screen.h"
#include "ED_space_api.h"
+#include "ED_util.h"
#include "ED_view3d.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 2415c85e299..4b440aa7367 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -55,7 +55,6 @@ struct FModifier;
struct bAction;
struct uiBlock;
-struct uiLayout;
struct PointerRNA;
struct PropertyRNA;
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 7538dac1354..983ae94b637 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -145,6 +145,13 @@ void ED_fileselect_exit(struct wmWindowManager *wm,
struct SpaceFile *sfile);
bool ED_fileselect_is_asset_browser(const struct SpaceFile *sfile);
+struct ID *ED_fileselect_active_asset_get(const struct SpaceFile *sfile);
+
+/* Activate the file that corresponds to the given ID.
+ * Pass deferred=true to wait for the next refresh before activating. */
+void ED_fileselect_activate_by_id(struct SpaceFile *sfile,
+ struct ID *asset_id,
+ const bool deferred);
void ED_fileselect_window_params_get(const struct wmWindow *win,
int win_size[2],
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 5dfce6071f0..0767ce21382 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -163,8 +163,8 @@ extern struct EnumPropertyItem prop_make_parent_types[];
bool ED_object_parent_set(struct ReportList *reports,
const struct bContext *C,
struct Scene *scene,
- struct Object *ob,
- struct Object *par,
+ struct Object *const ob,
+ struct Object *const par,
int partype,
const bool xmirror,
const bool keep_transform,
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index deb6b7502c7..b3205acb8ee 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -52,7 +52,6 @@ struct rcti;
struct uiBlock;
struct uiLayout;
struct wmKeyConfig;
-struct wmMsgBus;
struct wmMsgSubscribeKey;
struct wmMsgSubscribeValue;
struct wmNotifier;
@@ -123,8 +122,6 @@ void ED_region_info_draw_multiline(ARegion *region,
const char *text_array[],
float fill_color[4],
const bool full_redraw);
-void ED_region_image_metadata_draw(
- int x, int y, struct ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy);
void ED_region_image_metadata_panel_draw(struct ImBuf *ibuf, struct uiLayout *layout);
void ED_region_grid_draw(struct ARegion *region, float zoomx, float zoomy, float x0, float y0);
float ED_region_blend_alpha(struct ARegion *region);
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index c50bbc2f1e9..fc474ea464d 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -76,11 +76,6 @@ void ED_region_draw_cb_exit(struct ARegionType *, void *);
void ED_region_draw_cb_remove_by_type(struct ARegionType *art,
void *draw_fn,
void (*free)(void *));
-/* generic callbacks */
-/* ed_util.c */
-void ED_region_draw_mouse_line_cb(const struct bContext *C,
- struct ARegion *region,
- void *arg_info);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 073186f6335..953f26aa45f 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -53,6 +53,14 @@ void ED_spacedata_id_remap(struct ScrArea *area,
void ED_operatortypes_edutils(void);
+/* Drawing */
+void ED_region_draw_mouse_line_cb(const struct bContext *C,
+ struct ARegion *region,
+ void *arg_info);
+
+void ED_region_image_metadata_draw(
+ int x, int y, struct ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy);
+
/* ************** XXX OLD CRUFT WARNING ************* */
void apply_keyb_grid(
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 81641239c6a..5620d39ab16 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -499,10 +499,14 @@ typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
typedef struct ARegion *(*uiButSearchCreateFn)(struct bContext *C,
struct ARegion *butregion,
struct uiButSearch *search_but);
+/* `is_first` is typically used to ignore search filtering when the menu is first opened in order
+ * to display the full list of options. The value will be false after the button's text is edited
+ * (for every call except the first). */
typedef void (*uiButSearchUpdateFn)(const struct bContext *C,
void *arg,
const char *str,
- uiSearchItems *items);
+ uiSearchItems *items,
+ const bool is_first);
typedef void (*uiButSearchArgFreeFn)(void *arg);
typedef bool (*uiButSearchContextMenuFn)(struct bContext *C,
void *arg,
@@ -1602,6 +1606,7 @@ void UI_but_func_search_set(uiBut *but,
void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn);
void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn);
void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string);
+void UI_but_func_search_set_results_are_suggestions(uiBut *but, const bool value);
/* height in pixels, it's using hardcoded values still */
int UI_searchbox_size_y(void);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 6e25ec9d275..c7f5385eac3 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -6661,11 +6661,20 @@ void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn)
but_search->item_tooltip_fn = tooltip_fn;
}
+void UI_but_func_search_set_results_are_suggestions(uiBut *but, const bool value)
+{
+ uiButSearch *but_search = (uiButSearch *)but;
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
+
+ but_search->results_are_suggestions = value;
+}
+
/* Callbacks for operator search button. */
static void operator_enum_search_update_fn(const struct bContext *C,
void *but,
const char *str,
- uiSearchItems *items)
+ uiSearchItems *items,
+ const bool UNUSED(is_first))
{
wmOperatorType *ot = ((uiBut *)but)->optype;
PropertyRNA *prop = ot->prop;
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index d10cdc207c2..40cfcaea883 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -120,7 +120,7 @@ void UI_draw_roundbox_4fv_ex(const rctf *rect,
};
GPUBatch *batch = ui_batch_roundbox_widget_get();
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
- GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 11, (const float(*)[4]) & widget_params);
GPU_blend(GPU_BLEND_ALPHA);
GPU_batch_draw(batch);
GPU_blend(GPU_BLEND_NONE);
@@ -2376,7 +2376,7 @@ void ui_draw_dropshadow(
GPUBatch *batch = ui_batch_roundbox_shadow_get();
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW);
- GPU_batch_uniform_4fv_array(batch, "parameters", 4, (float(*)[4]) & widget_params);
+ GPU_batch_uniform_4fv_array(batch, "parameters", 4, (const float(*)[4]) & widget_params);
GPU_batch_uniform_1f(batch, "alpha", 1.0f - visibility);
GPU_batch_draw(batch);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 5de330d7136..042f10ddded 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -168,12 +168,14 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
#define PIE_MENU_INTERVAL 0.01
#define BUTTON_AUTO_OPEN_THRESH 0.2
#define BUTTON_MOUSE_TOWARDS_THRESH 1.0
-/* pixels to move the cursor to get out of keyboard navigation */
+/** Pixels to move the cursor to get out of keyboard navigation. */
#define BUTTON_KEYNAV_PX_LIMIT 8
-#define MENU_TOWARDS_MARGIN 20 /* margin in pixels */
-#define MENU_TOWARDS_WIGGLE_ROOM 64 /* tolerance in pixels */
-/* drag-lock distance threshold in pixels */
+/** Margin around the menu, use to check if we're moving towards this rectangle (in pixels). */
+#define MENU_TOWARDS_MARGIN 20
+/** Tolerance for closing menus (in pixels). */
+#define MENU_TOWARDS_WIGGLE_ROOM 64
+/** Drag-lock distance threshold (in pixels). */
#define BUTTON_DRAGLOCK_THRESH 3
typedef enum uiButtonActivateType {
@@ -3408,8 +3410,12 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
if (data->searchbox) {
if (data->cancel == false) {
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
+ uiButSearch *but_search = (uiButSearch *)but;
+
if ((ui_searchbox_apply(but, data->searchbox) == false) &&
- (ui_searchbox_find_index(data->searchbox, but->editstr) == -1)) {
+ (ui_searchbox_find_index(data->searchbox, but->editstr) == -1) &&
+ !but_search->results_are_suggestions) {
data->cancel = true;
/* ensure menu (popup) too is closed! */
@@ -10440,7 +10446,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
}
}
- if (event->type == block->pie_data.event && !is_click_style) {
+ if (event->type == block->pie_data.event_type && !is_click_style) {
if (event->val != KM_RELEASE) {
ui_handle_menu_button(C, event, menu);
@@ -10614,7 +10620,7 @@ static int ui_handle_menus_recursive(bContext *C,
/* root pie menus accept the key that spawned
* them as double click to improve responsiveness */
const bool do_recursion = (!(block->flag & UI_BLOCK_RADIAL) ||
- event->type != block->pie_data.event);
+ event->type != block->pie_data.event_type);
if (do_recursion) {
if (is_parent_inside == false) {
@@ -10907,7 +10913,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata)
/* set last pie event to allow chained pie spawning */
if (block->flag & UI_BLOCK_RADIAL) {
- win->last_pie_event = block->pie_data.event;
+ win->pie_event_type_last = block->pie_data.event_type;
reset_pie = true;
}
@@ -10950,7 +10956,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata)
wmWindow *win = CTX_wm_window(C);
if (win) {
- win->last_pie_event = EVENT_NONE;
+ win->pie_event_type_last = EVENT_NONE;
}
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 3da66d45abd..1d4a44e0c76 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -31,6 +31,10 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct ARegion;
struct AnimationEvalContext;
struct CurveMapping;
@@ -316,6 +320,12 @@ typedef struct uiButSearch {
struct PointerRNA rnasearchpoin;
struct PropertyRNA *rnasearchprop;
+
+ /**
+ * The search box only provides suggestions, it does not force
+ * the string to match one of the search items when applying.
+ */
+ bool results_are_suggestions;
} uiButSearch;
/** Derived struct for #UI_BTYPE_DECORATOR */
@@ -414,8 +424,8 @@ struct PieMenuData {
float last_pos[2];
double duration_gesture;
int flags;
- /** initial event used to fire the pie menu, store here so we can query for release */
- int event;
+ /** Initial event used to fire the pie menu, store here so we can query for release */
+ short event_type;
float alphafac;
};
@@ -1193,10 +1203,15 @@ typedef struct uiRNACollectionSearch {
void ui_rna_collection_search_update_fn(const struct bContext *C,
void *arg,
const char *str,
- uiSearchItems *items);
+ uiSearchItems *items,
+ const bool is_first);
/* interface_ops.c */
bool ui_jump_to_target_button_poll(struct bContext *C);
/* interface_queries.c */
void ui_interface_tag_script_reload_queries(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index 81c627816b9..05aa139e055 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -122,26 +122,26 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co
* it is always assumed to be click style */
if (event->type == LEFTMOUSE || ELEM(event->val, KM_RELEASE, KM_CLICK)) {
pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE;
- pie->block_radial->pie_data.event = EVENT_NONE;
- win->lock_pie_event = EVENT_NONE;
+ pie->block_radial->pie_data.event_type = EVENT_NONE;
+ win->pie_event_type_lock = EVENT_NONE;
}
else {
- if (win->last_pie_event != EVENT_NONE) {
+ if (win->pie_event_type_last != EVENT_NONE) {
/* original pie key has been released, so don't propagate the event */
- if (win->lock_pie_event == EVENT_NONE) {
+ if (win->pie_event_type_lock == EVENT_NONE) {
event_type = EVENT_NONE;
pie->block_radial->pie_data.flags |= UI_PIE_CLICK_STYLE;
}
else {
- event_type = win->last_pie_event;
+ event_type = win->pie_event_type_last;
}
}
else {
event_type = event->type;
}
- pie->block_radial->pie_data.event = event_type;
- win->lock_pie_event = event_type;
+ pie->block_radial->pie_data.event_type = event_type;
+ win->pie_event_type_lock = event_type;
}
pie->layout = UI_block_layout(
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index 2c07f5c3c03..12044863b8c 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -468,7 +468,8 @@ static void ui_searchbox_update_fn(bContext *C,
wmWindow *win = CTX_wm_window(C);
WM_tooltip_clear(C, win);
}
- search_but->items_update_fn(C, search_but->arg, str, items);
+ const bool is_first_search = !search_but->but.changed;
+ search_but->items_update_fn(C, search_but->arg, str, items, is_first_search);
}
/* region is the search box itself */
@@ -1052,14 +1053,16 @@ void ui_but_search_refresh(uiButSearch *search_but)
ui_searchbox_update_fn(but->block->evil_C, search_but, but->drawstr, items);
- /* Only red-alert when we are sure of it, this can miss cases when >10 matches. */
- if (items->totitem == 0) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
- else if (items->more == 0) {
- if (UI_search_items_find_index(items, but->drawstr) == -1) {
+ if (!search_but->results_are_suggestions) {
+ /* Only red-alert when we are sure of it, this can miss cases when >10 matches. */
+ if (items->totitem == 0) {
UI_but_flag_enable(but, UI_BUT_REDALERT);
}
+ else if (items->more == 0) {
+ if (UI_search_items_find_index(items, but->drawstr) == -1) {
+ UI_but_flag_enable(but, UI_BUT_REDALERT);
+ }
+ }
}
for (x1 = 0; x1 < items->maxitem; x1++) {
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c
index 25cf2e12377..e1f8f63dcbf 100644
--- a/source/blender/editors/interface/interface_template_search_menu.c
+++ b/source/blender/editors/interface/interface_template_search_menu.c
@@ -990,7 +990,8 @@ static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
static void menu_search_update_fn(const bContext *UNUSED(C),
void *arg,
const char *str,
- uiSearchItems *items)
+ uiSearchItems *items,
+ const bool UNUSED(is_first))
{
struct MenuSearch_Data *data = arg;
diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c
index ff0f9a2e5cd..2c83f184ff0 100644
--- a/source/blender/editors/interface/interface_template_search_operator.c
+++ b/source/blender/editors/interface/interface_template_search_operator.c
@@ -59,7 +59,8 @@ static void operator_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
static void operator_search_update_fn(const bContext *C,
void *UNUSED(arg),
const char *str,
- uiSearchItems *items)
+ uiSearchItems *items,
+ const bool UNUSED(is_first))
{
GHashIterator iter;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 67446ca681f..c5e67e0334e 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -393,7 +393,8 @@ static bool id_search_add(const bContext *C, TemplateID *template_ui, uiSearchIt
static void id_search_cb(const bContext *C,
void *arg_template,
const char *str,
- uiSearchItems *items)
+ uiSearchItems *items,
+ const bool UNUSED(is_first))
{
TemplateID *template_ui = (TemplateID *)arg_template;
ListBase *lb = template_ui->idlb;
@@ -464,7 +465,8 @@ static void id_search_cb_tagged(const bContext *C,
static void id_search_cb_objects_from_scene(const bContext *C,
void *arg_template,
const char *str,
- uiSearchItems *items)
+ uiSearchItems *items,
+ const bool UNUSED(is_first))
{
TemplateID *template_ui = (TemplateID *)arg_template;
ListBase *lb = template_ui->idlb;
@@ -518,7 +520,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem)
static TemplateID template_ui;
PointerRNA active_item_ptr;
void (*id_search_update_fn)(
- const bContext *, void *, const char *, uiSearchItems *) = id_search_cb;
+ const bContext *, void *, const char *, uiSearchItems *, const bool) = id_search_cb;
/* arg_litem is malloced, can be freed by parent button */
template_ui = *((TemplateID *)arg_litem);
@@ -3985,7 +3987,7 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
BKE_curvemapping_changed(cumap, false);
break;
case UICURVE_FUNC_RESET_VIEW:
- cumap->curr = cumap->clipr;
+ BKE_curvemapping_reset_view(cumap);
break;
case UICURVE_FUNC_HANDLE_VECTOR: /* set vector */
BKE_curvemap_handle_set(cuma, HD_VECT);
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 5311bb57da9..877800c1ba2 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -405,7 +405,8 @@ static bool add_collection_search_item(CollItemSearch *cis,
void ui_rna_collection_search_update_fn(const struct bContext *C,
void *arg,
const char *str,
- uiSearchItems *items)
+ uiSearchItems *items,
+ const bool is_first)
{
uiRNACollectionSearch *data = arg;
const int flag = RNA_property_flag(data->target_prop);
@@ -415,7 +416,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
* match the RNA name exactly. So only for pointer properties, the name can be modified to add
* further UI hints. */
const bool requires_exact_data_name = !is_ptr_target;
- const bool skip_filter = data->search_but && !data->search_but->changed;
+ const bool skip_filter = is_first;
char name_buf[UI_MAX_DRAW_STR];
char *name;
bool has_id_icon = false;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 0fa5999976b..06b87dd857f 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1180,7 +1180,7 @@ void UI_widgetbase_draw_cache_flush(void)
/* draw single */
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
GPU_batch_uniform_4fv_array(
- batch, "parameters", MAX_WIDGET_PARAMETERS, (float(*)[4])g_widget_base_batch.params);
+ batch, "parameters", MAX_WIDGET_PARAMETERS, (const float(*)[4])g_widget_base_batch.params);
GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
GPU_batch_draw(batch);
}
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 66a7b97b440..340a7ae92ff 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -50,6 +50,7 @@
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_transform.h"
+#include "ED_util.h"
#include "ED_view3d.h"
#include "mesh_intern.h" /* own include */
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 9000a942e50..73d79805f60 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -46,6 +46,7 @@
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_transform.h"
+#include "ED_util.h"
#include "ED_view3d.h"
#include "mesh_intern.h" /* own include */
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 1f894ec0f1d..b5ec3f388a0 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -966,7 +966,7 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
float planes[4][4];
planes_from_projmat(
- (float(*)[4])kcd->projmat, planes[2], planes[0], planes[3], planes[1], NULL, NULL);
+ (const float(*)[4])kcd->projmat, planes[2], planes[0], planes[3], planes[1], NULL, NULL);
/* ray-cast all planes */
{
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 334afdfb2d9..88151b07fb9 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -1967,9 +1967,9 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op)
static int edbm_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
edbm_duplicate_exec(C, op);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
return OPERATOR_FINISHED;
}
@@ -4172,15 +4172,7 @@ static Base *mesh_separate_tagged(
}));
BM_mesh_elem_toolflags_ensure(bm_new); /* needed for 'duplicate' bmo */
- CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
- CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
- CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
- CustomData_copy(&bm_old->pdata, &bm_new->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
-
- CustomData_bmesh_init_pool(&bm_new->vdata, bm_mesh_allocsize_default.totvert, BM_VERT);
- CustomData_bmesh_init_pool(&bm_new->edata, bm_mesh_allocsize_default.totedge, BM_EDGE);
- CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP);
- CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE);
+ BM_mesh_copy_init_customdata(bm_new, bm_old, &bm_mesh_allocsize_default);
/* Take into account user preferences for duplicating actions. */
const eDupli_ID_Flags dupflag = USER_DUP_MESH | (U.dupflag & USER_DUP_ACT);
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 9618774eea8..a5cad4e087c 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -572,7 +572,7 @@ static int multiresbake_image_exec(bContext *C, wmOperator *op)
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
/* add modal handler for ESC */
WM_event_add_modal_handler(C, op);
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 9ec0c625f71..610551e8539 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -1897,7 +1897,7 @@ static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
/* add modal handler for ESC */
WM_event_add_modal_handler(C, op);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index da14d4ef52a..c774bc9f9cc 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1330,9 +1330,9 @@ static int object_clear_paths_exec(bContext *C, wmOperator *op)
}
/* operator callback/wrapper */
-static int object_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+static int object_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
+ if ((event->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
RNA_boolean_set(op->ptr, "only_selected", true);
}
return object_clear_paths_exec(C, op);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 5a2ef1c6556..e74d04ab17f 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -893,10 +893,10 @@ bool ED_object_parent_set(ReportList *reports,
reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
}
else if (partype == PAR_ARMATURE_AUTO) {
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
ED_object_vgroup_calc_from_armature(
reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
}
/* get corrected inverse */
ob->partype = PAROBJECT;
@@ -912,9 +912,9 @@ bool ED_object_parent_set(ReportList *reports,
ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_NAME);
}
else if (ELEM(partype, PAR_ARMATURE_AUTO, PAR_ARMATURE_ENVELOPE)) {
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_AUTO);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
}
/* get corrected inverse */
ob->partype = PAROBJECT;
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index b525d8a373e..1f59e361526 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -938,7 +938,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
}
/* handle UI stuff */
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
/* flush sculpt and editmode changes */
ED_editors_flush_edits_ex(bmain, true, false);
@@ -1058,7 +1058,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
/* we set G.is_rendering here already instead of only in the job, this ensure
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 32d4abcabd4..bfad79a1da9 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -1224,7 +1224,7 @@ static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *U
WM_jobs_start(wm, wm_job);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 2c71345699f..bd2b1c4c553 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -3516,297 +3516,6 @@ void ED_region_info_draw(ARegion *region,
ED_region_info_draw_multiline(region, text_array, fill_color, full_redraw);
}
-#define MAX_METADATA_STR 1024
-
-static const char *meta_data_list[] = {
- "File",
- "Strip",
- "Date",
- "RenderTime",
- "Note",
- "Marker",
- "Time",
- "Frame",
- "Camera",
- "Scene",
-};
-
-BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset)
-{
- return (IMB_metadata_get_field(
- ibuf->metadata, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) &&
- r_str[0]);
-}
-
-BLI_INLINE bool metadata_is_custom_drawable(const char *field)
-{
- /* Metadata field stored by Blender for multilayer EXR images. Is rather
- * useless to be viewed all the time. Can still be seen in the Metadata
- * panel. */
- if (STREQ(field, "BlenderMultiChannel")) {
- return false;
- }
- /* Is almost always has value "scanlineimage", also useless to be seen
- * all the time. */
- if (STREQ(field, "type")) {
- return false;
- }
- return !BKE_stamp_is_known_field(field);
-}
-
-typedef struct MetadataCustomDrawContext {
- int fontid;
- int xmin, ymin;
- int vertical_offset;
- int current_y;
-} MetadataCustomDrawContext;
-
-static void metadata_custom_draw_fields(const char *field, const char *value, void *ctx_v)
-{
- if (!metadata_is_custom_drawable(field)) {
- return;
- }
- MetadataCustomDrawContext *ctx = (MetadataCustomDrawContext *)ctx_v;
- char temp_str[MAX_METADATA_STR];
- BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: %s", field, value);
- BLF_position(ctx->fontid, ctx->xmin, ctx->ymin + ctx->current_y, 0.0f);
- BLF_draw(ctx->fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- ctx->current_y += ctx->vertical_offset;
-}
-
-static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const bool is_top)
-{
- char temp_str[MAX_METADATA_STR];
- int ofs_y = 0;
- const float height = BLF_height_max(fontid);
- const float margin = height / 8;
- const float vertical_offset = (height + margin);
-
- /* values taking margins into account */
- const float descender = BLF_descender(fontid);
- const float xmin = (rect->xmin + margin);
- const float xmax = (rect->xmax - margin);
- const float ymin = (rect->ymin + margin) - descender;
- const float ymax = (rect->ymax - margin) - descender;
-
- if (is_top) {
- for (int i = 0; i < 4; i++) {
- /* first line */
- if (i == 0) {
- bool do_newline = false;
- int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]);
- if (metadata_is_valid(ibuf, temp_str, 0, len)) {
- BLF_position(fontid, xmin, ymax - vertical_offset, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- do_newline = true;
- }
-
- len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]);
- if (metadata_is_valid(ibuf, temp_str, 1, len)) {
- int line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_position(fontid, xmax - line_width, ymax - vertical_offset, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- do_newline = true;
- }
-
- if (do_newline) {
- ofs_y += vertical_offset;
- }
- } /* Strip */
- else if (ELEM(i, 1, 2)) {
- int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
- if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
- BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- ofs_y += vertical_offset;
- }
- } /* Note (wrapped) */
- else if (i == 3) {
- int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
- if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
- struct ResultBLF info;
- BLF_enable(fontid, BLF_WORD_WRAP);
- BLF_wordwrap(fontid, ibuf->x - (margin * 2));
- BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
- BLF_draw_ex(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX, &info);
- BLF_wordwrap(fontid, 0);
- BLF_disable(fontid, BLF_WORD_WRAP);
- ofs_y += vertical_offset * info.lines;
- }
- }
- else {
- int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
- if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
- int line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_position(fontid, xmax - line_width, ymax - vertical_offset - ofs_y, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- ofs_y += vertical_offset;
- }
- }
- }
- }
- else {
- MetadataCustomDrawContext ctx;
- ctx.fontid = fontid;
- ctx.xmin = xmin;
- ctx.ymin = ymin;
- ctx.current_y = ofs_y;
- ctx.vertical_offset = vertical_offset;
- IMB_metadata_foreach(ibuf, metadata_custom_draw_fields, &ctx);
- int ofs_x = 0;
- ofs_y = ctx.current_y;
- for (int i = 5; i < 10; i++) {
- int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]);
- if (metadata_is_valid(ibuf, temp_str, i, len)) {
- BLF_position(fontid, xmin + ofs_x, ymin + ofs_y, 0.0f);
- BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
-
- ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X;
- }
- }
- }
-}
-
-typedef struct MetadataCustomCountContext {
- int count;
-} MetadataCustomCountContext;
-
-static void metadata_custom_count_fields(const char *field, const char *UNUSED(value), void *ctx_v)
-{
- if (!metadata_is_custom_drawable(field)) {
- return;
- }
- MetadataCustomCountContext *ctx = (MetadataCustomCountContext *)ctx_v;
- ctx->count++;
-}
-
-static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
-{
- const float height = BLF_height_max(fontid);
- const float margin = (height / 8);
- char str[MAX_METADATA_STR] = "";
- short count = 0;
-
- if (is_top) {
- if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) {
- count++;
- }
- for (int i = 2; i < 5; i++) {
- if (metadata_is_valid(ibuf, str, i, 0)) {
- if (i == 4) {
- struct {
- struct ResultBLF info;
- rctf rect;
- } wrap;
-
- BLF_enable(fontid, BLF_WORD_WRAP);
- BLF_wordwrap(fontid, ibuf->x - (margin * 2));
- BLF_boundbox_ex(fontid, str, sizeof(str), &wrap.rect, &wrap.info);
- BLF_wordwrap(fontid, 0);
- BLF_disable(fontid, BLF_WORD_WRAP);
-
- count += wrap.info.lines;
- }
- else {
- count++;
- }
- }
- }
- }
- else {
- for (int i = 5; i < 10; i++) {
- if (metadata_is_valid(ibuf, str, i, 0)) {
- count = 1;
- break;
- }
- }
- MetadataCustomCountContext ctx;
- ctx.count = 0;
- IMB_metadata_foreach(ibuf, metadata_custom_count_fields, &ctx);
- count += ctx.count;
- }
-
- if (count) {
- return (height + margin) * count;
- }
-
- return 0;
-}
-
-#undef MAX_METADATA_STR
-
-void ED_region_image_metadata_draw(
- int x, int y, ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy)
-{
- const uiStyle *style = UI_style_get_dpi();
-
- if (!ibuf->metadata) {
- return;
- }
-
- /* find window pixel coordinates of origin */
- GPU_matrix_push();
-
- /* offset and zoom using ogl */
- GPU_matrix_translate_2f(x, y);
- GPU_matrix_scale_2f(zoomx, zoomy);
-
- BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi);
-
- /* *** upper box*** */
-
- /* get needed box height */
- float box_y = metadata_box_height_get(ibuf, blf_mono_font, true);
-
- if (box_y) {
- /* set up rect */
- rctf rect;
- BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymax, frame->ymax + box_y);
- /* draw top box */
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_METADATA_BG);
- immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- immUnbindProgram();
-
- BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- BLF_enable(blf_mono_font, BLF_CLIPPING);
-
- UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
- metadata_draw_imbuf(ibuf, &rect, blf_mono_font, true);
-
- BLF_disable(blf_mono_font, BLF_CLIPPING);
- }
-
- /* *** lower box*** */
-
- box_y = metadata_box_height_get(ibuf, blf_mono_font, false);
-
- if (box_y) {
- /* set up box rect */
- rctf rect;
- BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymin - box_y, frame->ymin);
- /* draw top box */
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_METADATA_BG);
- immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- immUnbindProgram();
-
- BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- BLF_enable(blf_mono_font, BLF_CLIPPING);
-
- UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
- metadata_draw_imbuf(ibuf, &rect, blf_mono_font, false);
-
- BLF_disable(blf_mono_font, BLF_CLIPPING);
- }
-
- GPU_matrix_pop();
-}
-
typedef struct MetadataPanelDrawContext {
uiLayout *layout;
} MetadataPanelDrawContext;
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 5b426e827e7..e4996e8196b 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -62,10 +62,12 @@ set(SRC
sculpt_cloth.c
sculpt_detail.c
sculpt_dyntopo.c
+ sculpt_expand.c
sculpt_face_set.c
sculpt_filter_color.c
sculpt_filter_mask.c
sculpt_filter_mesh.c
+ sculpt_geodesic.c
sculpt_mask_expand.c
sculpt_multiplane_scrape.c
sculpt_paint_color.c
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 38810d6e131..c76fa01816b 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1626,6 +1626,16 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
paint_cursor_pose_brush_origins_draw(pcontext);
}
+ /* Expand operation origin. */
+ if (pcontext->ss->expand_cache) {
+ cursor_draw_point_screen_space(
+ pcontext->pos,
+ pcontext->region,
+ SCULPT_vertex_co_get(pcontext->ss, pcontext->ss->expand_cache->initial_active_vertex),
+ pcontext->vc.obact->obmat,
+ 2);
+ }
+
if (brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) {
paint_cursor_preview_boundary_data_update(pcontext, update_previews);
paint_cursor_preview_boundary_data_pivot_draw(pcontext);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index f4586fa130d..e1dc8fa30b9 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -1393,4 +1393,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
/* paint stroke */
keymap = paint_stroke_modal_keymap(keyconf);
WM_modalkeymap_assign(keymap, "SCULPT_OT_brush_stroke");
+
+ /* sculpt expand. */
+ sculpt_expand_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index b593b51c1e5..4bb9bcfdc0a 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1405,12 +1405,14 @@ void SCULPT_floodfill_add_initial(SculptFloodFill *flood, SculptVertRef index)
BLI_gsqueue_push(flood->queue, &index);
}
-void SCULPT_floodfill_add_initial_with_symmetry(Sculpt *sd,
- Object *ob,
- SculptSession *ss,
- SculptFloodFill *flood,
- SculptVertRef vertex,
- float radius)
+void SCULPT_floodfill_add_and_skip_initial(SculptFloodFill *flood, int index)
+{
+ BLI_gsqueue_push(flood->queue, &index);
+ BLI_BITMAP_ENABLE(flood->visited_vertices, index);
+}
+
+void SCULPT_floodfill_add_initial_with_symmetry(
+ Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, SculptVertRef index, float radius)
{
/* Add active vertex and symmetric vertices to the queue. */
const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
@@ -9543,7 +9545,7 @@ static bool SCULPT_connected_components_floodfill_cb(SculptSession *ss,
return true;
}
-static void sculpt_connected_components_ensure(Object *ob)
+void SCULPT_connected_components_ensure(Object *ob)
{
SculptSession *ss = ob->sculpt;
@@ -9622,7 +9624,7 @@ void SCULPT_fake_neighbors_ensure(Sculpt *sd, Object *ob, const float max_dist)
return;
}
- sculpt_connected_components_ensure(ob);
+ SCULPT_connected_components_ensure(ob);
SCULPT_fake_neighbor_init(ss, max_dist);
for (int i = 0; i < totvert; i++) {
@@ -10335,4 +10337,6 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_color_filter);
WM_operatortype_append(SCULPT_OT_mask_by_color);
WM_operatortype_append(SCULPT_OT_dyntopo_detail_size_edit);
+
+ WM_operatortype_append(SCULPT_OT_expand);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c
index 4636654c3a9..a92b14eb661 100644
--- a/source/blender/editors/sculpt_paint/sculpt_boundary.c
+++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c
@@ -555,11 +555,13 @@ SculptBoundary *SCULPT_boundary_data_init(Object *object,
SculptBoundary *boundary = MEM_callocN(sizeof(SculptBoundary), "Boundary edit data");
- const bool init_boundary_distances = brush->boundary_falloff_type !=
- BRUSH_BOUNDARY_FALLOFF_CONSTANT;
+ const bool init_boundary_distances = brush ? brush->boundary_falloff_type !=
+ BRUSH_BOUNDARY_FALLOFF_CONSTANT :
+ false;
+
sculpt_boundary_indices_init(ss, boundary, init_boundary_distances, boundary_initial_vertex);
- const float boundary_radius = radius * (1.0f + brush->boundary_offset);
+ const float boundary_radius = brush ? radius * (1.0f + brush->boundary_offset) : radius;
sculpt_boundary_edit_data_init(ss, boundary, boundary_initial_vertex, boundary_radius);
return boundary;
diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c
new file mode 100644
index 00000000000..892b30048f6
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_expand.c
@@ -0,0 +1,2291 @@
+/*
+ * 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) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_linklist_stack.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_ccg.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_image.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_multires.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_subdiv_ccg.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_view3d.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "IMB_colormanagement.h"
+#include "IMB_imbuf.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+/* Sculpt Expand. */
+/* Operator for creating selections and patterns in Sculpt Mode. Expand can create masks, face sets
+ * and fill vertex colors. */
+/* The main functionality of the operator
+ * - The operator initializes a value per vertex, called "falloff". There are multiple algorithms
+ * to generate these falloff values which will create different patterns in the result when using
+ * the operator. These falloff values require algorithms that rely on mesh connectivity, so they
+ * are only valid on parts of the mesh that are in the same connected component as the given
+ * initial vertices. If needed, these falloff values are propagated from vertex or grids into the
+ * base mesh faces.
+ *
+ * - On each modal callback, the operator gets the active vertex and face and gets its falloff
+ * value from its precalculated falloff. This is now the active falloff value.
+ * - Using the active falloff value and the settings of the expand operation (which can be modified
+ * during execution using the modal key-map), the operator loops over all elements in the mesh to
+ * check if they are enabled of not.
+ * - Based on each element state after evaluating the settings, the desired mesh data (mask, face
+ * sets, colors...) is updated.
+ */
+
+/**
+ * Used for defining an invalid vertex state (for example, when the cursor is not over the mesh).
+ */
+#define SCULPT_EXPAND_VERTEX_NONE -1
+
+/** Used for defining an uninitialized active component index for an unused symmetry pass. */
+#define EXPAND_ACTIVE_COMPONENT_NONE -1
+/**
+ * Defines how much each time the texture distortion is increased/decreased
+ * when using the modal key-map.
+ */
+#define SCULPT_EXPAND_TEXTURE_DISTORTION_STEP 0.01f
+
+/**
+ * This threshold offsets the required falloff value to start a new loop. This is needed because in
+ * some situations, vertices which have the same falloff value as max_falloff will start a new
+ * loop, which is undesired.
+ */
+#define SCULPT_EXPAND_LOOP_THRESHOLD 0.00001f
+
+/**
+ * Defines how much changes in curvature in the mesh affect the falloff shape when using normal
+ * falloff. This default was found experimentally and it works well in most cases, but can be
+ * exposed for tweaking if needed.
+ */
+#define SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY 300
+
+/* Expand Modal Key-map. */
+enum {
+ SCULPT_EXPAND_MODAL_CONFIRM = 1,
+ SCULPT_EXPAND_MODAL_CANCEL,
+ SCULPT_EXPAND_MODAL_INVERT,
+ SCULPT_EXPAND_MODAL_PRESERVE_TOGGLE,
+ SCULPT_EXPAND_MODAL_GRADIENT_TOGGLE,
+ SCULPT_EXPAND_MODAL_FALLOFF_CYCLE,
+ SCULPT_EXPAND_MODAL_RECURSION_STEP_GEODESIC,
+ SCULPT_EXPAND_MODAL_RECURSION_STEP_TOPOLOGY,
+ SCULPT_EXPAND_MODAL_MOVE_TOGGLE,
+ SCULPT_EXPAND_MODAL_FALLOFF_GEODESIC,
+ SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY,
+ SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY_DIAGONALS,
+ SCULPT_EXPAND_MODAL_FALLOFF_SPHERICAL,
+ SCULPT_EXPAND_MODAL_SNAP_TOGGLE,
+ SCULPT_EXPAND_MODAL_LOOP_COUNT_INCREASE,
+ SCULPT_EXPAND_MODAL_LOOP_COUNT_DECREASE,
+ SCULPT_EXPAND_MODAL_BRUSH_GRADIENT_TOGGLE,
+ SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_INCREASE,
+ SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_DECREASE,
+};
+
+/* Functions for getting the state of mesh elements (vertices and base mesh faces). When the main
+ * functions for getting the state of an element return true it means that data associated to that
+ * element will be modified by expand. */
+
+/**
+ * Returns true if the vertex is in a connected component with correctly initialized falloff
+ * values.
+ */
+static bool sculpt_expand_is_vert_in_active_component(SculptSession *ss,
+ ExpandCache *expand_cache,
+ const int v)
+{
+ for (int i = 0; i < EXPAND_SYMM_AREAS; i++) {
+ if (ss->vertex_info.connected_component[v] == expand_cache->active_connected_components[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Returns true if the face is in a connected component with correctly initialized falloff values.
+ */
+static bool sculpt_expand_is_face_in_active_component(SculptSession *ss,
+ ExpandCache *expand_cache,
+ const int f)
+{
+ const MLoop *loop = &ss->mloop[ss->mpoly[f].loopstart];
+ return sculpt_expand_is_vert_in_active_component(ss, expand_cache, loop->v);
+}
+
+/**
+ * Returns the falloff value of a vertex. This function includes texture distortion, which is not
+ * precomputed into the initial falloff values.
+ */
+static float sculpt_expand_falloff_value_vertex_get(SculptSession *ss,
+ ExpandCache *expand_cache,
+ const int v)
+{
+ if (expand_cache->texture_distortion_strength == 0.0f) {
+ return expand_cache->vert_falloff[v];
+ }
+
+ if (!expand_cache->brush->mtex.tex) {
+ return expand_cache->vert_falloff[v];
+ }
+
+ float rgba[4];
+ const float *vertex_co = SCULPT_vertex_co_get(ss, BKE_pbvh_table_index_to_vertex(ss->pbvh, v));
+ const float avg = BKE_brush_sample_tex_3d(
+ expand_cache->scene, expand_cache->brush, vertex_co, rgba, 0, ss->tex_pool);
+
+ const float distortion = (avg - 0.5f) * expand_cache->texture_distortion_strength *
+ expand_cache->max_vert_falloff;
+ return expand_cache->vert_falloff[v] + distortion;
+}
+
+/**
+ * Returns the maximum valid falloff value stored in the falloff array, taking the maximum possible
+ * texture distortion into account.
+ */
+static float sculpt_expand_max_vertex_falloff_get(ExpandCache *expand_cache)
+{
+ if (expand_cache->texture_distortion_strength == 0.0f) {
+ return expand_cache->max_vert_falloff;
+ }
+
+ if (!expand_cache->brush->mtex.tex) {
+ return expand_cache->max_vert_falloff;
+ }
+
+ return expand_cache->max_vert_falloff +
+ (0.5f * expand_cache->texture_distortion_strength * expand_cache->max_vert_falloff);
+}
+
+/**
+ * Main function to get the state of a vertex for the current state and settings of a #ExpandCache.
+ * Returns true when the target data should be modified by expand.
+ */
+static bool sculpt_expand_state_get(SculptSession *ss, ExpandCache *expand_cache, const int v)
+{
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, v);
+
+ if (!SCULPT_vertex_visible_get(ss, vref)) {
+ return false;
+ }
+
+ if (!sculpt_expand_is_vert_in_active_component(ss, expand_cache, v)) {
+ return false;
+ }
+
+ if (expand_cache->all_enabled) {
+ return true;
+ }
+
+ bool enabled = false;
+
+ if (expand_cache->snap) {
+ /* Face Sets are not being modified when using this function, so it is ok to get this directly
+ * from the Sculpt API instead of implementing a custom function to get them from
+ * expand_cache->original_face_sets. */
+ const int face_set = SCULPT_vertex_face_set_get(ss, vref);
+ enabled = BLI_gset_haskey(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set));
+ }
+ else {
+ const float max_falloff_factor = sculpt_expand_max_vertex_falloff_get(expand_cache);
+ const float loop_len = (max_falloff_factor / expand_cache->loop_count) +
+ SCULPT_EXPAND_LOOP_THRESHOLD;
+
+ const float vertex_falloff_factor = sculpt_expand_falloff_value_vertex_get(
+ ss, expand_cache, v);
+ const float active_factor = fmod(expand_cache->active_falloff, loop_len);
+ const float falloff_factor = fmod(vertex_falloff_factor, loop_len);
+
+ enabled = falloff_factor < active_factor;
+ }
+
+ if (expand_cache->invert) {
+ enabled = !enabled;
+ }
+ return enabled;
+}
+
+/**
+ * Main function to get the state of a face for the current state and settings of a #ExpandCache.
+ * Returns true when the target data should be modified by expand.
+ */
+static bool sculpt_expand_face_state_get(SculptSession *ss, ExpandCache *expand_cache, const int f)
+{
+ if (ss->face_sets[f] <= 0) {
+ return false;
+ }
+
+ if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, f)) {
+ return false;
+ }
+
+ if (expand_cache->all_enabled) {
+ return true;
+ }
+
+ bool enabled = false;
+
+ if (expand_cache->snap_enabled_face_sets) {
+ const int face_set = expand_cache->original_face_sets[f];
+ enabled = BLI_gset_haskey(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set));
+ }
+ else {
+ const float loop_len = (expand_cache->max_face_falloff / expand_cache->loop_count) +
+ SCULPT_EXPAND_LOOP_THRESHOLD;
+
+ const float active_factor = fmod(expand_cache->active_falloff, loop_len);
+ const float falloff_factor = fmod(expand_cache->face_falloff[f], loop_len);
+ enabled = falloff_factor < active_factor;
+ }
+
+ if (expand_cache->falloff_type == SCULPT_EXPAND_FALLOFF_ACTIVE_FACE_SET) {
+ if (ss->face_sets[f] == expand_cache->initial_active_face_set) {
+ enabled = false;
+ }
+ }
+
+ if (expand_cache->invert) {
+ enabled = !enabled;
+ }
+
+ return enabled;
+}
+
+/**
+ * For target modes that support gradients (such as sculpt masks or colors), this function returns
+ * the corresponding gradient value for an enabled vertex.
+ */
+static float sculpt_expand_gradient_value_get(SculptSession *ss,
+ ExpandCache *expand_cache,
+ const int v)
+{
+ if (!expand_cache->falloff_gradient) {
+ return 1.0f;
+ }
+
+ const float max_falloff_factor = sculpt_expand_max_vertex_falloff_get(expand_cache);
+ const float loop_len = (max_falloff_factor / expand_cache->loop_count) +
+ SCULPT_EXPAND_LOOP_THRESHOLD;
+
+ const float vertex_falloff_factor = sculpt_expand_falloff_value_vertex_get(ss, expand_cache, v);
+ const float active_factor = fmod(expand_cache->active_falloff, loop_len);
+ const float falloff_factor = fmod(vertex_falloff_factor, loop_len);
+
+ float linear_falloff;
+
+ if (expand_cache->invert) {
+ /* Active factor is the result of a modulus operation using loop_len, so they will never be
+ * equal and loop_len - active_factor should never be 0. */
+ BLI_assert((loop_len - active_factor) != 0.0f);
+ linear_falloff = (falloff_factor - active_factor) / (loop_len - active_factor);
+ }
+ else {
+ linear_falloff = 1.0f - (falloff_factor / active_factor);
+ }
+
+ if (!expand_cache->brush_gradient) {
+ return linear_falloff;
+ }
+
+ return BKE_brush_curve_strength(expand_cache->brush, linear_falloff, 1.0f);
+}
+
+/* Utility functions for getting all vertices state during expand. */
+
+/**
+ * Returns a bitmap indexed by vertex index which contains if the vertex was enabled or not for a
+ * give expand_cache state.
+ */
+static BLI_bitmap *sculpt_expand_bitmap_from_enabled(SculptSession *ss, ExpandCache *expand_cache)
+{
+ const int totvert = SCULPT_vertex_count_get(ss);
+ BLI_bitmap *enabled_vertices = BLI_BITMAP_NEW(totvert, "enabled vertices");
+ for (int i = 0; i < totvert; i++) {
+ const bool enabled = sculpt_expand_state_get(ss, expand_cache, i);
+ BLI_BITMAP_SET(enabled_vertices, i, enabled);
+ }
+ return enabled_vertices;
+}
+
+/**
+ * Returns a bitmap indexed by vertex index which contains if the vertex is in the boundary of the
+ * enabled vertices. This is defined as vertices that are enabled and at least have one connected
+ * vertex that is not enabled.
+ */
+static BLI_bitmap *sculpt_expand_boundary_from_enabled(SculptSession *ss,
+ const BLI_bitmap *enabled_vertices,
+ const bool use_mesh_boundary)
+{
+ const int totvert = SCULPT_vertex_count_get(ss);
+ BLI_bitmap *boundary_vertices = BLI_BITMAP_NEW(totvert, "boundary vertices");
+ for (int i = 0; i < totvert; i++) {
+ SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (!BLI_BITMAP_TEST(enabled_vertices, i)) {
+ continue;
+ }
+
+ bool is_expand_boundary = false;
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
+ if (!BLI_BITMAP_TEST(enabled_vertices, ni.index)) {
+ is_expand_boundary = true;
+ }
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+ if (use_mesh_boundary && SCULPT_vertex_is_boundary(ss, vertex)) {
+ is_expand_boundary = true;
+ }
+
+ BLI_BITMAP_SET(boundary_vertices, i, is_expand_boundary);
+ }
+
+ return boundary_vertices;
+}
+
+/* Functions implementing different algorithms for initializing falloff values. */
+
+/**
+ * Utility function to get the closet vertex after flipping an original vertex position based on
+ * an symmetry pass iteration index.
+ */
+static SculptVertRef sculpt_expand_get_vertex_index_for_symmetry_pass(Object *ob,
+ const char symm_it,
+ const SculptVertRef original_vertex)
+{
+ SculptSession *ss = ob->sculpt;
+ SculptVertRef symm_vertex = {SCULPT_EXPAND_VERTEX_NONE};
+
+ if (symm_it == 0) {
+ symm_vertex = original_vertex;
+ }
+ else {
+ float location[3];
+ flip_v3_v3(location, SCULPT_vertex_co_get(ss, original_vertex), symm_it);
+ symm_vertex = SCULPT_nearest_vertex_get(NULL, ob, location, FLT_MAX, false);
+ }
+ return symm_vertex;
+}
+
+/**
+ * Geodesic: Initializes the falloff with geodesic distances from the given active vertex, taking
+ * symmetry into account.
+ */
+static float *sculpt_expand_geodesic_falloff_create(Sculpt *sd, Object *ob, const int v)
+{
+ return SCULPT_geodesic_from_vertex_and_symm(sd, ob, v, FLT_MAX);
+}
+
+/**
+ * Topology: Initializes the falloff using a flood-fill operation,
+ * increasing the falloff value by 1 when visiting a new vertex.
+ */
+typedef struct ExpandFloodFillData {
+ float original_normal[3];
+ float edge_sensitivity;
+ float *dists;
+ float *edge_factor;
+} ExpandFloodFillData;
+
+static bool expand_topology_floodfill_cb(
+ SculptSession *ss, SculptVertRef from_v, SculptVertRef to_v, bool is_duplicate, void *userdata)
+{
+ ExpandFloodFillData *data = userdata;
+ int from_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_v);
+ int to_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_v);
+
+ if (!is_duplicate) {
+ const float to_it = data->dists[from_v_i] + 1.0f;
+ data->dists[to_v_i] = to_it;
+ }
+ else {
+ data->dists[to_v_i] = data->dists[from_v_i];
+ }
+ return true;
+}
+
+static float *sculpt_expand_topology_falloff_create(Sculpt *sd, Object *ob, const SculptVertRef v)
+{
+ SculptSession *ss = ob->sculpt;
+ const int totvert = SCULPT_vertex_count_get(ss);
+ float *dists = MEM_calloc_arrayN(sizeof(float), totvert, "topology dist");
+
+ SculptFloodFill flood;
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, v, FLT_MAX);
+
+ ExpandFloodFillData fdata;
+ fdata.dists = dists;
+
+ SCULPT_floodfill_execute(ss, &flood, expand_topology_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ return dists;
+}
+
+/**
+ * Normals: Flood-fills the mesh and reduces the falloff depending on the normal difference between
+ * each vertex and the previous one.
+ * This creates falloff patterns that follow and snap to the hard edges of the object.
+ */
+static bool mask_expand_normal_floodfill_cb(
+ SculptSession *ss, SculptVertRef from_v, SculptVertRef to_v, bool is_duplicate, void *userdata)
+{
+ ExpandFloodFillData *data = userdata;
+ int from_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_v);
+ int to_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_v);
+
+ if (!is_duplicate) {
+ float current_normal[3], prev_normal[3];
+ SCULPT_vertex_normal_get(ss, to_v, current_normal);
+ SCULPT_vertex_normal_get(ss, from_v, prev_normal);
+ const float from_edge_factor = data->edge_factor[from_v_i];
+ data->edge_factor[to_v_i] = dot_v3v3(current_normal, prev_normal) * from_edge_factor;
+ data->dists[to_v_i] = dot_v3v3(data->original_normal, current_normal) *
+ powf(from_edge_factor, data->edge_sensitivity);
+ CLAMP(data->dists[to_v_i], 0.0f, 1.0f);
+ }
+ else {
+ /* PBVH_GRIDS duplicate handling. */
+ data->edge_factor[to_v_i] = data->edge_factor[from_v_i];
+ data->dists[to_v_i] = data->dists[from_v_i];
+ }
+
+ return true;
+}
+
+static float *sculpt_expand_normal_falloff_create(Sculpt *sd,
+ Object *ob,
+ const SculptVertRef v,
+ const float edge_sensitivity)
+{
+ SculptSession *ss = ob->sculpt;
+ const int totvert = SCULPT_vertex_count_get(ss);
+ float *dists = MEM_malloc_arrayN(sizeof(float), totvert, "normal dist");
+ float *edge_factor = MEM_callocN(sizeof(float) * totvert, "mask edge factor");
+ for (int i = 0; i < totvert; i++) {
+ edge_factor[i] = 1.0f;
+ }
+
+ SculptFloodFill flood;
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, v, FLT_MAX);
+
+ ExpandFloodFillData fdata;
+ fdata.dists = dists;
+ fdata.edge_factor = edge_factor;
+ fdata.edge_sensitivity = edge_sensitivity;
+ SCULPT_vertex_normal_get(ss, v, fdata.original_normal);
+
+ SCULPT_floodfill_execute(ss, &flood, mask_expand_normal_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ for (int repeat = 0; repeat < 2; repeat++) {
+ for (int i = 0; i < totvert; i++) {
+ float avg = 0.0f;
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vref, ni) {
+ avg += dists[ni.index];
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ dists[i] = avg / ni.size;
+ }
+ }
+
+ MEM_SAFE_FREE(edge_factor);
+
+ return dists;
+}
+
+/**
+ * Spherical: Initializes the falloff based on the distance from a vertex, taking symmetry into
+ * account.
+ */
+static float *sculpt_expand_spherical_falloff_create(Object *ob, const SculptVertRef v)
+{
+ SculptSession *ss = ob->sculpt;
+ const int totvert = SCULPT_vertex_count_get(ss);
+
+ float *dists = MEM_malloc_arrayN(sizeof(float), totvert, "spherical dist");
+ for (int i = 0; i < totvert; i++) {
+ dists[i] = FLT_MAX;
+ }
+ const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
+
+ for (char symm_it = 0; symm_it <= symm; symm_it++) {
+ if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
+ continue;
+ }
+ const int symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(ob, symm_it, v);
+ if (symm_vertex != -1) {
+ const float *co = SCULPT_vertex_co_get(ss, symm_vertex);
+ for (int i = 0; i < totvert; i++) {
+ dists[i] = min_ff(dists[i], len_v3v3(co, SCULPT_vertex_co_get(ss, BKE_pbvh_table_index_to_vertex(ss->pbvh, i))));
+ }
+ }
+ }
+
+ return dists;
+}
+
+/**
+ * Boundary: This falloff mode uses the code from sculpt_boundary to initialize the closest mesh
+ * boundary to a falloff value of 0. Then, it propagates that falloff to the rest of the mesh so it
+ * stays parallel to the boundary, increasing the falloff value by 1 on each step.
+ */
+static float *sculpt_expand_boundary_topology_falloff_create(Object *ob, const SculptVertRef v)
+{
+ SculptSession *ss = ob->sculpt;
+ const int totvert = SCULPT_vertex_count_get(ss);
+ float *dists = MEM_calloc_arrayN(sizeof(float), totvert, "spherical dist");
+ BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(totvert, "visited vertices");
+ GSQueue *queue = BLI_gsqueue_new(sizeof(SculptVertRef));
+
+ /* Search and initialize a boundary per symmetry pass, then mark those vertices as visited. */
+ const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
+ for (char symm_it = 0; symm_it <= symm; symm_it++) {
+ if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
+ continue;
+ }
+
+ const SculptVertRef symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(ob, symm_it, v);
+
+ SculptBoundary *boundary = SCULPT_boundary_data_init(ob, NULL, symm_vertex, FLT_MAX);
+ if (!boundary) {
+ continue;
+ }
+
+ for (int i = 0; i < boundary->num_vertices; i++) {
+ BLI_gsqueue_push(queue, &boundary->vertices[i]);
+ BLI_BITMAP_ENABLE(visited_vertices, boundary->vertices[i]);
+ }
+ SCULPT_boundary_data_free(boundary);
+ }
+
+ /* If there are no boundaries, return a falloff with all values set to 0. */
+ if (BLI_gsqueue_is_empty(queue)) {
+ return dists;
+ }
+
+ /* Propagate the values from the boundaries to the rest of the mesh. */
+ while (!BLI_gsqueue_is_empty(queue)) {
+ SculptVertRef v_next;
+ BLI_gsqueue_pop(queue, &v_next);
+
+ SculptVertexNeighborIter ni;
+ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v_next, ni) {
+ if (BLI_BITMAP_TEST(visited_vertices, ni.index)) {
+ continue;
+ }
+
+ const int v_next_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, v_next);
+
+ dists[ni.index] = dists[v_next_i] + 1.0f;
+ BLI_BITMAP_ENABLE(visited_vertices, ni.index);
+ BLI_gsqueue_push(queue, &ni.index);
+ }
+ SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+ }
+
+ BLI_gsqueue_free(queue);
+ MEM_freeN(visited_vertices);
+ return dists;
+}
+
+/**
+ * Topology diagonals. This falloff is similar to topology, but it also considers the diagonals of
+ * the base mesh faces when checking a vertex neighbor. For this reason, this is not implement
+ * using the general flood-fill and sculpt neighbors accessors.
+ */
+static float *sculpt_expand_diagonals_falloff_create(Object *ob, const SculptVertRef v)
+{
+ SculptSession *ss = ob->sculpt;
+ const int totvert = SCULPT_vertex_count_get(ss);
+ float *dists = MEM_calloc_arrayN(sizeof(float), totvert, "spherical dist");
+
+ /* This algorithm uses mesh data (polys and loops), so this falloff type can't be initialized for
+ * Multires. It also does not make sense to implement it for dyntopo as the result will be the
+ * same as Topology falloff. */
+ if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
+ return dists;
+ }
+
+ /* Search and mask as visited the initial vertices using the enabled symmetry passes. */
+ BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(totvert, "visited vertices");
+ GSQueue *queue = BLI_gsqueue_new(sizeof(SculptVertRef));
+ const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
+ for (char symm_it = 0; symm_it <= symm; symm_it++) {
+ if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
+ continue;
+ }
+
+ const SculptVertRef symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(ob, symm_it, v);
+
+ BLI_gsqueue_push(queue, &symm_vertex);
+ BLI_BITMAP_ENABLE(visited_vertices, symm_vertex);
+ }
+
+ if (BLI_gsqueue_is_empty(queue)) {
+ return dists;
+ }
+
+ /* Propagate the falloff increasing the value by 1 each time a new vertex is visited. */
+ Mesh *mesh = ob->data;
+ while (!BLI_gsqueue_is_empty(queue)) {
+ SculptVertRef v_next;
+ BLI_gsqueue_pop(queue, &v_next);
+
+ int v_next_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, v_next);
+
+ for (int j = 0; j < ss->pmap[v_next_i].count; j++) {
+ MPoly *p = &ss->mpoly[ss->pmap[v_next_i].indices[j]];
+ for (int l = 0; l < p->totloop; l++) {
+ const int neighbor_v = mesh->mloop[p->loopstart + l].v;
+
+ if (BLI_BITMAP_TEST(visited_vertices, neighbor_v)) {
+ continue;
+ }
+
+ dists[neighbor_v] = dists[v_next_i] + 1.0f;
+ BLI_BITMAP_ENABLE(visited_vertices, neighbor_v);
+ BLI_gsqueue_push(queue, &neighbor_v);
+ }
+ }
+ }
+
+ BLI_gsqueue_free(queue);
+ MEM_freeN(visited_vertices);
+ return dists;
+}
+
+/* Functions to update the max_falloff value in the #ExpandCache. These functions are called after
+ * initializing a new falloff to make sure that this value is always updated. */
+
+/**
+ * Updates the max_falloff value for vertices in a #ExpandCache based on the current values of the
+ * falloff, skipping any invalid values initialized to FLT_MAX and not initialized components.
+ */
+static void sculpt_expand_update_max_vert_falloff_value(SculptSession *ss,
+ ExpandCache *expand_cache)
+{
+ const int totvert = SCULPT_vertex_count_get(ss);
+ expand_cache->max_vert_falloff = -FLT_MAX;
+ for (int i = 0; i < totvert; i++) {
+ if (expand_cache->vert_falloff[i] == FLT_MAX) {
+ continue;
+ }
+
+ if (!sculpt_expand_is_vert_in_active_component(ss, expand_cache, i)) {
+ continue;
+ }
+
+ expand_cache->max_vert_falloff = max_ff(expand_cache->max_vert_falloff,
+ expand_cache->vert_falloff[i]);
+ }
+}
+
+/**
+ * Updates the max_falloff value for faces in a ExpandCache based on the current values of the
+ * falloff, skipping any invalid values initialized to FLT_MAX and not initialized components.
+ */
+static void sculpt_expand_update_max_face_falloff_factor(SculptSession *ss,
+ ExpandCache *expand_cache)
+{
+ const int totface = ss->totfaces;
+ expand_cache->max_face_falloff = -FLT_MAX;
+ for (int i = 0; i < totface; i++) {
+ if (expand_cache->face_falloff[i] == FLT_MAX) {
+ continue;
+ }
+
+ if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
+ continue;
+ }
+
+ expand_cache->max_face_falloff = max_ff(expand_cache->max_face_falloff,
+ expand_cache->face_falloff[i]);
+ }
+}
+
+/**
+ * Functions to get falloff values for faces from the values from the vertices. This is used for
+ * expanding Face Sets. Depending on the data type of the #SculptSession, this needs to get the per
+ * face falloff value from the connected vertices of each face or from the grids stored per loops
+ * for each face.
+ */
+static void sculpt_expand_grids_to_faces_falloff(SculptSession *ss,
+ Mesh *mesh,
+ ExpandCache *expand_cache)
+{
+
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+
+ for (int p = 0; p < mesh->totpoly; p++) {
+ MPoly *poly = &mesh->mpoly[p];
+ float accum = 0.0f;
+ for (int l = 0; l < poly->totloop; l++) {
+ const int grid_loop_index = (poly->loopstart + l) * key->grid_area;
+ for (int g = 0; g < key->grid_area; g++) {
+ accum += expand_cache->vert_falloff[grid_loop_index + g];
+ }
+ }
+ expand_cache->face_falloff[p] = accum / (poly->totloop * key->grid_area);
+ }
+}
+
+static void sculpt_expand_vertex_to_faces_falloff(Mesh *mesh, ExpandCache *expand_cache)
+{
+ for (int p = 0; p < mesh->totpoly; p++) {
+ MPoly *poly = &mesh->mpoly[p];
+ float accum = 0.0f;
+ for (int l = 0; l < poly->totloop; l++) {
+ MLoop *loop = &mesh->mloop[l + poly->loopstart];
+ accum += expand_cache->vert_falloff[loop->v];
+ }
+ expand_cache->face_falloff[p] = accum / poly->totloop;
+ }
+}
+
+/**
+ * Main function to update the faces falloff from a already calculated vertex falloff.
+ */
+static void sculpt_expand_mesh_face_falloff_from_vertex_falloff(SculptSession *ss,
+ Mesh *mesh,
+ ExpandCache *expand_cache)
+{
+ BLI_assert(expand_cache->vert_falloff != NULL);
+
+ if (!expand_cache->face_falloff) {
+ expand_cache->face_falloff = MEM_malloc_arrayN(
+ mesh->totpoly, sizeof(float), "face falloff factors");
+ }
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
+ sculpt_expand_vertex_to_faces_falloff(mesh, expand_cache);
+ }
+ else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
+ sculpt_expand_grids_to_faces_falloff(ss, mesh, expand_cache);
+ }
+ else {
+ BLI_assert(false);
+ }
+}
+
+/* Recursions. These functions will generate new falloff values based on the state of the vertices
+ * from the current ExpandCache options and falloff values. */
+
+/**
+ * Geodesic recursion: Initializes falloff values using geodesic distances from the boundary of the
+ * current vertices state.
+ */
+static void sculpt_expand_geodesics_from_state_boundary(Object *ob,
+ ExpandCache *expand_cache,
+ BLI_bitmap *enabled_vertices)
+{
+ SculptSession *ss = ob->sculpt;
+ BLI_assert(BKE_pbvh_type(ss->pbvh) == PBVH_FACES);
+
+ GSet *initial_vertices = BLI_gset_int_new("initial_vertices");
+ BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(ss, enabled_vertices, false);
+ const int totvert = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totvert; i++) {
+ if (!BLI_BITMAP_TEST(boundary_vertices, i)) {
+ continue;
+ }
+ BLI_gset_add(initial_vertices, POINTER_FROM_INT(i));
+ }
+ MEM_freeN(boundary_vertices);
+
+ MEM_SAFE_FREE(expand_cache->vert_falloff);
+ MEM_SAFE_FREE(expand_cache->face_falloff);
+
+ expand_cache->vert_falloff = SCULPT_geodesic_distances_create(ob, initial_vertices, FLT_MAX);
+ BLI_gset_free(initial_vertices, NULL);
+}
+
+/**
+ * Topology recursion: Initializes falloff values using topology steps from the boundary of the
+ * current vertices state, increasing the value by 1 each time a new vertex is visited.
+ */
+static void sculpt_expand_topology_from_state_boundary(Object *ob,
+ ExpandCache *expand_cache,
+ BLI_bitmap *enabled_vertices)
+{
+ MEM_SAFE_FREE(expand_cache->vert_falloff);
+ MEM_SAFE_FREE(expand_cache->face_falloff);
+
+ SculptSession *ss = ob->sculpt;
+ const int totvert = SCULPT_vertex_count_get(ss);
+
+ float *dists = MEM_calloc_arrayN(sizeof(float), totvert, "topology dist");
+ BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(ss, enabled_vertices, false);
+
+ SculptFloodFill flood;
+ SCULPT_floodfill_init(ss, &flood);
+ for (int i = 0; i < totvert; i++) {
+ if (!BLI_BITMAP_TEST(boundary_vertices, i)) {
+ continue;
+ }
+ SCULPT_floodfill_add_and_skip_initial(&flood, i);
+ }
+ MEM_freeN(boundary_vertices);
+
+ ExpandFloodFillData fdata;
+ fdata.dists = dists;
+ SCULPT_floodfill_execute(ss, &flood, expand_topology_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ expand_cache->vert_falloff = dists;
+}
+
+/**
+ * Main function to create a recursion step from the current #ExpandCache state.
+ */
+static void sculpt_expand_resursion_step_add(Object *ob,
+ ExpandCache *expand_cache,
+ const eSculptExpandRecursionType recursion_type)
+{
+ SculptSession *ss = ob->sculpt;
+ if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
+ return;
+ }
+
+ BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache);
+
+ /* Each time a new recursion step is created, reset the distortion strength. This is the expected
+ * result from the recursion, as otherwise the new falloff will render with undesired distortion
+ * from the beginning. */
+ expand_cache->texture_distortion_strength = 0.0f;
+
+ switch (recursion_type) {
+ case SCULPT_EXPAND_RECURSION_GEODESICS:
+ sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_vertices);
+ break;
+ case SCULPT_EXPAND_RECURSION_TOPOLOGY:
+ sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_vertices);
+ break;
+ }
+
+ sculpt_expand_update_max_vert_falloff_value(ss, expand_cache);
+ if (expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
+ sculpt_expand_mesh_face_falloff_from_vertex_falloff(ss, ob->data, expand_cache);
+ sculpt_expand_update_max_face_falloff_factor(ss, expand_cache);
+ }
+
+ MEM_freeN(enabled_vertices);
+}
+
+/* Face Set Boundary falloff. */
+
+/**
+ * When internal falloff is set to true, the falloff will fill the active Face Set with a gradient,
+ * otherwise the active Face Set will be filled with a constant falloff of 0.0f.
+ */
+static void sculpt_expand_initialize_from_face_set_boundary(Object *ob,
+ ExpandCache *expand_cache,
+ const int active_face_set,
+ const bool internal_falloff)
+{
+ SculptSession *ss = ob->sculpt;
+ const int totvert = SCULPT_vertex_count_get(ss);
+
+ BLI_bitmap *enabled_vertices = BLI_BITMAP_NEW(totvert, "enabled vertices");
+ for (int i = 0; i < totvert; i++) {
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (!SCULPT_vertex_has_unique_face_set(ss, vref)) {
+ continue;
+ }
+ if (!SCULPT_vertex_has_face_set(ss, vref, active_face_set)) {
+ continue;
+ }
+ BLI_BITMAP_ENABLE(enabled_vertices, i);
+ }
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
+ sculpt_expand_geodesics_from_state_boundary(ob, expand_cache, enabled_vertices);
+ }
+ else {
+ sculpt_expand_topology_from_state_boundary(ob, expand_cache, enabled_vertices);
+ }
+
+ MEM_freeN(enabled_vertices);
+
+ if (internal_falloff) {
+ for (int i = 0; i < totvert; i++) {
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (!(SCULPT_vertex_has_face_set(ss, vref, active_face_set) &&
+ SCULPT_vertex_has_unique_face_set(ss, vref))) {
+ continue;
+ }
+ expand_cache->vert_falloff[i] *= -1.0f;
+ }
+
+ float min_factor = FLT_MAX;
+ for (int i = 0; i < totvert; i++) {
+ min_factor = min_ff(expand_cache->vert_falloff[i], min_factor);
+ }
+
+ const float additional_falloff = fabsf(min_factor);
+ for (int i = 0; i < totvert; i++) {
+ expand_cache->vert_falloff[i] += additional_falloff;
+ }
+ }
+ else {
+ for (int i = 0; i < totvert; i++) {
+ SculptVertRef vref = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
+
+ if (!SCULPT_vertex_has_face_set(ss, vref, active_face_set)) {
+ continue;
+ }
+ expand_cache->vert_falloff[i] = 0.0f;
+ }
+ }
+}
+
+/**
+ * Main function to initialize new falloff values in a #ExpandCache given an initial vertex and a
+ * falloff type.
+ */
+static void sculpt_expand_falloff_factors_from_vertex_and_symm_create(
+ ExpandCache *expand_cache,
+ Sculpt *sd,
+ Object *ob,
+ const int v,
+ eSculptExpandFalloffType falloff_type)
+{
+ MEM_SAFE_FREE(expand_cache->vert_falloff);
+ expand_cache->falloff_type = falloff_type;
+
+ SculptSession *ss = ob->sculpt;
+ const bool has_topology_info = BKE_pbvh_type(ss->pbvh) == PBVH_FACES;
+
+ switch (falloff_type) {
+ case SCULPT_EXPAND_FALLOFF_GEODESIC:
+ expand_cache->vert_falloff = has_topology_info ?
+ sculpt_expand_geodesic_falloff_create(sd, ob, v) :
+ sculpt_expand_spherical_falloff_create(ob, v);
+ break;
+ case SCULPT_EXPAND_FALLOFF_TOPOLOGY:
+ expand_cache->vert_falloff = sculpt_expand_topology_falloff_create(sd, ob, v);
+ break;
+ case SCULPT_EXPAND_FALLOFF_TOPOLOGY_DIAGONALS:
+ expand_cache->vert_falloff = has_topology_info ?
+ sculpt_expand_diagonals_falloff_create(ob, v) :
+ sculpt_expand_topology_falloff_create(sd, ob, v);
+ break;
+ case SCULPT_EXPAND_FALLOFF_NORMALS:
+ expand_cache->vert_falloff = sculpt_expand_normal_falloff_create(
+ sd, ob, v, SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY);
+ break;
+ case SCULPT_EXPAND_FALLOFF_SPHERICAL:
+ expand_cache->vert_falloff = sculpt_expand_spherical_falloff_create(ob, v);
+ break;
+ case SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY:
+ expand_cache->vert_falloff = sculpt_expand_boundary_topology_falloff_create(ob, v);
+ break;
+ case SCULPT_EXPAND_FALLOFF_BOUNDARY_FACE_SET:
+ sculpt_expand_initialize_from_face_set_boundary(
+ ob, expand_cache, expand_cache->initial_active_face_set, true);
+ break;
+ case SCULPT_EXPAND_FALLOFF_ACTIVE_FACE_SET:
+ sculpt_expand_initialize_from_face_set_boundary(
+ ob, expand_cache, expand_cache->initial_active_face_set, false);
+ break;
+ }
+
+ /* Update max falloff values and propagate to base mesh faces if needed. */
+ sculpt_expand_update_max_vert_falloff_value(ss, expand_cache);
+ if (expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
+ sculpt_expand_mesh_face_falloff_from_vertex_falloff(ss, ob->data, expand_cache);
+ sculpt_expand_update_max_face_falloff_factor(ss, expand_cache);
+ }
+}
+
+/**
+ * Adds to the snapping Face Set `gset` all Face Sets which contain all enabled vertices for the
+ * current #ExpandCache state. This improves the usability of snapping, as already enabled elements
+ * won't switch their state when toggling snapping with the modal key-map.
+ */
+static void sculpt_expand_snap_initialize_from_enabled(SculptSession *ss,
+ ExpandCache *expand_cache)
+{
+ if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
+ return;
+ }
+
+ /* Make sure this code runs with snapping and invert disabled. This simplifies the code and
+ * prevents using this function with snapping already enabled. */
+ const bool prev_snap_state = expand_cache->snap;
+ const bool prev_invert_state = expand_cache->invert;
+ expand_cache->snap = false;
+ expand_cache->invert = false;
+
+ BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache);
+
+ const int totface = ss->totfaces;
+ for (int i = 0; i < totface; i++) {
+ const int face_set = expand_cache->original_face_sets[i];
+ BLI_gset_add(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set));
+ }
+
+ for (int p = 0; p < totface; p++) {
+ MPoly *poly = &ss->mpoly[p];
+ bool any_disabled = false;
+ for (int l = 0; l < poly->totloop; l++) {
+ MLoop *loop = &ss->mloop[l + poly->loopstart];
+ if (!BLI_BITMAP_TEST(enabled_vertices, loop->v)) {
+ any_disabled = true;
+ break;
+ }
+ }
+ if (any_disabled) {
+ const int face_set = expand_cache->original_face_sets[p];
+ BLI_gset_remove(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(face_set), NULL);
+ }
+ }
+
+ MEM_freeN(enabled_vertices);
+ expand_cache->snap = prev_snap_state;
+ expand_cache->invert = prev_invert_state;
+}
+
+/**
+ * Functions to free a #ExpandCache.
+ */
+static void sculpt_expand_cache_data_free(ExpandCache *expand_cache)
+{
+ if (expand_cache->snap_enabled_face_sets) {
+ BLI_gset_free(expand_cache->snap_enabled_face_sets, NULL);
+ }
+ MEM_SAFE_FREE(expand_cache->nodes);
+ MEM_SAFE_FREE(expand_cache->vert_falloff);
+ MEM_SAFE_FREE(expand_cache->face_falloff);
+ MEM_SAFE_FREE(expand_cache->original_mask);
+ MEM_SAFE_FREE(expand_cache->original_face_sets);
+ MEM_SAFE_FREE(expand_cache->initial_face_sets);
+ MEM_SAFE_FREE(expand_cache->original_colors);
+ MEM_SAFE_FREE(expand_cache);
+}
+
+static void sculpt_expand_cache_free(SculptSession *ss)
+{
+ sculpt_expand_cache_data_free(ss->expand_cache);
+ /* Needs to be set to NULL as the paint cursor relies on checking this pointer detecting if an
+ * expand operation is running. */
+ ss->expand_cache = NULL;
+}
+
+/**
+ * Functions to restore the original state from the #ExpandCache when canceling the operator.
+ */
+static void sculpt_expand_restore_face_set_data(SculptSession *ss, ExpandCache *expand_cache)
+{
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ for (int n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
+ BKE_pbvh_node_mark_redraw(node);
+ }
+ MEM_freeN(nodes);
+ for (int i = 0; i < ss->totfaces; i++) {
+ ss->face_sets[i] = expand_cache->original_face_sets[i];
+ }
+}
+
+static void sculpt_expand_restore_color_data(SculptSession *ss, ExpandCache *expand_cache)
+{
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ for (int n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ copy_v4_v4(vd.col, expand_cache->original_colors[vd.index]);
+ }
+ BKE_pbvh_vertex_iter_end;
+ BKE_pbvh_node_mark_redraw(node);
+ }
+ MEM_freeN(nodes);
+}
+
+static void sculpt_expand_restore_mask_data(SculptSession *ss, ExpandCache *expand_cache)
+{
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ for (int n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ *vd.mask = expand_cache->original_mask[vd.index];
+ }
+ BKE_pbvh_vertex_iter_end;
+ BKE_pbvh_node_mark_redraw(node);
+ }
+ MEM_freeN(nodes);
+}
+
+/* Main function to restore the original state of the data to how it was before starting the expand
+ * operation. */
+static void sculpt_expand_restore_original_state(bContext *C,
+ Object *ob,
+ ExpandCache *expand_cache)
+{
+
+ SculptSession *ss = ob->sculpt;
+ switch (expand_cache->target) {
+ case SCULPT_EXPAND_TARGET_MASK:
+ sculpt_expand_restore_mask_data(ss, expand_cache);
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
+ SCULPT_tag_update_overlays(C);
+ break;
+ case SCULPT_EXPAND_TARGET_FACE_SETS:
+ sculpt_expand_restore_face_set_data(ss, expand_cache);
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
+ SCULPT_tag_update_overlays(C);
+ break;
+ case SCULPT_EXPAND_TARGET_COLORS:
+ sculpt_expand_restore_color_data(ss, expand_cache);
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_COLOR);
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR);
+ break;
+ }
+}
+
+/**
+ * Cancel operator callback.
+ */
+static void sculpt_expand_cancel(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+
+ sculpt_expand_restore_original_state(C, ob, ss->expand_cache);
+
+ SCULPT_undo_push_end();
+ sculpt_expand_cache_free(ss);
+}
+
+/* Functions to update the sculpt mesh data. */
+
+/**
+ * Callback to update mask data per PBVH node.
+ */
+static void sculpt_expand_mask_update_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+ ExpandCache *expand_cache = ss->expand_cache;
+
+ bool any_changed = false;
+
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
+ {
+ const float initial_mask = *vd.mask;
+ const bool enabled = sculpt_expand_state_get(ss, expand_cache, vd.index);
+
+ float new_mask;
+
+ if (enabled) {
+ new_mask = sculpt_expand_gradient_value_get(ss, expand_cache, vd.index);
+ }
+ else {
+ new_mask = 0.0f;
+ }
+
+ if (expand_cache->preserve) {
+ new_mask = max_ff(new_mask, expand_cache->original_mask[vd.index]);
+ }
+
+ if (new_mask == initial_mask) {
+ continue;
+ }
+
+ *vd.mask = clamp_f(new_mask, 0.0f, 1.0f);
+ any_changed = true;
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ if (any_changed) {
+ BKE_pbvh_node_mark_update_mask(node);
+ }
+}
+
+/**
+ * Update Face Set data. Not multi-threaded per node as nodes don't contain face arrays.
+ */
+static void sculpt_expand_face_sets_update(SculptSession *ss, ExpandCache *expand_cache)
+{
+ const int totface = ss->totfaces;
+ for (int f = 0; f < totface; f++) {
+ const bool enabled = sculpt_expand_face_state_get(ss, expand_cache, f);
+ if (!enabled) {
+ continue;
+ }
+ if (expand_cache->preserve) {
+ ss->face_sets[f] += expand_cache->next_face_set;
+ }
+ else {
+ ss->face_sets[f] = expand_cache->next_face_set;
+ }
+ }
+
+ for (int i = 0; i < expand_cache->totnode; i++) {
+ BKE_pbvh_node_mark_redraw(ss->expand_cache->nodes[i]);
+ }
+}
+
+/**
+ * Callback to update vertex colors per PBVH node.
+ */
+static void sculpt_expand_colors_update_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+ ExpandCache *expand_cache = ss->expand_cache;
+
+ bool any_changed = false;
+
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
+ {
+ float initial_color[4];
+ copy_v4_v4(initial_color, vd.col);
+
+ const bool enabled = sculpt_expand_state_get(ss, expand_cache, vd.index);
+ float fade;
+
+ if (enabled) {
+ fade = sculpt_expand_gradient_value_get(ss, expand_cache, vd.index);
+ }
+ else {
+ fade = 0.0f;
+ }
+
+ fade *= 1.0f - *vd.mask;
+ fade = clamp_f(fade, 0.0f, 1.0f);
+
+ float final_color[4];
+ float final_fill_color[4];
+ mul_v4_v4fl(final_fill_color, expand_cache->fill_color, fade);
+ IMB_blend_color_float(final_color,
+ expand_cache->original_colors[vd.index],
+ final_fill_color,
+ expand_cache->blend_mode);
+
+ if (equals_v4v4(initial_color, final_color)) {
+ continue;
+ }
+
+ copy_v4_v4(vd.col, final_color);
+ any_changed = true;
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+ if (any_changed) {
+ BKE_pbvh_node_mark_update_color(node);
+ }
+}
+
+static void sculpt_expand_flush_updates(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ switch (ss->expand_cache->target) {
+ case SCULPT_EXPAND_TARGET_MASK:
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
+ break;
+ case SCULPT_EXPAND_TARGET_FACE_SETS:
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
+ break;
+ case SCULPT_EXPAND_TARGET_COLORS:
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_COLOR);
+ break;
+ default:
+ break;
+ }
+}
+
+/* Store the original mesh data state in the expand cache. */
+static void sculpt_expand_original_state_store(Object *ob, ExpandCache *expand_cache)
+{
+ SculptSession *ss = ob->sculpt;
+ const int totvert = SCULPT_vertex_count_get(ss);
+ const int totface = ss->totfaces;
+
+ /* Face Sets are always stored as they are needed for snapping. */
+ expand_cache->initial_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "initial face set");
+ expand_cache->original_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "original face set");
+ for (int i = 0; i < totface; i++) {
+ expand_cache->initial_face_sets[i] = ss->face_sets[i];
+ expand_cache->original_face_sets[i] = ss->face_sets[i];
+ }
+
+ if (expand_cache->target == SCULPT_EXPAND_TARGET_MASK) {
+ expand_cache->original_mask = MEM_malloc_arrayN(totvert, sizeof(float), "initial mask");
+ for (int i = 0; i < totvert; i++) {
+ expand_cache->original_mask[i] = SCULPT_vertex_mask_get(ss, i);
+ }
+ }
+
+ if (expand_cache->target == SCULPT_EXPAND_TARGET_COLORS) {
+ expand_cache->original_colors = MEM_malloc_arrayN(totvert, sizeof(float[4]), "initial colors");
+ for (int i = 0; i < totvert; i++) {
+ copy_v4_v4(expand_cache->original_colors[i], SCULPT_vertex_color_get(ss, i));
+ }
+ }
+}
+
+/**
+ * Restore the state of the Face Sets before a new update.
+ */
+static void sculpt_expand_face_sets_restore(SculptSession *ss, ExpandCache *expand_cache)
+{
+ const int totfaces = ss->totfaces;
+ for (int i = 0; i < totfaces; i++) {
+ ss->face_sets[i] = expand_cache->initial_face_sets[i];
+ }
+}
+
+static void sculpt_expand_update_for_vertex(bContext *C, Object *ob, const SculptVertRef vertex)
+{
+ SculptSession *ss = ob->sculpt;
+ const int vertex_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, vertex);
+
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ ExpandCache *expand_cache = ss->expand_cache;
+
+ /* Update the active factor in the cache. */
+ if (vertex.i == SCULPT_EXPAND_VERTEX_NONE) {
+ /* This means that the cursor is not over the mesh, so a valid active falloff can't be
+ * determined. In this situations, don't evaluate enabled states and default all vertices in
+ * connected components to enabled. */
+ expand_cache->active_falloff = expand_cache->max_vert_falloff;
+ expand_cache->all_enabled = true;
+ }
+ else {
+ expand_cache->active_falloff = expand_cache->vert_falloff[vertex_i];
+ expand_cache->all_enabled = false;
+ }
+
+ if (expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
+ /* Face sets needs to be restored their initial state on each iteration as the overwrite
+ * existing data. */
+ sculpt_expand_face_sets_restore(ss, expand_cache);
+ }
+
+ /* Update the mesh sculpt data. */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = expand_cache->nodes,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, expand_cache->totnode);
+
+ switch (expand_cache->target) {
+ case SCULPT_EXPAND_TARGET_MASK:
+ BLI_task_parallel_range(
+ 0, expand_cache->totnode, &data, sculpt_expand_mask_update_task_cb, &settings);
+ break;
+ case SCULPT_EXPAND_TARGET_FACE_SETS:
+ sculpt_expand_face_sets_update(ss, expand_cache);
+ break;
+ case SCULPT_EXPAND_TARGET_COLORS:
+ BLI_task_parallel_range(
+ 0, expand_cache->totnode, &data, sculpt_expand_colors_update_task_cb, &settings);
+ break;
+ }
+
+ sculpt_expand_flush_updates(C);
+}
+
+/**
+ * Updates the #SculptSession cursor data and gets the active vertex
+ * if the cursor is over the mesh.
+ */
+static SculptVertRef sculpt_expand_target_vertex_update_and_get(bContext *C,
+ Object *ob,
+ const float mouse[2])
+{
+ SculptSession *ss = ob->sculpt;
+ SculptCursorGeometryInfo sgi;
+ if (SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false)) {
+ return SCULPT_active_vertex_get(ss);
+ }
+
+ SculptVertRef ret = {SCULPT_EXPAND_VERTEX_NONE};
+ return ret;
+}
+
+/**
+ * Moves the sculpt pivot to the average point of the boundary enabled vertices of the current
+ * expand state. Take symmetry and active components into account.
+ */
+static void sculpt_expand_reposition_pivot(bContext *C, Object *ob, ExpandCache *expand_cache)
+{
+ SculptSession *ss = ob->sculpt;
+ const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
+ const int totvert = SCULPT_vertex_count_get(ss);
+
+ const bool initial_invert_state = expand_cache->invert;
+ expand_cache->invert = false;
+ BLI_bitmap *enabled_vertices = sculpt_expand_bitmap_from_enabled(ss, expand_cache);
+
+ /* For boundary topology, position the pivot using only the boundary of the enabled vertices,
+ * without taking mesh boundary into account. This allows to create deformations like bending the
+ * mesh from the boundary of the mask that was just created. */
+ const float use_mesh_boundary = expand_cache->falloff_type !=
+ SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY;
+
+ BLI_bitmap *boundary_vertices = sculpt_expand_boundary_from_enabled(
+ ss, enabled_vertices, use_mesh_boundary);
+
+ /* Ignore invert state, as this is the expected behavior in most cases and mask are created in
+ * inverted state by default. */
+ expand_cache->invert = initial_invert_state;
+
+ int total = 0;
+ float avg[3] = {0.0f};
+
+ const float *expand_init_co = SCULPT_vertex_co_get(ss, expand_cache->initial_active_vertex);
+
+ for (int i = 0; i < totvert; i++) {
+ if (!BLI_BITMAP_TEST(boundary_vertices, i)) {
+ continue;
+ }
+
+ if (!sculpt_expand_is_vert_in_active_component(ss, expand_cache, i)) {
+ continue;
+ }
+
+ const float *vertex_co = SCULPT_vertex_co_get(ss, i);
+
+ if (!SCULPT_check_vertex_pivot_symmetry(vertex_co, expand_init_co, symm)) {
+ continue;
+ }
+
+ add_v3_v3(avg, vertex_co);
+ total++;
+ }
+
+ MEM_freeN(enabled_vertices);
+ MEM_freeN(boundary_vertices);
+
+ if (total > 0) {
+ mul_v3_v3fl(ss->pivot_pos, avg, 1.0f / total);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+}
+
+static void sculpt_expand_finish(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ SCULPT_undo_push_end();
+
+ /* Tag all nodes to redraw to avoid artifacts after the fast partial updates. */
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ for (int n = 0; n < totnode; n++) {
+ BKE_pbvh_node_mark_update_mask(nodes[n]);
+ }
+ MEM_freeN(nodes);
+
+ switch (ss->expand_cache->target) {
+ case SCULPT_EXPAND_TARGET_MASK:
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
+ break;
+ case SCULPT_EXPAND_TARGET_FACE_SETS:
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
+ break;
+ case SCULPT_EXPAND_TARGET_COLORS:
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR);
+ break;
+ }
+
+ sculpt_expand_cache_free(ss);
+ ED_workspace_status_text(C, NULL);
+}
+
+/**
+ * Finds and stores in the #ExpandCache the sculpt connected component index for each symmetry pass
+ * needed for expand.
+ */
+static void sculpt_expand_find_active_connected_components_from_vert(Object *ob,
+ ExpandCache *expand_cache,
+ const SculptVertRef initial_vertex)
+{
+ SculptSession *ss = ob->sculpt;
+ for (int i = 0; i < EXPAND_SYMM_AREAS; i++) {
+ expand_cache->active_connected_components[i] = EXPAND_ACTIVE_COMPONENT_NONE;
+ }
+
+ const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
+ for (char symm_it = 0; symm_it <= symm; symm_it++) {
+ if (!SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
+ continue;
+ }
+
+ const SculptVertRef symm_vertex = sculpt_expand_get_vertex_index_for_symmetry_pass(
+ ob, symm_it, initial_vertex);
+ const int symm_vertex_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, symm_vertex);
+
+ expand_cache->active_connected_components[(int)symm_it] =
+ ss->vertex_info.connected_component[symm_vertex_i];
+ }
+}
+
+/**
+ * Stores the active vertex, Face Set and mouse coordinates in the #ExpandCache based on the
+ * current cursor position.
+ */
+static void sculpt_expand_set_initial_components_for_mouse(bContext *C,
+ Object *ob,
+ ExpandCache *expand_cache,
+ const float mouse[2])
+{
+ SculptSession *ss = ob->sculpt;
+ SculptVertRef initial_vertex = sculpt_expand_target_vertex_update_and_get(C, ob, mouse);
+
+ if (initial_vertex.i == SCULPT_EXPAND_VERTEX_NONE) {
+ /* Cursor not over the mesh, for creating valid initial falloffs, fallback to the last active
+ * vertex in the sculpt session. */
+ initial_vertex = SCULPT_active_vertex_get(ss);
+ }
+ copy_v2_v2(ss->expand_cache->initial_mouse, mouse);
+ expand_cache->initial_active_vertex = initial_vertex;
+ expand_cache->initial_active_face_set = SCULPT_active_face_set_get(ss);
+
+ if (expand_cache->next_face_set == SCULPT_FACE_SET_NONE) {
+ /* Only set the next face set once, otherwise this ID will constantly update to a new one each
+ * time this function is called for using a new initial vertex from a different cursor
+ * position. */
+ if (expand_cache->modify_active_face_set) {
+ expand_cache->next_face_set = SCULPT_active_face_set_get(ss);
+ }
+ else {
+ expand_cache->next_face_set = ED_sculpt_face_sets_find_next_available_id(ob->data);
+ }
+ }
+
+ /* The new mouse position can be over a different connected component, so this needs to be
+ * updated. */
+ sculpt_expand_find_active_connected_components_from_vert(ob, expand_cache, initial_vertex);
+}
+
+/**
+ * Displaces the initial mouse coordinates using the new mouse position to get a new active vertex.
+ * After that, initializes a new falloff of the same type with the new active vertex.
+ */
+static void sculpt_expand_move_propagation_origin(bContext *C,
+ Object *ob,
+ const wmEvent *event,
+ ExpandCache *expand_cache)
+{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+
+ const float mouse[2] = {event->mval[0], event->mval[1]};
+ float move_disp[2];
+ sub_v2_v2v2(move_disp, mouse, expand_cache->initial_mouse_move);
+
+ float new_mouse[2];
+ add_v2_v2v2(new_mouse, move_disp, expand_cache->original_mouse_move);
+
+ sculpt_expand_set_initial_components_for_mouse(C, ob, expand_cache, new_mouse);
+ sculpt_expand_falloff_factors_from_vertex_and_symm_create(
+ expand_cache,
+ sd,
+ ob,
+ expand_cache->initial_active_vertex,
+ expand_cache->move_preview_falloff_type);
+}
+
+/**
+ * Ensures that the #SculptSession contains the required data needed for Expand.
+ */
+static void sculpt_expand_ensure_sculptsession_data(Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ SCULPT_vertex_random_access_ensure(ss);
+ SCULPT_connected_components_ensure(ob);
+ SCULPT_boundary_info_ensure(ob);
+ if (!ss->tex_pool) {
+ ss->tex_pool = BKE_image_pool_new();
+ }
+}
+
+/**
+ * Returns the active Face Sets ID from the enabled face or grid in the #SculptSession.
+ */
+static int sculpt_expand_active_face_set_id_get(SculptSession *ss, ExpandCache *expand_cache)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ return expand_cache->original_face_sets[ss->active_face_index];
+ case PBVH_GRIDS: {
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg,
+ ss->active_grid_index);
+ return expand_cache->original_face_sets[face_index];
+ }
+ case PBVH_BMESH: {
+ /* Dyntopo does not support Face Set functionality. */
+ BLI_assert(false);
+ }
+ }
+ return SCULPT_FACE_SET_NONE;
+}
+
+static int sculpt_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+
+ /* Skips INBETWEEN_MOUSEMOVE events and other events that may cause unnecessary updates. */
+ if (!ELEM(event->type, MOUSEMOVE, EVT_MODAL_MAP)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ /* Update SculptSession data. */
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
+ sculpt_expand_ensure_sculptsession_data(ob);
+
+ /* Update and get the active vertex (and face) from the cursor. */
+ const float mouse[2] = {event->mval[0], event->mval[1]};
+ const int target_expand_vertex = sculpt_expand_target_vertex_update_and_get(C, ob, mouse);
+
+ /* Handle the modal keymap state changes. */
+ ExpandCache *expand_cache = ss->expand_cache;
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case SCULPT_EXPAND_MODAL_CANCEL: {
+ sculpt_expand_cancel(C, op);
+ return OPERATOR_FINISHED;
+ }
+ case SCULPT_EXPAND_MODAL_INVERT: {
+ expand_cache->invert = !expand_cache->invert;
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_PRESERVE_TOGGLE: {
+ expand_cache->preserve = !expand_cache->preserve;
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_GRADIENT_TOGGLE: {
+ expand_cache->falloff_gradient = !expand_cache->falloff_gradient;
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_BRUSH_GRADIENT_TOGGLE: {
+ expand_cache->brush_gradient = !expand_cache->brush_gradient;
+ if (expand_cache->brush_gradient) {
+ expand_cache->falloff_gradient = true;
+ }
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_SNAP_TOGGLE: {
+ if (expand_cache->snap) {
+ expand_cache->snap = false;
+ if (expand_cache->snap_enabled_face_sets) {
+ BLI_gset_free(expand_cache->snap_enabled_face_sets, NULL);
+ expand_cache->snap_enabled_face_sets = NULL;
+ }
+ }
+ else {
+ expand_cache->snap = true;
+ if (!expand_cache->snap_enabled_face_sets) {
+ expand_cache->snap_enabled_face_sets = BLI_gset_int_new("snap face sets");
+ }
+ sculpt_expand_snap_initialize_from_enabled(ss, expand_cache);
+ }
+ } break;
+ case SCULPT_EXPAND_MODAL_MOVE_TOGGLE: {
+ if (expand_cache->move) {
+ expand_cache->move = false;
+ sculpt_expand_falloff_factors_from_vertex_and_symm_create(
+ expand_cache,
+ sd,
+ ob,
+ expand_cache->initial_active_vertex,
+ expand_cache->move_original_falloff_type);
+ break;
+ }
+ expand_cache->move = true;
+ expand_cache->move_original_falloff_type = expand_cache->falloff_type;
+ copy_v2_v2(expand_cache->initial_mouse_move, mouse);
+ copy_v2_v2(expand_cache->original_mouse_move, expand_cache->initial_mouse);
+ if (expand_cache->falloff_type == SCULPT_EXPAND_FALLOFF_GEODESIC &&
+ SCULPT_vertex_count_get(ss) > expand_cache->max_geodesic_move_preview) {
+ /* Set to spherical falloff for preview in high poly meshes as it is the fastest one.
+ * In most cases it should match closely the preview from geodesic. */
+ expand_cache->move_preview_falloff_type = SCULPT_EXPAND_FALLOFF_SPHERICAL;
+ }
+ else {
+ expand_cache->move_preview_falloff_type = expand_cache->falloff_type;
+ }
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_RECURSION_STEP_GEODESIC: {
+ sculpt_expand_resursion_step_add(ob, expand_cache, SCULPT_EXPAND_RECURSION_GEODESICS);
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_RECURSION_STEP_TOPOLOGY: {
+ sculpt_expand_resursion_step_add(ob, expand_cache, SCULPT_EXPAND_RECURSION_TOPOLOGY);
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_CONFIRM: {
+ sculpt_expand_update_for_vertex(C, ob, target_expand_vertex);
+
+ if (expand_cache->reposition_pivot) {
+ sculpt_expand_reposition_pivot(C, ob, expand_cache);
+ }
+
+ sculpt_expand_finish(C);
+ return OPERATOR_FINISHED;
+ }
+ case SCULPT_EXPAND_MODAL_FALLOFF_GEODESIC: {
+ sculpt_expand_falloff_factors_from_vertex_and_symm_create(
+ expand_cache,
+ sd,
+ ob,
+ expand_cache->initial_active_vertex,
+ SCULPT_EXPAND_FALLOFF_GEODESIC);
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY: {
+ sculpt_expand_falloff_factors_from_vertex_and_symm_create(
+ expand_cache,
+ sd,
+ ob,
+ expand_cache->initial_active_vertex,
+ SCULPT_EXPAND_FALLOFF_TOPOLOGY);
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY_DIAGONALS: {
+ sculpt_expand_falloff_factors_from_vertex_and_symm_create(
+ expand_cache,
+ sd,
+ ob,
+ expand_cache->initial_active_vertex,
+ SCULPT_EXPAND_FALLOFF_TOPOLOGY_DIAGONALS);
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_FALLOFF_SPHERICAL: {
+ sculpt_expand_falloff_factors_from_vertex_and_symm_create(
+ expand_cache,
+ sd,
+ ob,
+ expand_cache->initial_active_vertex,
+ SCULPT_EXPAND_FALLOFF_SPHERICAL);
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_LOOP_COUNT_INCREASE: {
+ expand_cache->loop_count += 1;
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_LOOP_COUNT_DECREASE: {
+ expand_cache->loop_count -= 1;
+ expand_cache->loop_count = max_ii(expand_cache->loop_count, 1);
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_INCREASE: {
+ if (expand_cache->texture_distortion_strength == 0.0f) {
+ if (expand_cache->brush->mtex.tex == NULL) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Active brush does not contain any texture to distort the expand boundary");
+ break;
+ }
+ if (expand_cache->brush->mtex.brush_map_mode != MTEX_MAP_MODE_3D) {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Texture mapping not set to 3D, results may be unpredictable");
+ }
+ }
+ expand_cache->texture_distortion_strength += SCULPT_EXPAND_TEXTURE_DISTORTION_STEP;
+ break;
+ }
+ case SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_DECREASE: {
+ expand_cache->texture_distortion_strength -= SCULPT_EXPAND_TEXTURE_DISTORTION_STEP;
+ expand_cache->texture_distortion_strength = max_ff(
+ expand_cache->texture_distortion_strength, 0.0f);
+ break;
+ }
+ }
+ }
+
+ /* Handle expand origin movement if enabled. */
+ if (expand_cache->move) {
+ sculpt_expand_move_propagation_origin(C, ob, event, expand_cache);
+ }
+
+ /* Add new Face Sets IDs to the snapping gset if enabled. */
+ if (expand_cache->snap) {
+ const int active_face_set_id = sculpt_expand_active_face_set_id_get(ss, expand_cache);
+ if (!BLI_gset_haskey(expand_cache->snap_enabled_face_sets,
+ POINTER_FROM_INT(active_face_set_id))) {
+ BLI_gset_add(expand_cache->snap_enabled_face_sets, POINTER_FROM_INT(active_face_set_id));
+ }
+ }
+
+ /* Update the sculpt data with the current state of the #ExpandCache. */
+ sculpt_expand_update_for_vertex(C, ob, target_expand_vertex);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/**
+ * Deletes the `delete_id` Face Set ID from the mesh Face Sets
+ * and stores the result in `r_face_set`.
+ * The faces that were using the `delete_id` Face Set are filled
+ * using the content from their neighbors.
+ */
+static void sculpt_expand_delete_face_set_id(
+ int *r_face_sets, Mesh *mesh, MeshElemMap *pmap, const int totface, const int delete_id)
+{
+ /* Check that all the face sets IDs in the mesh are not equal to `delete_id`
+ * before attempting to delete it. */
+ bool all_same_id = true;
+ for (int i = 0; i < totface; i++) {
+ if (r_face_sets[i] != delete_id) {
+ all_same_id = false;
+ break;
+ }
+ }
+ if (all_same_id) {
+ return;
+ }
+
+ BLI_LINKSTACK_DECLARE(queue, void *);
+ BLI_LINKSTACK_DECLARE(queue_next, void *);
+
+ BLI_LINKSTACK_INIT(queue);
+ BLI_LINKSTACK_INIT(queue_next);
+
+ for (int i = 0; i < totface; i++) {
+ if (r_face_sets[i] == delete_id) {
+ BLI_LINKSTACK_PUSH(queue, POINTER_FROM_INT(i));
+ }
+ }
+
+ while (BLI_LINKSTACK_SIZE(queue)) {
+ while (BLI_LINKSTACK_SIZE(queue)) {
+ const int f_index = POINTER_AS_INT(BLI_LINKSTACK_POP(queue));
+ int other_id = delete_id;
+ const MPoly *c_poly = &mesh->mpoly[f_index];
+ for (int l = 0; l < c_poly->totloop; l++) {
+ const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
+ const MeshElemMap *vert_map = &pmap[c_loop->v];
+ for (int i = 0; i < vert_map->count; i++) {
+
+ const int neighbor_face_index = vert_map->indices[i];
+ if (r_face_sets[neighbor_face_index] != delete_id) {
+ other_id = r_face_sets[neighbor_face_index];
+ }
+ }
+ }
+
+ if (other_id != delete_id) {
+ r_face_sets[f_index] = other_id;
+ }
+ else {
+ BLI_LINKSTACK_PUSH(queue_next, POINTER_FROM_INT(f_index));
+ }
+ }
+
+ BLI_LINKSTACK_SWAP(queue, queue_next);
+ }
+
+ BLI_LINKSTACK_FREE(queue);
+ BLI_LINKSTACK_FREE(queue_next);
+}
+
+static void sculpt_expand_cache_initial_config_set(bContext *C,
+ wmOperator *op,
+ ExpandCache *expand_cache)
+{
+ /* RNA properties. */
+ expand_cache->invert = RNA_boolean_get(op->ptr, "invert");
+ expand_cache->preserve = RNA_boolean_get(op->ptr, "use_mask_preserve");
+ expand_cache->falloff_gradient = RNA_boolean_get(op->ptr, "use_falloff_gradient");
+ expand_cache->target = RNA_enum_get(op->ptr, "target");
+ expand_cache->modify_active_face_set = RNA_boolean_get(op->ptr, "use_modify_active");
+ expand_cache->reposition_pivot = RNA_boolean_get(op->ptr, "use_reposition_pivot");
+ expand_cache->max_geodesic_move_preview = RNA_int_get(op->ptr, "max_geodesic_move_preview");
+
+ /* These can be exposed in RNA if needed. */
+ expand_cache->loop_count = 1;
+ expand_cache->brush_gradient = false;
+
+ /* Texture and color data from the active Brush. */
+ Object *ob = CTX_data_active_object(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ SculptSession *ss = ob->sculpt;
+ expand_cache->brush = BKE_paint_brush(&sd->paint);
+ BKE_curvemapping_init(expand_cache->brush->curve);
+ copy_v4_fl(expand_cache->fill_color, 1.0f);
+ copy_v3_v3(expand_cache->fill_color, BKE_brush_color_get(ss->scene, expand_cache->brush));
+ IMB_colormanagement_srgb_to_scene_linear_v3(expand_cache->fill_color);
+
+ expand_cache->scene = CTX_data_scene(C);
+ expand_cache->mtex = &expand_cache->brush->mtex;
+ expand_cache->texture_distortion_strength = 0.0f;
+ expand_cache->blend_mode = expand_cache->brush->blend;
+}
+
+/**
+ * Does the undo sculpt push for the affected target data of the #ExpandCache.
+ */
+static void sculpt_expand_undo_push(Object *ob, ExpandCache *expand_cache)
+{
+ SculptSession *ss = ob->sculpt;
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+
+ switch (expand_cache->target) {
+ case SCULPT_EXPAND_TARGET_MASK:
+ for (int i = 0; i < totnode; i++) {
+ SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
+ }
+ break;
+ case SCULPT_EXPAND_TARGET_FACE_SETS:
+ SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
+ break;
+ case SCULPT_EXPAND_TARGET_COLORS:
+ for (int i = 0; i < totnode; i++) {
+ SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_COLOR);
+ }
+ break;
+ }
+
+ MEM_freeN(nodes);
+}
+
+static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+
+ /* Create and configure the Expand Cache. */
+ ss->expand_cache = MEM_callocN(sizeof(ExpandCache), "expand cache");
+ sculpt_expand_cache_initial_config_set(C, op, ss->expand_cache);
+
+ /* Update object. */
+ const bool needs_colors = ss->expand_cache->target == SCULPT_EXPAND_TARGET_COLORS;
+
+ if (needs_colors) {
+ /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of
+ * earlier steps modifying the data. */
+ BKE_sculpt_color_layer_create_if_needed(ob);
+ depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ }
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, needs_colors);
+
+ /* Do nothing when the mesh has 0 vertices. */
+ const int totvert = SCULPT_vertex_count_get(ss);
+ if (totvert == 0) {
+ sculpt_expand_cache_free(ss);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Face Set operations are not supported in dyntopo. */
+ if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS &&
+ BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ sculpt_expand_cache_free(ss);
+ return OPERATOR_CANCELLED;
+ }
+
+ sculpt_expand_ensure_sculptsession_data(ob);
+
+ /* Initialize undo. */
+ SCULPT_undo_push_begin(ob, "expand");
+ sculpt_expand_undo_push(ob, ss->expand_cache);
+
+ /* Set the initial element for expand from the event position. */
+ const float mouse[2] = {event->mval[0], event->mval[1]};
+ sculpt_expand_set_initial_components_for_mouse(C, ob, ss->expand_cache, mouse);
+
+ /* Cache PBVH nodes. */
+ BKE_pbvh_search_gather(
+ ss->pbvh, NULL, NULL, &ss->expand_cache->nodes, &ss->expand_cache->totnode);
+
+ /* Store initial state. */
+ sculpt_expand_original_state_store(ob, ss->expand_cache);
+
+ if (ss->expand_cache->modify_active_face_set) {
+ sculpt_expand_delete_face_set_id(ss->expand_cache->initial_face_sets,
+ ob->data,
+ ss->pmap,
+ ss->totfaces,
+ ss->expand_cache->next_face_set);
+ }
+
+ /* Initialize the falloff. */
+ eSculptExpandFalloffType falloff_type = RNA_enum_get(op->ptr, "falloff_type");
+
+ /* When starting from a boundary vertex, set the initial falloff to boundary. */
+ if (SCULPT_vertex_is_boundary(ss, ss->expand_cache->initial_active_vertex)) {
+ falloff_type = SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY;
+ }
+
+ sculpt_expand_falloff_factors_from_vertex_and_symm_create(
+ ss->expand_cache, sd, ob, ss->expand_cache->initial_active_vertex, falloff_type);
+
+ /* Initial mesh data update, resets all target data in the sculpt mesh. */
+ sculpt_expand_update_for_vertex(C, ob, ss->expand_cache->initial_active_vertex);
+
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void sculpt_expand_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {SCULPT_EXPAND_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ {SCULPT_EXPAND_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {SCULPT_EXPAND_MODAL_INVERT, "INVERT", 0, "Invert", ""},
+ {SCULPT_EXPAND_MODAL_PRESERVE_TOGGLE, "PRESERVE", 0, "Toggle Preserve State", ""},
+ {SCULPT_EXPAND_MODAL_GRADIENT_TOGGLE, "GRADIENT", 0, "Toggle Gradient", ""},
+ {SCULPT_EXPAND_MODAL_RECURSION_STEP_GEODESIC,
+ "RECURSION_STEP_GEODESIC",
+ 0,
+ "Geodesic recursion step",
+ ""},
+ {SCULPT_EXPAND_MODAL_RECURSION_STEP_TOPOLOGY,
+ "RECURSION_STEP_TOPOLOGY",
+ 0,
+ "Topology recursion Step",
+ ""},
+ {SCULPT_EXPAND_MODAL_MOVE_TOGGLE, "MOVE_TOGGLE", 0, "Move Origin", ""},
+ {SCULPT_EXPAND_MODAL_FALLOFF_GEODESIC, "FALLOFF_GEODESICS", 0, "Geodesic Falloff", ""},
+ {SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY, "FALLOFF_TOPOLOGY", 0, "Topology Falloff", ""},
+ {SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY_DIAGONALS,
+ "FALLOFF_TOPOLOGY_DIAGONALS",
+ 0,
+ "Diagonals Falloff",
+ ""},
+ {SCULPT_EXPAND_MODAL_FALLOFF_SPHERICAL, "FALLOFF_SPHERICAL", 0, "Spherical Falloff", ""},
+ {SCULPT_EXPAND_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap expand to Face Sets", ""},
+ {SCULPT_EXPAND_MODAL_LOOP_COUNT_INCREASE,
+ "LOOP_COUNT_INCREASE",
+ 0,
+ "Loop Count Increase",
+ ""},
+ {SCULPT_EXPAND_MODAL_LOOP_COUNT_DECREASE,
+ "LOOP_COUNT_DECREASE",
+ 0,
+ "Loop Count Decrease",
+ ""},
+ {SCULPT_EXPAND_MODAL_BRUSH_GRADIENT_TOGGLE,
+ "BRUSH_GRADIENT_TOGGLE",
+ 0,
+ "Toggle Brush Gradient",
+ ""},
+ {SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_INCREASE,
+ "TEXTURE_DISTORTION_INCREASE",
+ 0,
+ "Texture Distortion Increase",
+ ""},
+ {SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_DECREASE,
+ "TEXTURE_DISTORTION_DECREASE",
+ 0,
+ "Texture Distortion Decrease",
+ ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const char *name = "Sculpt Expand Modal";
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name);
+
+ /* This function is called for each spacetype, only needs to add map once. */
+ if (keymap && keymap->modal_items) {
+ return;
+ }
+
+ keymap = WM_modalkeymap_ensure(keyconf, name, modal_items);
+ WM_modalkeymap_assign(keymap, "SCULPT_OT_expand");
+}
+
+void SCULPT_OT_expand(wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Expand";
+ ot->idname = "SCULPT_OT_expand";
+ ot->description = "Generic sculpt expand operator";
+
+ /* API callbacks. */
+ ot->invoke = sculpt_expand_invoke;
+ ot->modal = sculpt_expand_modal;
+ ot->cancel = sculpt_expand_cancel;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ static EnumPropertyItem prop_sculpt_expand_falloff_type_items[] = {
+ {SCULPT_EXPAND_FALLOFF_GEODESIC, "GEODESIC", 0, "Geodesic", ""},
+ {SCULPT_EXPAND_FALLOFF_TOPOLOGY, "TOPOLOGY", 0, "Topology", ""},
+ {SCULPT_EXPAND_FALLOFF_TOPOLOGY_DIAGONALS,
+ "TOPOLOGY_DIAGONALS",
+ 0,
+ "Topology Diagonals",
+ ""},
+ {SCULPT_EXPAND_FALLOFF_NORMALS, "NORMALS", 0, "Normals", ""},
+ {SCULPT_EXPAND_FALLOFF_SPHERICAL, "SPHERICAL", 0, "Spherical", ""},
+ {SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY, "BOUNDARY_TOPOLOGY", 0, "Boundary Topology", ""},
+ {SCULPT_EXPAND_FALLOFF_BOUNDARY_FACE_SET, "BOUNDARY_FACE_SET", 0, "Boundary Face Set", ""},
+ {SCULPT_EXPAND_FALLOFF_ACTIVE_FACE_SET, "ACTIVE_FACE_SET", 0, "Active Face Set", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static EnumPropertyItem prop_sculpt_expand_target_type_items[] = {
+ {SCULPT_EXPAND_TARGET_MASK, "MASK", 0, "Mask", ""},
+ {SCULPT_EXPAND_TARGET_FACE_SETS, "FACE_SETS", 0, "Face Sets", ""},
+ {SCULPT_EXPAND_TARGET_COLORS, "COLOR", 0, "Color", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ RNA_def_enum(ot->srna,
+ "target",
+ prop_sculpt_expand_target_type_items,
+ SCULPT_EXPAND_TARGET_MASK,
+ "Data Target",
+ "Data that is going to be modified in the expand operation");
+
+ RNA_def_enum(ot->srna,
+ "falloff_type",
+ prop_sculpt_expand_falloff_type_items,
+ SCULPT_EXPAND_FALLOFF_GEODESIC,
+ "Falloff Type",
+ "Initial falloff of the expand operation");
+
+ ot->prop = RNA_def_boolean(
+ ot->srna, "invert", false, "Invert", "Invert the expand active elements");
+ ot->prop = RNA_def_boolean(ot->srna,
+ "use_mask_preserve",
+ false,
+ "Preserve Previous",
+ "Preserve the previous state of the target data");
+ ot->prop = RNA_def_boolean(ot->srna,
+ "use_falloff_gradient",
+ false,
+ "Falloff Gradient",
+ "Expand Using a linear falloff");
+
+ ot->prop = RNA_def_boolean(ot->srna,
+ "use_modify_active",
+ false,
+ "Modify Active",
+ "Modify the active Face Set instead of creating a new one");
+
+ ot->prop = RNA_def_boolean(
+ ot->srna,
+ "use_reposition_pivot",
+ true,
+ "Reposition Pivot",
+ "Reposition the sculpt transform pivot to the boundary of the expand active area");
+
+ ot->prop = RNA_def_int(ot->srna,
+ "max_geodesic_move_preview",
+ 10000,
+ 0,
+ INT_MAX,
+ "Max Vertex Count for Geodesic Move Preview",
+ "Maximum number of vertices in the mesh for using geodesic falloff when "
+ "moving the origin of expand. If the total number of vertices is greater "
+ "than this value, the falloff will be set to spherical when moving",
+ 0,
+ 1000000);
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.c b/source/blender/editors/sculpt_paint/sculpt_geodesic.c
new file mode 100644
index 00000000000..d86d0938300
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.c
@@ -0,0 +1,360 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_linklist_stack.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_ccg.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_image.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_multires.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+#include "BKE_subdiv_ccg.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_view3d.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "IMB_colormanagement.h"
+#include "IMB_imbuf.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+#define SCULPT_GEODESIC_VERTEX_NONE -1
+
+/* Propagate distance from v1 and v2 to v0. */
+static bool sculpt_geodesic_mesh_test_dist_add(
+ MVert *mvert, const int v0, const int v1, const int v2, float *dists, GSet *initial_vertices)
+{
+ if (BLI_gset_haskey(initial_vertices, POINTER_FROM_INT(v0))) {
+ return false;
+ }
+
+ BLI_assert(dists[v1] != FLT_MAX);
+ if (dists[v0] <= dists[v1]) {
+ return false;
+ }
+
+ float dist0;
+ if (v2 != SCULPT_GEODESIC_VERTEX_NONE) {
+ BLI_assert(dists[v2] != FLT_MAX);
+ if (dists[v0] <= dists[v2]) {
+ return false;
+ }
+ dist0 = geodesic_distance_propagate_across_triangle(
+ mvert[v0].co, mvert[v1].co, mvert[v2].co, dists[v1], dists[v2]);
+ }
+ else {
+ float vec[3];
+ sub_v3_v3v3(vec, mvert[v1].co, mvert[v0].co);
+ dist0 = dists[v1] + len_v3(vec);
+ }
+
+ if (dist0 < dists[v0]) {
+ dists[v0] = dist0;
+ return true;
+ }
+
+ return false;
+}
+
+static float *SCULPT_geodesic_mesh_create(Object *ob,
+ GSet *initial_vertices,
+ const float limit_radius)
+{
+ SculptSession *ss = ob->sculpt;
+ Mesh *mesh = BKE_object_get_original_mesh(ob);
+
+ const int totvert = mesh->totvert;
+ const int totedge = mesh->totedge;
+
+ const float limit_radius_sq = limit_radius * limit_radius;
+
+ MEdge *edges = mesh->medge;
+ MVert *verts = SCULPT_mesh_deformed_mverts_get(ss);
+
+ float *dists = MEM_malloc_arrayN(totvert, sizeof(float), "distances");
+ BLI_bitmap *edge_tag = BLI_BITMAP_NEW(totedge, "edge tag");
+
+ if (!ss->epmap) {
+ BKE_mesh_edge_poly_map_create(&ss->epmap,
+ &ss->epmap_mem,
+ mesh->medge,
+ mesh->totedge,
+ mesh->mpoly,
+ mesh->totpoly,
+ mesh->mloop,
+ mesh->totloop);
+ }
+ if (!ss->vemap) {
+ BKE_mesh_vert_edge_map_create(
+ &ss->vemap, &ss->vemap_mem, mesh->medge, mesh->totvert, mesh->totedge);
+ }
+
+ /* Both contain edge indices encoded as *void. */
+ BLI_LINKSTACK_DECLARE(queue, void *);
+ BLI_LINKSTACK_DECLARE(queue_next, void *);
+
+ BLI_LINKSTACK_INIT(queue);
+ BLI_LINKSTACK_INIT(queue_next);
+
+ for (int i = 0; i < totvert; i++) {
+ if (BLI_gset_haskey(initial_vertices, POINTER_FROM_INT(i))) {
+ dists[i] = 0.0f;
+ }
+ else {
+ dists[i] = FLT_MAX;
+ }
+ }
+
+ /* Masks vertices that are further than limit radius from an initial vertex. As there is no need
+ * to define a distance to them the algorithm can stop earlier by skipping them. */
+ BLI_bitmap *affected_vertex = BLI_BITMAP_NEW(totvert, "affected vertex");
+ GSetIterator gs_iter;
+
+ if (limit_radius == FLT_MAX) {
+ /* In this case, no need to loop through all initial vertices to check distances as they are
+ * all going to be affected. */
+ BLI_bitmap_set_all(affected_vertex, true, totvert);
+ }
+ else {
+ /* This is an O(n^2) loop used to limit the geodesic distance calculation to a radius. When
+ * this optimization is needed, it is expected for the tool to request the distance to a low
+ * number of vertices (usually just 1 or 2). */
+ GSET_ITER (gs_iter, initial_vertices) {
+ const int v = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
+ float *v_co = verts[v].co;
+ for (int i = 0; i < totvert; i++) {
+ if (len_squared_v3v3(v_co, verts[i].co) <= limit_radius_sq) {
+ BLI_BITMAP_ENABLE(affected_vertex, i);
+ }
+ }
+ }
+ }
+
+ /* Add edges adjacent to an initial vertex to the queue. */
+ for (int i = 0; i < totedge; i++) {
+ const int v1 = edges[i].v1;
+ const int v2 = edges[i].v2;
+ if (!BLI_BITMAP_TEST(affected_vertex, v1) && !BLI_BITMAP_TEST(affected_vertex, v2)) {
+ continue;
+ }
+ if (dists[v1] != FLT_MAX || dists[v2] != FLT_MAX) {
+ BLI_LINKSTACK_PUSH(queue, POINTER_FROM_INT(i));
+ }
+ }
+
+ do {
+ while (BLI_LINKSTACK_SIZE(queue)) {
+ const int e = POINTER_AS_INT(BLI_LINKSTACK_POP(queue));
+ int v1 = edges[e].v1;
+ int v2 = edges[e].v2;
+
+ if (dists[v1] == FLT_MAX || dists[v2] == FLT_MAX) {
+ if (dists[v1] > dists[v2]) {
+ SWAP(int, v1, v2);
+ }
+ sculpt_geodesic_mesh_test_dist_add(
+ verts, v2, v1, SCULPT_GEODESIC_VERTEX_NONE, dists, initial_vertices);
+ }
+
+ if (ss->epmap[e].count != 0) {
+ for (int poly_map_index = 0; poly_map_index < ss->epmap[e].count; poly_map_index++) {
+ const int poly = ss->epmap[e].indices[poly_map_index];
+ if (ss->face_sets[poly] <= 0) {
+ continue;
+ }
+ const MPoly *mpoly = &mesh->mpoly[poly];
+
+ for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) {
+ const MLoop *mloop = &mesh->mloop[loop_index + mpoly->loopstart];
+ const int v_other = mloop->v;
+ if (ELEM(v_other, v1, v2)) {
+ continue;
+ }
+ if (sculpt_geodesic_mesh_test_dist_add(
+ verts, v_other, v1, v2, dists, initial_vertices)) {
+ for (int edge_map_index = 0; edge_map_index < ss->vemap[v_other].count;
+ edge_map_index++) {
+ const int e_other = ss->vemap[v_other].indices[edge_map_index];
+ int ev_other;
+ if (edges[e_other].v1 == (uint)v_other) {
+ ev_other = edges[e_other].v2;
+ }
+ else {
+ ev_other = edges[e_other].v1;
+ }
+
+ if (e_other != e && !BLI_BITMAP_TEST(edge_tag, e_other) &&
+ (ss->epmap[e_other].count == 0 || dists[ev_other] != FLT_MAX)) {
+ if (BLI_BITMAP_TEST(affected_vertex, v_other) ||
+ BLI_BITMAP_TEST(affected_vertex, ev_other)) {
+ BLI_BITMAP_ENABLE(edge_tag, e_other);
+ BLI_LINKSTACK_PUSH(queue_next, POINTER_FROM_INT(e_other));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (LinkNode *lnk = queue_next; lnk; lnk = lnk->next) {
+ const int e = POINTER_AS_INT(lnk->link);
+ BLI_BITMAP_DISABLE(edge_tag, e);
+ }
+
+ BLI_LINKSTACK_SWAP(queue, queue_next);
+
+ } while (BLI_LINKSTACK_SIZE(queue));
+
+ BLI_LINKSTACK_FREE(queue);
+ BLI_LINKSTACK_FREE(queue_next);
+ MEM_SAFE_FREE(edge_tag);
+ MEM_SAFE_FREE(affected_vertex);
+
+ return dists;
+}
+
+/* For sculpt mesh data that does not support a geodesic distances algorithm, fallback to the
+ * distance to each vertex. In this case, only one of the initial vertices will be used to
+ * calculate the distance. */
+static float *SCULPT_geodesic_fallback_create(Object *ob, GSet *initial_vertices)
+{
+
+ SculptSession *ss = ob->sculpt;
+ Mesh *mesh = BKE_object_get_original_mesh(ob);
+ const int totvert = mesh->totvert;
+ float *dists = MEM_malloc_arrayN(totvert, sizeof(float), "distances");
+ int first_affected = SCULPT_GEODESIC_VERTEX_NONE;
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, initial_vertices) {
+ first_affected = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
+ break;
+ }
+
+ if (first_affected == SCULPT_GEODESIC_VERTEX_NONE) {
+ for (int i = 0; i < totvert; i++) {
+ dists[i] = FLT_MAX;
+ }
+ return dists;
+ }
+
+ const float *first_affected_co = SCULPT_vertex_co_get(ss, first_affected);
+ for (int i = 0; i < totvert; i++) {
+ dists[i] = len_v3v3(first_affected_co, SCULPT_vertex_co_get(ss, i));
+ }
+
+ return dists;
+}
+
+float *SCULPT_geodesic_distances_create(Object *ob,
+ GSet *initial_vertices,
+ const float limit_radius)
+{
+ SculptSession *ss = ob->sculpt;
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ return SCULPT_geodesic_mesh_create(ob, initial_vertices, limit_radius);
+ case PBVH_BMESH:
+ case PBVH_GRIDS:
+ return SCULPT_geodesic_fallback_create(ob, initial_vertices);
+ }
+ BLI_assert(false);
+ return NULL;
+}
+
+float *SCULPT_geodesic_from_vertex_and_symm(Sculpt *sd,
+ Object *ob,
+ const int vertex,
+ const float limit_radius)
+{
+ SculptSession *ss = ob->sculpt;
+ GSet *initial_vertices = BLI_gset_int_new("initial_vertices");
+
+ const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
+ for (char i = 0; i <= symm; ++i) {
+ if (SCULPT_is_symmetry_iteration_valid(i, symm)) {
+ int v = -1;
+ if (i == 0) {
+ v = vertex;
+ }
+ else {
+ float location[3];
+ flip_v3_v3(location, SCULPT_vertex_co_get(ss, vertex), i);
+ v = SCULPT_nearest_vertex_get(sd, ob, location, FLT_MAX, false);
+ }
+ if (v != -1) {
+ BLI_gset_add(initial_vertices, POINTER_FROM_INT(v));
+ }
+ }
+ }
+
+ float *dists = SCULPT_geodesic_distances_create(ob, initial_vertices, limit_radius);
+ BLI_gset_free(initial_vertices, NULL);
+ return dists;
+}
+
+float *SCULPT_geodesic_from_vertex(Object *ob, const int vertex, const float limit_radius)
+{
+ GSet *initial_vertices = BLI_gset_int_new("initial_vertices");
+ BLI_gset_add(initial_vertices, POINTER_FROM_INT(vertex));
+ float *dists = SCULPT_geodesic_distances_create(ob, initial_vertices, limit_radius);
+ BLI_gset_free(initial_vertices, NULL);
+ return dists;
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 10433b90e16..6ec6f923a1d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -194,6 +194,8 @@ void SCULPT_boundary_info_ensure(Object *object);
/* Boundary Info needs to be initialized in order to use this function. */
bool SCULPT_vertex_is_boundary(const SculptSession *ss, const SculptVertRef index);
+void SCULPT_connected_components_ensure(Object *ob);
+
/* Sculpt Visibility API */
void SCULPT_vertex_visible_set(SculptSession *ss, SculptVertRef index, bool visible);
@@ -304,15 +306,14 @@ void SCULPT_floodfill_add_initial_with_symmetry(struct Sculpt *sd,
SculptFloodFill *flood,
SculptVertRef index,
float radius);
+
void SCULPT_floodfill_add_initial(SculptFloodFill *flood, SculptVertRef index);
-void SCULPT_floodfill_execute(struct SculptSession *ss,
- SculptFloodFill *flood,
- bool (*func)(SculptSession *ss,
- SculptVertRef from_v,
- SculptVertRef to_v,
- bool is_duplicate,
- void *userdata),
- void *userdata);
+void SCULPT_floodfill_add_and_skip_initial(SculptFloodFill *flood, int index);
+void SCULPT_floodfill_execute(
+ struct SculptSession *ss,
+ SculptFloodFill *flood,
+ bool (*func)(SculptSession *ss, SculptVertRef from_v, SculptVertRef to_v, bool is_duplicate, void *userdata),
+ void *userdata);
void SCULPT_floodfill_free(SculptFloodFill *flood);
/* Dynamic topology */
@@ -374,6 +375,21 @@ float *SCULPT_boundary_automasking_init(Object *ob,
int propagation_steps,
float *automask_factor);
+/* Geodesic distances. */
+
+/* Returns an array indexed by vertex index containing the geodesic distance to the closest vertex
+in the initial vertex set. The caller is responsible for freeing the array.
+Geodesic distances will only work when used with PBVH_FACES, for other types of PBVH it will
+fallback to euclidean distances to one of the initial vertices in the set. */
+float *SCULPT_geodesic_distances_create(struct Object *ob,
+ struct GSet *initial_vertices,
+ const float limit_radius);
+float *SCULPT_geodesic_from_vertex_and_symm(struct Sculpt *sd,
+ struct Object *ob,
+ const int vertex,
+ const float limit_radius);
+float *SCULPT_geodesic_from_vertex(Object *ob, const int vertex, const float limit_radius);
+
/* Filters. */
void SCULPT_filter_cache_init(struct bContext *C, Object *ob, Sculpt *sd, const int undo_type);
void SCULPT_filter_cache_free(SculptSession *ss);
@@ -1091,6 +1107,155 @@ void SCULPT_filter_to_orientation_space(float r_v[3], struct FilterCache *filter
void SCULPT_filter_to_object_space(float r_v[3], struct FilterCache *filter_cache);
void SCULPT_filter_zero_disabled_axis_components(float r_v[3], struct FilterCache *filter_cache);
+/* Sculpt Expand. */
+typedef enum eSculptExpandFalloffType {
+ SCULPT_EXPAND_FALLOFF_GEODESIC,
+ SCULPT_EXPAND_FALLOFF_TOPOLOGY,
+ SCULPT_EXPAND_FALLOFF_TOPOLOGY_DIAGONALS,
+ SCULPT_EXPAND_FALLOFF_NORMALS,
+ SCULPT_EXPAND_FALLOFF_SPHERICAL,
+ SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY,
+ SCULPT_EXPAND_FALLOFF_BOUNDARY_FACE_SET,
+ SCULPT_EXPAND_FALLOFF_ACTIVE_FACE_SET,
+} eSculptExpandFalloffType;
+
+typedef enum eSculptExpandTargetType {
+ SCULPT_EXPAND_TARGET_MASK,
+ SCULPT_EXPAND_TARGET_FACE_SETS,
+ SCULPT_EXPAND_TARGET_COLORS,
+} eSculptExpandTargetType;
+
+typedef enum eSculptExpandRecursionType {
+ SCULPT_EXPAND_RECURSION_TOPOLOGY,
+ SCULPT_EXPAND_RECURSION_GEODESICS,
+} eSculptExpandRecursionType;
+
+#define EXPAND_SYMM_AREAS 8
+
+typedef struct ExpandCache {
+ /* Target data elements that the expand operation will affect. */
+ eSculptExpandTargetType target;
+
+ /* Falloff data. */
+ eSculptExpandFalloffType falloff_type;
+
+ /* Indexed by vertex index, precalculated falloff value of that vertex (without any falloff
+ * editing modification applied). */
+ float *vert_falloff;
+ /* Max falloff value in *vert_falloff. */
+ float max_vert_falloff;
+
+ /* Indexed by base mesh poly index, precalculated falloff value of that face. These values are
+ * calculated from the per vertex falloff (*vert_falloff) when needed. */
+ float *face_falloff;
+ float max_face_falloff;
+
+ /* Falloff value of the active element (vertex or base mesh face) that Expand will expand to. */
+ float active_falloff;
+
+ /* When set to true, expand skips all falloff computations and considers all elements as enabled.
+ */
+ bool all_enabled;
+
+ /* Initial mouse and cursor data from where the current falloff started. This data can be changed
+ * during the execution of Expand by moving the origin. */
+ float initial_mouse_move[2];
+ float initial_mouse[2];
+ SculptVertRef initial_active_vertex;
+ int initial_active_face_set;
+
+ /* Maximum number of vertices allowed in the SculptSession for previewing the falloff using
+ * geodesic distances. */
+ int max_geodesic_move_preview;
+
+ /* Original falloff type before starting the move operation. */
+ eSculptExpandFalloffType move_original_falloff_type;
+ /* Falloff type using when moving the origin for preview. */
+ eSculptExpandFalloffType move_preview_falloff_type;
+
+ /* Face set ID that is going to be used when creating a new Face Set. */
+ int next_face_set;
+
+ /* Face Set ID of the Face set selected for editing. */
+ int update_face_set;
+
+ /* Mouse position since the last time the origin was moved. Used for reference when moving the
+ * initial position of Expand. */
+ float original_mouse_move[2];
+
+ /* Active components checks. */
+ /* Indexed by symmetry pass index, contains the connected component ID found in
+ * SculptSession->vertex_info.connected_component. Other connected components not found in this
+ * array will be ignored by Expand. */
+ int active_connected_components[EXPAND_SYMM_AREAS];
+
+ /* Snapping. */
+ /* GSet containing all Face Sets IDs that Expand will use to snap the new data. */
+ GSet *snap_enabled_face_sets;
+
+ /* Texture distortion data. */
+ Brush *brush;
+ struct Scene *scene;
+ struct MTex *mtex;
+
+ /* Controls how much texture distortion will be applied to the current falloff */
+ float texture_distortion_strength;
+
+ /* Cached PBVH nodes. This allows to skip gathering all nodes from the PBVH each time expand
+ * needs to update the state of the elements. */
+ PBVHNode **nodes;
+ int totnode;
+
+ /* Expand state options. */
+
+ /* Number of loops (times that the falloff is going to be repeated). */
+ int loop_count;
+
+ /* Invert the falloff result. */
+ bool invert;
+
+ /* When set to true, preserves the previous state of the data and adds the new one on top. */
+ bool preserve;
+
+ /* When set to true, the mask or colors will be applied as a gradient. */
+ bool falloff_gradient;
+
+ /* When set to true, Expand will use the Brush falloff curve data to shape the gradient. */
+ bool brush_gradient;
+
+ /* When set to true, Expand will move the origin (initial active vertex and cursor position)
+ * instead of updating the active vertex and active falloff. */
+ bool move;
+
+ /* When set to true, Expand will snap the new data to the Face Sets IDs found in
+ * *original_face_sets. */
+ bool snap;
+
+ /* When set to true, Expand will use the current Face Set ID to modify an existing Face Set
+ * instead of creating a new one. */
+ bool modify_active_face_set;
+
+ /* When set to true, Expand will reposition the sculpt pivot to the boundary of the expand result
+ * after finishing the operation. */
+ bool reposition_pivot;
+
+ /* Color target data type related data. */
+ float fill_color[4];
+ short blend_mode;
+
+ /* Face Sets at the first step of the expand operation, before starting modifying the active
+ * vertex and active falloff. These are not the original Face Sets of the sculpt before starting
+ * the operator as they could have been modified by Expand when initializing the operator and
+ * before starting changing the active vertex. These Face Sets are used for restoring and
+ * checking the Face Sets state while the Expand operation modal runs. */
+ int *initial_face_sets;
+
+ /* Original data of the sculpt as it was before running the Expand operator. */
+ float *original_mask;
+ int *original_face_sets;
+ float (*original_colors)[4];
+} ExpandCache;
+
typedef struct FilterCache {
bool enabled_axis[3];
bool enabled_force_axis[3];
@@ -1184,6 +1349,10 @@ bool SCULPT_get_redraw_rect(struct ARegion *region,
/* Operators. */
+/* Expand. */
+void SCULPT_OT_expand(struct wmOperatorType *ot);
+void sculpt_expand_modal_keymap(struct wmKeyConfig *keyconf);
+
/* Gestures. */
void SCULPT_OT_face_set_lasso_gesture(struct wmOperatorType *ot);
void SCULPT_OT_face_set_box_gesture(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index 3a584a7f0cb..efa714e315d 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -663,11 +663,11 @@ static int action_unlink_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
/* NOTE: this is hardcoded to match the behavior for the unlink button
* (in interface_templates.c). */
- RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
+ RNA_boolean_set(op->ptr, "force_delete", event->shift != 0);
return action_unlink_exec(C, op);
}
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index c112c678a09..1bd8d13b25b 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -274,9 +274,7 @@ void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type)
void ED_region_draw_cb_remove_by_type(ARegionType *art, void *draw_fn, void (*free)(void *))
{
- RegionDrawCB *rdc = art->drawcalls.first;
- while (rdc) {
- RegionDrawCB *rdc_next = rdc->next;
+ LISTBASE_FOREACH_MUTABLE (RegionDrawCB *, rdc, &art->drawcalls) {
if (rdc->draw == draw_fn) {
if (free) {
free(rdc->customdata);
@@ -284,7 +282,6 @@ void ED_region_draw_cb_remove_by_type(ARegionType *art, void *draw_fn, void (*fr
BLI_remlink(&art->drawcalls, rdc);
MEM_freeN(rdc);
}
- rdc = rdc_next;
}
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 4847e8738df..43128ed00fa 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -64,13 +64,42 @@
#include "ED_screen.h"
#include "WM_api.h"
+#include "WM_types.h"
#include "../interface/interface_intern.h"
#include "buttons_intern.h" /* own include */
+static ScrArea *find_area_properties(const bContext *C);
+static SpaceProperties *find_space_properties(const bContext *C);
+
/************************* Texture User **************************/
+static void buttons_texture_user_node_property_add(ListBase *users,
+ ID *id,
+ PointerRNA ptr,
+ PropertyRNA *prop,
+ bNodeTree *ntree,
+ bNode *node,
+ const char *category,
+ int icon,
+ const char *name)
+{
+ ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser");
+
+ user->id = id;
+ user->ptr = ptr;
+ user->prop = prop;
+ user->ntree = ntree;
+ user->node = node;
+ user->category = category;
+ user->icon = icon;
+ user->name = name;
+ user->index = BLI_listbase_count(users);
+
+ BLI_addtail(users, user);
+}
+
static void buttons_texture_user_property_add(ListBase *users,
ID *id,
PointerRNA ptr,
@@ -139,20 +168,66 @@ static void buttons_texture_users_find_nodetree(ListBase *users,
}
}
+static void buttons_texture_modifier_geonodes_users_add(Object *ob,
+ NodesModifierData *nmd,
+ bNodeTree *node_tree,
+ ListBase *users)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) {
+ if (node->type == NODE_GROUP && node->id) {
+ /* Recurse into the node group */
+ buttons_texture_modifier_geonodes_users_add(ob, nmd, (bNodeTree *)node->id, users);
+ }
+ else if (node->type == GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE) {
+ RNA_pointer_create(&node_tree->id, &RNA_Node, node, &ptr);
+ prop = RNA_struct_find_property(&ptr, "texture");
+ if (prop == NULL) {
+ continue;
+ }
+
+ PointerRNA texptr = RNA_property_pointer_get(&ptr, prop);
+ Tex *tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? (Tex *)texptr.data : NULL;
+ if (tex != NULL) {
+ buttons_texture_user_node_property_add(users,
+ &ob->id,
+ ptr,
+ prop,
+ node_tree,
+ node,
+ N_("Geometry Nodes"),
+ RNA_struct_ui_icon(ptr.type),
+ nmd->modifier.name);
+ }
+ }
+ }
+}
+
static void buttons_texture_modifier_foreach(void *userData,
Object *ob,
ModifierData *md,
const char *propname)
{
- PointerRNA ptr;
- PropertyRNA *prop;
ListBase *users = userData;
- RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
- prop = RNA_struct_find_property(&ptr, propname);
+ if (md->type == eModifierType_Nodes) {
+ NodesModifierData *nmd = (NodesModifierData *)md;
+ if (nmd->node_group != NULL) {
+ buttons_texture_modifier_geonodes_users_add(ob, nmd, nmd->node_group, users);
+ }
+ }
+ else {
+ PointerRNA ptr;
+ PropertyRNA *prop;
- buttons_texture_user_property_add(
- users, &ob->id, ptr, prop, N_("Modifiers"), RNA_struct_ui_icon(ptr.type), md->name);
+ RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
+ prop = RNA_struct_find_property(&ptr, propname);
+
+ buttons_texture_user_property_add(
+ users, &ob->id, ptr, prop, N_("Modifiers"), RNA_struct_ui_icon(ptr.type), md->name);
+ }
}
static void buttons_texture_modifier_gpencil_foreach(void *userData,
@@ -325,31 +400,32 @@ void buttons_texture_context_compute(const bContext *C, SpaceProperties *sbuts)
ct->texture = NULL;
if (ct->user) {
+ if (ct->user->node != NULL) {
+ /* Detect change of active texture node in same node tree, in that
+ * case we also automatically switch to the other node. */
+ if ((ct->user->node->flag & NODE_ACTIVE_TEXTURE) == 0) {
+ ButsTextureUser *user;
+ for (user = ct->users.first; user; user = user->next) {
+ if (user->ntree == ct->user->ntree && user->node != ct->user->node) {
+ if (user->node->flag & NODE_ACTIVE_TEXTURE) {
+ ct->user = user;
+ ct->index = BLI_findindex(&ct->users, user);
+ break;
+ }
+ }
+ }
+ }
+ }
if (ct->user->ptr.data) {
PointerRNA texptr;
Tex *tex;
- /* get texture datablock pointer if it's a property */
+ /* Get texture datablock pointer if it's a property. */
texptr = RNA_property_pointer_get(&ct->user->ptr, ct->user->prop);
tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL;
ct->texture = tex;
}
- else if (ct->user->node && !(ct->user->node->flag & NODE_ACTIVE_TEXTURE)) {
- ButsTextureUser *user;
-
- /* detect change of active texture node in same node tree, in that
- * case we also automatically switch to the other node */
- for (user = ct->users.first; user; user = user->next) {
- if (user->ntree == ct->user->ntree && user->node != ct->user->node) {
- if (user->node->flag & NODE_ACTIVE_TEXTURE) {
- ct->user = user;
- ct->index = BLI_findindex(&ct->users, user);
- break;
- }
- }
- }
- }
}
}
}
@@ -357,7 +433,7 @@ void buttons_texture_context_compute(const bContext *C, SpaceProperties *sbuts)
static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg))
{
/* callback when selecting a texture user in the menu */
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
+ SpaceProperties *sbuts = find_space_properties(C);
ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
ButsTextureUser *user = (ButsTextureUser *)user_p;
PointerRNA texptr;
@@ -371,8 +447,15 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)
if (user->node) {
ED_node_set_active(CTX_data_main(C), user->ntree, user->node, NULL);
ct->texture = NULL;
+
+ /* Not totally sure if we should also change selection? */
+ LISTBASE_FOREACH (bNode *, node, &user->ntree->nodes) {
+ nodeSetSelected(node, false);
+ }
+ nodeSetSelected(user->node, true);
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
- else {
+ if (user->ptr.data) {
texptr = RNA_property_pointer_get(&user->ptr, user->prop);
tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL;
@@ -511,16 +594,53 @@ void uiTemplateTextureUser(uiLayout *layout, bContext *C)
/************************* Texture Show **************************/
+static ScrArea *find_area_properties(const bContext *C)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ Object *ob = CTX_data_active_object(C);
+
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ if (area->spacetype == SPACE_PROPERTIES) {
+ /* Only if unpinned, or if pinned object matches. */
+ SpaceProperties *sbuts = area->spacedata.first;
+ ID *pinid = sbuts->pinid;
+ if (pinid == NULL || ((GS(pinid->name) == ID_OB) && (Object *)pinid == ob)) {
+ return area;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static SpaceProperties *find_space_properties(const bContext *C)
+{
+ ScrArea *area = find_area_properties(C);
+ if (area != NULL) {
+ return area->spacedata.first;
+ }
+
+ return NULL;
+}
+
static void template_texture_show(bContext *C, void *data_p, void *prop_p)
{
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
- ButsTextureUser *user;
+ if (data_p == NULL || prop_p == NULL) {
+ return;
+ }
+
+ ScrArea *area = find_area_properties(C);
+ if (area == NULL) {
+ return;
+ }
+ SpaceProperties *sbuts = (SpaceProperties *)area->spacedata.first;
+ ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
if (!ct) {
return;
}
+ ButsTextureUser *user;
for (user = ct->users.first; user; user = user->next) {
if (user->ptr.data == data_p && user->prop == prop_p) {
break;
@@ -537,48 +657,65 @@ static void template_texture_show(bContext *C, void *data_p, void *prop_p)
sbuts->preview = 1;
/* redraw editor */
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(area);
}
}
+/* Button to quickly show texture in Properties Editor texture tab. */
void uiTemplateTextureShow(uiLayout *layout, const bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
- /* button to quickly show texture in texture tab */
- SpaceProperties *sbuts = CTX_wm_space_properties(C);
- ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
- ButsTextureUser *user;
+ /* Only show the button if there is actually a texture assigned. */
+ Tex *texture = RNA_property_pointer_get(ptr, prop).data;
+ if (texture == NULL) {
+ return;
+ }
- /* only show button in other tabs in properties editor */
- if (!ct || sbuts->mainb == BCONTEXT_TEXTURE) {
+ /* Only show the button if we are not in the Properties Editor's texture tab. */
+ SpaceProperties *sbuts_context = CTX_wm_space_properties(C);
+ if (sbuts_context != NULL && sbuts_context->mainb == BCONTEXT_TEXTURE) {
return;
}
+ SpaceProperties *sbuts = find_space_properties(C);
+ ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL;
+
/* find corresponding texture user */
- for (user = ct->users.first; user; user = user->next) {
- if (user->ptr.data == ptr->data && user->prop == prop) {
- break;
+ ButsTextureUser *user;
+ bool user_found = false;
+ if (ct != NULL) {
+ for (user = ct->users.first; user; user = user->next) {
+ if (user->ptr.data == ptr->data && user->prop == prop) {
+ user_found = true;
+ break;
+ }
}
}
- /* draw button */
- if (user) {
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but;
-
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_PROPERTIES,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- TIP_("Show texture in texture tab"));
- UI_but_func_set(but, template_texture_show, user->ptr.data, user->prop);
+ /* Draw button (disabled if we cannot find a Properties Editor to display this in). */
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *but;
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_PROPERTIES,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Show texture in texture tab"));
+ UI_but_func_set(but,
+ template_texture_show,
+ user_found ? user->ptr.data : NULL,
+ user_found ? user->prop : NULL);
+ if (ct == NULL) {
+ UI_but_disable(but, TIP_("No (unpinned) Properties Editor found to display texture in"));
+ }
+ else if (!user_found) {
+ UI_but_disable(but, TIP_("No texture user found"));
}
}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index cbe8ec4ba00..471b4a4bf5b 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -46,6 +46,7 @@
#include "ED_gpencil.h"
#include "ED_mask.h"
#include "ED_screen.h"
+#include "ED_util.h"
#include "BIF_glutil.h"
diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c
index b65dc909d5f..96504651e44 100644
--- a/source/blender/editors/space_clip/tracking_ops_solve.c
+++ b/source/blender/editors/space_clip/tracking_ops_solve.c
@@ -244,7 +244,7 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
/* add modal handler for ESC */
WM_event_add_modal_handler(C, op);
diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c
index e480ec2db05..9882304d97d 100644
--- a/source/blender/editors/space_clip/tracking_ops_track.c
+++ b/source/blender/editors/space_clip/tracking_ops_track.c
@@ -356,7 +356,7 @@ static int track_markers(bContext *C, wmOperator *op, bool use_job)
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
/* Add modal handler for ESC. */
WM_event_add_modal_handler(C, op);
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index 56fb588776e..deb32812f44 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -112,6 +112,21 @@ int autocomplete_file(struct bContext *C, char *str, void *arg_v);
void file_params_renamefile_activate(struct SpaceFile *sfile, struct FileSelectParams *params);
+typedef void *onReloadFnData;
+typedef void (*onReloadFn)(struct SpaceFile *space_data, onReloadFnData custom_data);
+typedef struct SpaceFile_Runtime {
+ /* Called once after the file browser has reloaded. Reset to NULL after calling.
+ * Use file_on_reload_callback_register() to register a callback. */
+ onReloadFn on_reload;
+ onReloadFnData on_reload_custom_data;
+} SpaceFile_Runtime;
+
+/* Register an on-reload callback function. Note that there can only be one such function at a
+ * time; registering a new one will overwrite the previous one. */
+void file_on_reload_callback_register(struct SpaceFile *sfile,
+ onReloadFn callback,
+ onReloadFnData custom_data);
+
/* file_panels.c */
void file_tool_props_region_panels_register(struct ARegionType *art);
void file_execute_region_panels_register(struct ARegionType *art);
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 33c37875372..757ec7c741f 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -410,14 +410,14 @@ typedef struct FileList {
/* Set given path as root directory,
* if last bool is true may change given string in place to a valid value.
* Returns True if valid dir. */
- bool (*checkdirf)(struct FileList *, char *, const bool);
+ bool (*check_dir_fn)(struct FileList *, char *, const bool);
/* Fill filelist (to be called by read job). */
- void (*read_jobf)(
+ void (*read_job_fn)(
Main *, struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
/* Filter an entry of current filelist. */
- bool (*filterf)(struct FileListInternEntry *, const char *, FileListFilter *);
+ bool (*filter_fn)(struct FileListInternEntry *, const char *, FileListFilter *);
short tags; /* FileListTags */
} FileList;
@@ -963,7 +963,7 @@ void filelist_filter(FileList *filelist)
/* Filter remap & count how many files are left after filter in a single loop. */
for (file = filelist->filelist_intern.entries.first; file; file = file->next) {
- if (filelist->filterf(file, filelist->filelist.root, &filelist->filter_data)) {
+ if (filelist->filter_fn(file, filelist->filelist.root, &filelist->filter_data)) {
filtered_tmp[num_filtered++] = file;
}
}
@@ -1742,25 +1742,25 @@ void filelist_settype(FileList *filelist, short type)
filelist->tags = 0;
switch (filelist->type) {
case FILE_MAIN:
- filelist->checkdirf = filelist_checkdir_main;
- filelist->read_jobf = filelist_readjob_main;
- filelist->filterf = is_filtered_main;
+ filelist->check_dir_fn = filelist_checkdir_main;
+ filelist->read_job_fn = filelist_readjob_main;
+ filelist->filter_fn = is_filtered_main;
break;
case FILE_LOADLIB:
- filelist->checkdirf = filelist_checkdir_lib;
- filelist->read_jobf = filelist_readjob_lib;
- filelist->filterf = is_filtered_lib;
+ filelist->check_dir_fn = filelist_checkdir_lib;
+ filelist->read_job_fn = filelist_readjob_lib;
+ filelist->filter_fn = is_filtered_lib;
break;
case FILE_MAIN_ASSET:
- filelist->checkdirf = filelist_checkdir_main_assets;
- filelist->read_jobf = filelist_readjob_main_assets;
- filelist->filterf = is_filtered_main_assets;
+ filelist->check_dir_fn = filelist_checkdir_main_assets;
+ filelist->read_job_fn = filelist_readjob_main_assets;
+ filelist->filter_fn = is_filtered_main_assets;
filelist->tags |= FILELIST_TAGS_USES_MAIN_DATA | FILELIST_TAGS_NO_THREADS;
break;
default:
- filelist->checkdirf = filelist_checkdir_dir;
- filelist->read_jobf = filelist_readjob_dir;
- filelist->filterf = is_filtered_file;
+ filelist->check_dir_fn = filelist_checkdir_dir;
+ filelist->read_job_fn = filelist_readjob_dir;
+ filelist->filter_fn = is_filtered_file;
break;
}
@@ -1867,7 +1867,7 @@ const char *filelist_dir(struct FileList *filelist)
bool filelist_is_dir(struct FileList *filelist, const char *path)
{
- return filelist->checkdirf(filelist, (char *)path, false);
+ return filelist->check_dir_fn(filelist, (char *)path, false);
}
/**
@@ -1879,7 +1879,7 @@ void filelist_setdir(struct FileList *filelist, char *r_dir)
BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
BLI_path_normalize_dir(BKE_main_blendfile_path_from_global(), r_dir);
- const bool is_valid_path = filelist->checkdirf(filelist, r_dir, !allow_invalid);
+ const bool is_valid_path = filelist->check_dir_fn(filelist, r_dir, !allow_invalid);
BLI_assert(is_valid_path || allow_invalid);
UNUSED_VARS_NDEBUG(is_valid_path);
@@ -1990,9 +1990,7 @@ static void filelist_file_release_entry(FileList *filelist, FileDirEntry *entry)
filelist_entry_free(entry);
}
-static FileDirEntry *filelist_file_ex(struct FileList *filelist,
- const int index,
- const bool use_request)
+FileDirEntry *filelist_file_ex(struct FileList *filelist, const int index, const bool use_request)
{
FileDirEntry *ret = NULL, *old;
FileListEntryCache *cache = &filelist->filelist_cache;
@@ -3358,13 +3356,13 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update
BLI_mutex_unlock(&flrj->lock);
- flrj->tmp_filelist->read_jobf(flrj->current_main,
- flrj->tmp_filelist,
- flrj->main_name,
- stop,
- do_update,
- progress,
- &flrj->lock);
+ flrj->tmp_filelist->read_job_fn(flrj->current_main,
+ flrj->tmp_filelist,
+ flrj->main_name,
+ stop,
+ do_update,
+ progress,
+ &flrj->lock);
}
static void filelist_readjob_update(void *flrjv)
@@ -3464,7 +3462,7 @@ void filelist_readjob_start(FileList *filelist, const bContext *C)
filelist_readjob_endjob(flrj);
filelist_readjob_free(flrj);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST | NA_JOB_FINISHED, NULL);
return;
}
@@ -3476,7 +3474,10 @@ void filelist_readjob_start(FileList *filelist, const bContext *C)
WM_JOB_PROGRESS,
WM_JOB_TYPE_FILESEL_READDIR);
WM_jobs_customdata_set(wm_job, flrj, filelist_readjob_free);
- WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST);
+ WM_jobs_timer(wm_job,
+ 0.01,
+ NC_SPACE | ND_SPACE_FILE_LIST,
+ NC_SPACE | ND_SPACE_FILE_LIST | NA_JOB_FINISHED);
WM_jobs_callbacks(
wm_job, filelist_readjob_startjob, NULL, filelist_readjob_update, filelist_readjob_endjob);
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index 16984bb6e43..7eecd7a05de 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -93,6 +93,8 @@ void filelist_setdir(struct FileList *filelist, char *r_dir);
int filelist_files_ensure(struct FileList *filelist);
int filelist_needs_reading(struct FileList *filelist);
FileDirEntry *filelist_file(struct FileList *filelist, int index);
+FileDirEntry *filelist_file_ex(struct FileList *filelist, int index, bool use_request);
+
int filelist_file_findpath(struct FileList *filelist, const char *file);
struct ID *filelist_file_get_id(const struct FileDirEntry *file);
FileDirEntry *filelist_entry_find_uuid(struct FileList *filelist, const int uuid[4]);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 6917893ab5f..7015ca970a3 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -454,6 +454,66 @@ bool ED_fileselect_is_asset_browser(const SpaceFile *sfile)
return (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS);
}
+struct ID *ED_fileselect_active_asset_get(const SpaceFile *sfile)
+{
+ if (!ED_fileselect_is_asset_browser(sfile)) {
+ return NULL;
+ }
+
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ const FileDirEntry *file = filelist_file(sfile->files, params->active_file);
+ if (file == NULL) {
+ return NULL;
+ }
+
+ return filelist_file_get_id(file);
+}
+
+static void on_reload_activate_by_id(SpaceFile *sfile, onReloadFnData custom_data)
+{
+ ID *asset_id = (ID *)custom_data;
+ ED_fileselect_activate_by_id(sfile, asset_id, false);
+}
+
+void ED_fileselect_activate_by_id(SpaceFile *sfile, ID *asset_id, const bool deferred)
+{
+ if (!ED_fileselect_is_asset_browser(sfile)) {
+ return;
+ }
+
+ /* If there are filelist operations running now ("pending" true) or soon ("force reset" true),
+ * there is a fair chance that the to-be-activated ID will only be present after these operations
+ * have completed. Defer activation until then. */
+ if (deferred || filelist_pending(sfile->files) || filelist_needs_force_reset(sfile->files)) {
+ /* This should be thread-safe, as this function is likely called from the main thread, and
+ * notifiers (which cause a call to the on-reload callback function) are handled on the main
+ * thread as well. */
+ file_on_reload_callback_register(sfile, on_reload_activate_by_id, asset_id);
+ return;
+ }
+
+ FileSelectParams *params = ED_fileselect_get_active_params(sfile);
+ struct FileList *files = sfile->files;
+
+ const int num_files_filtered = filelist_files_ensure(files);
+ for (int file_index = 0; file_index < num_files_filtered; ++file_index) {
+ const FileDirEntry *file = filelist_file_ex(files, file_index, false);
+
+ if (filelist_file_get_id(file) != asset_id) {
+ filelist_entry_select_set(files, file, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ continue;
+ }
+
+ params->active_file = file_index;
+ filelist_entry_select_set(files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+
+ /* Keep looping to deselect the other files. */
+ }
+
+ WM_main_add_notifier(NC_ASSET | NA_ACTIVATED, NULL);
+ WM_main_add_notifier(NC_ASSET | NA_SELECTED, NULL);
+}
+
/* The subset of FileSelectParams.flag items we store into preferences. Note that FILE_SORT_ALPHA
* may also be remembered, but only conditionally. */
#define PARAMS_FLAGS_REMEMBERED (FILE_HIDE_DOT)
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index b175844a710..2c9c2688e88 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -173,6 +173,7 @@ static void file_free(SpaceLink *sl)
MEM_SAFE_FREE(sfile->params);
MEM_SAFE_FREE(sfile->asset_params);
+ MEM_SAFE_FREE(sfile->runtime);
if (sfile->layout) {
MEM_freeN(sfile->layout);
@@ -188,6 +189,10 @@ static void file_init(wmWindowManager *UNUSED(wm), ScrArea *area)
if (sfile->layout) {
sfile->layout->dirty = true;
}
+
+ if (sfile->runtime == NULL) {
+ sfile->runtime = MEM_callocN(sizeof(*sfile->runtime), __func__);
+ }
}
static void file_exit(wmWindowManager *wm, ScrArea *area)
@@ -209,6 +214,7 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
/* clear or remove stuff from old */
sfilen->op = NULL; /* file window doesn't own operators */
+ sfilen->runtime = NULL;
sfilen->previews_timer = NULL;
sfilen->smoothscroll_timer = NULL;
@@ -392,6 +398,26 @@ static void file_refresh(const bContext *C, ScrArea *area)
ED_area_tag_redraw(area);
}
+void file_on_reload_callback_register(SpaceFile *sfile,
+ onReloadFn callback,
+ onReloadFnData custom_data)
+{
+ sfile->runtime->on_reload = callback;
+ sfile->runtime->on_reload_custom_data = custom_data;
+}
+
+static void file_on_reload_callback_call(SpaceFile *sfile)
+{
+ if (sfile->runtime->on_reload == NULL) {
+ return;
+ }
+
+ sfile->runtime->on_reload(sfile, sfile->runtime->on_reload_custom_data);
+
+ sfile->runtime->on_reload = NULL;
+ sfile->runtime->on_reload_custom_data = NULL;
+}
+
static void file_listener(const wmSpaceTypeListenerParams *params)
{
ScrArea *area = params->area;
@@ -419,12 +445,26 @@ static void file_listener(const wmSpaceTypeListenerParams *params)
}
break;
}
+ switch (wmn->action) {
+ case NA_JOB_FINISHED:
+ file_on_reload_callback_call(sfile);
+ break;
+ }
break;
case NC_ASSET: {
- if (sfile->files && filelist_needs_reset_on_main_changes(sfile->files)) {
- /* Full refresh of the file list if local asset data was changed. Refreshing this view is
- * cheap and users expect this to be updated immediately. */
- file_tag_reset_list(area, sfile);
+ switch (wmn->action) {
+ case NA_SELECTED:
+ case NA_ACTIVATED:
+ ED_area_tag_refresh(area);
+ break;
+ case NA_ADDED:
+ case NA_REMOVED:
+ if (sfile->files && filelist_needs_reset_on_main_changes(sfile->files)) {
+ /* Full refresh of the file list if local asset data was changed. Refreshing this view
+ * is cheap and users expect this to be updated immediately. */
+ file_tag_reset_list(area, sfile);
+ }
+ break;
}
break;
}
@@ -464,8 +504,7 @@ static void file_main_region_listener(const wmRegionListenerParams *params)
}
break;
case NC_ID:
- if (ELEM(wmn->action, NA_RENAME)) {
- /* In case the filelist shows ID names. */
+ if (ELEM(wmn->action, NA_SELECTED, NA_ACTIVATED, NA_RENAME)) {
ED_region_tag_redraw(region);
}
break;
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 67d5055ec65..2be6d31369c 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -68,6 +68,7 @@
#include "ED_mask.h"
#include "ED_render.h"
#include "ED_screen.h"
+#include "ED_util.h"
#include "UI_interface.h"
#include "UI_resources.h"
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 4008ca228ac..fc3619f01b9 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1816,11 +1816,11 @@ static bool save_image_op(
opts->save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") &&
RNA_boolean_get(op->ptr, "save_as_render"));
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
bool ok = BKE_image_save(op->reports, bmain, ima, iuser, opts);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
/* Remember file path for next save. */
BLI_strncpy(G.ima, opts->filepath, sizeof(G.ima));
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 95ca8aba399..c51d2f25efd 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -54,6 +54,7 @@
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_transform.h"
+#include "ED_util.h"
#include "ED_uvedit.h"
#include "WM_api.h"
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index fb297672f0f..f2cea23af76 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -594,11 +594,11 @@ static int nla_action_unlink_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
/* NOTE: this is hardcoded to match the behavior for the unlink button
* (in interface_templates.c) */
- RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
+ RNA_boolean_set(op->ptr, "force_delete", event->shift != 0);
return nla_action_unlink_exec(C, op);
}
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index c640b076ba4..bc043a4e665 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -42,6 +42,7 @@ set(SRC
node_buttons.c
node_draw.cc
node_edit.c
+ node_geometry_attribute_search.cc
node_gizmo.c
node_group.c
node_ops.c
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 82a1cd818c9..977c2053187 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -3389,7 +3389,15 @@ static void std_node_socket_draw(
case SOCK_STRING: {
uiLayout *row = uiLayoutSplit(layout, 0.5f, false);
uiItemL(row, text, 0);
- uiItemR(row, ptr, "default_value", DEFAULT_FLAGS, "", 0);
+
+ const bNodeTree *node_tree = (const bNodeTree *)node_ptr->owner_id;
+ if (node_tree->type == NTREE_GEOMETRY) {
+ node_geometry_add_attribute_search_button(node_tree, node, ptr, row);
+ }
+ else {
+ uiItemR(row, ptr, "default_value", DEFAULT_FLAGS, "", 0);
+ }
+
break;
}
case SOCK_OBJECT: {
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 162f3878f7e..5a0cacf070b 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -1236,16 +1236,15 @@ static char *node_errors_tooltip_fn(bContext *UNUSED(C), void *argN, const char
for (const NodeWarning &warning : warnings.drop_back(1)) {
complete_string += warning.message;
+ /* Adding the period is not ideal for multi-line messages, but it is consistent
+ * with other tooltip implementations in Blender, so it is added here. */
+ complete_string += '.';
complete_string += '\n';
}
+ /* Let the tooltip system automatically add the last period. */
complete_string += warnings.last().message;
- /* Remove the last period-- the tooltip system adds this automatically. */
- if (complete_string.back() == '.') {
- complete_string.pop_back();
- }
-
return BLI_strdupn(complete_string.c_str(), complete_string.size());
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 4826b6c72ba..5205e50b0bf 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -2231,10 +2231,13 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
link->tosock->new_sock);
}
- ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+ Main *bmain = CTX_data_main(C);
+ ntreeUpdateTree(bmain, snode->edittree);
snode_notify(C, snode);
snode_dag_update(C, snode);
+ /* Pasting nodes can create arbitrary new relations, because nodes can reference IDs. */
+ DEG_relations_tag_update(bmain);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc
new file mode 100644
index 00000000000..b03346577a8
--- /dev/null
+++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+#include "BLI_index_range.hh"
+#include "BLI_listbase.h"
+#include "BLI_map.hh"
+#include "BLI_set.hh"
+#include "BLI_string_ref.hh"
+#include "BLI_string_search.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_node_ui_storage.hh"
+#include "BKE_object.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "node_intern.h"
+
+using blender::IndexRange;
+using blender::Map;
+using blender::Set;
+using blender::StringRef;
+
+struct AttributeSearchData {
+ const bNodeTree &node_tree;
+ const bNode &node;
+
+ uiBut *search_button;
+
+ /* Used to keep track of a button pointer over multiple redraws. Since the UI code
+ * may reallocate the button, without this we might end up with a dangling pointer. */
+ uiButStore *button_store;
+ uiBlock *button_store_block;
+};
+
+static void attribute_search_update_fn(
+ const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
+{
+ AttributeSearchData *data = static_cast<AttributeSearchData *>(arg);
+ const NodeUIStorage *ui_storage = BKE_node_tree_ui_storage_get_from_context(
+ C, data->node_tree, data->node);
+ if (ui_storage == nullptr) {
+ return;
+ }
+
+ const Set<std::string> &attribute_name_hints = ui_storage->attribute_name_hints;
+
+ if (str[0] != '\0' && !attribute_name_hints.contains_as(StringRef(str))) {
+ /* Any string may be valid, so add the current search string with the hints. */
+ UI_search_item_add(items, str, (void *)str, ICON_ADD, 0, 0);
+ }
+
+ if (str[0] == '\0' && !is_first) {
+ /* Allow clearing the text field when the string is empty, but not on the first pass,
+ * or opening an attribute field for the first time would show this search item. */
+ UI_search_item_add(items, str, (void *)str, ICON_X, 0, 0);
+ }
+
+ /* Don't filter when the menu is first opened, but still run the search
+ * so the items are in the same order they will appear in while searching. */
+ const char *string = is_first ? "" : str;
+
+ StringSearch *search = BLI_string_search_new();
+ for (const std::string &attribute_name : attribute_name_hints) {
+ BLI_string_search_add(search, attribute_name.c_str(), (void *)&attribute_name);
+ }
+
+ std::string **filtered_items;
+ const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items);
+
+ for (const int i : IndexRange(filtered_amount)) {
+ std::string *item = filtered_items[i];
+ if (!UI_search_item_add(items, item->c_str(), item, ICON_NONE, 0, 0)) {
+ break;
+ }
+ }
+
+ MEM_freeN(filtered_items);
+ BLI_string_search_free(search);
+}
+
+static void attribute_search_free_fn(void *arg)
+{
+ AttributeSearchData *data = static_cast<AttributeSearchData *>(arg);
+
+ UI_butstore_free(data->button_store_block, data->button_store);
+ delete data;
+}
+
+void node_geometry_add_attribute_search_button(const bNodeTree *node_tree,
+ const bNode *node,
+ PointerRNA *socket_ptr,
+ uiLayout *layout)
+{
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiBut *but = uiDefIconTextButR(block,
+ UI_BTYPE_SEARCH_MENU,
+ 0,
+ ICON_NONE,
+ "",
+ 0,
+ 0,
+ 10 * UI_UNIT_X, /* Dummy value, replaced by layout system. */
+ UI_UNIT_Y,
+ socket_ptr,
+ "default_value",
+ 0,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ "");
+
+ AttributeSearchData *data = new AttributeSearchData{
+ *node_tree,
+ *node,
+ but,
+ UI_butstore_create(block),
+ block,
+ };
+
+ UI_butstore_register(data->button_store, &data->search_button);
+
+ UI_but_func_search_set_results_are_suggestions(but, true);
+ UI_but_func_search_set(but,
+ nullptr,
+ attribute_search_update_fn,
+ static_cast<void *>(data),
+ attribute_search_free_fn,
+ nullptr,
+ nullptr);
+}
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 5973d59e68f..19700b258ae 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -57,6 +57,9 @@ typedef struct bNodeLinkDrag {
ListBase links;
bool from_multi_input_socket;
int in_out;
+
+ /** Temporarily stores the last picked link from multi input socket operator. */
+ struct bNodeLink *last_picked_multi_input_socket_link;
} bNodeLinkDrag;
typedef struct SpaceNode_Runtime {
@@ -289,6 +292,12 @@ void NODE_GGT_backdrop_corner_pin(struct wmGizmoGroupType *gzgt);
void NODE_OT_cryptomatte_layer_add(struct wmOperatorType *ot);
void NODE_OT_cryptomatte_layer_remove(struct wmOperatorType *ot);
+/* node_geometry_attribute_search.cc */
+void node_geometry_add_attribute_search_button(const struct bNodeTree *node_tree,
+ const struct bNode *node,
+ struct PointerRNA *socket_ptr,
+ struct uiLayout *layout);
+
extern const char *node_context_dir[];
/* XXXXXX */
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index d6edfcce8e8..35dd865047e 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -280,7 +280,7 @@ static void pick_input_link_by_link_intersect(const bContext *C,
float distance = dist_squared_to_line_segment_v2(cursor, l1, l2);
if (distance < cursor_link_touch_distance) {
link_to_pick = link;
- RNA_int_set(op->ptr, "last_picked_link_index", link->multi_input_socket_index);
+ nldrag->last_picked_multi_input_socket_link = link_to_pick;
}
}
}
@@ -290,13 +290,9 @@ static void pick_input_link_by_link_intersect(const bContext *C,
* Not essential for the basic behavior, but can make interaction feel a bit better if
* the mouse moves to the right and loses the "selection." */
if (!link_to_pick) {
- int last_picked_link_index = RNA_int_get(op->ptr, "last_picked_link_index");
- if (last_picked_link_index > -1) {
- LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
- if (link->multi_input_socket_index == last_picked_link_index) {
- link_to_pick = link;
- }
- }
+ bNodeLink *last_picked_link = nldrag->last_picked_multi_input_socket_link;
+ if (last_picked_link) {
+ link_to_pick = last_picked_link;
}
}
@@ -1032,7 +1028,6 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
float cursor[2];
UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
RNA_float_set_array(op->ptr, "drag_start", cursor);
- RNA_int_set(op->ptr, "last_picked_link_index", -1);
RNA_boolean_set(op->ptr, "has_link_picked", false);
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
@@ -1102,15 +1097,6 @@ void NODE_OT_link(wmOperatorType *ot)
-UI_PRECISION_FLOAT_MAX,
UI_PRECISION_FLOAT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN);
- RNA_def_int(ot->srna,
- "last_picked_link_index",
- -1,
- -1,
- 4095,
- "Last Picked Link Index",
- "The index of the last picked link on a multi-input socket",
- -1,
- 4095);
RNA_def_property_flag(prop, PROP_HIDDEN);
}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index 58d22c2864f..704b7350bb9 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -1178,7 +1178,8 @@ static void node_find_create_label(const bNode *node, char *str, int maxlen)
static void node_find_update_fn(const struct bContext *C,
void *UNUSED(arg),
const char *str,
- uiSearchItems *items)
+ uiSearchItems *items,
+ const bool UNUSED(is_first))
{
SpaceNode *snode = CTX_wm_space_node(C);
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index d54265aa292..7b9bc44f986 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -57,6 +57,8 @@ set(SRC
tree/tree_element.cc
tree/tree_element_anim_data.cc
tree/tree_element_driver_base.cc
+ tree/tree_element_gpencil_layer.cc
+ tree/tree_element_id.cc
tree/tree_element_nla.cc
outliner_intern.h
@@ -66,6 +68,8 @@ set(SRC
tree/tree_element.hh
tree/tree_element_anim_data.hh
tree/tree_element_driver_base.hh
+ tree/tree_element_gpencil_layer.hh
+ tree/tree_element_id.hh
tree/tree_element_nla.hh
)
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 0afc26e0d8a..d54e35f659c 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -71,7 +71,7 @@ bool outliner_is_collection_tree_element(const TreeElement *te)
TSE_VIEW_COLLECTION_BASE)) {
return true;
}
- if (tselem->type == 0 && te->idcode == ID_GR) {
+ if ((tselem->type == TSE_SOME_ID) && te->idcode == ID_GR) {
return true;
}
@@ -94,7 +94,7 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te)
Scene *scene = (Scene *)tselem->id;
return scene->master_collection;
}
- if (tselem->type == 0 && te->idcode == ID_GR) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_GR)) {
return (Collection *)tselem->id;
}
@@ -111,7 +111,7 @@ TreeTraversalAction outliner_find_selected_collections(TreeElement *te, void *cu
return TRAVERSE_CONTINUE;
}
- if (tselem->type || (tselem->id && GS(tselem->id->name) != ID_GR)) {
+ if ((tselem->type != TSE_SOME_ID) || (tselem->id && GS(tselem->id->name) != ID_GR)) {
return TRAVERSE_SKIP_CHILDS;
}
@@ -127,7 +127,7 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom
return TRAVERSE_CONTINUE;
}
- if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
+ if ((tselem->type != TSE_SOME_ID) || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
return TRAVERSE_SKIP_CHILDS;
}
@@ -1367,7 +1367,7 @@ void OUTLINER_OT_collection_enable(wmOperatorType *ot)
/* identifiers */
ot->name = "Enable Collection";
ot->idname = "OUTLINER_OT_collection_enable";
- ot->description = "Enable viewport drawing in the view layers";
+ ot->description = "Enable viewport display in the view layers";
/* api callbacks */
ot->exec = collection_flag_exec;
@@ -1382,7 +1382,7 @@ void OUTLINER_OT_collection_disable(wmOperatorType *ot)
/* identifiers */
ot->name = "Disable Collection";
ot->idname = "OUTLINER_OT_collection_disable";
- ot->description = "Disable viewport drawing in the view layers";
+ ot->description = "Disable viewport display in the view layers";
/* api callbacks */
ot->exec = collection_flag_exec;
@@ -1458,7 +1458,7 @@ static TreeTraversalAction outliner_hide_find_data_to_edit(TreeElement *te, void
BLI_gset_add(data->collections_to_edit, lc);
}
}
- else if (tselem->type == 0 && te->idcode == ID_OB) {
+ else if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
Object *ob = (Object *)tselem->id;
Base *base = BKE_view_layer_base_find(data->view_layer, ob);
BLI_gset_add(data->bases_to_edit, base);
diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c
index e2b3b79e027..4293d8da73e 100644
--- a/source/blender/editors/space_outliner/outliner_context.c
+++ b/source/blender/editors/space_outliner/outliner_context.c
@@ -34,7 +34,7 @@ static void outliner_context_selected_ids_recursive(const ListBase *subtree,
{
LISTBASE_FOREACH (const TreeElement *, te, subtree) {
const TreeStoreElem *tse = TREESTORE(te);
- if ((tse->flag & TSE_SELECTED) && (ELEM(tse->type, 0, TSE_LAYER_COLLECTION))) {
+ if ((tse->flag & TSE_SELECTED) && (ELEM(tse->type, TSE_SOME_ID, TSE_LAYER_COLLECTION))) {
CTX_data_id_list_add(result, tse->id);
}
outliner_context_selected_ids_recursive(&te->subtree, result);
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
index 3090cab75ae..01fb0fc6f78 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -124,7 +124,7 @@ static ID *outliner_ID_drop_find(bContext *C, const wmEvent *event, short idcode
TreeElement *te = outliner_drop_find(C, event);
TreeStoreElem *tselem = (te) ? TREESTORE(te) : NULL;
- if (te && te->idcode == idcode && tselem->type == 0) {
+ if (te && (te->idcode == idcode) && (tselem->type == TSE_SOME_ID)) {
return tselem->id;
}
return NULL;
@@ -215,7 +215,7 @@ static bool is_collection_element(TreeElement *te)
static bool is_object_element(TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
- return tselem->type == 0 && te->idcode == ID_OB;
+ return (tselem->type == TSE_SOME_ID) && te->idcode == ID_OB;
}
static bool is_pchan_element(TreeElement *te)
@@ -281,7 +281,7 @@ static int outliner_get_insert_index(TreeElement *drag_te,
static bool parent_drop_allowed(TreeElement *te, Object *potential_child)
{
TreeStoreElem *tselem = TREESTORE(te);
- if (te->idcode != ID_OB || tselem->type != 0) {
+ if ((te->idcode != ID_OB) || (tselem->type != TSE_SOME_ID)) {
return false;
}
@@ -421,7 +421,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
TreeElement *te = outliner_drop_find(C, event);
TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
- if (!(te && te->idcode == ID_OB && tselem->type == 0)) {
+ if (!(te && (te->idcode == ID_OB) && (tselem->type == TSE_SOME_ID))) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 008ae727947..690adb09570 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -675,7 +675,7 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
if (ts && tselem) {
TreeElement *te = outliner_find_tree_element(&space_outliner->tree, tselem);
- if (tselem->type == 0) {
+ if (tselem->type == TSE_SOME_ID) {
BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
switch (GS(tselem->id->name)) {
@@ -1100,11 +1100,11 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
}
}
- else if ((tselem->type == 0 && te->idcode == ID_OB) &&
+ else if (((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) &&
(te->flag & TE_CHILD_NOT_IN_COLLECTION)) {
/* Don't show restrict columns for children that are not directly inside the collection. */
}
- else if (tselem->type == 0 && te->idcode == ID_OB) {
+ else if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
PointerRNA ptr;
Object *ob = (Object *)tselem->id;
RNA_id_pointer_create(&ob->id, &ptr);
@@ -1699,7 +1699,7 @@ static void outliner_draw_userbuts(uiBlock *block,
LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) {
- if (tselem->type == 0) {
+ if (tselem->type == TSE_SOME_ID) {
uiBut *bt;
ID *id = tselem->id;
const char *tip = NULL;
@@ -1949,7 +1949,7 @@ static void outliner_draw_mode_column_toggle(uiBlock *block,
TreeStoreElem *tselem,
const bool lock_object_modes)
{
- if (tselem->type != 0 || te->idcode != ID_OB) {
+ if ((tselem->type != TSE_SOME_ID) || (te->idcode != ID_OB)) {
return;
}
@@ -2046,7 +2046,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
{
TreeElementIcon data = {0};
- if (tselem->type) {
+ if (tselem->type != TSE_SOME_ID) {
switch (tselem->type) {
case TSE_ANIM_DATA:
data.icon = ICON_ANIM_DATA; /* XXX */
@@ -2825,7 +2825,8 @@ int tree_element_id_type_to_index(TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
- const int id_index = tselem->type == 0 ? BKE_idtype_idcode_to_index(te->idcode) : INDEX_ID_GR;
+ const int id_index = (tselem->type == TSE_SOME_ID) ? BKE_idtype_idcode_to_index(te->idcode) :
+ INDEX_ID_GR;
if (id_index < INDEX_ID_OB) {
return id_index;
}
@@ -2862,9 +2863,9 @@ static void outliner_draw_iconrow(bContext *C,
te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED);
/* object hierarchy always, further constrained on level */
- if (level < 1 || (tselem->type == 0 && te->idcode == ID_OB)) {
+ if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB))) {
/* active blocks get white circle */
- if (tselem->type == 0) {
+ if (tselem->type == TSE_SOME_ID) {
if (te->idcode == ID_OB) {
active = (tvc->obact == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
}
@@ -2879,7 +2880,7 @@ static void outliner_draw_iconrow(bContext *C,
active = tree_element_type_active_state_get(C, tvc, te, tselem);
}
- if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION, TSE_R_LAYER, TSE_GP_LAYER)) {
+ if (!ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION, TSE_R_LAYER, TSE_GP_LAYER)) {
outliner_draw_iconrow_doit(block, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1);
}
else {
@@ -2954,7 +2955,7 @@ static bool element_should_draw_faded(const TreeViewContext *tvc,
const TreeElement *te,
const TreeStoreElem *tselem)
{
- if (tselem->type == 0) {
+ if (tselem->type == TSE_SOME_ID) {
switch (te->idcode) {
case ID_OB: {
const Object *ob = (const Object *)tselem->id;
@@ -3023,7 +3024,7 @@ static void outliner_draw_tree_element(bContext *C,
GPU_blend(GPU_BLEND_ALPHA);
/* Colors for active/selected data. */
- if (tselem->type == 0) {
+ if (tselem->type == TSE_SOME_ID) {
if (te->idcode == ID_OB) {
Object *ob = (Object *)tselem->id;
Base *base = (te->directdata) ? (Base *)te->directdata :
@@ -3080,7 +3081,7 @@ static void outliner_draw_tree_element(bContext *C,
if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
/* Scene collection in view layer can't expand/collapse. */
}
- else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) ||
+ else if (te->subtree.first || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_SCE)) ||
(te->flag & TE_LAZY_CLOSED)) {
/* Open/close icon, only when sub-levels, except for scene. */
int icon_x = startx;
@@ -3117,7 +3118,7 @@ static void outliner_draw_tree_element(bContext *C,
offsx += 2 * ufac;
}
- if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) ||
+ if (ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION) ||
((tselem->type == TSE_RNA_STRUCT) && RNA_struct_is_ID(te->rnaptr.type))) {
const BIFIconID lib_icon = UI_icon_from_library(tselem->id);
if (lib_icon != ICON_NONE) {
@@ -3143,7 +3144,7 @@ static void outliner_draw_tree_element(bContext *C,
/* Closed item, we draw the icons, not when it's a scene, or master-server list though. */
if (!TSELEM_OPEN(tselem, space_outliner)) {
if (te->subtree.first) {
- if (tselem->type == 0 && te->idcode == ID_SCE) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_SCE)) {
/* Pass. */
}
/* this tree element always has same amount of branches, so don't draw */
@@ -3210,7 +3211,7 @@ static bool subtree_contains_object(ListBase *lb)
{
LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
return true;
}
}
@@ -3265,7 +3266,7 @@ static void outliner_draw_hierarchy_lines_recursive(uint pos,
y = *starty;
}
- else if (tselem->type == 0 && te->idcode == ID_OB) {
+ else if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
if (subtree_contains_object(&te->subtree)) {
draw_hierarchy_line = true;
is_object_line = true;
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index d1260f02c67..18abe17d515 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -464,7 +464,8 @@ static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeSto
ID *id = tselem->id;
BLI_assert(id != NULL);
- BLI_assert(ELEM(tselem->type, 0 && te->idcode != 0, TSE_LAYER_COLLECTION));
+ BLI_assert(((tselem->type == TSE_SOME_ID) && (te->idcode != 0)) ||
+ (tselem->type == TSE_LAYER_COLLECTION));
UNUSED_VARS_NDEBUG(te);
if (te->idcode == ID_LI && ((Library *)id)->parent != NULL) {
@@ -638,7 +639,7 @@ static bool outliner_id_remap_find_tree_element(bContext *C,
if (y > te->ys && y < te->ys + UI_UNIT_Y) {
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0 && tselem->id) {
+ if ((tselem->type == TSE_SOME_ID) && tselem->id) {
printf("found id %s (%p)!\n", tselem->id->name, tselem->id);
RNA_enum_set(op->ptr, "id_type", GS(tselem->id->name));
@@ -763,7 +764,7 @@ static int outliner_id_copy_tag(SpaceOutliner *space_outliner, ListBase *tree)
TreeStoreElem *tselem = TREESTORE(te);
/* if item is selected and is an ID, tag it as needing to be copied. */
- if (tselem->flag & TSE_SELECTED && ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
+ if (tselem->flag & TSE_SELECTED && ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) {
ID *id = tselem->id;
if (!(id->tag & LIB_TAG_DOIT)) {
BKE_copybuffer_tag_ID(tselem->id);
@@ -1640,7 +1641,7 @@ static int subtree_has_objects(ListBase *lb)
{
LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
return 1;
}
if (subtree_has_objects(&te->subtree)) {
@@ -1658,7 +1659,7 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOutliner *space_outli
TreeStoreElem *tselem = TREESTORE(te);
if (ELEM(tselem->type,
- 0,
+ TSE_SOME_ID,
TSE_SCENE_OBJECTS_BASE,
TSE_VIEW_COLLECTION_BASE,
TSE_LAYER_COLLECTION)) {
@@ -2267,7 +2268,7 @@ static bool ed_operator_outliner_id_orphans_active(bContext *C)
/** \} */
-static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
+static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Main *bmain = CTX_data_main(C);
int num_tagged[INDEX_ID_MAX] = {0};
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index e31af48ab7e..d53a37fa60e 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -198,7 +198,7 @@ void outliner_item_mode_toggle(bContext *C,
{
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
Object *ob = (Object *)tselem->id;
Base *base = BKE_view_layer_base_find(tvc->view_layer, ob);
@@ -301,7 +301,7 @@ static void tree_element_object_activate(bContext *C,
Object *ob = NULL;
/* if id is not object, we search back */
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
ob = (Object *)tselem->id;
}
else {
@@ -443,7 +443,7 @@ static void tree_element_world_activate(bContext *C, Scene *scene, TreeElement *
TreeElement *tep = te->parent;
if (tep) {
TreeStoreElem *tselem = TREESTORE(tep);
- if (tselem->type == 0) {
+ if (tselem->type == TSE_SOME_ID) {
sce = (Scene *)tselem->id;
}
}
@@ -1165,7 +1165,7 @@ static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreE
int context = 0;
/* ID Types */
- if (tselem->type == 0) {
+ if (tselem->type == TSE_SOME_ID) {
RNA_id_pointer_create(tselem->id, &ptr);
switch (te->idcode) {
@@ -1374,12 +1374,12 @@ static void do_outliner_item_activate_tree_element(bContext *C,
tvc->scene,
tvc->view_layer,
te,
- (extend && tselem->type == 0) ? OL_SETSEL_EXTEND :
- OL_SETSEL_NORMAL,
- recursive && tselem->type == 0);
+ (extend && tselem->type == TSE_SOME_ID) ? OL_SETSEL_EXTEND :
+ OL_SETSEL_NORMAL,
+ recursive && tselem->type == TSE_SOME_ID);
}
- if (tselem->type == 0) { /* The lib blocks. */
+ if (tselem->type == TSE_SOME_ID) { /* The lib blocks. */
if (do_activate_data == false) {
/* Only select in outliner. */
}
diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c
index 8bd5e3a130a..6543a909a41 100644
--- a/source/blender/editors/space_outliner/outliner_sync.c
+++ b/source/blender/editors/space_outliner/outliner_sync.c
@@ -326,7 +326,7 @@ static void outliner_sync_selection_from_outliner(Scene *scene,
LISTBASE_FOREACH (TreeElement *, te, tree) {
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
if (sync_types->object) {
outliner_select_sync_to_object(view_layer, te, tselem, selected_items->objects);
}
@@ -503,7 +503,7 @@ static void outliner_sync_selection_to_outliner(ViewLayer *view_layer,
LISTBASE_FOREACH (TreeElement *, te, tree) {
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && te->idcode == ID_OB) {
if (sync_types->object) {
outliner_select_sync_from_object(view_layer, active_data->object, te, tselem);
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 8726fd768d4..9af2ba6a82b 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -106,7 +106,7 @@ static void get_element_operation_type(
TreeStoreElem *tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
/* Layer collection points to collection ID. */
- if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
+ if (!ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) {
if (*datalevel == 0) {
*datalevel = tselem->type;
}
@@ -402,7 +402,8 @@ static void outliner_do_libdata_operation(bContext *C,
LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
- if ((tselem->type == 0 && te->idcode != 0) || tselem->type == TSE_LAYER_COLLECTION) {
+ if (((tselem->type == TSE_SOME_ID) && (te->idcode != 0)) ||
+ tselem->type == TSE_LAYER_COLLECTION) {
TreeStoreElem *tsep = te->parent ? TREESTORE(te->parent) : NULL;
operation_fn(C, reports, scene, te, tsep, tselem, user_data);
}
@@ -554,7 +555,8 @@ static void merged_element_search_fn_recursive(
static void merged_element_search_update_fn(const bContext *UNUSED(C),
void *data,
const char *str,
- uiSearchItems *items)
+ uiSearchItems *items,
+ const bool UNUSED(is_first))
{
MergedSearchData *search_data = (MergedSearchData *)data;
TreeElement *parent = search_data->parent_element;
@@ -1043,7 +1045,7 @@ void outliner_do_object_operation_ex(bContext *C,
TreeStoreElem *tselem = TREESTORE(te);
bool select_handled = false;
if (tselem->flag & TSE_SELECTED) {
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
/* When objects selected in other scenes... dunno if that should be allowed. */
Scene *scene_owner = (Scene *)outliner_search_back(te, ID_SCE);
if (scene_owner && scene_act != scene_owner) {
@@ -1600,7 +1602,7 @@ static TreeTraversalAction outliner_find_objects_to_delete(TreeElement *te, void
return TRAVERSE_CONTINUE;
}
- if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
+ if ((tselem->type != TSE_SOME_ID) || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
return TRAVERSE_SKIP_CHILDS;
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index f94f19246fa..6ca986660c1 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -307,7 +307,7 @@ static void outliner_add_line_styles(SpaceOutliner *space_outliner,
continue;
}
linestyle->id.tag &= ~LIB_TAG_DOIT;
- outliner_add_element(space_outliner, lb, linestyle, te, 0, 0);
+ outliner_add_element(space_outliner, lb, linestyle, te, TSE_SOME_ID, 0);
}
}
}
@@ -332,7 +332,7 @@ static void outliner_add_scene_contents(SpaceOutliner *space_outliner,
}
/* World */
- outliner_add_element(space_outliner, lb, sce->world, te, 0, 0);
+ outliner_add_element(space_outliner, lb, sce->world, te, TSE_SOME_ID, 0);
/* Collections */
ten = outliner_add_element(space_outliner, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0);
@@ -343,7 +343,7 @@ static void outliner_add_scene_contents(SpaceOutliner *space_outliner,
ten = outliner_add_element(space_outliner, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0);
ten->name = IFACE_("Objects");
FOREACH_SCENE_OBJECT_BEGIN (sce, ob) {
- outliner_add_element(space_outliner, &ten->subtree, ob, ten, 0, 0);
+ outliner_add_element(space_outliner, &ten->subtree, ob, ten, TSE_SOME_ID, 0);
}
FOREACH_SCENE_OBJECT_END;
outliner_make_object_parent_hierarchy(&ten->subtree);
@@ -368,14 +368,14 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
&te->subtree,
ob->poselib,
te,
- 0,
+ TSE_SOME_ID,
0); /* XXX FIXME.. add a special type for this. */
if (ob->proxy && !ID_IS_LINKED(ob)) {
outliner_add_element(space_outliner, &te->subtree, ob->proxy, te, TSE_PROXY, 0);
}
- outliner_add_element(space_outliner, &te->subtree, ob->data, te, 0, 0);
+ outliner_add_element(space_outliner, &te->subtree, ob->data, te, TSE_SOME_ID, 0);
if (ob->pose) {
bArmature *arm = ob->data;
@@ -458,7 +458,7 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
}
for (int a = 0; a < ob->totcol; a++) {
- outliner_add_element(space_outliner, &te->subtree, ob->mat[a], te, 0, a);
+ outliner_add_element(space_outliner, &te->subtree, ob->mat[a], te, TSE_SOME_ID, a);
}
if (!BLI_listbase_is_empty(&ob->constraints)) {
@@ -624,7 +624,8 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
/* duplicated group */
if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
- outliner_add_element(space_outliner, &te->subtree, ob->instance_collection, te, 0, 0);
+ outliner_add_element(
+ space_outliner, &te->subtree, ob->instance_collection, te, TSE_SOME_ID, 0);
}
}
@@ -686,9 +687,9 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
outliner_add_element(space_outliner, &te->subtree, me, te, TSE_ANIM_DATA, 0);
}
- outliner_add_element(space_outliner, &te->subtree, me->key, te, 0, 0);
+ outliner_add_element(space_outliner, &te->subtree, me->key, te, TSE_SOME_ID, 0);
for (int a = 0; a < me->totcol; a++) {
- outliner_add_element(space_outliner, &te->subtree, me->mat[a], te, 0, a);
+ outliner_add_element(space_outliner, &te->subtree, me->mat[a], te, TSE_SOME_ID, a);
}
/* could do tfaces with image links, but the images are not grouped nicely.
* would require going over all tfaces, sort images in use. etc... */
@@ -702,7 +703,7 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
}
for (int a = 0; a < cu->totcol; a++) {
- outliner_add_element(space_outliner, &te->subtree, cu->mat[a], te, 0, a);
+ outliner_add_element(space_outliner, &te->subtree, cu->mat[a], te, TSE_SOME_ID, a);
}
break;
}
@@ -714,7 +715,7 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
}
for (int a = 0; a < mb->totcol; a++) {
- outliner_add_element(space_outliner, &te->subtree, mb->mat[a], te, 0, a);
+ outliner_add_element(space_outliner, &te->subtree, mb->mat[a], te, TSE_SOME_ID, a);
}
break;
}
@@ -730,7 +731,7 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
if (outliner_animdata_test(tex->adt)) {
outliner_add_element(space_outliner, &te->subtree, tex, te, TSE_ANIM_DATA, 0);
}
- outliner_add_element(space_outliner, &te->subtree, tex->ima, te, 0, 0);
+ outliner_add_element(space_outliner, &te->subtree, tex->ima, te, TSE_SOME_ID, 0);
break;
}
case ID_CA: {
@@ -991,24 +992,23 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
else if (type == TSE_ID_BASE) {
/* pass */
}
+ else if (type == TSE_SOME_ID) {
+ if (!te->type) {
+ BLI_assert(!"Expected this ID type to be ported to new Outliner tree-element design");
+ }
+ }
else {
/* Other cases must be caught above. */
BLI_assert(TSE_IS_REAL_ID(tselem));
- /* do here too, for blend file viewer, own ID_LI then shows file name */
- if (GS(id->name) == ID_LI) {
- te->name = ((Library *)id)->filepath;
- }
- else {
- te->name = id->name + 2; /* Default, can be overridden by Library or non-ID data. */
- }
+ te->name = id->name + 2; /* Default, can be overridden by Library or non-ID data. */
te->idcode = GS(id->name);
}
- if (te->type) {
+ if (te->type && outliner_tree_element_type_is_expand_valid(te->type)) {
outliner_tree_element_type_expand(te->type, space_outliner);
}
- else if (type == 0) {
+ else if (type == TSE_SOME_ID) {
TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
/* ID data-block. */
@@ -1016,16 +1016,16 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
outliner_add_id_contents(space_outliner, te, tselem, id);
}
}
- else if (ELEM(type, TSE_ANIM_DATA, TSE_DRIVER_BASE, TSE_NLA, TSE_NLA_ACTION, TSE_NLA_TRACK)) {
+ else if (ELEM(type,
+ TSE_ANIM_DATA,
+ TSE_DRIVER_BASE,
+ TSE_NLA,
+ TSE_NLA_ACTION,
+ TSE_NLA_TRACK,
+ TSE_GP_LAYER)) {
/* Should already use new AbstractTreeElement design. */
BLI_assert(0);
}
- else if (type == TSE_GP_LAYER) {
- bGPDlayer *gpl = (bGPDlayer *)idv;
-
- te->name = gpl->info;
- te->directdata = gpl;
- }
else if (type == TSE_SEQUENCE) {
Sequence *seq = (Sequence *)idv;
@@ -1229,7 +1229,7 @@ BLI_INLINE void outliner_add_collection_objects(SpaceOutliner *space_outliner,
TreeElement *parent)
{
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
- outliner_add_element(space_outliner, tree, cob->ob, parent, 0, 0);
+ outliner_add_element(space_outliner, tree, cob->ob, parent, TSE_SOME_ID, 0);
}
}
@@ -1240,7 +1240,8 @@ static TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outli
outliner_add_collection_init(ten, collection);
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
- outliner_add_element(space_outliner, &ten->subtree, &child->collection->id, ten, 0, 0);
+ outliner_add_element(
+ space_outliner, &ten->subtree, &child->collection->id, ten, TSE_SOME_ID, 0);
}
if (space_outliner->outlinevis != SO_SCENES) {
@@ -1265,7 +1266,7 @@ void outliner_make_object_parent_hierarchy(ListBase *lb)
TreeElement *ten = te->next;
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && te->idcode == ID_OB) {
Object *ob = (Object *)tselem->id;
if (ob->parent && ob->parent->id.newid) {
BLI_remlink(lb, te);
@@ -1406,7 +1407,7 @@ static void outliner_sort(ListBase *lb)
/* sorting rules; only object lists, ID lists, or deformgroups */
if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) ||
- (tselem->type == 0 && te->idcode == ID_OB)) {
+ ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB))) {
int totelem = BLI_listbase_count(lb);
if (totelem > 1) {
@@ -1420,7 +1421,7 @@ static void outliner_sort(ListBase *lb)
tp->name = te->name;
tp->idcode = te->idcode;
- if (tselem->type && tselem->type != TSE_DEFGROUP) {
+ if ((tselem->type != TSE_SOME_ID) && tselem->type != TSE_DEFGROUP) {
tp->idcode = 0; /* Don't sort this. */
}
if (tselem->type == TSE_ID_BASE) {
@@ -1471,7 +1472,7 @@ static void outliner_collections_children_sort(ListBase *lb)
TreeStoreElem *tselem = TREESTORE(te);
/* Sorting rules: only object lists. */
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
int totelem = BLI_listbase_count(lb);
if (totelem > 1) {
@@ -1546,7 +1547,7 @@ static bool test_collection_callback(TreeElement *te)
static bool test_object_callback(TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
- return ((tselem->type == 0) && (te->idcode == ID_OB));
+ return ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB));
}
/**
@@ -1707,7 +1708,7 @@ static bool outliner_element_visible_get(ViewLayer *view_layer,
}
TreeStoreElem *tselem = TREESTORE(te);
- if ((tselem->type == 0) && (te->idcode == ID_OB)) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
if ((exclude_filter & SO_FILTER_OB_TYPE) == SO_FILTER_OB_TYPE) {
return false;
}
@@ -1790,14 +1791,15 @@ static bool outliner_element_visible_get(ViewLayer *view_layer,
return is_visible;
}
- if ((te->parent != NULL) && (TREESTORE(te->parent)->type == 0) &&
+ if ((te->parent != NULL) && (TREESTORE(te->parent)->type == TSE_SOME_ID) &&
(te->parent->idcode == ID_OB)) {
if (exclude_filter & SO_FILTER_NO_CHILDREN) {
return false;
}
}
}
- else if (te->parent != NULL && TREESTORE(te->parent)->type == 0 && te->parent->idcode == ID_OB) {
+ else if ((te->parent != NULL) && (TREESTORE(te->parent)->type == TSE_SOME_ID) &&
+ (te->parent->idcode == ID_OB)) {
if (exclude_filter & SO_FILTER_NO_OB_CONTENT) {
return false;
}
@@ -1821,7 +1823,7 @@ static bool outliner_element_is_collection_or_object(TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
- if ((tselem->type == 0) && (te->idcode == ID_OB)) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
return true;
}
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
index 92178cfdfc9..562457c62e9 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -226,7 +226,7 @@ TreeElement *outliner_find_id(SpaceOutliner *space_outliner, ListBase *lb, const
{
LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0) {
+ if (tselem->type == TSE_SOME_ID) {
if (tselem->id == id) {
return te;
}
@@ -266,7 +266,7 @@ TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone)
}
TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, 0, TSE_EBONE)) {
+ if (ELEM(tselem->type, TSE_SOME_ID, TSE_EBONE)) {
TreeElement *tes = outliner_find_editbone(&te->subtree, ebone);
if (tes) {
return tes;
@@ -283,7 +283,7 @@ TreeElement *outliner_search_back_te(TreeElement *te, short idcode)
while (te) {
tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == idcode) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == idcode)) {
return te;
}
te = te->parent;
@@ -510,7 +510,7 @@ Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2])
te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]);
if (te) {
TreeStoreElem *tselem = TREESTORE(te);
- if ((tselem->type == 0) && (te->idcode == ID_OB)) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
Object *ob = (Object *)tselem->id;
base = (te->directdata) ? (Base *)te->directdata : BKE_view_layer_base_find(view_layer, ob);
}
diff --git a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc
index cb5f42f08e1..91b690d35fa 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_libraries.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_libraries.cc
@@ -111,7 +111,7 @@ TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar,
{
const short filter_id_type = id_filter_get();
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int tot;
if (filter_id_type) {
lbarray[0] = which_libbase(&mainvar, space_outliner_.filter_id_type);
@@ -144,7 +144,7 @@ TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar,
if (!tenlib) {
/* Create library tree element on demand, depending if there are any data-blocks. */
if (lib) {
- tenlib = outliner_add_element(&space_outliner_, &lb, lib, nullptr, 0, 0);
+ tenlib = outliner_add_element(&space_outliner_, &lb, lib, nullptr, TSE_SOME_ID, 0);
}
else {
tenlib = outliner_add_element(&space_outliner_, &lb, &mainvar, nullptr, TSE_ID_BASE, 0);
@@ -168,7 +168,7 @@ TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar,
for (ID *id : List<ID>(lbarray[a])) {
if (library_id_filter_poll(lib, id)) {
- outliner_add_element(&space_outliner_, &ten->subtree, id, ten, 0, 0);
+ outliner_add_element(&space_outliner_, &ten->subtree, id, ten, TSE_SOME_ID, 0);
}
}
}
diff --git a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc
index 0b17ea98831..69ccf014642 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc
@@ -42,7 +42,7 @@ TreeDisplayIDOrphans::TreeDisplayIDOrphans(SpaceOutliner &space_outliner)
ListBase TreeDisplayIDOrphans::buildTree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
short filter_id_type = (space_outliner_.filter & SO_FILTER_ID_TYPE) ?
space_outliner_.filter_id_type :
0;
@@ -76,7 +76,8 @@ ListBase TreeDisplayIDOrphans::buildTree(const TreeSourceData &source_data)
/* Add the orphaned data-blocks - these will not be added with any subtrees attached. */
for (ID *id : List<ID>(lbarray[a])) {
if (ID_REAL_USERS(id) <= 0) {
- outliner_add_element(&space_outliner_, (te) ? &te->subtree : &tree, id, te, 0, 0);
+ outliner_add_element(
+ &space_outliner_, (te) ? &te->subtree : &tree, id, te, TSE_SOME_ID, 0);
}
}
}
diff --git a/source/blender/editors/space_outliner/tree/tree_display_scenes.cc b/source/blender/editors/space_outliner/tree/tree_display_scenes.cc
index f377512d81e..390f81cfcd1 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_scenes.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_scenes.cc
@@ -46,7 +46,8 @@ ListBase TreeDisplayScenes::buildTree(const TreeSourceData &source_data)
for (ID *id : List<ID>(source_data.bmain->scenes)) {
Scene *scene = reinterpret_cast<Scene *>(id);
- TreeElement *te = outliner_add_element(&space_outliner_, &tree, scene, nullptr, 0, 0);
+ TreeElement *te = outliner_add_element(
+ &space_outliner_, &tree, scene, nullptr, TSE_SOME_ID, 0);
TreeStoreElem *tselem = TREESTORE(te);
/* New scene elements open by default */
diff --git a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
index a0ebac5f451..89c9960a24f 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_view_layer.cc
@@ -80,7 +80,7 @@ ListBase TreeDisplayViewLayer::buildTree(const TreeSourceData &source_data)
/* Show objects in the view layer. */
for (Base *base : List<Base>(view_layer_->object_bases)) {
TreeElement *te_object = outliner_add_element(
- &space_outliner_, &tree, base->object, nullptr, 0, 0);
+ &space_outliner_, &tree, base->object, nullptr, TSE_SOME_ID, 0);
te_object->directdata = base;
}
@@ -158,7 +158,7 @@ void TreeDisplayViewLayer::add_layer_collection_objects(ListBase &tree,
for (CollectionObject *cob : List<CollectionObject>(lc.collection->gobject)) {
Base *base = BKE_view_layer_base_find(view_layer_, cob->ob);
TreeElement *te_object = outliner_add_element(
- &space_outliner_, &tree, base->object, &ten, 0, 0);
+ &space_outliner_, &tree, base->object, &ten, TSE_SOME_ID, 0);
te_object->directdata = base;
}
}
@@ -203,7 +203,7 @@ void ObjectsChildrenBuilder::object_tree_elements_lookup_create_recursive(TreeEl
continue;
}
- if (tselem->type == 0 && te->idcode == ID_OB) {
+ if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
Object *ob = (Object *)tselem->id;
/* Lookup children or add new, empty children vector. */
Vector<TreeElement *> &tree_elements = object_tree_elements_map_.lookup_or_add(ob, {});
@@ -261,8 +261,12 @@ void ObjectsChildrenBuilder::make_object_parent_hierarchy_collections()
if (!found) {
/* We add the child in the tree even if it is not in the collection.
* We deliberately clear its sub-tree though, to make it less prominent. */
- TreeElement *child_ob_tree_element = outliner_add_element(
- &outliner_, &parent_ob_tree_element->subtree, child, parent_ob_tree_element, 0, 0);
+ TreeElement *child_ob_tree_element = outliner_add_element(&outliner_,
+ &parent_ob_tree_element->subtree,
+ child,
+ parent_ob_tree_element,
+ TSE_SOME_ID,
+ 0);
outliner_free_tree(&child_ob_tree_element->subtree);
child_ob_tree_element->flag |= TE_CHILD_NOT_IN_COLLECTION;
child_ob_tree_elements.append(child_ob_tree_element);
diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc
index 27846614994..79c2831475f 100644
--- a/source/blender/editors/space_outliner/tree/tree_element.cc
+++ b/source/blender/editors/space_outliner/tree/tree_element.cc
@@ -22,6 +22,8 @@
#include "tree_element_anim_data.hh"
#include "tree_element_driver_base.hh"
+#include "tree_element_gpencil_layer.hh"
+#include "tree_element_id.hh"
#include "tree_element_nla.hh"
#include "tree_element.h"
@@ -36,6 +38,8 @@ static AbstractTreeElement *tree_element_create(int type, TreeElement &legacy_te
ID &id = *static_cast<ID *>(idv);
switch (type) {
+ case TSE_SOME_ID:
+ return TreeElementID::createFromID(legacy_te, id);
case TSE_ANIM_DATA:
return new TreeElementAnimData(legacy_te, id);
case TSE_DRIVER_BASE:
@@ -46,6 +50,8 @@ static AbstractTreeElement *tree_element_create(int type, TreeElement &legacy_te
return new TreeElementNLATrack(legacy_te, *static_cast<NlaTrack *>(idv));
case TSE_NLA_ACTION:
return new TreeElementNLAAction(legacy_te);
+ case TSE_GP_LAYER:
+ return new TreeElementGPencilLayer(legacy_te, *static_cast<bGPDlayer *>(idv));
default:
break;
}
@@ -79,6 +85,12 @@ void outliner_tree_element_type_expand(TreeElementType *type, SpaceOutliner *spa
outliner::tree_element_expand(reinterpret_cast<outliner::AbstractTreeElement &>(*type),
*space_outliner);
}
+bool outliner_tree_element_type_is_expand_valid(TreeElementType *type)
+{
+ outliner::AbstractTreeElement &element = reinterpret_cast<outliner::AbstractTreeElement &>(
+ *type);
+ return element.isExpandValid();
+}
void outliner_tree_element_type_free(TreeElementType **type)
{
diff --git a/source/blender/editors/space_outliner/tree/tree_element.h b/source/blender/editors/space_outliner/tree/tree_element.h
index d88c37180b3..c3dec1bf68a 100644
--- a/source/blender/editors/space_outliner/tree/tree_element.h
+++ b/source/blender/editors/space_outliner/tree/tree_element.h
@@ -39,6 +39,7 @@ TreeElementType *outliner_tree_element_type_create(int type, TreeElement *legacy
void outliner_tree_element_type_free(TreeElementType **type);
void outliner_tree_element_type_expand(TreeElementType *type, SpaceOutliner *space_outliner);
+bool outliner_tree_element_type_is_expand_valid(TreeElementType *type);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/space_outliner/tree/tree_element.hh b/source/blender/editors/space_outliner/tree/tree_element.hh
index 8a1ebb51eae..3e61dd25898 100644
--- a/source/blender/editors/space_outliner/tree/tree_element.hh
+++ b/source/blender/editors/space_outliner/tree/tree_element.hh
@@ -48,6 +48,15 @@ class AbstractTreeElement {
virtual void expand(SpaceOutliner &) const
{
}
+
+ /**
+ * Just while transitioning to the new tree-element design: Some types are only partially ported,
+ * and the expanding isn't done yet.
+ */
+ virtual bool isExpandValid() const
+ {
+ return true;
+ }
};
} // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_element_anim_data.cc b/source/blender/editors/space_outliner/tree/tree_element_anim_data.cc
index 13a25800800..5a9568ea906 100644
--- a/source/blender/editors/space_outliner/tree/tree_element_anim_data.cc
+++ b/source/blender/editors/space_outliner/tree/tree_element_anim_data.cc
@@ -44,7 +44,8 @@ TreeElementAnimData::TreeElementAnimData(TreeElement &legacy_te, ID &id)
void TreeElementAnimData::expand(SpaceOutliner &space_outliner) const
{
/* Animation data-block itself. */
- outliner_add_element(&space_outliner, &legacy_te_.subtree, anim_data_.action, &legacy_te_, 0, 0);
+ outliner_add_element(
+ &space_outliner, &legacy_te_.subtree, anim_data_.action, &legacy_te_, TSE_SOME_ID, 0);
expand_drivers(space_outliner);
expand_NLA_tracks(space_outliner);
diff --git a/source/blender/editors/space_outliner/tree/tree_element_gpencil_layer.cc b/source/blender/editors/space_outliner/tree/tree_element_gpencil_layer.cc
new file mode 100644
index 00000000000..91e6fdcde4b
--- /dev/null
+++ b/source/blender/editors/space_outliner/tree/tree_element_gpencil_layer.cc
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup spoutliner
+ */
+
+#include "BLI_utildefines.h"
+
+#include "DNA_gpencil_types.h"
+
+#include "../outliner_intern.h"
+
+#include "tree_element_gpencil_layer.hh"
+
+namespace blender::ed::outliner {
+
+TreeElementGPencilLayer::TreeElementGPencilLayer(TreeElement &legacy_te, bGPDlayer &gplayer)
+ : AbstractTreeElement(legacy_te)
+{
+ BLI_assert(legacy_te.store_elem->type == TSE_GP_LAYER);
+ /* this element's info */
+ legacy_te.name = gplayer.info;
+ legacy_te.directdata = &gplayer;
+}
+
+} // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_element_gpencil_layer.hh b/source/blender/editors/space_outliner/tree/tree_element_gpencil_layer.hh
new file mode 100644
index 00000000000..da57ef63f1f
--- /dev/null
+++ b/source/blender/editors/space_outliner/tree/tree_element_gpencil_layer.hh
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup spoutliner
+ */
+
+#pragma once
+
+#include "tree_element.hh"
+
+struct bGPDlayer;
+
+namespace blender::ed::outliner {
+
+class TreeElementGPencilLayer final : public AbstractTreeElement {
+ public:
+ TreeElementGPencilLayer(TreeElement &legacy_te, bGPDlayer &gplayer);
+};
+
+} // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.cc b/source/blender/editors/space_outliner/tree/tree_element_id.cc
new file mode 100644
index 00000000000..26787475635
--- /dev/null
+++ b/source/blender/editors/space_outliner/tree/tree_element_id.cc
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup spoutliner
+ */
+
+#include "DNA_ID.h"
+
+#include "BLI_utildefines.h"
+
+#include "../outliner_intern.h"
+
+#include "tree_element_id.hh"
+
+namespace blender::ed::outliner {
+
+TreeElementID::TreeElementID(TreeElement &legacy_te, const ID &id) : AbstractTreeElement(legacy_te)
+{
+ BLI_assert(legacy_te_.store_elem->type == TSE_SOME_ID);
+ BLI_assert(TSE_IS_REAL_ID(legacy_te_.store_elem));
+
+ /* Default, some specific types override this. */
+ legacy_te_.name = id.name + 2;
+ legacy_te_.idcode = GS(id.name);
+}
+
+TreeElementID *TreeElementID::createFromID(TreeElement &legacy_te, const ID &id)
+{
+ switch (ID_Type type = GS(id.name); type) {
+ case ID_LI:
+ return new TreeElementIDLibrary(legacy_te, id);
+ case ID_SCE:
+ case ID_OB:
+ case ID_ME:
+ case ID_CU:
+ case ID_MB:
+ case ID_MA:
+ case ID_TE:
+ case ID_LT:
+ case ID_LA:
+ case ID_CA:
+ case ID_KE:
+ case ID_SCR:
+ case ID_WO:
+ case ID_SPK:
+ case ID_GR:
+ case ID_NT:
+ case ID_BR:
+ case ID_PA:
+ case ID_MC:
+ case ID_MSK:
+ case ID_LS:
+ case ID_LP:
+ case ID_GD:
+ case ID_WS:
+ case ID_HA:
+ case ID_PT:
+ case ID_VO:
+ case ID_SIM:
+ case ID_WM:
+ case ID_IM:
+ case ID_VF:
+ case ID_TXT:
+ case ID_SO:
+ case ID_AR:
+ case ID_AC:
+ case ID_PAL:
+ case ID_PC:
+ case ID_CF:
+ return new TreeElementID(legacy_te, id);
+ /* Deprecated */
+ case ID_IP:
+ BLI_assert(!"Outliner trying to build tree-element for deprecated ID type");
+ return nullptr;
+ }
+
+ return nullptr;
+}
+
+TreeElementIDLibrary::TreeElementIDLibrary(TreeElement &legacy_te, const ID &id)
+ : TreeElementID(legacy_te, id)
+{
+ legacy_te.name = ((Library &)id).filepath;
+}
+
+} // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.hh b/source/blender/editors/space_outliner/tree/tree_element_id.hh
new file mode 100644
index 00000000000..612c1cd4a6f
--- /dev/null
+++ b/source/blender/editors/space_outliner/tree/tree_element_id.hh
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup spoutliner
+ */
+
+#pragma once
+
+#include "tree_element.hh"
+
+namespace blender::ed::outliner {
+
+class TreeElementID : public AbstractTreeElement {
+ public:
+ TreeElementID(TreeElement &legacy_te, const ID &id);
+
+ static TreeElementID *createFromID(TreeElement &legacy_te, const ID &id);
+
+ /**
+ * Expanding not implemented for all types yet. Once it is, this can be set to true or
+ * `AbstractTreeElement::expandValid()` can be removed altogether.
+ */
+ bool isExpandValid() const override
+ {
+ return false;
+ }
+};
+
+class TreeElementIDLibrary final : public TreeElementID {
+ public:
+ TreeElementIDLibrary(TreeElement &legacy_te, const ID &id);
+};
+
+} // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index a9033b98708..844dbe6a0a5 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -36,6 +36,7 @@
#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
#include "BKE_context.h"
#include "BKE_lib_id.h"
@@ -44,6 +45,8 @@
#include "BKE_movieclip.h"
#include "BKE_report.h"
+#include "IMB_imbuf.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -89,8 +92,6 @@ typedef struct SequencerAddData {
#define SEQPROP_NOCHAN (1 << 3)
#define SEQPROP_FIT_METHOD (1 << 4)
-#define SELECT 1
-
static const EnumPropertyItem scale_fit_methods[] = {
{SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"},
{SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image to completely fill the canvas"},
@@ -216,7 +217,7 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i
}
}
-static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperator *op)
+static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -224,69 +225,56 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
const bool relative = (prop = RNA_struct_find_property(op->ptr, "relative_path")) &&
RNA_property_boolean_get(op->ptr, prop);
int is_file = -1;
- memset(seq_load, 0, sizeof(SeqLoadInfo));
+ memset(load_data, 0, sizeof(SeqLoadData));
- seq_load->start_frame = RNA_int_get(op->ptr, "frame_start");
- seq_load->end_frame = seq_load->start_frame;
- seq_load->channel = RNA_int_get(op->ptr, "channel");
- seq_load->len = 1;
- seq_load->fit_method = RNA_enum_get(op->ptr, "fit_method");
- SEQ_tool_settings_fit_method_set(CTX_data_scene(C), seq_load->fit_method);
+ load_data->start_frame = RNA_int_get(op->ptr, "frame_start");
+ load_data->channel = RNA_int_get(op->ptr, "channel");
+ load_data->image.end_frame = load_data->start_frame;
+ load_data->image.len = 1;
+ load_data->fit_method = RNA_enum_get(op->ptr, "fit_method");
+ SEQ_tool_settings_fit_method_set(CTX_data_scene(C), load_data->fit_method);
if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
/* Full path, file is set by the caller. */
- RNA_property_string_get(op->ptr, prop, seq_load->path);
+ RNA_property_string_get(op->ptr, prop, load_data->path);
is_file = 1;
}
else if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
/* Full path, file is set by the caller. */
- RNA_property_string_get(op->ptr, prop, seq_load->path);
+ RNA_property_string_get(op->ptr, prop, load_data->path);
is_file = 0;
}
if ((is_file != -1) && relative) {
- BLI_path_rel(seq_load->path, BKE_main_blendfile_path(bmain));
+ BLI_path_rel(load_data->path, BKE_main_blendfile_path(bmain));
}
if ((prop = RNA_struct_find_property(op->ptr, "frame_end"))) {
- seq_load->end_frame = RNA_property_int_get(op->ptr, prop);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "replace_sel")) &&
- RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_REPLACE_SEL;
+ load_data->image.end_frame = RNA_property_int_get(op->ptr, prop);
}
if ((prop = RNA_struct_find_property(op->ptr, "cache")) &&
RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_SOUND_CACHE;
+ load_data->flags |= SEQ_LOAD_SOUND_CACHE;
}
if ((prop = RNA_struct_find_property(op->ptr, "mono")) &&
RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_SOUND_MONO;
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "sound")) &&
- RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_MOVIE_SOUND;
+ load_data->flags |= SEQ_LOAD_SOUND_MONO;
}
if ((prop = RNA_struct_find_property(op->ptr, "use_framerate")) &&
RNA_property_boolean_get(op->ptr, prop)) {
- seq_load->flag |= SEQ_LOAD_SYNC_FPS;
+ load_data->flags |= SEQ_LOAD_MOVIE_SYNC_FPS;
}
- /* Create consecutive array of strips. */
- seq_load->flag |= SEQ_LOAD_FRAME_ADVANCE;
-
if (is_file == 1) {
- BLI_strncpy(seq_load->name, BLI_path_basename(seq_load->path), sizeof(seq_load->name));
+ BLI_strncpy(load_data->name, BLI_path_basename(load_data->path), sizeof(load_data->name));
}
else if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
char *name = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- BLI_strncpy(seq_load->name, name, sizeof(seq_load->name));
+ BLI_strncpy(load_data->name, name, sizeof(load_data->name));
MEM_freeN(name);
break;
}
@@ -299,36 +287,31 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
SequencerAddData *sad = op->customdata;
ImageFormatData *imf = &sad->im_format;
- seq_load->views_format = imf->views_format;
- seq_load->flag |= SEQ_USE_VIEWS;
- seq_load->stereo3d_format = &imf->stereo3d_format;
+ load_data->use_multiview = true;
+ load_data->views_format = imf->views_format;
+ load_data->stereo3d_format = &imf->stereo3d_format;
}
}
}
-/**
- * Apply generic operator options.
- */
-static void sequencer_add_apply_overlap(bContext *C, wmOperator *op, Sequence *seq)
+static void seq_load_apply_generic_options(bContext *C, wmOperator *op, Sequence *seq)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
- if (RNA_boolean_get(op->ptr, "overlap") == false) {
- if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
- SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
- }
+ if (seq == NULL) {
+ return;
}
-}
-
-static void sequencer_add_apply_replace_sel(bContext *C, wmOperator *op, Sequence *seq)
-{
- Scene *scene = CTX_data_scene(C);
if (RNA_boolean_get(op->ptr, "replace_sel")) {
- ED_sequencer_deselect_all(scene);
- SEQ_select_active_set(scene, seq);
seq->flag |= SELECT;
+ SEQ_select_active_set(scene, seq);
+ }
+
+ if (RNA_boolean_get(op->ptr, "overlap") == false) {
+ if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
+ }
}
}
@@ -356,34 +339,24 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = SEQ_editing_get(scene, true);
- Scene *sce_seq;
- Sequence *seq;
-
- int start_frame, channel;
- start_frame = RNA_int_get(op->ptr, "frame_start");
- channel = RNA_int_get(op->ptr, "channel");
- sce_seq = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
+ const Editing *ed = SEQ_editing_get(scene, true);
+ Scene *sce_seq = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
if (sce_seq == NULL) {
BKE_report(op->reports, RPT_ERROR, "Scene not found");
return OPERATOR_CANCELLED;
}
- seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_SCENE);
- seq->blend_mode = SEQ_TYPE_CROSS;
- seq->scene = sce_seq;
- seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
-
- BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2);
- SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ ED_sequencer_deselect_all(scene);
+ }
- SEQ_time_update_sequence_bounds(scene, seq);
- SEQ_sort(scene);
+ SeqLoadData load_data;
+ load_data_init_from_operator(&load_data, C, op);
+ load_data.scene = sce_seq;
- sequencer_add_apply_replace_sel(C, op, seq);
- sequencer_add_apply_overlap(C, op, seq);
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ Sequence *seq = SEQ_add_scene_strip(scene, ed->seqbasep, &load_data);
+ seq_load_apply_generic_options(C, op, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
DEG_relations_tag_update(bmain);
@@ -430,36 +403,24 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = SEQ_editing_get(scene, true);
- MovieClip *clip;
- Sequence *seq;
-
- int start_frame, channel;
- start_frame = RNA_int_get(op->ptr, "frame_start");
- channel = RNA_int_get(op->ptr, "channel");
- clip = BLI_findlink(&bmain->movieclips, RNA_enum_get(op->ptr, "clip"));
+ const Editing *ed = SEQ_editing_get(scene, true);
+ MovieClip *clip = BLI_findlink(&bmain->movieclips, RNA_enum_get(op->ptr, "clip"));
if (clip == NULL) {
BKE_report(op->reports, RPT_ERROR, "Movie clip not found");
return OPERATOR_CANCELLED;
}
- seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MOVIECLIP);
- seq->blend_mode = SEQ_TYPE_CROSS;
- seq->clip = clip;
- seq->len = BKE_movieclip_get_duration(clip);
-
- id_us_ensure_real(&seq->clip->id);
-
- BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2);
- SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ ED_sequencer_deselect_all(scene);
+ }
- SEQ_time_update_sequence_bounds(scene, seq);
- SEQ_sort(scene);
+ SeqLoadData load_data;
+ load_data_init_from_operator(&load_data, C, op);
+ load_data.clip = clip;
- sequencer_add_apply_replace_sel(C, op, seq);
- sequencer_add_apply_overlap(C, op, seq);
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ Sequence *seq = SEQ_add_movieclip_strip(scene, ed->seqbasep, &load_data);
+ seq_load_apply_generic_options(C, op, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -506,36 +467,24 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Editing *ed = SEQ_editing_get(scene, true);
- Mask *mask;
- Sequence *seq;
-
- int start_frame, channel;
- start_frame = RNA_int_get(op->ptr, "frame_start");
- channel = RNA_int_get(op->ptr, "channel");
- mask = BLI_findlink(&bmain->masks, RNA_enum_get(op->ptr, "mask"));
+ const Editing *ed = SEQ_editing_get(scene, true);
+ Mask *mask = BLI_findlink(&bmain->masks, RNA_enum_get(op->ptr, "mask"));
if (mask == NULL) {
BKE_report(op->reports, RPT_ERROR, "Mask not found");
return OPERATOR_CANCELLED;
}
- seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MASK);
- seq->blend_mode = SEQ_TYPE_CROSS;
- seq->mask = mask;
- seq->len = BKE_mask_get_duration(mask);
-
- id_us_ensure_real(&seq->mask->id);
-
- BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2);
- SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ ED_sequencer_deselect_all(scene);
+ }
- SEQ_time_update_sequence_bounds(scene, seq);
- SEQ_sort(scene);
+ SeqLoadData load_data;
+ load_data_init_from_operator(&load_data, C, op);
+ load_data.mask = mask;
- sequencer_add_apply_replace_sel(C, op, seq);
- sequencer_add_apply_overlap(C, op, seq);
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ Sequence *seq = SEQ_add_mask_strip(scene, ed->seqbasep, &load_data);
+ seq_load_apply_generic_options(C, op, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -577,100 +526,120 @@ void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot)
ot->prop = prop;
}
-static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFn seq_load_fn)
+static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Editing *ed = SEQ_editing_get(scene, true);
- SeqLoadInfo seq_load;
- int tot_files;
-
- seq_load_operator_info(&seq_load, C, op);
+ op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__);
+}
- if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) {
- ED_sequencer_deselect_all(scene);
+static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op)
+{
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
}
+ op->customdata = NULL;
+}
- tot_files = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
-
- if (tot_files > 1) {
- char dir_only[FILE_MAX];
- char file_only[FILE_MAX];
-
- RNA_BEGIN (op->ptr, itemptr, "files") {
- Sequence *seq;
+static bool sequencer_add_draw_check_fn(PointerRNA *UNUSED(ptr),
+ PropertyRNA *prop,
+ void *UNUSED(user_data))
+{
+ const char *prop_id = RNA_property_identifier(prop);
- RNA_string_get(op->ptr, "directory", dir_only);
- RNA_string_get(&itemptr, "name", file_only);
- BLI_join_dirfile(seq_load.path, sizeof(seq_load.path), dir_only, file_only);
+ return !(STR_ELEM(prop_id, "filepath", "directory", "filename"));
+}
- /* Set seq_load.name, otherwise all video/audio files get the same name. */
- BLI_strncpy(seq_load.name, file_only, sizeof(seq_load.name));
+static void sequencer_add_movie_multiple_strips(bContext *C,
+ wmOperator *op,
+ SeqLoadData *load_data)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ const Editing *ed = SEQ_editing_get(scene, true);
- seq = seq_load_fn(C, ed->seqbasep, &seq_load);
- if (seq) {
- if (seq_load.seq_sound) {
- sequencer_add_apply_overlap(C, op, seq_load.seq_sound);
- }
- sequencer_add_apply_overlap(C, op, seq);
- }
+ RNA_BEGIN (op->ptr, itemptr, "files") {
+ char dir_only[FILE_MAX];
+ char file_only[FILE_MAX];
+ RNA_string_get(op->ptr, "directory", dir_only);
+ RNA_string_get(&itemptr, "name", file_only);
+ BLI_join_dirfile(load_data->path, sizeof(load_data->path), dir_only, file_only);
+ BLI_strncpy(load_data->name, file_only, sizeof(load_data->name));
+ Sequence *seq_movie = NULL;
+ Sequence *seq_sound = NULL;
+ load_data->channel++;
+ seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
+ load_data->channel--;
+ if (seq_movie == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
}
- RNA_END;
- }
- else { /* Single file./ */
- Sequence *seq;
- seq = seq_load_fn(C, ed->seqbasep, &seq_load);
-
- if (seq) {
- if (seq_load.seq_sound) {
- sequencer_add_apply_overlap(C, op, seq_load.seq_sound);
+ else {
+ if (RNA_boolean_get(op->ptr, "sound")) {
+ seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
}
- sequencer_add_apply_overlap(C, op, seq);
+ load_data->start_frame += seq_movie->enddisp - seq_movie->startdisp;
+ seq_load_apply_generic_options(C, op, seq_sound);
+ seq_load_apply_generic_options(C, op, seq_movie);
}
}
+ RNA_END;
+}
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
+static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ const Editing *ed = SEQ_editing_get(scene, true);
- if (seq_load.tot_success == 0) {
- BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", seq_load.path);
+ Sequence *seq_movie = NULL;
+ Sequence *seq_sound = NULL;
+ load_data->channel++;
+ seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
+ load_data->channel--;
- return OPERATOR_CANCELLED;
+ if (seq_movie == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
+ return false;
}
+ if (RNA_boolean_get(op->ptr, "sound")) {
+ seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
+ }
+ seq_load_apply_generic_options(C, op, seq_sound);
+ seq_load_apply_generic_options(C, op, seq_movie);
- SEQ_sort(scene);
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-
- return OPERATOR_FINISHED;
+ return true;
}
-static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op)
+static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
{
- op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__);
-}
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ SeqLoadData load_data;
+
+ load_data_init_from_operator(&load_data, C, op);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ ED_sequencer_deselect_all(scene);
+ }
+
+ const int tot_files = RNA_property_collection_length(op->ptr,
+ RNA_struct_find_property(op->ptr, "files"));
+ if (tot_files > 1) {
+ sequencer_add_movie_multiple_strips(C, op, &load_data);
+ }
+ else {
+ if (!sequencer_add_movie_single_strip(C, op, &load_data)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
-static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op)
-{
if (op->customdata) {
MEM_freeN(op->customdata);
}
- op->customdata = NULL;
-}
-
-static bool sequencer_add_draw_check_fn(PointerRNA *UNUSED(ptr),
- PropertyRNA *prop,
- void *UNUSED(user_data))
-{
- const char *prop_id = RNA_property_identifier(prop);
- return !(STR_ELEM(prop_id, "filepath", "directory", "filename"));
-}
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
-static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
-{
- return sequencer_add_generic_strip_exec(C, op, SEQ_add_movie_strip);
+ return OPERATOR_FINISHED;
}
static int sequencer_add_movie_strip_invoke(bContext *C,
@@ -681,7 +650,8 @@ static int sequencer_add_movie_strip_invoke(bContext *C,
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
- /* Only enable "use_framerate" if there aren't any existing strips, unless overridden by user. */
+ /* Only enable "use_framerate" if there aren't any existing strips, unless overridden by user.
+ */
if (ed && ed->seqbasep && ed->seqbasep->first) {
RNA_boolean_set(op->ptr, "use_framerate", false);
}
@@ -761,9 +731,80 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
"Use framerate from the movie to keep sound and video in sync");
}
+static void sequencer_add_sound_multiple_strips(bContext *C,
+ wmOperator *op,
+ SeqLoadData *load_data)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = SEQ_editing_get(scene, true);
+
+ RNA_BEGIN (op->ptr, itemptr, "files") {
+ char dir_only[FILE_MAX];
+ char file_only[FILE_MAX];
+ RNA_string_get(op->ptr, "directory", dir_only);
+ RNA_string_get(&itemptr, "name", file_only);
+ BLI_join_dirfile(load_data->path, sizeof(load_data->path), dir_only, file_only);
+ BLI_strncpy(load_data->name, file_only, sizeof(load_data->name));
+ Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
+ if (seq == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
+ }
+ else {
+ seq_load_apply_generic_options(C, op, seq);
+ load_data->start_frame += seq->enddisp - seq->startdisp;
+ }
+ }
+ RNA_END;
+}
+
+static bool sequencer_add_sound_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = SEQ_editing_get(scene, true);
+
+ Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
+ if (seq == NULL) {
+ BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
+ return false;
+ }
+ seq_load_apply_generic_options(C, op, seq);
+
+ return true;
+}
+
static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
{
- return sequencer_add_generic_strip_exec(C, op, SEQ_add_sound_strip);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ SeqLoadData load_data;
+ load_data_init_from_operator(&load_data, C, op);
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ ED_sequencer_deselect_all(scene);
+ }
+
+ const int tot_files = RNA_property_collection_length(op->ptr,
+ RNA_struct_find_property(op->ptr, "files"));
+ if (tot_files > 1) {
+ sequencer_add_sound_multiple_strips(C, op, &load_data);
+ }
+ else {
+ if (!sequencer_add_sound_single_strip(C, op, &load_data)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
}
static int sequencer_add_sound_strip_invoke(bContext *C,
@@ -873,78 +914,80 @@ void sequencer_image_seq_reserve_frames(
}
}
-static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
+static int sequencer_add_image_strip_calculate_length(wmOperator *op,
+ const int start_frame,
+ int *minframe,
+ int *numdigits)
{
- int minframe, numdigits;
- Scene *scene = CTX_data_scene(C);
- Editing *ed = SEQ_editing_get(scene, true);
- SeqLoadInfo seq_load;
- Sequence *seq;
- Strip *strip;
- StripElem *se;
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
- seq_load_operator_info(&seq_load, C, op);
-
- /* Images are unique in how they handle this - 1 per strip elem. */
if (use_placeholders) {
- seq_load.len = sequencer_image_seq_get_minmax_frame(
- op, seq_load.start_frame, &minframe, &numdigits);
- }
- else {
- seq_load.len = RNA_property_collection_length(op->ptr,
- RNA_struct_find_property(op->ptr, "files"));
- }
-
- if (seq_load.len == 0) {
- return OPERATOR_CANCELLED;
+ return sequencer_image_seq_get_minmax_frame(op, start_frame, minframe, numdigits);
}
+ return RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+}
- if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) {
- ED_sequencer_deselect_all(scene);
- }
+static void sequencer_add_image_strip_load_files(
+ wmOperator *op, Sequence *seq, SeqLoadData *load_data, const int minframe, const int numdigits)
+{
+ const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
- /* Main adding function. */
- seq = SEQ_add_image_strip(C, ed->seqbasep, &seq_load);
- strip = seq->strip;
- se = strip->stripdata;
- seq->blend_mode = SEQ_TYPE_ALPHAOVER;
+ SEQ_add_image_set_directory(seq, load_data->path);
if (use_placeholders) {
- sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe, numdigits);
+ sequencer_image_seq_reserve_frames(
+ op, seq->strip->stripdata, load_data->image.len, minframe, numdigits);
}
else {
+ size_t strip_frame = 0;
RNA_BEGIN (op->ptr, itemptr, "files") {
char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- BLI_strncpy(se->name, filename, sizeof(se->name));
+ SEQ_add_image_load_file(seq, strip_frame, filename);
MEM_freeN(filename);
- se++;
+ strip_frame++;
}
RNA_END;
}
+}
- if (seq_load.len == 1) {
- if (seq_load.start_frame < seq_load.end_frame) {
- seq->endstill = seq_load.end_frame - seq_load.start_frame;
- }
+static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = SEQ_editing_get(scene, true);
+
+ SeqLoadData load_data;
+ load_data_init_from_operator(&load_data, C, op);
+
+ int minframe, numdigits;
+ load_data.image.len = sequencer_add_image_strip_calculate_length(
+ op, load_data.start_frame, &minframe, &numdigits);
+ if (load_data.image.len == 0) {
+ return OPERATOR_CANCELLED;
}
- SEQ_render_init_colorspace(seq);
- SEQ_time_update_sequence_bounds(scene, seq);
- SEQ_sort(scene);
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ ED_sequencer_deselect_all(scene);
+ }
- /* Last active name. */
- BLI_strncpy(ed->act_imagedir, strip->dir, sizeof(ed->act_imagedir));
- sequencer_add_apply_overlap(C, op, seq);
+ Sequence *seq = SEQ_add_image_strip(CTX_data_main(C), scene, ed->seqbasep, &load_data);
+ sequencer_add_image_strip_load_files(op, seq, &load_data, minframe, numdigits);
+ SEQ_add_image_init_alpha_mode(seq);
- if (op->customdata) {
- MEM_freeN(op->customdata);
+ /* Adjust length. */
+ if (load_data.image.len == 1) {
+ SEQ_transform_set_right_handle_frame(seq, load_data.image.end_frame);
+ SEQ_time_update_sequence(scene, seq);
}
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ seq_load_apply_generic_options(C, op, seq);
+
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+
return OPERATOR_FINISHED;
}
@@ -1016,80 +1059,46 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, true);
- Sequence *seq;
- struct SeqEffectHandle sh;
- Sequence *seq1, *seq2, *seq3;
const char *error_msg;
- int start_frame, end_frame, channel, type;
- start_frame = RNA_int_get(op->ptr, "frame_start");
- end_frame = RNA_int_get(op->ptr, "frame_end");
- channel = RNA_int_get(op->ptr, "channel");
- type = RNA_enum_get(op->ptr, "type");
+ SeqLoadData load_data;
+ load_data_init_from_operator(&load_data, C, op);
+ load_data.effect.type = RNA_enum_get(op->ptr, "type");
- if (!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) {
+ Sequence *seq1, *seq2, *seq3;
+ if (!seq_effect_find_selected(
+ scene, NULL, load_data.effect.type, &seq1, &seq2, &seq3, &error_msg)) {
BKE_report(op->reports, RPT_ERROR, error_msg);
return OPERATOR_CANCELLED;
}
- /* Check its start and end frames are valid. */
- if (seq1 == NULL && end_frame <= start_frame) {
- end_frame = start_frame + 1;
- RNA_int_set(op->ptr, "frame_end", end_frame);
- }
-
- seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, type);
- BLI_strncpy(seq->name + 2, SEQ_sequence_give_name(seq), sizeof(seq->name) - 2);
- SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
-
- sh = SEQ_effect_handle_get(seq);
- sh.init(seq);
- seq->seq1 = seq1;
- seq->seq2 = seq2;
- seq->seq3 = seq3;
-
- if (!seq1) {
- seq->len = 1; /* Effect is generator, set non zero length. */
- SEQ_transform_set_right_handle_frame(seq, end_frame);
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ ED_sequencer_deselect_all(scene);
}
- seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
- SEQ_time_update_sequence(scene, seq);
-
- if (seq->type == SEQ_TYPE_COLOR) {
- SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
- RNA_float_get_array(op->ptr, "color", colvars->col);
- seq->blend_mode = SEQ_TYPE_CROSS;
- }
- else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
- seq->blend_mode = SEQ_TYPE_CROSS;
- }
- else if (seq->type == SEQ_TYPE_TEXT) {
- seq->blend_mode = SEQ_TYPE_ALPHAOVER;
- }
- else if (SEQ_effect_get_num_inputs(seq->type) == 1) {
- seq->blend_mode = seq1->blend_mode;
- }
+ load_data.effect.seq1 = seq1;
+ load_data.effect.seq2 = seq2;
+ load_data.effect.seq3 = seq3;
/* Set channel. If unset, use lowest free one above strips. */
if (!RNA_struct_property_is_set(op->ptr, "channel")) {
- if (seq->seq1) {
- int chan = max_iii(seq->seq1 ? seq->seq1->machine : 0,
- seq->seq2 ? seq->seq2->machine : 0,
- seq->seq3 ? seq->seq3->machine : 0);
+ if (seq1 != NULL) {
+ int chan = max_iii(
+ seq1 ? seq1->machine : 0, seq2 ? seq2->machine : 0, seq3 ? seq3->machine : 0);
if (chan < MAXSEQ) {
- seq->machine = chan;
+ load_data.channel = chan;
}
}
}
- sequencer_add_apply_replace_sel(C, op, seq);
- sequencer_add_apply_overlap(C, op, seq);
+ Sequence *seq = SEQ_add_effect_strip(scene, ed->seqbasep, &load_data);
+ seq_load_apply_generic_options(C, op, seq);
- SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */
- SEQ_sort(scene);
+ if (seq->type == SEQ_TYPE_COLOR) {
+ SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
+ RNA_float_get_array(op->ptr, "color", colvars->col);
+ }
- SEQ_relations_invalidate_cache_composite(scene, seq);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index b9fb577eb43..9828368ccf7 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -66,6 +66,7 @@
#include "ED_sequencer.h"
#include "ED_space_api.h"
#include "ED_time_scrub_ui.h"
+#include "ED_util.h"
#include "BIF_glutil.h"
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 608e220c582..78d263dffad 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -1870,93 +1870,28 @@ void SEQUENCER_OT_images_separate(wmOperatorType *ot)
/** \name Toggle Meta Strip Operator
* \{ */
-void recurs_sel_seq(Sequence *seqm)
-{
- Sequence *seq;
-
- seq = seqm->seqbase.first;
- while (seq) {
-
- if (seqm->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) {
- seq->flag &= ~SEQ_ALLSEL;
- }
- else if (seqm->flag & SELECT) {
- seq->flag |= SELECT;
- }
- else {
- seq->flag &= ~SEQ_ALLSEL;
- }
-
- if (seq->seqbase.first) {
- recurs_sel_seq(seq);
- }
-
- seq = seq->next;
- }
-}
-
static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
- Sequence *last_seq = SEQ_select_active_get(scene);
- MetaStack *ms;
+ Sequence *active_seq = SEQ_select_active_get(scene);
- if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) {
+ if (active_seq && active_seq->type == SEQ_TYPE_META && active_seq->flag & SELECT) {
/* Enter metastrip. */
- ms = MEM_mallocN(sizeof(MetaStack), "metastack");
- BLI_addtail(&ed->metastack, ms);
- ms->parseq = last_seq;
- ms->oldbasep = ed->seqbasep;
- copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
-
- ed->seqbasep = &last_seq->seqbase;
-
+ SEQ_meta_stack_alloc(ed, active_seq);
+ SEQ_seqbase_active_set(ed, &active_seq->seqbase);
SEQ_select_active_set(scene, NULL);
}
else {
/* Exit metastrip if possible. */
-
- Sequence *seq;
-
if (BLI_listbase_is_empty(&ed->metastack)) {
return OPERATOR_CANCELLED;
}
- ms = ed->metastack.last;
- BLI_remlink(&ed->metastack, ms);
-
- ed->seqbasep = ms->oldbasep;
-
- /* For old files, update from meta. */
- if (ms->disp_range[0] == ms->disp_range[1]) {
- copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
- }
-
- /* Recalc all: the meta can have effects connected to it. */
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- SEQ_time_update_sequence(scene, seq);
- }
-
- /* 2.73+, keeping endpoints is important!
- * Moving them around means you can't usefully use metas in a complex edit. */
-#if 1
- SEQ_transform_set_left_handle_frame(ms->parseq, ms->disp_range[0]);
- SEQ_transform_set_right_handle_frame(ms->parseq, ms->disp_range[1]);
- SEQ_transform_fix_single_image_seq_offsets(ms->parseq);
- SEQ_time_update_sequence(scene, ms->parseq);
-#else
- if (SEQ_transform_test_overlap(ed->seqbasep, ms->parseq)) {
- SEQ_transform_seqbase_shuffle(ed->seqbasep, ms->parseq, scene);
- }
-#endif
-
+ MetaStack *ms = SEQ_meta_stack_active_get(ed);
+ SEQ_seqbase_active_set(ed, ms->oldbasep);
SEQ_select_active_set(scene, ms->parseq);
-
- ms->parseq->flag |= SELECT;
- recurs_sel_seq(ms->parseq);
-
- MEM_freeN(ms);
+ SEQ_meta_stack_free(ed, ms);
}
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -1990,48 +1925,44 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *active_seq = SEQ_select_active_get(scene);
+ ListBase *active_seqbase = SEQ_active_seqbase_get(ed);
- Sequence *seq, *seqm, *next, *last_seq = SEQ_select_active_get(scene);
- int channel_max = 1;
-
- if (SEQ_transform_seqbase_isolated_sel_check(ed->seqbasep) == false) {
+ if (SEQ_transform_seqbase_isolated_sel_check(active_seqbase) == false) {
BKE_report(op->reports, RPT_ERROR, "Please select all related strips");
return OPERATOR_CANCELLED;
}
SEQ_prefetch_stop(scene);
- /* Remove all selected from main list, and put in meta. */
-
- seqm = SEQ_sequence_alloc(ed->seqbasep, 1, 1, SEQ_TYPE_META); /* Channel number set later. */
- strcpy(seqm->name + 2, "MetaStrip");
- seqm->flag = SELECT;
+ int channel_max = 1, meta_start_frame = MAXFRAME, meta_end_frame = MINFRAME;
+ Sequence *seqm = SEQ_sequence_alloc(active_seqbase, 1, 1, SEQ_TYPE_META);
- seq = ed->seqbasep->first;
- while (seq) {
- next = seq->next;
- if (seq != seqm && (seq->flag & SELECT)) {
- SEQ_relations_invalidate_cache_composite(scene, seq);
- channel_max = max_ii(seq->machine, channel_max);
- /* Sequence is moved within the same edit, no need to re-generate the UUID. */
- BLI_remlink(ed->seqbasep, seq);
+ /* Remove all selected from main list, and put in meta.
+ * Sequence is moved within the same edit, no need to re-generate the UUID. */
+ LISTBASE_FOREACH_MUTABLE (Sequence *, seq, active_seqbase) {
+ if (seq != seqm && seq->flag & SELECT) {
+ BLI_remlink(active_seqbase, seq);
BLI_addtail(&seqm->seqbase, seq);
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
+ channel_max = max_ii(seq->machine, channel_max);
+ meta_start_frame = min_ii(seq->startdisp, meta_start_frame);
+ meta_end_frame = max_ii(seq->enddisp, meta_end_frame);
}
- seq = next;
}
- seqm->machine = last_seq ? last_seq->machine : channel_max;
- SEQ_time_update_sequence(scene, seqm);
+ seqm->machine = active_seq ? active_seq->machine : channel_max;
+ strcpy(seqm->name + 2, "MetaStrip");
+ SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seqm);
+ seqm->start = meta_start_frame;
+ seqm->len = meta_end_frame - meta_start_frame;
+ SEQ_time_update_sequence(scene, seqm);
SEQ_select_active_set(scene, seqm);
-
- if (SEQ_transform_test_overlap(ed->seqbasep, seqm)) {
- SEQ_transform_seqbase_shuffle(ed->seqbasep, seqm, scene);
+ if (SEQ_transform_test_overlap(active_seqbase, seqm)) {
+ SEQ_transform_seqbase_shuffle(active_seqbase, seqm, scene);
}
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
-
- SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm);
- SEQ_relations_invalidate_cache_composite(scene, seqm);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -2058,95 +1989,43 @@ void SEQUENCER_OT_meta_make(wmOperatorType *ot)
/** \name UnMeta Strip Operator
* \{ */
-static int seq_depends_on_meta(Sequence *seq, Sequence *seqm)
-{
- if (seq == seqm) {
- return 1;
- }
- if (seq->seq1 && seq_depends_on_meta(seq->seq1, seqm)) {
- return 1;
- }
- if (seq->seq2 && seq_depends_on_meta(seq->seq2, seqm)) {
- return 1;
- }
- if (seq->seq3 && seq_depends_on_meta(seq->seq3, seqm)) {
- return 1;
- }
- return 0;
-}
-
-static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
-{
- Sequence *seq, *seqn;
- Sequence *last_seq = SEQ_select_active_get(scene);
-
- seq = lb->first;
- while (seq) {
- seqn = seq->next;
- if ((seq->flag & flag) || deleteall) {
- BLI_remlink(lb, seq);
- if (seq == last_seq) {
- SEQ_select_active_set(scene, NULL);
- }
- if (seq->type == SEQ_TYPE_META) {
- recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
- }
- SEQ_sequence_free(scene, seq, true);
- }
- seq = seqn;
- }
-}
-
static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene, false);
+ Sequence *active_seq = SEQ_select_active_get(scene);
- Sequence *seq, *last_seq = SEQ_select_active_get(scene); /* last_seq checks (ed == NULL) */
-
- if (last_seq == NULL || last_seq->type != SEQ_TYPE_META) {
+ if (active_seq == NULL || active_seq->type != SEQ_TYPE_META) {
return OPERATOR_CANCELLED;
}
SEQ_prefetch_stop(scene);
- for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) {
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ LISTBASE_FOREACH (Sequence *, seq, &active_seq->seqbase) {
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
}
- /* This moves strips from meta to parent, sating within same edit and no new strips are
- * allocated. If the UUID was unique already (as it should) it will stay unique.
- * No need to re-generate the UUIDs. */
- BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase);
+ /* Remove all selected from meta, and put in main list.
+ * Sequence is moved within the same edit, no need to re-generate the UUID. */
+ BLI_movelisttolist(ed->seqbasep, &active_seq->seqbase);
+ BLI_listbase_clear(&active_seq->seqbase);
- BLI_listbase_clear(&last_seq->seqbase);
+ ListBase *active_seqbase = SEQ_active_seqbase_get(ed);
+ SEQ_edit_flag_for_removal(scene, active_seqbase, active_seq);
+ SEQ_edit_remove_flagged_sequences(scene, active_seqbase);
- BLI_remlink(ed->seqbasep, last_seq);
- SEQ_sequence_free(scene, last_seq, true);
-
- /* Empty meta strip, delete all effects depending on it. */
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if ((seq->type & SEQ_TYPE_EFFECT) && seq_depends_on_meta(seq, last_seq)) {
- seq->flag |= SEQ_FLAG_DELETE;
- }
- }
-
- recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0);
-
- /* Test for effects and overlap
- * don't use SEQ_CURRENT_BEGIN since that would be recursive. */
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ /* Test for effects and overlap. */
+ LISTBASE_FOREACH (Sequence *, seq, active_seqbase) {
if (seq->flag & SELECT) {
seq->flag &= ~SEQ_OVERLAP;
- if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
- SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
+ if (SEQ_transform_test_overlap(active_seqbase, seq)) {
+ SEQ_transform_seqbase_shuffle(active_seqbase, seq, scene);
}
}
}
SEQ_sort(scene);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
-
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 4c942a83f2b..767ac76efe6 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -79,7 +79,7 @@ struct Sequence *find_neighboring_sequence(struct Scene *scene,
struct Sequence *test,
int lr,
int sel);
-void recurs_sel_seq(struct Sequence *seqm);
+void recurs_sel_seq(struct Sequence *seq_meta);
int seq_effect_find_selected(struct Scene *scene,
struct Sequence *activeseq,
int type,
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index ffcb3d35d5a..5f0a18fbd0b 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -360,6 +360,31 @@ static void select_neighbor_from_last(Scene *scene, int lr)
}
#endif
+void recurs_sel_seq(Sequence *seq_meta)
+{
+ Sequence *seq;
+
+ seq = seq_meta->seqbase.first;
+ while (seq) {
+
+ if (seq_meta->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
+ else if (seq_meta->flag & SELECT) {
+ seq->flag |= SELECT;
+ }
+ else {
+ seq->flag &= ~SEQ_ALLSEL;
+ }
+
+ if (seq->seqbase.first) {
+ recurs_sel_seq(seq);
+ }
+
+ seq = seq->next;
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 93d5d41e121..2037981e655 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -550,7 +550,7 @@ static void applyObjectConstraintSize(TransInfo *t,
}
static void constraints_rotation_impl(TransInfo *t,
- float axismtx[3][3],
+ const float axismtx[3][3],
float r_vec[3],
float *r_angle)
{
@@ -572,7 +572,8 @@ static void constraints_rotation_impl(TransInfo *t,
break;
}
/* don't flip axis if asked to or if num input */
- if (r_angle && !((mode & CON_NOFLIP) || hasNumInput(&t->num) || (t->flag & T_INPUT_IS_VALUES_FINAL))) {
+ if (r_angle &&
+ !((mode & CON_NOFLIP) || hasNumInput(&t->num) || (t->flag & T_INPUT_IS_VALUES_FINAL))) {
float view_vector[3];
view_vector_calc(t, t->center_global, view_vector);
if (dot_v3v3(r_vec, view_vector) > 0.0f) {
@@ -620,7 +621,7 @@ static void applyObjectConstraintRot(
{
if (t->con.mode & CON_APPLY) {
float tmp_axismtx[3][3];
- float(*axismtx)[3];
+ const float(*axismtx)[3];
/* on setup call, use first object */
if (td == NULL) {
diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c
index 244cd552495..45df0e66691 100644
--- a/source/blender/editors/transform/transform_convert_gpencil.c
+++ b/source/blender/editors/transform/transform_convert_gpencil.c
@@ -37,6 +37,7 @@
#include "BKE_gpencil_geom.h"
#include "ED_gpencil.h"
+#include "ED_keyframing.h"
#include "transform.h"
#include "transform_convert.h"
@@ -114,6 +115,7 @@ static void createTransGPencil_curves(bContext *C,
#define SEL_F3 (1 << 2)
View3D *v3d = t->view;
+ Scene *scene = CTX_data_scene(C);
const bool handle_only_selected_visible = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
const bool handle_all_visible = (v3d->overlay.handle_display == CURVE_HANDLE_ALL);
@@ -230,7 +232,9 @@ static void createTransGPencil_curves(bContext *C,
}
if ((gpf->framenum != cfra) && (!is_multiedit)) {
- gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
+ if (IS_AUTOKEY_ON(scene)) {
+ gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
+ }
/* in some weird situations (framelock enabled) return NULL */
if (gpf == NULL) {
continue;
@@ -405,6 +409,7 @@ static void createTransGPencil_strokes(bContext *C,
const bool is_prop_edit_connected,
const bool is_scale_thickness)
{
+ Scene *scene = CTX_data_scene(C);
TransData *td = NULL;
float mtx[3][3], smtx[3][3];
@@ -517,7 +522,9 @@ static void createTransGPencil_strokes(bContext *C,
* spent too much time editing the wrong frame...
*/
if ((gpf->framenum != cfra) && (!is_multiedit)) {
- gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
+ if (IS_AUTOKEY_ON(scene)) {
+ gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
+ }
/* in some weird situations (framelock enabled) return NULL */
if (gpf == NULL) {
continue;
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 4ab52b78002..30418471d6d 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -90,35 +90,17 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_c
Scene *scene = t->scene;
int cfra = CFRA;
- int left = SEQ_transform_get_left_handle_frame(seq, true);
- int right = SEQ_transform_get_right_handle_frame(seq, true);
+ int left = SEQ_transform_get_left_handle_frame(seq, false);
+ int right = SEQ_transform_get_right_handle_frame(seq, false);
if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) {
*r_recursive = false;
*r_count = 0;
*r_flag = 0;
}
- else if (seq->type == SEQ_TYPE_META) {
-
- /* for meta's we only ever need to extend their children, no matter what depth
- * just check the meta's are in the bounds */
- if (t->frame_side == 'R' && right <= cfra) {
- *r_recursive = false;
- }
- else if (t->frame_side == 'L' && left >= cfra) {
- *r_recursive = false;
- }
- else {
- *r_recursive = true;
- }
-
- *r_count = 1;
- *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
- }
else {
-
- *r_recursive = false; /* not a meta, so no thinking here */
- *r_count = 1; /* unless its set to 0, extend will never set 2 handles at once */
+ *r_recursive = false;
+ *r_count = 1; /* unless its set to 0, extend will never set 2 handles at once */
*r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
if (t->frame_side == 'R') {
@@ -183,26 +165,9 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_c
else {
/* Nested, different rules apply */
-#ifdef SEQ_TX_NESTED_METAS
*r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
*r_count = 1; /* ignore the selection for nested */
*r_recursive = (seq->type == SEQ_TYPE_META);
-#else
- if (seq->type == SEQ_TYPE_META) {
- /* Meta's can only directly be moved between channels since they
- * don't have their start and length set directly (children affect that)
- * since this Meta is nested we don't need any of its data in fact.
- * SEQ_time_update_sequence() will update its settings when run on the top-level meta. */
- *r_flag = 0;
- *r_count = 0;
- *r_recursive = true;
- }
- else {
- *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
- *r_count = 1; /* ignore the selection for nested */
- *r_recursive = false;
- }
-#endif
}
}
}
@@ -645,8 +610,6 @@ void createTransSeqData(TransInfo *t)
/* commented _only_ because the meta may have animation data which
* needs moving too T28158. */
-#define SEQ_TX_NESTED_METAS
-
BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int sel_flag)
{
if (seq->depth == 0) {
@@ -693,17 +656,10 @@ static void flushTransSeq(TransInfo *t)
switch (tdsq->sel_flag) {
case SELECT:
-#ifdef SEQ_TX_NESTED_METAS
if ((seq->depth != 0 || SEQ_transform_sequence_can_be_translated(seq))) {
/* for meta's, their children move */
seq->start = new_frame - tdsq->start_offset;
}
-#else
- if (seq->type != SEQ_TYPE_META && (seq->depth != 0 || seq_tx_test(seq))) {
- /* for meta's, their children move */
- seq->start = new_frame - tdsq->start_offset;
- }
-#endif
if (seq->depth == 0) {
seq->machine = round_fl_to_int(td2d->loc[1]);
CLAMP(seq->machine, 1, MAXSEQ);
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index 4fd8c180a4b..9189adaf4d1 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -152,7 +152,7 @@ static void memfile_undosys_step_decode(struct bContext *C,
bool use_old_bmain_data = true;
- if (USER_EXPERIMENTAL_TEST(&U, use_undo_legacy)) {
+ if (USER_EXPERIMENTAL_TEST(&U, use_undo_legacy) || !(U.uiflag & USER_GLOBALUNDO)) {
use_old_bmain_data = false;
}
else if (undo_direction == STEP_REDO) {
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 38655b8490e..7d7d10004a3 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -21,6 +21,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../blenfont
../../bmesh
../../depsgraph
../../gpu
@@ -36,6 +37,7 @@ set(INC
set(SRC
+ ed_draw.c
ed_transverts.c
ed_util.c
ed_util_imbuf.c
diff --git a/source/blender/editors/util/ed_draw.c b/source/blender/editors/util/ed_draw.c
new file mode 100644
index 00000000000..d7b22b4f601
--- /dev/null
+++ b/source/blender/editors/util/ed_draw.c
@@ -0,0 +1,385 @@
+/*
+ * 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) 2008 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edutil
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_image.h"
+
+#include "BLF_api.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_metadata.h"
+
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_util.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
+/**
+ * Callback that draws a line between the mouse and a position given as the initial argument.
+ */
+void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_info)
+{
+ wmWindow *win = CTX_wm_window(C);
+ const float *mval_src = (float *)arg_info;
+ const float mval_dst[2] = {
+ win->eventstate->x - region->winrct.xmin,
+ win->eventstate->y - region->winrct.ymin,
+ };
+
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ GPU_line_width(1.0f);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformThemeColor3(TH_VIEW_OVERLAY);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(shdr_pos, mval_src);
+ immVertex2fv(shdr_pos, mval_dst);
+ immEnd();
+
+ immUnbindProgram();
+}
+
+#define MAX_METADATA_STR 1024
+
+static const char *meta_data_list[] = {
+ "File",
+ "Strip",
+ "Date",
+ "RenderTime",
+ "Note",
+ "Marker",
+ "Time",
+ "Frame",
+ "Camera",
+ "Scene",
+};
+
+BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset)
+{
+ return (IMB_metadata_get_field(
+ ibuf->metadata, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) &&
+ r_str[0]);
+}
+
+BLI_INLINE bool metadata_is_custom_drawable(const char *field)
+{
+ /* Metadata field stored by Blender for multi-layer EXR images. Is rather
+ * useless to be viewed all the time. Can still be seen in the Metadata
+ * panel. */
+ if (STREQ(field, "BlenderMultiChannel")) {
+ return false;
+ }
+ /* Is almost always has value "scanlineimage", also useless to be seen
+ * all the time. */
+ if (STREQ(field, "type")) {
+ return false;
+ }
+ return !BKE_stamp_is_known_field(field);
+}
+
+typedef struct MetadataCustomDrawContext {
+ int fontid;
+ int xmin, ymin;
+ int vertical_offset;
+ int current_y;
+} MetadataCustomDrawContext;
+
+static void metadata_custom_draw_fields(const char *field, const char *value, void *ctx_v)
+{
+ if (!metadata_is_custom_drawable(field)) {
+ return;
+ }
+ MetadataCustomDrawContext *ctx = (MetadataCustomDrawContext *)ctx_v;
+ char temp_str[MAX_METADATA_STR];
+ BLI_snprintf(temp_str, MAX_METADATA_STR, "%s: %s", field, value);
+ BLF_position(ctx->fontid, ctx->xmin, ctx->ymin + ctx->current_y, 0.0f);
+ BLF_draw(ctx->fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ctx->current_y += ctx->vertical_offset;
+}
+
+static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const bool is_top)
+{
+ char temp_str[MAX_METADATA_STR];
+ int ofs_y = 0;
+ const float height = BLF_height_max(fontid);
+ const float margin = height / 8;
+ const float vertical_offset = (height + margin);
+
+ /* values taking margins into account */
+ const float descender = BLF_descender(fontid);
+ const float xmin = (rect->xmin + margin);
+ const float xmax = (rect->xmax - margin);
+ const float ymin = (rect->ymin + margin) - descender;
+ const float ymax = (rect->ymax - margin) - descender;
+
+ if (is_top) {
+ for (int i = 0; i < 4; i++) {
+ /* first line */
+ if (i == 0) {
+ bool do_newline = false;
+ int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]);
+ if (metadata_is_valid(ibuf, temp_str, 0, len)) {
+ BLF_position(fontid, xmin, ymax - vertical_offset, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ do_newline = true;
+ }
+
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]);
+ if (metadata_is_valid(ibuf, temp_str, 1, len)) {
+ int line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_position(fontid, xmax - line_width, ymax - vertical_offset, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ do_newline = true;
+ }
+
+ if (do_newline) {
+ ofs_y += vertical_offset;
+ }
+ } /* Strip */
+ else if (i == 1 || i == 2) {
+ int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ofs_y += vertical_offset;
+ }
+ } /* Note (wrapped) */
+ else if (i == 3) {
+ int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ struct ResultBLF info;
+ BLF_enable(fontid, BLF_WORD_WRAP);
+ BLF_wordwrap(fontid, ibuf->x - (margin * 2));
+ BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw_ex(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX, &info);
+ BLF_wordwrap(fontid, 0);
+ BLF_disable(fontid, BLF_WORD_WRAP);
+ ofs_y += vertical_offset * info.lines;
+ }
+ }
+ else {
+ int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ int line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_position(fontid, xmax - line_width, ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ofs_y += vertical_offset;
+ }
+ }
+ }
+ }
+ else {
+ MetadataCustomDrawContext ctx;
+ ctx.fontid = fontid;
+ ctx.xmin = xmin;
+ ctx.ymin = ymin;
+ ctx.current_y = ofs_y;
+ ctx.vertical_offset = vertical_offset;
+ IMB_metadata_foreach(ibuf, metadata_custom_draw_fields, &ctx);
+ int ofs_x = 0;
+ ofs_y = ctx.current_y;
+ for (int i = 5; i < 10; i++) {
+ int len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]);
+ if (metadata_is_valid(ibuf, temp_str, i, len)) {
+ BLF_position(fontid, xmin + ofs_x, ymin + ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+
+ ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X;
+ }
+ }
+ }
+}
+
+typedef struct MetadataCustomCountContext {
+ int count;
+} MetadataCustomCountContext;
+
+static void metadata_custom_count_fields(const char *field, const char *UNUSED(value), void *ctx_v)
+{
+ if (!metadata_is_custom_drawable(field)) {
+ return;
+ }
+ MetadataCustomCountContext *ctx = (MetadataCustomCountContext *)ctx_v;
+ ctx->count++;
+}
+
+static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
+{
+ const float height = BLF_height_max(fontid);
+ const float margin = (height / 8);
+ char str[MAX_METADATA_STR] = "";
+ short count = 0;
+
+ if (is_top) {
+ if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) {
+ count++;
+ }
+ for (int i = 2; i < 5; i++) {
+ if (metadata_is_valid(ibuf, str, i, 0)) {
+ if (i == 4) {
+ struct {
+ struct ResultBLF info;
+ rctf rect;
+ } wrap;
+
+ BLF_enable(fontid, BLF_WORD_WRAP);
+ BLF_wordwrap(fontid, ibuf->x - (margin * 2));
+ BLF_boundbox_ex(fontid, str, sizeof(str), &wrap.rect, &wrap.info);
+ BLF_wordwrap(fontid, 0);
+ BLF_disable(fontid, BLF_WORD_WRAP);
+
+ count += wrap.info.lines;
+ }
+ else {
+ count++;
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 5; i < 10; i++) {
+ if (metadata_is_valid(ibuf, str, i, 0)) {
+ count = 1;
+ break;
+ }
+ }
+ MetadataCustomCountContext ctx;
+ ctx.count = 0;
+ IMB_metadata_foreach(ibuf, metadata_custom_count_fields, &ctx);
+ count += ctx.count;
+ }
+
+ if (count) {
+ return (height + margin) * count;
+ }
+
+ return 0;
+}
+
+/* Should be kept in sync with BKE_image_stamp_buf */
+void ED_region_image_metadata_draw(
+ int x, int y, ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy)
+{
+ const uiStyle *style = UI_style_get_dpi();
+
+ if (!ibuf->metadata) {
+ return;
+ }
+
+ /* find window pixel coordinates of origin */
+ GPU_matrix_push();
+
+ /* offset and zoom using ogl */
+ GPU_matrix_translate_2f(x, y);
+ GPU_matrix_scale_2f(zoomx, zoomy);
+
+ BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi);
+
+ /* *** upper box*** */
+
+ /* get needed box height */
+ float box_y = metadata_box_height_get(ibuf, blf_mono_font, true);
+
+ if (box_y) {
+ /* set up rect */
+ rctf rect;
+ BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymax, frame->ymax + box_y);
+ /* draw top box */
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_METADATA_BG);
+ immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ immUnbindProgram();
+
+ BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(blf_mono_font, BLF_CLIPPING);
+
+ UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
+ metadata_draw_imbuf(ibuf, &rect, blf_mono_font, true);
+
+ BLF_disable(blf_mono_font, BLF_CLIPPING);
+ }
+
+ /* *** lower box*** */
+
+ box_y = metadata_box_height_get(ibuf, blf_mono_font, false);
+
+ if (box_y) {
+ /* set up box rect */
+ rctf rect;
+ BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymin - box_y, frame->ymin);
+ /* draw top box */
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_METADATA_BG);
+ immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ immUnbindProgram();
+
+ BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(blf_mono_font, BLF_CLIPPING);
+
+ UI_FontThemeColor(blf_mono_font, TH_METADATA_TEXT);
+ metadata_draw_imbuf(ibuf, &rect, blf_mono_font, false);
+
+ BLF_disable(blf_mono_font, BLF_CLIPPING);
+ }
+
+ GPU_matrix_pop();
+}
+
+#undef MAX_METADATA_STR
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 695db9ba246..9903711834a 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -434,44 +434,6 @@ void unpack_menu(bContext *C,
UI_popup_menu_end(C, pup);
}
-/* ********************* generic callbacks for drawcall api *********************** */
-
-/**
- * Callback that draws a line between the mouse and a position given as the initial argument.
- */
-void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_info)
-{
- wmWindow *win = CTX_wm_window(C);
- const float *mval_src = (float *)arg_info;
- const float mval_dst[2] = {
- win->eventstate->x - region->winrct.xmin,
- win->eventstate->y - region->winrct.ymin,
- };
-
- const uint shdr_pos = GPU_vertformat_attr_add(
- immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- GPU_line_width(1.0f);
-
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
-
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformThemeColor3(TH_VIEW_OVERLAY);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(shdr_pos, mval_src);
- immVertex2fv(shdr_pos, mval_dst);
- immEnd();
-
- immUnbindProgram();
-}
-
/**
* Use to free ID references within runtime data (stored outside of DNA)
*
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index 88802e0d868..f46975c9378 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -3313,7 +3313,6 @@ static bool do_lasso_select_mesh_uv(bContext *C,
uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
}
- /* don't indent to avoid diff noise! */
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
@@ -3323,7 +3322,7 @@ static bool do_lasso_select_mesh_uv(bContext *C,
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- if (use_face_center) { /* Face Center Sel */
+ if (use_face_center) { /* Face Center Select. */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
/* assume not touched */
@@ -3366,7 +3365,7 @@ static bool do_lasso_select_mesh_uv(bContext *C,
}
}
}
- else { /* Vert Sel */
+ else { /* Vert Selection. */
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc
index e56dcd16528..062741a6270 100644
--- a/source/blender/gpu/intern/gpu_immediate.cc
+++ b/source/blender/gpu/intern/gpu_immediate.cc
@@ -606,7 +606,7 @@ void immUniform4fv(const char *name, const float data[4])
/* Note array index is not supported for name (i.e: "array[0]"). */
void immUniformArray4fv(const char *name, const float *data, int count)
{
- GPU_shader_uniform_4fv_array(imm->shader, name, count, (float(*)[4])data);
+ GPU_shader_uniform_4fv_array(imm->shader, name, count, (const float(*)[4])data);
}
void immUniformMatrix4fv(const char *name, const float data[4][4])
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl
index 8131958313b..ec49cc86761 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl
@@ -5,12 +5,13 @@ void node_bsdf_anisotropic(vec4 color,
float rotation,
vec3 N,
vec3 T,
- float use_multiscatter,
+ const float use_multiscatter,
+ const float ssr_id,
out Closure result)
{
- node_bsdf_glossy(color, roughness, N, -1, use_multiscatter, result);
+ node_bsdf_glossy(color, roughness, N, use_multiscatter, ssr_id, result);
}
#else
/* Stub anisotropic because it is not compatible with volumetrics. */
-# define node_bsdf_anisotropic(a, b, c, d, e, f, g, result) (result = CLOSURE_DEFAULT)
+# define node_bsdf_anisotropic(a, b, c, d, e, f, g, h, result) (result = CLOSURE_DEFAULT)
#endif
diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
index 31dca888732..89e648a7d6a 100644
--- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h
+++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
@@ -32,7 +32,6 @@ extern "C" {
struct ImBuf;
struct OCIO_ConstCPUProcessorRcPtr;
-struct OCIO_ConstProcessorRcPtr;
extern float imbuf_luma_coefficients[3];
extern float imbuf_xyz_to_rgb[3][3];
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 28bf26aa343..d36c7bbe486 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -1149,7 +1149,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
}
}
else {
- pos = (int64_t)(position - anim->preseek) * AV_TIME_BASE / frame_rate;
+ pos = (int64_t)position * AV_TIME_BASE / frame_rate;
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 9d01617905f..14f0fef5270 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -168,7 +168,7 @@ typedef struct IDOverrideLibraryPropertyOperation {
int subitem_local_index;
} IDOverrideLibraryPropertyOperation;
-/* IDOverridePropertyOperation->operation. */
+/* IDOverrideLibraryPropertyOperation->operation. */
enum {
/* Basic operations. */
IDOVERRIDE_LIBRARY_OP_NOOP = 0, /* Special value, forbids any overriding. */
@@ -188,7 +188,7 @@ enum {
/* We can add more if needed (move, delete, ...). */
};
-/* IDOverridePropertyOperation->flag. */
+/* IDOverrideLibraryPropertyOperation->flag. */
enum {
/** User cannot remove that override operation. */
IDOVERRIDE_LIBRARY_FLAG_MANDATORY = 1 << 0,
@@ -210,10 +210,14 @@ typedef struct IDOverrideLibraryProperty {
*/
char *rna_path;
- /** List of overriding operations (IDOverridePropertyOperation) applied to this property. */
+ /**
+ * List of overriding operations (IDOverrideLibraryPropertyOperation) applied to this property.
+ */
ListBase operations;
- /** Runtime, tags are common to both IDOverrideProperty and IDOverridePropertyOperation. */
+ /**
+ * Runtime, tags are common to both IDOverrideLibraryProperty and
+ * IDOverrideLibraryPropertyOperation. */
short tag;
char _pad[2];
@@ -221,7 +225,7 @@ typedef struct IDOverrideLibraryProperty {
unsigned int rna_prop_type;
} IDOverrideLibraryProperty;
-/* IDOverrideProperty->tag and IDOverridePropertyOperation->tag. */
+/* IDOverrideLibraryProperty->tag and IDOverrideLibraryPropertyOperation->tag. */
enum {
/** This override property (operation) is unused and should be removed by cleanup process. */
IDOVERRIDE_LIBRARY_TAG_UNUSED = 1 << 0,
@@ -244,7 +248,7 @@ enum {
typedef struct IDOverrideLibrary {
/** Reference linked ID which this one overrides. */
struct ID *reference;
- /** List of IDOverrideProperty structs. */
+ /** List of IDOverrideLibraryProperty structs. */
ListBase properties;
/* Read/write data. */
@@ -718,8 +722,36 @@ typedef enum IDRecalcFlag {
FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | \
FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO | FILTER_ID_SIM)
-/* IMPORTANT: this enum matches the order currently use in set_listbasepointers,
- * keep them in sync! */
+/**
+ * This enum defines the index assigned to each type of IDs in the array returned by
+ * #set_listbasepointers, and by extension, controls the default order in which each ID type is
+ * processed during standard 'foreach' looping over all IDs of a #Main data-base.
+ *
+ * About Order:
+ * ------------
+ *
+ * This is (loosely) defined with a relationship order in mind, from lowest level (ID types using,
+ * referencing almost no other ID types) to highest level (ID types potentially using many other ID
+ * types).
+ *
+ * So e.g. it ensures that this dependency chain is respected:
+ * #Material <- #Mesh <- #Object <- #Collection <- #Scene
+ *
+ * Default order of processing of IDs in 'foreach' macros (#FOREACH_MAIN_ID_BEGIN and the like),
+ * built on top of #set_listbasepointers, is actually reversed compared to the order defined here,
+ * since processing usually needs to happen on users before it happens on used IDs (when freeing
+ * e.g.).
+ *
+ * DO NOT rely on this order as being full-proofed dependency order, there are many cases were it
+ * can be violated (most obvious cases being custom properties and drivers, which can reference any
+ * other ID types).
+ *
+ * However, this order can be considered as an optimization heuristic, especially when processing
+ * relationships in a non-recursive pattern: in typical cases, a vast majority of those
+ * relationships can be processed fine in the first pass, and only few additional passes are
+ * required to address all remaining relationship cases.
+ * See e.g. how #BKE_library_unused_linked_data_set_tag is doing this.
+ */
enum {
INDEX_ID_LI = 0,
INDEX_ID_IP,
@@ -759,6 +791,8 @@ enum {
INDEX_ID_SCE,
INDEX_ID_WS,
INDEX_ID_WM,
+ /* TODO: This should probably be tweaked, #Mask and #Simulation are rather low-level types that
+ * should most likely be defined //before// #Object and geometry type indices? */
INDEX_ID_MSK,
INDEX_ID_SIM,
INDEX_ID_NULL,
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 16129768b60..7a39e0caef3 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -73,6 +73,16 @@ enum {
/** #TreeStoreElem.types */
typedef enum eTreeStoreElemType {
+ /**
+ * If an element is of this type, `TreeStoreElem.id` points to a valid ID and the ID-type can be
+ * received through `TreeElement.idcode` (or `GS(TreeStoreElem.id->name)`). Note however that the
+ * types below may also have a valid ID pointer (see #TSE_IS_REAL_ID()).
+ *
+ * In cases where the type is still checked against "0" (even implicitly), please replace it with
+ * an explicit check against `TSE_SOME_ID`.
+ */
+ TSE_SOME_ID = 0,
+
TSE_NLA = 1, /* NO ID */
TSE_NLA_ACTION = 2,
TSE_DEFGROUP_BASE = 3,
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index dc1775b09c6..856fa569645 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -66,6 +66,9 @@ typedef struct SpaceProperties_Runtime SpaceProperties_Runtime;
/* Defined in `node_intern.h`. */
typedef struct SpaceNode_Runtime SpaceNode_Runtime;
+/* Defined in `file_intern.h`. */
+typedef struct SpaceFile_Runtime SpaceFile_Runtime;
+
/* -------------------------------------------------------------------- */
/** \name SpaceLink (Base)
* \{ */
@@ -846,6 +849,8 @@ typedef struct SpaceFile {
short recentnr, bookmarknr;
short systemnr, system_bookmarknr;
+
+ SpaceFile_Runtime *runtime;
} SpaceFile;
/* SpaceFile.browse_mode (File Space Browsing Mode) */
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 1635aa7646b..68d69a671ba 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -154,8 +154,8 @@ typedef struct wmWindowManager {
/** Operator registry. */
ListBase operators;
- /** Refresh/redraw wmNotifier structs. */
- ListBase queue;
+ /** Refresh/redraw #wmNotifier structs. */
+ ListBase notifier_queue;
/** Information and error reports. */
struct ReportList reports;
@@ -251,13 +251,14 @@ typedef struct wmWindow {
struct bScreen *screen DNA_DEPRECATED;
+ /** Winid also in screens, is for retrieving this window after read. */
+ int winid;
/** Window coords. */
short posx, posy, sizex, sizey;
/** Borderless, full. */
char windowstate;
/** Set to 1 if an active window, for quick rejects. */
char active;
- char _pad0[4];
/** Current mouse cursor type. */
short cursor;
/** Previous cursor when setting modal one. */
@@ -271,16 +272,22 @@ typedef struct wmWindow {
char addmousemove;
char tag_cursor_refresh;
- /** Winid also in screens, is for retrieving this window after read. */
- int winid;
+ /* Track the state of the event queue,
+ * these store the state that needs to be kept between handling events in the queue. */
+ /** Enable when #KM_PRESS events are not handled (keyboard/mouse-buttons only). */
+ char event_queue_check_click;
+ /** Enable when #KM_PRESS events are not handled (keyboard/mouse-buttons only). */
+ char event_queue_check_drag;
+
+ char _pad0[2];
/** Internal, lock pie creation from this event until released. */
- short lock_pie_event;
+ short pie_event_type_lock;
/**
* Exception to the above rule for nested pies, store last pie event for operators
* that spawn a new pie right after destruction of last pie.
*/
- short last_pie_event;
+ short pie_event_type_last;
/** Storage for event system. */
struct wmEvent *eventstate;
@@ -292,8 +299,8 @@ typedef struct wmWindow {
* Currently WIN32, runtime-only data. */
struct wmIMEData *ime_data;
- /** All events (ghost level events were handled). */
- ListBase queue;
+ /** All events #wmEvent (ghost level events were handled). */
+ ListBase event_queue;
/** Window+screen handlers, handled last. */
ListBase handlers;
/** Priority handlers, handled first. */
@@ -355,7 +362,7 @@ typedef struct wmKeyMapItem {
short val;
/** Oskey is apple or windowskey, value denotes order of pressed. */
short shift, ctrl, alt, oskey;
- /** Rawkey modifier. */
+ /** Raw-key modifier. */
short keymodifier;
/* flag: inactive, expanded */
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index c12426ffcd0..c49a52ceed7 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -421,7 +421,7 @@ void RNA_def_property_string_funcs(PropertyRNA *prop,
const char *length,
const char *set);
void RNA_def_property_pointer_funcs(
- PropertyRNA *prop, const char *get, const char *set, const char *typef, const char *poll);
+ PropertyRNA *prop, const char *get, const char *set, const char *type_fn, const char *poll);
void RNA_def_property_collection_funcs(PropertyRNA *prop,
const char *begin,
const char *next,
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index bec3db10905..1f887c2eec3 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -3671,7 +3671,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
}
}
else {
- if (!defaultfound && !(eprop->itemf && eprop->item == DummyRNA_NULL_items)) {
+ if (!defaultfound && !(eprop->item_fn && eprop->item == DummyRNA_NULL_items)) {
CLOG_ERROR(&LOG,
"%s%s.%s, enum default is not in items.",
srna->identifier,
@@ -3992,7 +3992,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
"\t%s, %s, %s, %s, %s, NULL, ",
rna_function_string(eprop->get),
rna_function_string(eprop->set),
- rna_function_string(eprop->itemf),
+ rna_function_string(eprop->item_fn),
rna_function_string(eprop->get_ex),
rna_function_string(eprop->set_ex));
if (eprop->item) {
@@ -4010,7 +4010,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
"\t%s, %s, %s, %s,",
rna_function_string(pprop->get),
rna_function_string(pprop->set),
- rna_function_string(pprop->typef),
+ rna_function_string(pprop->type_fn),
rna_function_string(pprop->poll));
if (pprop->type) {
fprintf(f, "&RNA_%s\n", (const char *)pprop->type);
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index fd19352a9a5..6e2005b7314 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -528,6 +528,9 @@ static ID *rna_ID_copy(ID *id, Main *bmain)
if (newid != NULL) {
id_us_min(newid);
}
+
+ WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
+
return newid;
}
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index c5dd516d16e..8e5e70642cc 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -1571,8 +1571,8 @@ StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
if (prop->type == PROP_POINTER) {
PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
- if (pprop->typef) {
- return pprop->typef(ptr);
+ if (pprop->type_fn) {
+ return pprop->type_fn(ptr);
}
if (pprop->type) {
return pprop->type;
@@ -1623,14 +1623,14 @@ void RNA_property_enum_items_ex(bContext *C,
*r_free = false;
- if (!use_static && eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
+ if (!use_static && eprop->item_fn && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
const EnumPropertyItem *item;
if (prop->flag & PROP_ENUM_NO_CONTEXT) {
- item = eprop->itemf(NULL, ptr, prop, r_free);
+ item = eprop->item_fn(NULL, ptr, prop, r_free);
}
else {
- item = eprop->itemf(C, ptr, prop, r_free);
+ item = eprop->item_fn(C, ptr, prop, r_free);
}
/* any callbacks returning NULL should be fixed */
@@ -1753,16 +1753,16 @@ void RNA_property_enum_items_gettexted_all(bContext *C,
*r_totitem = eprop->totitem;
}
- if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
+ if (eprop->item_fn && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
const EnumPropertyItem *item;
int i;
bool free = false;
if (prop->flag & PROP_ENUM_NO_CONTEXT) {
- item = eprop->itemf(NULL, ptr, prop, &free);
+ item = eprop->item_fn(NULL, ptr, prop, &free);
}
else {
- item = eprop->itemf(C, ptr, prop, &free);
+ item = eprop->item_fn(C, ptr, prop, &free);
}
/* any callbacks returning NULL should be fixed */
@@ -3662,8 +3662,8 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
}
/* for groups, data is idprop itself */
- if (pprop->typef) {
- return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop);
+ if (pprop->type_fn) {
+ return rna_pointer_inherit_refine(ptr, pprop->type_fn(ptr), idprop);
}
return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
}
diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c
index 8e95388fe2b..7be155605e6 100644
--- a/source/blender/makesrna/intern/rna_animviz.c
+++ b/source/blender/makesrna/intern/rna_animviz.c
@@ -150,7 +150,7 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna)
prop = RNA_def_property(srna, "line_thickness", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "line_thickness");
RNA_def_property_range(prop, 1, 6);
- RNA_def_property_ui_text(prop, "Line Thickness", "Line thickness for drawing path");
+ RNA_def_property_ui_text(prop, "Line Thickness", "Line thickness for motion path");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
/* Settings */
@@ -176,7 +176,7 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna)
/* Draw lines between keyframes */
prop = RNA_def_property(srna, "lines", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_LINES);
- RNA_def_property_ui_text(prop, "Lines", "Draw straight lines between keyframe points");
+ RNA_def_property_ui_text(prop, "Lines", "Use straight lines between keyframe points");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 32162b068f6..554f04ca23c 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -966,10 +966,11 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
prop = RNA_def_property(srna, "show_wire", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_DRAWWIRE);
- RNA_def_property_ui_text(prop,
- "Display Wire",
- "Bone is always drawn as Wireframe regardless of viewport draw mode "
- "(useful for non-obstructive custom bone shapes)");
+ RNA_def_property_ui_text(
+ prop,
+ "Display Wire",
+ "Bone is always displayed in wireframe regardless of viewport shading mode "
+ "(useful for non-obstructive custom bone shapes)");
RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
/* XXX: use_cyclic_offset is deprecated in 2.5. May/may not return */
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index f662b6d2709..d603fea5a4a 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1895,7 +1895,8 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_lasso", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_BRUSH_DISSABLE_LASSO);
- RNA_def_property_ui_text(prop, "Show Lasso", "Do not draw fill color while drawing the stroke");
+ RNA_def_property_ui_text(
+ prop, "Show Lasso", "Do not display fill color while drawing the stroke");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "use_occlude_eraser", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index ea019c70445..206ebc2cb14 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -896,6 +896,9 @@ static void rna_def_curvemapping(BlenderRNA *brna)
func = RNA_def_function(srna, "update", "BKE_curvemapping_changed_all");
RNA_def_function_ui_description(func, "Update curve mapping after making changes");
+ func = RNA_def_function(srna, "reset_view", "BKE_curvemapping_reset_view");
+ RNA_def_function_ui_description(func, "Reset the curve mapping grid to its clipping size");
+
func = RNA_def_function(srna, "initialize", "rna_CurveMap_initialize");
RNA_def_function_ui_description(func, "Initialize curve");
@@ -1107,7 +1110,7 @@ static void rna_def_histogram(BlenderRNA *brna)
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, prop_mode_items);
- RNA_def_property_ui_text(prop, "Mode", "Channels to display when drawing the histogram");
+ RNA_def_property_ui_text(prop, "Mode", "Channels to display in the histogram");
prop = RNA_def_property(srna, "show_line", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", HISTO_FLAG_LINE);
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index df3bd0cca29..5e188285e39 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -3267,7 +3267,7 @@ void RNA_def_property_enum_funcs(PropertyRNA *prop,
eprop->set = (PropEnumSetFunc)set;
}
if (item) {
- eprop->itemf = (PropEnumItemFunc)item;
+ eprop->item_fn = (PropEnumItemFunc)item;
}
break;
}
@@ -3292,7 +3292,7 @@ void RNA_def_property_enum_funcs_runtime(PropertyRNA *prop,
eprop->set_ex = setfunc;
}
if (itemfunc) {
- eprop->itemf = itemfunc;
+ eprop->item_fn = itemfunc;
}
if (getfunc || setfunc) {
@@ -3373,7 +3373,7 @@ void RNA_def_property_string_funcs_runtime(PropertyRNA *prop,
}
void RNA_def_property_pointer_funcs(
- PropertyRNA *prop, const char *get, const char *set, const char *typef, const char *poll)
+ PropertyRNA *prop, const char *get, const char *set, const char *type_fn, const char *poll)
{
StructRNA *srna = DefRNA.laststruct;
@@ -3392,8 +3392,8 @@ void RNA_def_property_pointer_funcs(
if (set) {
pprop->set = (PropPointerSetFunc)set;
}
- if (typef) {
- pprop->typef = (PropPointerTypeFunc)typef;
+ if (type_fn) {
+ pprop->type_fn = (PropPointerTypeFunc)type_fn;
}
if (poll) {
pprop->poll = (PropPointerPollFunc)poll;
@@ -3821,7 +3821,7 @@ PropertyRNA *RNA_def_enum_flag(StructOrFunctionRNA *cont_,
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
- eprop->itemf = itemfunc;
+ eprop->item_fn = itemfunc;
}
PropertyRNA *RNA_def_float(StructOrFunctionRNA *cont_,
diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c
index a34c3c7b536..dab76c84e6a 100644
--- a/source/blender/makesrna/intern/rna_fluid.c
+++ b/source/blender/makesrna/intern/rna_fluid.c
@@ -2553,7 +2553,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "display_thickness");
RNA_def_property_range(prop, 0.001, 1000.0);
RNA_def_property_ui_range(prop, 0.1, 100.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "Thickness", "Thickness of smoke drawing in the viewport");
+ RNA_def_property_ui_text(prop, "Thickness", "Thickness of smoke display in the viewport");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
prop = RNA_def_property(srna, "display_interpolation", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index f9caa746dac..1a0497b72f4 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -1632,7 +1632,7 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna)
prop = RNA_def_property(srna, "display_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, stroke_display_mode_items);
- RNA_def_property_ui_text(prop, "Draw Mode", "Coordinate space that stroke is in");
+ RNA_def_property_ui_text(prop, "Display Mode", "Coordinate space that stroke is in");
RNA_def_property_update(prop, 0, "rna_GPencil_update");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
@@ -2227,13 +2227,13 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_points", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_DRAWDEBUG);
RNA_def_property_ui_text(
- prop, "Show Points", "Draw the points which make up the strokes (for debugging purposes)");
+ prop, "Show Points", "Show the points which make up the strokes (for debugging purposes)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* In Front */
prop = RNA_def_property(srna, "show_in_front", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_LAYER_NO_XRAY);
- RNA_def_property_ui_text(prop, "In Front", "Make the layer draw in front of objects");
+ RNA_def_property_ui_text(prop, "In Front", "Make the layer display in front of objects");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Parent object */
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index bfcb0039ca8..95972dd444f 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -424,6 +424,7 @@ void RNA_api_window(struct StructRNA *srna);
void RNA_api_wm(struct StructRNA *srna);
void RNA_api_space_node(struct StructRNA *srna);
void RNA_api_space_text(struct StructRNA *srna);
+void RNA_api_space_filebrowser(struct StructRNA *srna);
void RNA_api_region_view3d(struct StructRNA *srna);
void RNA_api_texture(struct StructRNA *srna);
void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop, const bool metastrip);
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index e6ed0f69300..1dd08bb1074 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -453,7 +453,7 @@ typedef struct EnumPropertyRNA {
PropEnumGetFunc get;
PropEnumSetFunc set;
- PropEnumItemFunc itemf;
+ PropEnumItemFunc item_fn;
PropEnumGetFuncEx get_ex;
PropEnumSetFuncEx set_ex;
@@ -471,7 +471,7 @@ typedef struct PointerPropertyRNA {
PropPointerGetFunc get;
PropPointerSetFunc set;
- PropPointerTypeFunc typef;
+ PropPointerTypeFunc type_fn;
/** unlike operators, 'set' can still run if poll fails, used for filtering display. */
PropPointerPollFunc poll;
diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c
index 319aeb69a2b..707799e5633 100644
--- a/source/blender/makesrna/intern/rna_lattice.c
+++ b/source/blender/makesrna/intern/rna_lattice.c
@@ -371,7 +371,7 @@ static void rna_def_lattice(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", LT_OUTSIDE);
RNA_def_property_boolean_funcs(prop, NULL, "rna_Lattice_use_outside_set");
RNA_def_property_ui_text(
- prop, "Outside", "Only draw, and take into account, the outer vertices");
+ prop, "Outside", "Only display and take into account the outer vertices");
RNA_def_property_update(prop, 0, "rna_Lattice_update_data_editlatt");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c
index 433d499b4c1..52ebd5af993 100644
--- a/source/blender/makesrna/intern/rna_light.c
+++ b/source/blender/makesrna/intern/rna_light.c
@@ -504,7 +504,7 @@ static void rna_def_spot_light(BlenderRNA *brna)
RNA_def_property_ui_text(
prop,
"Show Cone",
- "Draw transparent cone in 3D view to visualize which objects are contained in it");
+ "Display transparent cone in 3D view to visualize which objects are contained in it");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
}
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 94b56e4f4e0..84c831a178e 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -616,7 +616,7 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, gpcolordata_mode_types_items);
- RNA_def_property_ui_text(prop, "Mode Type", "Select draw mode for stroke");
+ RNA_def_property_ui_text(prop, "Line Type", "Select line type for strokes");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
/* stroke style */
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index fe375cda24a..2635d8b9669 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1743,8 +1743,7 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_only_control_edges", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", eSubsurfModifierFlag_ControlEdges);
- RNA_def_property_ui_text(
- prop, "Optimal Display", "Skip drawing/rendering of interior subdivided edges");
+ RNA_def_property_ui_text(prop, "Optimal Display", "Skip displaying interior subdivided edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "use_creases", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index d32872d1682..c9520c939f4 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -290,7 +290,7 @@ static void rna_def_moviecliUser(BlenderRNA *brna)
RNA_def_property_enum_items(prop, clip_render_size_items);
RNA_def_property_ui_text(prop,
"Proxy Render Size",
- "Draw preview using full resolution or different proxy resolutions");
+ "Display preview using full resolution or different proxy resolutions");
RNA_def_property_update(
prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClipUser_proxy_render_settings_update");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 2c0d7ba3d06..dfb882cde33 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -10366,7 +10366,7 @@ static void rna_def_node(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_texture", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_ACTIVE_TEXTURE);
- RNA_def_property_ui_text(prop, "Show Texture", "Draw node in viewport textured draw mode");
+ RNA_def_property_ui_text(prop, "Show Texture", "Display node in viewport textured shading mode");
RNA_def_property_update(prop, 0, "rna_Node_update");
/* generic property update function */
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 799d1e8190c..a70b776b07a 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -3316,7 +3316,8 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_wire", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWWIRE);
- RNA_def_property_ui_text(prop, "Display Wire", "Add the object's wireframe over solid drawing");
+ RNA_def_property_ui_text(
+ prop, "Display Wire", "Display the object's wireframe over solid shading");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
prop = RNA_def_property(srna, "show_all_edges", PROP_BOOLEAN, PROP_NONE);
@@ -3338,7 +3339,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_in_front", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAW_IN_FRONT);
- RNA_def_property_ui_text(prop, "In Front", "Make the object draw in front of others");
+ RNA_def_property_ui_text(prop, "In Front", "Make the object display in front of others");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_GPencil_update");
/* pose */
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index f81f965d0c8..d94e68a6808 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -2694,7 +2694,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_health", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_HEALTH);
- RNA_def_property_ui_text(prop, "Health", "Draw boid health");
+ RNA_def_property_ui_text(prop, "Health", "Display boid health");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "use_absolute_path_time", PROP_BOOLEAN, PROP_NONE);
@@ -2742,7 +2742,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_render_adaptive", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_ADAPT);
- RNA_def_property_ui_text(prop, "Adaptive Render", "Draw steps of the particle path");
+ RNA_def_property_ui_text(prop, "Adaptive Render", "Display steps of the particle path");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "use_velocity_length", PROP_BOOLEAN, PROP_NONE);
@@ -2764,7 +2764,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "draw_as");
RNA_def_property_enum_items(prop, part_draw_as_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particle_draw_as_itemf");
- RNA_def_property_ui_text(prop, "Particle Drawing", "How particles are drawn in viewport");
+ RNA_def_property_ui_text(prop, "Particle Display", "How particles are displayed in viewport");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "render_type", PROP_ENUM, PROP_NONE);
@@ -2777,14 +2777,14 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "display_color", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "draw_col");
RNA_def_property_enum_items(prop, draw_col_items);
- RNA_def_property_ui_text(prop, "Draw Color", "Draw additional particle data as a color");
+ RNA_def_property_ui_text(prop, "Display Color", "Display additional particle data as a color");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "display_size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "draw_size");
RNA_def_property_range(prop, 0, 1000);
RNA_def_property_ui_range(prop, 0, 100, 1, -1);
- RNA_def_property_ui_text(prop, "Draw Size", "Size of particles on viewport");
+ RNA_def_property_ui_text(prop, "Display Size", "Size of particles on viewport");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "child_type", PROP_ENUM, PROP_NONE);
@@ -2797,7 +2797,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "draw_step");
RNA_def_property_range(prop, 0, 10);
RNA_def_property_ui_range(prop, 0, 7, 1, -1);
- RNA_def_property_ui_text(prop, "Steps", "How many steps paths are drawn with (power of 2)");
+ RNA_def_property_ui_text(prop, "Steps", "How many steps paths are displayed with (power of 2)");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "render_step", PROP_INT, PROP_NONE);
@@ -3418,13 +3418,13 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "path_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "path_start");
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_PartSetting_pathstartend_range");
- RNA_def_property_ui_text(prop, "Path Start", "Starting time of drawn path");
+ RNA_def_property_ui_text(prop, "Path Start", "Starting time of path");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "path_end", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "path_end");
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_PartSetting_pathstartend_range");
- RNA_def_property_ui_text(prop, "Path End", "End time of drawn path");
+ RNA_def_property_ui_text(prop, "Path End", "End time of path");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "trail_count", PROP_INT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index bd45990fe30..ba65e42895c 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -425,22 +425,6 @@ static void rna_Itasc_update_rebuild(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_Itasc_update(bmain, scene, ptr);
}
-static void rna_PoseChannel_bone_custom_set(PointerRNA *ptr,
- PointerRNA value,
- struct ReportList *UNUSED(reports))
-{
- bPoseChannel *pchan = (bPoseChannel *)ptr->data;
-
- if (pchan->custom) {
- id_us_min(&pchan->custom->id);
- pchan->custom = NULL;
- }
-
- pchan->custom = value.data;
-
- id_us_plus(&pchan->custom->id);
-}
-
static PointerRNA rna_PoseChannel_bone_group_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->owner_id;
@@ -1368,11 +1352,10 @@ static void rna_def_pose_channel(BlenderRNA *brna)
prop = RNA_def_property(srna, "custom_shape", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "custom");
RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
- RNA_def_property_pointer_funcs(prop, NULL, "rna_PoseChannel_bone_custom_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
- prop, "Custom Object", "Object that defines custom draw type for this bone");
+ prop, "Custom Object", "Object that defines custom display shape for this bone");
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_dependency_update");
diff --git a/source/blender/makesrna/intern/rna_pose_api.c b/source/blender/makesrna/intern/rna_pose_api.c
index 59704b00391..d93972aa0ad 100644
--- a/source/blender/makesrna/intern/rna_pose_api.c
+++ b/source/blender/makesrna/intern/rna_pose_api.c
@@ -38,9 +38,14 @@
#ifdef RNA_RUNTIME
-/* #include "DNA_anim_types.h" */
+# include "BKE_animsys.h"
# include "BKE_armature.h"
-# include "DNA_action_types.h" /* bPose */
+# include "BKE_context.h"
+
+# include "DNA_action_types.h"
+# include "DNA_anim_types.h"
+
+# include "BLI_ghash.h"
static float rna_PoseBone_do_envelope(bPoseChannel *chan, float *vec)
{
@@ -102,12 +107,49 @@ static void rna_PoseBone_compute_bbone_handles(bPoseChannel *pchan,
BKE_pchan_bbone_handles_compute(
&params, ret_h1, ret_roll1, ret_h2, ret_roll2, ease || offsets, offsets);
}
+
+static void rna_Pose_apply_pose_from_action(ID *pose_owner,
+ bContext *C,
+ bAction *action,
+ const float evaluation_time)
+{
+ BLI_assert(GS(pose_owner->name) == ID_OB);
+ Object *pose_owner_ob = (Object *)pose_owner;
+
+ AnimationEvalContext anim_eval_context = {CTX_data_depsgraph_pointer(C), evaluation_time};
+ BKE_pose_apply_action(pose_owner_ob, action, &anim_eval_context);
+
+ /* Do NOT tag with ID_RECALC_ANIMATION, as that would overwrite the just-applied pose. */
+ DEG_id_tag_update(pose_owner, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pose_owner);
+}
+
#else
-void RNA_api_pose(StructRNA *UNUSED(srna))
+void RNA_api_pose(StructRNA *srna)
{
- /* FunctionRNA *func; */
- /* PropertyRNA *parm; */
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "apply_pose_from_action", "rna_Pose_apply_pose_from_action");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(
+ func,
+ "Apply the given action to this pose by evaluating it at a specific time. Only updates the "
+ "pose of selected bones, or all bones if none are selected");
+
+ parm = RNA_def_pointer(func, "action", "Action", "Action", "The Action containing the pose");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ parm = RNA_def_float(func,
+ "evaluation_time",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Evaluation Time",
+ "Time at which the given action is evaluated to obtain the pose",
+ -FLT_MAX,
+ FLT_MAX);
}
void RNA_api_pose_channel(StructRNA *srna)
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index b0a942cd39e..d553ead1e45 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -910,14 +910,14 @@ static const EnumPropertyItem *rna_EnumProperty_default_itemf(bContext *C,
return DummyRNA_NULL_items;
}
- if ((eprop->itemf == NULL) || (eprop->itemf == rna_EnumProperty_default_itemf) ||
+ if ((eprop->item_fn == NULL) || (eprop->item_fn == rna_EnumProperty_default_itemf) ||
(ptr->type == &RNA_EnumProperty) || (C == NULL)) {
if (eprop->item) {
return eprop->item;
}
}
- return eprop->itemf(C, ptr, prop, r_free);
+ return eprop->item_fn(C, ptr, prop, r_free);
}
/* XXX - not sure this is needed? */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 170bbc7e372..1ac224b27e4 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -5977,7 +5977,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "frs_sec");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 1, SHRT_MAX);
- RNA_def_property_ui_range(prop, 1, 120, 1, -1);
+ RNA_def_property_ui_range(prop, 1, 240, 1, -1);
RNA_def_property_ui_text(prop, "FPS", "Framerate, expressed in frames per second");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_fps_update");
@@ -6445,7 +6445,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "seq_prev_type");
RNA_def_property_enum_items(prop, rna_enum_shading_type_items);
RNA_def_property_ui_text(
- prop, "Sequencer Preview Shading", "Method to draw in the sequencer view");
+ prop, "Sequencer Preview Shading", "Display method used in the sequencer view");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update");
# if 0 /* UNUSED, see R_SEQ_GL_REND comment */
@@ -6454,7 +6454,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_enum_items(prop, rna_enum_shading_type_items);
/* XXX Label and tooltips are obviously wrong! */
RNA_def_property_ui_text(
- prop, "Sequencer Preview Shading", "Method to draw in the sequencer view");
+ prop, "Sequencer Preview Shading", "Display method used in the sequencer view");
# endif
prop = RNA_def_property(srna, "use_sequencer_override_scene_strip", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 070fb08c3b4..00d8c43a111 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -53,6 +53,7 @@
# include "SEQ_add.h"
# include "SEQ_edit.h"
+# include "SEQ_effects.h"
# include "SEQ_relations.h"
# include "SEQ_render.h"
# include "SEQ_sequencer.h"
@@ -80,34 +81,6 @@ static void rna_Sequence_swap_internal(Sequence *seq_self,
}
}
-static Sequence *alloc_generic_sequence(
- ListBase *seqbase, const char *name, int frame_start, int channel, int type, const char *file)
-{
- Sequence *seq;
- StripElem *se;
-
- seq = SEQ_sequence_alloc(seqbase, frame_start, channel, type);
-
- BLI_strncpy(seq->name + 2, name, sizeof(seq->name) - 2);
- SEQ_sequence_base_unique_name_recursive(seqbase, seq);
-
- Strip *strip = seq->strip;
-
- /* Don't allocate StripElem for clip, mask and scene types. This struct is not handled in
- * seq_dupli() function. */
- if (file && !ELEM(type, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK, SEQ_TYPE_SCENE)) {
- strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
- BLI_split_dirfile(file, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
-
- SEQ_render_init_colorspace(seq);
- }
- else {
- strip->stripdata = NULL;
- }
-
- return seq;
-}
-
static Sequence *rna_Sequences_new_clip(ID *id,
ListBase *seqbase,
Main *bmain,
@@ -117,15 +90,10 @@ static Sequence *rna_Sequences_new_clip(ID *id,
int frame_start)
{
Scene *scene = (Scene *)id;
- Sequence *seq;
-
- seq = alloc_generic_sequence(
- seqbase, name, frame_start, channel, SEQ_TYPE_MOVIECLIP, clip->filepath);
- seq->clip = clip;
- seq->len = BKE_movieclip_get_duration(clip);
- id_us_plus((ID *)clip);
-
- SEQ_time_update_sequence_bounds(scene, seq);
+ SeqLoadData load_data;
+ SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel);
+ load_data.clip = clip;
+ Sequence *seq = SEQ_add_movieclip_strip(scene, seqbase, &load_data);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -165,15 +133,10 @@ static Sequence *rna_Sequences_new_mask(ID *id,
int frame_start)
{
Scene *scene = (Scene *)id;
- Sequence *seq;
-
- seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_MASK, mask->id.name);
- seq->mask = mask;
- seq->len = BKE_mask_get_duration(mask);
- id_us_plus((ID *)mask);
-
- SEQ_time_update_sequence_bounds(scene, seq);
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ SeqLoadData load_data;
+ SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel);
+ load_data.mask = mask;
+ Sequence *seq = SEQ_add_mask_strip(scene, seqbase, &load_data);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -202,15 +165,10 @@ static Sequence *rna_Sequences_new_scene(ID *id,
int frame_start)
{
Scene *scene = (Scene *)id;
- Sequence *seq;
-
- seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_SCENE, NULL);
- seq->scene = sce_seq;
- seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
- id_us_plus((ID *)sce_seq);
-
- SEQ_time_update_sequence_bounds(scene, seq);
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ SeqLoadData load_data;
+ SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel);
+ load_data.scene = sce_seq;
+ Sequence *seq = SEQ_add_scene_strip(scene, seqbase, &load_data);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -244,27 +202,24 @@ static Sequence *rna_Sequences_meta_new_scene(ID *id,
static Sequence *rna_Sequences_new_image(ID *id,
ListBase *seqbase,
Main *bmain,
- ReportList *reports,
+ ReportList *UNUSED(reports),
const char *name,
const char *file,
int channel,
int frame_start)
{
Scene *scene = (Scene *)id;
- Sequence *seq;
- seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_IMAGE, file);
- seq->len = 1;
+ SeqLoadData load_data;
+ SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
+ load_data.image.len = 1;
+ Sequence *seq = SEQ_add_image_strip(bmain, scene, seqbase, &load_data);
- if (seq->strip->stripdata->name[0] == '\0') {
- BKE_report(reports, RPT_ERROR, "Sequences.new_image: unable to open image file");
- BLI_remlink(seqbase, seq);
- SEQ_sequence_free(scene, seq, true);
- return NULL;
- }
-
- SEQ_time_update_sequence_bounds(scene, seq);
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ char dir[FILE_MAX], filename[FILE_MAX];
+ BLI_split_dirfile(file, dir, filename, sizeof(dir), sizeof(filename));
+ SEQ_add_image_set_directory(seq, dir);
+ SEQ_add_image_load_file(seq, 0, filename);
+ SEQ_add_image_init_alpha_mode(seq);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -299,48 +254,47 @@ static Sequence *rna_Sequences_meta_new_image(ID *id,
id, &seq->seqbase, bmain, reports, name, file, channel, frame_start);
}
-static Sequence *rna_Sequences_new_movie(
- ID *id, ListBase *seqbase, const char *name, const char *file, int channel, int frame_start)
+static Sequence *rna_Sequences_new_movie(ID *id,
+ ListBase *seqbase,
+ Main *bmain,
+ const char *name,
+ const char *file,
+ int channel,
+ int frame_start)
{
Scene *scene = (Scene *)id;
- Sequence *seq;
- StripAnim *sanim;
-
- seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_MOVIE, file);
-
- struct anim *an = openanim(file, IB_rect, 0, NULL);
- if (an == NULL) {
- /* Without anim, the strip gets duration 0, which makes it impossible to select in the UI. */
- seq->len = 1;
- }
- else {
- sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
- BLI_addtail(&seq->anims, sanim);
- sanim->anim = an;
-
- seq->anim_preseek = IMB_anim_get_preseek(an);
- seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN);
- }
-
- SEQ_time_update_sequence_bounds(scene, seq);
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ SeqLoadData load_data;
+ SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
+ load_data.allow_invalid_file = true;
+ Sequence *seq = SEQ_add_movie_strip(bmain, scene, seqbase, &load_data);
+ DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
return seq;
}
-static Sequence *rna_Sequences_editing_new_movie(
- ID *id, Editing *ed, const char *name, const char *file, int channel, int frame_start)
+static Sequence *rna_Sequences_editing_new_movie(ID *id,
+ Editing *ed,
+ Main *bmain,
+ const char *name,
+ const char *file,
+ int channel,
+ int frame_start)
{
- return rna_Sequences_new_movie(id, &ed->seqbase, name, file, channel, frame_start);
+ return rna_Sequences_new_movie(id, &ed->seqbase, bmain, name, file, channel, frame_start);
}
-static Sequence *rna_Sequences_meta_new_movie(
- ID *id, Sequence *seq, const char *name, const char *file, int channel, int frame_start)
+static Sequence *rna_Sequences_meta_new_movie(ID *id,
+ Sequence *seq,
+ Main *bmain,
+ const char *name,
+ const char *file,
+ int channel,
+ int frame_start)
{
- return rna_Sequences_new_movie(id, &seq->seqbase, name, file, channel, frame_start);
+ return rna_Sequences_new_movie(id, &seq->seqbase, bmain, name, file, channel, frame_start);
}
# ifdef WITH_AUDASPACE
@@ -354,22 +308,15 @@ static Sequence *rna_Sequences_new_sound(ID *id,
int frame_start)
{
Scene *scene = (Scene *)id;
- Sequence *seq;
+ SeqLoadData load_data;
+ SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
+ load_data.allow_invalid_file = true;
+ Sequence *seq = SEQ_add_sound_strip(bmain, scene, seqbase, &load_data);
- bSound *sound = BKE_sound_new_file(bmain, file);
-
- SoundInfo info;
- if (!BKE_sound_info_get(bmain, sound, &info)) {
- BKE_id_free(bmain, sound);
+ if (seq == NULL) {
BKE_report(reports, RPT_ERROR, "Sequences.new_sound: unable to open sound file");
return NULL;
}
- seq = alloc_generic_sequence(
- seqbase, name, frame_start, channel, SEQ_TYPE_SOUND_RAM, sound->filepath);
- seq->sound = sound;
- seq->len = ceil((double)info.length * FPS);
-
- SEQ_time_update_sequence_bounds(scene, seq);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
@@ -432,8 +379,7 @@ static Sequence *rna_Sequences_new_effect(ID *id,
{
Scene *scene = (Scene *)id;
Sequence *seq;
- struct SeqEffectHandle sh;
- int num_inputs = SEQ_effect_get_num_inputs(type);
+ const int num_inputs = SEQ_effect_get_num_inputs(type);
switch (num_inputs) {
case 0:
@@ -469,26 +415,14 @@ static Sequence *rna_Sequences_new_effect(ID *id,
return NULL;
}
- seq = alloc_generic_sequence(seqbase, name, frame_start, channel, type, NULL);
-
- sh = SEQ_effect_handle_get(seq);
-
- seq->seq1 = seq1;
- seq->seq2 = seq2;
- seq->seq3 = seq3;
-
- sh.init(seq);
-
- if (!seq1) { /* effect has no deps */
- seq->len = 1;
- SEQ_transform_set_right_handle_frame(seq, frame_end);
- }
-
- seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
-
- SEQ_time_update_sequence(scene, seq);
- SEQ_time_update_sequence_bounds(scene, seq);
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ SeqLoadData load_data;
+ SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel);
+ load_data.effect.end_frame = frame_end;
+ load_data.effect.type = type;
+ load_data.effect.seq1 = seq1;
+ load_data.effect.seq2 = seq2;
+ load_data.effect.seq3 = seq3;
+ seq = SEQ_add_effect_strip(scene, seqbase, &load_data);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
@@ -865,7 +799,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop, const bool metastri
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "new_movie", new_movie_func_name);
- RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Add a new movie sequence");
parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 3b43ad5e766..5312aea9295 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3178,7 +3178,7 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
prop = RNA_def_property(srna, "display_stretch_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "dt_uvstretch");
RNA_def_property_enum_items(prop, dt_uvstretch_items);
- RNA_def_property_ui_text(prop, "Display Stretch Type", "Type of stretch to draw");
+ RNA_def_property_ui_text(prop, "Display Stretch Type", "Type of stretch to display");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
prop = RNA_def_property(srna, "show_modified_edges", PROP_BOOLEAN, PROP_NONE);
@@ -3562,7 +3562,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
prop = RNA_def_property(srna, "cavity_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, cavity_type_items);
- RNA_def_property_ui_text(prop, "Cavity Type", "Way to draw the cavity shading");
+ RNA_def_property_ui_text(prop, "Cavity Type", "Way to display the cavity shading");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
prop = RNA_def_property(srna, "curvature_ridge_factor", PROP_FLOAT, PROP_FACTOR);
@@ -3671,7 +3671,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
prop = RNA_def_property(srna, "background_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, background_type_items);
- RNA_def_property_ui_text(prop, "Background", "Way to draw the background");
+ RNA_def_property_ui_text(prop, "Background", "Way to display the background");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
prop = RNA_def_property(srna, "background_color", PROP_FLOAT, PROP_COLOR);
@@ -4028,56 +4028,56 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_edges", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_EDGES);
- RNA_def_property_ui_text(prop, "Draw Edges", "Highlight selected edges");
+ RNA_def_property_ui_text(prop, "Display Edges", "Highlight selected edges");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_faces", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_FACES);
- RNA_def_property_ui_text(prop, "Draw Faces", "Highlight selected faces");
+ RNA_def_property_ui_text(prop, "Display Faces", "Highlight selected faces");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_face_center", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_FACE_DOT);
RNA_def_property_ui_text(
prop,
- "Draw Face Center",
+ "Display Face Center",
"Display face center when face selection is enabled in solid shading modes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_edge_crease", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_CREASES);
RNA_def_property_ui_text(
- prop, "Draw Creases", "Display creases created for Subdivision Surface modifier");
+ prop, "Display Creases", "Display creases created for Subdivision Surface modifier");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_edge_bevel_weight", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_BWEIGHTS);
RNA_def_property_ui_text(
- prop, "Draw Bevel Weights", "Display weights created for the Bevel modifier");
+ prop, "Display Bevel Weights", "Display weights created for the Bevel modifier");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_edge_seams", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_SEAMS);
- RNA_def_property_ui_text(prop, "Draw Seams", "Display UV unwrapping seams");
+ RNA_def_property_ui_text(prop, "Display Seams", "Display UV unwrapping seams");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_edge_sharp", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_SHARP);
RNA_def_property_ui_text(
- prop, "Draw Sharp", "Display sharp edges, used with the Edge Split modifier");
+ prop, "Display Sharp", "Display sharp edges, used with the Edge Split modifier");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_freestyle_edge_marks", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_FREESTYLE_EDGE);
RNA_def_property_ui_text(prop,
- "Draw Freestyle Edge Marks",
+ "Display Freestyle Edge Marks",
"Display Freestyle edge marks, used with the Freestyle renderer");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_freestyle_face_marks", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_FREESTYLE_FACE);
RNA_def_property_ui_text(prop,
- "Draw Freestyle Face Marks",
+ "Display Freestyle Face Marks",
"Display Freestyle face marks, used with the Freestyle renderer");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -4563,7 +4563,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "multiview_eye");
RNA_def_property_enum_items(prop, stereo3d_eye_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceView3D_stereo3d_camera_itemf");
- RNA_def_property_ui_text(prop, "Stereo Eye", "Current stereo eye being drawn");
+ RNA_def_property_ui_text(prop, "Stereo Eye", "Current stereo eye being displayed");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "stereo_3d_camera", PROP_ENUM, PROP_NONE);
@@ -4977,7 +4977,7 @@ static void rna_def_space_image(BlenderRNA *brna)
"rna_SpaceImageEditor_display_channels_get",
NULL,
"rna_SpaceImageEditor_display_channels_itemf");
- RNA_def_property_ui_text(prop, "Display Channels", "Channels of the image to draw");
+ RNA_def_property_ui_text(prop, "Display Channels", "Channels of the image to display");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
prop = RNA_def_property(srna, "show_stereo_3d", PROP_BOOLEAN, PROP_NONE);
@@ -5125,17 +5125,17 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
"NO_WAVEFORMS",
0,
"Waveforms Off",
- "No waveforms drawn for any sound strips"},
+ "Don't display waveforms for any sound strips"},
{SEQ_ALL_WAVEFORMS,
"ALL_WAVEFORMS",
0,
"Waveforms On",
- "Waveforms drawn for all sound strips"},
+ "Display waveforms for all sound strips"},
{0,
"DEFAULT_WAVEFORMS",
0,
"Use Strip Option",
- "Waveforms drawn according to strip setting"},
+ "Display waveforms depending on strip setting"},
{0, NULL, 0, NULL, NULL},
};
@@ -5226,13 +5226,13 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
prop = RNA_def_property(srna, "preview_channels", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, preview_channels_items);
- RNA_def_property_ui_text(prop, "Display Channels", "Channels of the preview to draw");
+ RNA_def_property_ui_text(prop, "Display Channels", "Channels of the preview to display");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, "rna_SequenceEditor_update_cache");
prop = RNA_def_property(srna, "waveform_display_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, waveform_type_display_items);
- RNA_def_property_ui_text(prop, "Waveform Display", "How Waveforms are drawn");
+ RNA_def_property_ui_text(prop, "Waveform Display", "How Waveforms are displayed");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
prop = RNA_def_property(srna, "use_zoom_to_fit", PROP_BOOLEAN, PROP_NONE);
@@ -5268,7 +5268,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
prop = RNA_def_property(srna, "overlay_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "overlay_type");
RNA_def_property_enum_items(prop, overlay_type_items);
- RNA_def_property_ui_text(prop, "Overlay Type", "Overlay draw type");
+ RNA_def_property_ui_text(prop, "Overlay Type", "Overlay display method");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
prop = RNA_def_property(srna, "show_backdrop", PROP_BOOLEAN, PROP_NONE);
@@ -6154,7 +6154,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_details_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "details_flags", FILE_DETAILS_SIZE);
- RNA_def_property_ui_text(prop, "File Size", "Draw a column listing the size of each file");
+ RNA_def_property_ui_text(prop, "File Size", "Show a column listing the size of each file");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "show_details_datetime", PROP_BOOLEAN, PROP_NONE);
@@ -6162,7 +6162,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(
prop,
"File Modification Date",
- "Draw a column listing the date and time of modification for each file");
+ "Show a column listing the date and time of modification for each file");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter", PROP_BOOLEAN, PROP_NONE);
@@ -6569,6 +6569,8 @@ static void rna_def_space_filebrowser(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(
prop, NC_SPACE | ND_SPACE_FILE_PARAMS, "rna_FileBrowser_FSMenu_active_update");
+
+ RNA_api_space_filebrowser(srna);
}
static void rna_def_space_info(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c
index e4c0ade1533..205a88edf84 100644
--- a/source/blender/makesrna/intern/rna_space_api.c
+++ b/source/blender/makesrna/intern/rna_space_api.c
@@ -27,6 +27,7 @@
# include "BKE_global.h"
+# include "ED_fileselect.h"
# include "ED_screen.h"
# include "ED_text.h"
@@ -115,4 +116,24 @@ void RNA_api_space_text(StructRNA *srna)
RNA_def_function_output(func, parm);
}
+void RNA_api_space_filebrowser(StructRNA *srna)
+{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "activate_asset_by_id", "ED_fileselect_activate_by_id");
+ RNA_def_function_ui_description(func, "Activate the asset entry that represents the given ID");
+
+ parm = RNA_def_property(func, "id_to_activate", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "ID");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ parm = RNA_def_boolean(
+ func,
+ "deferred",
+ 0,
+ "",
+ "Whether to activate the ID immediately (false) or after the file browser refreshes (true)");
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 5e5b3549986..aefb77c4077 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -1357,7 +1357,7 @@ static void rna_def_panel(BlenderRNA *brna)
0,
"Expand Header Layout",
"Allow buttons in the header to stretch and shrink to fill the entire layout width"},
- {PANEL_TYPE_DRAW_BOX, "DRAW_BOX", 0, "Box Style", "Draw panel with the box widget theme"},
+ {PANEL_TYPE_DRAW_BOX, "DRAW_BOX", 0, "Box Style", "Display panel with the box widget theme"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 4a50718c91d..b06ec674e81 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -3879,8 +3879,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
srna = RNA_def_struct(brna, "Theme", NULL);
RNA_def_struct_sdna(srna, "bTheme");
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
- RNA_def_struct_ui_text(
- srna, "Theme", "Theme settings defining draw style and colors in the user interface");
+ RNA_def_struct_ui_text(srna, "Theme", "User interface styling and color settings");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Name", "Name of the theme");
@@ -4270,12 +4269,13 @@ static void rna_def_userdef_solidlight(BlenderRNA *brna)
srna = RNA_def_struct(brna, "UserSolidLight", NULL);
RNA_def_struct_sdna(srna, "SolidLight");
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
- RNA_def_struct_ui_text(srna, "Solid Light", "Light used for Studio lighting in solid draw mode");
+ RNA_def_struct_ui_text(
+ srna, "Solid Light", "Light used for Studio lighting in solid shading mode");
prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", 1);
RNA_def_property_boolean_default(prop, true);
- RNA_def_property_ui_text(prop, "Enabled", "Enable this light in solid draw mode");
+ RNA_def_property_ui_text(prop, "Enabled", "Enable this light in solid shading mode");
RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update");
prop = RNA_def_property(srna, "smooth", PROP_FLOAT, PROP_FACTOR);
@@ -4815,7 +4815,8 @@ static void rna_def_userdef_view(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_text_antialiasing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "text_render", USER_TEXT_DISABLE_AA);
- RNA_def_property_ui_text(prop, "Text Anti-Aliasing", "Draw user interface text anti-aliased");
+ RNA_def_property_ui_text(
+ prop, "Text Anti-Aliasing", "Smooth jagged edges of user interface text");
RNA_def_property_update(prop, 0, "rna_userdef_text_update");
prop = RNA_def_property(srna, "text_hinting", PROP_ENUM, PROP_NONE);
@@ -5321,12 +5322,12 @@ static void rna_def_userdef_system(BlenderRNA *brna)
"2DTEXTURE",
0,
"2D Texture",
- "Use CPU for display transform and draw image with 2D texture"},
+ "Use CPU for display transform and display image with 2D texture"},
{IMAGE_DRAW_METHOD_GLSL,
"GLSL",
0,
"GLSL",
- "Use GLSL shaders for display transform and draw image with 2D texture"},
+ "Use GLSL shaders for display transform and display image with 2D texture"},
{0, NULL, 0, NULL, NULL},
};
@@ -5363,7 +5364,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(
prop,
"UI Scale",
- "Size multiplier to use when drawing custom user interface elements, so that "
+ "Size multiplier to use when displaying custom user interface elements, so that "
"they are scaled correctly on screens with different DPI. This value is based "
"on operating system DPI settings and Blender display scale");
@@ -5373,7 +5374,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(
prop,
"UI Line Width",
- "Suggested line thickness and point size in pixels, for add-ons drawing custom "
+ "Suggested line thickness and point size in pixels, for add-ons displaying custom "
"user interface elements, based on operating system settings and Blender UI scale");
prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE);
@@ -5442,7 +5443,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_region_overlap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_REGION_OVERLAP);
RNA_def_property_ui_text(
- prop, "Region Overlap", "Draw tool/property regions over the main region");
+ prop, "Region Overlap", "Display tool/property regions over the main region");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
prop = RNA_def_property(srna, "viewport_aa", PROP_ENUM, PROP_NONE);
@@ -5456,7 +5457,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_collection_sdna(prop, NULL, "light_param", "");
RNA_def_property_struct_type(prop, "UserSolidLight");
RNA_def_property_ui_text(
- prop, "Solid Lights", "Lights user to display objects in solid draw mode");
+ prop, "Solid Lights", "Lights user to display objects in solid shading mode");
prop = RNA_def_property(srna, "light_ambient", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "light_ambient");
@@ -6061,7 +6062,9 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_relative_paths", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_RELPATHS);
RNA_def_property_ui_text(
- prop, "Relative Paths", "Default relative path option for the file selector");
+ prop,
+ "Relative Paths",
+ "Default relative path option for the file selector, when no path is defined yet");
prop = RNA_def_property(srna, "use_file_compression", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_FILECOMPRESS);
@@ -6186,7 +6189,8 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SAVE_PREVIEWS);
RNA_def_property_ui_text(prop,
"Save Preview Images",
- "Enables automatic saving of preview images in the .blend file");
+ "Enables automatic saving of preview images in the .blend file "
+ "as well as a thumbnail of the .blend");
rna_def_userdef_filepaths_asset_library(brna);
diff --git a/source/blender/makesrna/intern/rna_volume.c b/source/blender/makesrna/intern/rna_volume.c
index d71dcc0700b..1bddd9152db 100644
--- a/source/blender/makesrna/intern/rna_volume.c
+++ b/source/blender/makesrna/intern/rna_volume.c
@@ -366,7 +366,7 @@ static void rna_def_volume_display(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.00001, FLT_MAX);
RNA_def_property_ui_range(prop, 0.1, 100.0, 1, 3);
- RNA_def_property_ui_text(prop, "Density", "Thickness of volume drawing in the viewport");
+ RNA_def_property_ui_text(prop, "Density", "Thickness of volume display in the viewport");
RNA_def_property_update(prop, 0, "rna_Volume_update_display");
static const EnumPropertyItem wireframe_type_items[] = {
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index e61482c91e2..f7d139dd706 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -1238,20 +1238,20 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
prop = RNA_def_property(srna, "use_draw_hover", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Gizmo_flag_use_draw_hover_get", "rna_Gizmo_flag_use_draw_hover_set");
- RNA_def_property_ui_text(prop, "Draw Hover", "");
+ RNA_def_property_ui_text(prop, "Show Hover", "");
RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_DRAW_MODAL */
prop = RNA_def_property(srna, "use_draw_modal", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Gizmo_flag_use_draw_modal_get", "rna_Gizmo_flag_use_draw_modal_set");
- RNA_def_property_ui_text(prop, "Draw Active", "Draw while dragging");
+ RNA_def_property_ui_text(prop, "Show Active", "Show while dragging");
RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_DRAW_VALUE */
prop = RNA_def_property(srna, "use_draw_value", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Gizmo_flag_use_draw_value_get", "rna_Gizmo_flag_use_draw_value_set");
RNA_def_property_ui_text(
- prop, "Draw Value", "Show an indicator for the current value while dragging");
+ prop, "Show Value", "Show an indicator for the current value while dragging");
RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_DRAW_OFFSET_SCALE */
prop = RNA_def_property(srna, "use_draw_offset_scale", PROP_BOOLEAN, PROP_NONE);
@@ -1391,7 +1391,7 @@ static void rna_def_gizmogroup(BlenderRNA *brna)
"SCALE",
0,
"Scale",
- "Scale to respect zoom (otherwise zoom independent draw size)"},
+ "Scale to respect zoom (otherwise zoom independent display size)"},
{WM_GIZMOGROUPTYPE_DEPTH_3D,
"DEPTH_3D",
0,
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index c7731815a2a..4d1823b8951 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -77,6 +77,7 @@
#include "NOD_type_callbacks.hh"
using blender::float3;
+using blender::FunctionRef;
using blender::IndexRange;
using blender::Map;
using blender::Set;
@@ -90,8 +91,8 @@ using blender::bke::PersistentObjectHandle;
using blender::fn::GMutablePointer;
using blender::fn::GValueMap;
using blender::nodes::GeoNodeExecParams;
-using namespace blender::nodes::derived_node_tree_types;
using namespace blender::fn::multi_function_types;
+using namespace blender::nodes::derived_node_tree_types;
static void initData(ModifierData *md)
{
@@ -233,6 +234,11 @@ static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *u
&settings);
}
+static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
+{
+ walk(userData, ob, md, "texture");
+}
+
static bool isDisabled(const struct Scene *UNUSED(scene),
ModifierData *md,
bool UNUSED(useRenderParams))
@@ -249,8 +255,8 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
class GeometryNodesEvaluator {
private:
blender::LinearAllocator<> allocator_;
- Map<std::pair<const DInputSocket *, const DOutputSocket *>, GMutablePointer> value_by_input_;
- Vector<const DInputSocket *> group_outputs_;
+ Map<std::pair<DInputSocket, DOutputSocket>, GMutablePointer> value_by_input_;
+ Vector<DInputSocket> group_outputs_;
blender::nodes::MultiFunctionByNode &mf_by_node_;
const blender::nodes::DataTypeConversions &conversions_;
const PersistentDataHandleMap &handle_map_;
@@ -259,8 +265,8 @@ class GeometryNodesEvaluator {
Depsgraph *depsgraph_;
public:
- GeometryNodesEvaluator(const Map<const DOutputSocket *, GMutablePointer> &group_input_data,
- Vector<const DInputSocket *> group_outputs,
+ GeometryNodesEvaluator(const Map<DOutputSocket, GMutablePointer> &group_input_data,
+ Vector<DInputSocket> group_outputs,
blender::nodes::MultiFunctionByNode &mf_by_node,
const PersistentDataHandleMap &handle_map,
const Object *self_object,
@@ -275,15 +281,15 @@ class GeometryNodesEvaluator {
depsgraph_(depsgraph)
{
for (auto item : group_input_data.items()) {
- this->forward_to_inputs(*item.key, item.value);
+ this->forward_to_inputs(item.key, item.value);
}
}
Vector<GMutablePointer> execute()
{
Vector<GMutablePointer> results;
- for (const DInputSocket *group_output : group_outputs_) {
- Vector<GMutablePointer> result = this->get_input_values(*group_output);
+ for (const DInputSocket &group_output : group_outputs_) {
+ Vector<GMutablePointer> result = this->get_input_values(group_output);
results.append(result[0]);
}
for (GMutablePointer value : value_by_input_.values()) {
@@ -293,62 +299,63 @@ class GeometryNodesEvaluator {
}
private:
- Vector<GMutablePointer> get_input_values(const DInputSocket &socket_to_compute)
+ Vector<GMutablePointer> get_input_values(const DInputSocket socket_to_compute)
{
+ Vector<DSocket> from_sockets;
+ socket_to_compute.foreach_origin_socket([&](DSocket socket) { from_sockets.append(socket); });
- Span<const DOutputSocket *> from_sockets = socket_to_compute.linked_sockets();
- Span<const DGroupInput *> from_group_inputs = socket_to_compute.linked_group_inputs();
- const int total_inputs = from_sockets.size() + from_group_inputs.size();
+ /* Multi-input sockets contain a vector of inputs. */
+ if (socket_to_compute->is_multi_input_socket()) {
+ Vector<GMutablePointer> values;
+ for (const DSocket from_socket : from_sockets) {
+ GMutablePointer value = get_input_from_incoming_link(socket_to_compute, from_socket);
+ values.append(value);
+ }
+ return values;
+ }
- if (total_inputs == 0) {
+ if (from_sockets.is_empty()) {
/* The input is not connected, use the value from the socket itself. */
- return {get_unlinked_input_value(socket_to_compute)};
+ const CPPType &type = *blender::nodes::socket_cpp_type_get(*socket_to_compute->typeinfo());
+ return {get_unlinked_input_value(socket_to_compute, type)};
}
- if (from_group_inputs.size() == 1) {
- return {get_unlinked_input_value(socket_to_compute)};
- }
+ const DSocket from_socket = from_sockets[0];
+ GMutablePointer value = this->get_input_from_incoming_link(socket_to_compute, from_socket);
+ return {value};
+ }
- /* Multi-input sockets contain a vector of inputs. */
- if (socket_to_compute.is_multi_input_socket()) {
- Vector<GMutablePointer> values;
- for (const DOutputSocket *from_socket : from_sockets) {
- const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair(
- &socket_to_compute, from_socket);
- std::optional<GMutablePointer> value = value_by_input_.pop_try(key);
- if (value.has_value()) {
- values.append(*value);
- }
- else {
- this->compute_output_and_forward(*from_socket);
- GMutablePointer value = value_by_input_.pop(key);
- values.append(value);
- }
+ GMutablePointer get_input_from_incoming_link(const DInputSocket socket_to_compute,
+ const DSocket from_socket)
+ {
+ if (from_socket->is_output()) {
+ const DOutputSocket from_output_socket{from_socket};
+ const std::pair<DInputSocket, DOutputSocket> key = std::make_pair(socket_to_compute,
+ from_output_socket);
+ std::optional<GMutablePointer> value = value_by_input_.pop_try(key);
+ if (value.has_value()) {
+ /* This input has been computed before, return it directly. */
+ return {*value};
}
- return values;
- }
- const DOutputSocket &from_socket = *from_sockets[0];
- const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair(
- &socket_to_compute, &from_socket);
- std::optional<GMutablePointer> value = value_by_input_.pop_try(key);
- if (value.has_value()) {
- /* This input has been computed before, return it directly. */
- return {*value};
+ /* Compute the socket now. */
+ this->compute_output_and_forward(from_output_socket);
+ return {value_by_input_.pop(key)};
}
- /* Compute the socket now. */
- this->compute_output_and_forward(from_socket);
- return {value_by_input_.pop(key)};
+ /* Get value from an unlinked input socket. */
+ const CPPType &type = *blender::nodes::socket_cpp_type_get(*socket_to_compute->typeinfo());
+ const DInputSocket from_input_socket{from_socket};
+ return {get_unlinked_input_value(from_input_socket, type)};
}
- void compute_output_and_forward(const DOutputSocket &socket_to_compute)
+ void compute_output_and_forward(const DOutputSocket socket_to_compute)
{
- const DNode &node = socket_to_compute.node();
+ const DNode node{socket_to_compute.context(), &socket_to_compute->node()};
- if (!socket_to_compute.is_available()) {
+ if (!socket_to_compute->is_available()) {
/* If the output is not available, use a default value. */
- const CPPType &type = *blender::nodes::socket_cpp_type_get(*socket_to_compute.typeinfo());
+ const CPPType &type = *blender::nodes::socket_cpp_type_get(*socket_to_compute->typeinfo());
void *buffer = allocator_.allocate(type.size(), type.alignment());
type.copy_to_uninitialized(type.default_value(), buffer);
this->forward_to_inputs(socket_to_compute, {type, buffer});
@@ -357,9 +364,9 @@ class GeometryNodesEvaluator {
/* Prepare inputs required to execute the node. */
GValueMap<StringRef> node_inputs_map{allocator_};
- for (const DInputSocket *input_socket : node.inputs()) {
+ for (const InputSocketRef *input_socket : node->inputs()) {
if (input_socket->is_available()) {
- Vector<GMutablePointer> values = this->get_input_values(*input_socket);
+ Vector<GMutablePointer> values = this->get_input_values({node.context(), input_socket});
for (int i = 0; i < values.size(); ++i) {
/* Values from Multi Input Sockets are stored in input map with the format
* <identifier>[<index>]. */
@@ -377,15 +384,15 @@ class GeometryNodesEvaluator {
this->execute_node(node, params);
/* Forward computed outputs to linked input sockets. */
- for (const DOutputSocket *output_socket : node.outputs()) {
+ for (const OutputSocketRef *output_socket : node->outputs()) {
if (output_socket->is_available()) {
GMutablePointer value = node_outputs_map.extract(output_socket->identifier());
- this->forward_to_inputs(*output_socket, value);
+ this->forward_to_inputs({node.context(), output_socket}, value);
}
}
}
- void execute_node(const DNode &node, GeoNodeExecParams params)
+ void execute_node(const DNode node, GeoNodeExecParams params)
{
const bNode &bnode = params.node();
@@ -398,7 +405,7 @@ class GeometryNodesEvaluator {
}
/* Use the multi-function implementation if it exists. */
- const MultiFunction *multi_function = mf_by_node_.lookup_default(&node, nullptr);
+ const MultiFunction *multi_function = mf_by_node_.lookup_default(node, nullptr);
if (multi_function != nullptr) {
this->execute_multi_function_node(node, params, *multi_function);
return;
@@ -408,51 +415,52 @@ class GeometryNodesEvaluator {
this->execute_unknown_node(node, params);
}
- void store_ui_hints(const DNode &node, GeoNodeExecParams params) const
+ void store_ui_hints(const DNode node, GeoNodeExecParams params) const
{
- for (const DInputSocket *dsocket : node.inputs()) {
- if (!dsocket->is_available()) {
+ for (const InputSocketRef *socket_ref : node->inputs()) {
+ if (!socket_ref->is_available()) {
continue;
}
- if (dsocket->bsocket()->type != SOCK_GEOMETRY) {
+ if (socket_ref->bsocket()->type != SOCK_GEOMETRY) {
continue;
}
- bNodeTree *btree_cow = node.node_ref().tree().btree();
+ bNodeTree *btree_cow = node->btree();
bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow);
const NodeTreeEvaluationContext context(*self_object_, *modifier_);
- const GeometrySet &geometry_set = params.get_input<GeometrySet>(dsocket->identifier());
+ const GeometrySet &geometry_set = params.get_input<GeometrySet>(socket_ref->identifier());
const Vector<const GeometryComponent *> components = geometry_set.get_components_for_read();
for (const GeometryComponent *component : components) {
- component->attribute_foreach([&](StringRefNull attribute_name,
- const AttributeMetaData &UNUSED(meta_data)) {
- BKE_nodetree_attribute_hint_add(*btree_original, context, *node.bnode(), attribute_name);
- return true;
- });
+ component->attribute_foreach(
+ [&](StringRefNull attribute_name, const AttributeMetaData &UNUSED(meta_data)) {
+ BKE_nodetree_attribute_hint_add(
+ *btree_original, context, *node->bnode(), attribute_name);
+ return true;
+ });
}
}
}
- void execute_multi_function_node(const DNode &node,
+ void execute_multi_function_node(const DNode node,
GeoNodeExecParams params,
const MultiFunction &fn)
{
MFContextBuilder fn_context;
MFParamsBuilder fn_params{fn, 1};
Vector<GMutablePointer> input_data;
- for (const DInputSocket *dsocket : node.inputs()) {
- if (dsocket->is_available()) {
- GMutablePointer data = params.extract_input(dsocket->identifier());
+ for (const InputSocketRef *socket_ref : node->inputs()) {
+ if (socket_ref->is_available()) {
+ GMutablePointer data = params.extract_input(socket_ref->identifier());
fn_params.add_readonly_single_input(GSpan(*data.type(), data.get(), 1));
input_data.append(data);
}
}
Vector<GMutablePointer> output_data;
- for (const DOutputSocket *dsocket : node.outputs()) {
- if (dsocket->is_available()) {
- const CPPType &type = *blender::nodes::socket_cpp_type_get(*dsocket->typeinfo());
+ for (const OutputSocketRef *socket_ref : node->outputs()) {
+ if (socket_ref->is_available()) {
+ const CPPType &type = *blender::nodes::socket_cpp_type_get(*socket_ref->typeinfo());
void *buffer = allocator_.allocate(type.size(), type.alignment());
fn_params.add_uninitialized_single_output(GMutableSpan(type, buffer, 1));
output_data.append(GMutablePointer(type, buffer));
@@ -463,19 +471,19 @@ class GeometryNodesEvaluator {
value.destruct();
}
int output_index = 0;
- for (const int i : node.outputs().index_range()) {
- if (node.output(i).is_available()) {
+ for (const int i : node->outputs().index_range()) {
+ if (node->output(i).is_available()) {
GMutablePointer value = output_data[output_index];
- params.set_output_by_move(node.output(i).identifier(), value);
+ params.set_output_by_move(node->output(i).identifier(), value);
value.destruct();
output_index++;
}
}
}
- void execute_unknown_node(const DNode &node, GeoNodeExecParams params)
+ void execute_unknown_node(const DNode node, GeoNodeExecParams params)
{
- for (const DOutputSocket *socket : node.outputs()) {
+ for (const OutputSocketRef *socket : node->outputs()) {
if (socket->is_available()) {
const CPPType &type = *blender::nodes::socket_cpp_type_get(*socket->typeinfo());
params.set_output_by_copy(socket->identifier(), {type, type.default_value()});
@@ -483,17 +491,18 @@ class GeometryNodesEvaluator {
}
}
- void forward_to_inputs(const DOutputSocket &from_socket, GMutablePointer value_to_forward)
+ void forward_to_inputs(const DOutputSocket from_socket, GMutablePointer value_to_forward)
{
/* For all sockets that are linked with the from_socket push the value to their node. */
- Span<const DInputSocket *> to_sockets_all = from_socket.linked_sockets();
+ Vector<DInputSocket> to_sockets_all;
+ from_socket.foreach_target_socket(
+ [&](DInputSocket to_socket) { to_sockets_all.append(to_socket); });
const CPPType &from_type = *value_to_forward.type();
- Vector<const DInputSocket *> to_sockets_same_type;
- for (const DInputSocket *to_socket : to_sockets_all) {
+ Vector<DInputSocket> to_sockets_same_type;
+ for (const DInputSocket &to_socket : to_sockets_all) {
const CPPType &to_type = *blender::nodes::socket_cpp_type_get(*to_socket->typeinfo());
- const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair(
- to_socket, &from_socket);
+ const std::pair<DInputSocket, DOutputSocket> key = std::make_pair(to_socket, from_socket);
if (from_type == to_type) {
to_sockets_same_type.append(to_socket);
}
@@ -515,23 +524,21 @@ class GeometryNodesEvaluator {
}
else if (to_sockets_same_type.size() == 1) {
/* This value is only used on one input socket, no need to copy it. */
- const DInputSocket *to_socket = to_sockets_same_type[0];
- const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair(
- to_socket, &from_socket);
+ const DInputSocket to_socket = to_sockets_same_type[0];
+ const std::pair<DInputSocket, DOutputSocket> key = std::make_pair(to_socket, from_socket);
add_value_to_input_socket(key, value_to_forward);
}
else {
/* Multiple inputs use the value, make a copy for every input except for one. */
- const DInputSocket *first_to_socket = to_sockets_same_type[0];
- Span<const DInputSocket *> other_to_sockets = to_sockets_same_type.as_span().drop_front(1);
+ const DInputSocket first_to_socket = to_sockets_same_type[0];
+ Span<DInputSocket> other_to_sockets = to_sockets_same_type.as_span().drop_front(1);
const CPPType &type = *value_to_forward.type();
- const std::pair<const DInputSocket *, const DOutputSocket *> first_key = std::make_pair(
- first_to_socket, &from_socket);
+ const std::pair<DInputSocket, DOutputSocket> first_key = std::make_pair(first_to_socket,
+ from_socket);
add_value_to_input_socket(first_key, value_to_forward);
- for (const DInputSocket *to_socket : other_to_sockets) {
- const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair(
- to_socket, &from_socket);
+ for (const DInputSocket &to_socket : other_to_sockets) {
+ const std::pair<DInputSocket, DOutputSocket> key = std::make_pair(to_socket, from_socket);
void *buffer = allocator_.allocate(type.size(), type.alignment());
type.copy_to_uninitialized(value_to_forward.get(), buffer);
add_value_to_input_socket(key, GMutablePointer{type, buffer});
@@ -539,22 +546,17 @@ class GeometryNodesEvaluator {
}
}
- void add_value_to_input_socket(const std::pair<const DInputSocket *, const DOutputSocket *> key,
+ void add_value_to_input_socket(const std::pair<DInputSocket, DOutputSocket> key,
GMutablePointer value)
{
value_by_input_.add_new(key, value);
}
- GMutablePointer get_unlinked_input_value(const DInputSocket &socket)
+ GMutablePointer get_unlinked_input_value(const DInputSocket &socket,
+ const CPPType &required_type)
{
- bNodeSocket *bsocket;
- if (socket.linked_group_inputs().size() == 0) {
- bsocket = socket.bsocket();
- }
- else {
- bsocket = socket.linked_group_inputs()[0]->bsocket();
- }
- const CPPType &type = *blender::nodes::socket_cpp_type_get(*socket.typeinfo());
+ bNodeSocket *bsocket = socket->bsocket();
+ const CPPType &type = *blender::nodes::socket_cpp_type_get(*socket->typeinfo());
void *buffer = allocator_.allocate(type.size(), type.alignment());
if (bsocket->type == SOCK_OBJECT) {
@@ -571,7 +573,19 @@ class GeometryNodesEvaluator {
blender::nodes::socket_cpp_value_get(*bsocket, buffer);
}
- return {type, buffer};
+ if (type == required_type) {
+ return {type, buffer};
+ }
+ if (conversions_.is_convertible(type, required_type)) {
+ void *converted_buffer = allocator_.allocate(required_type.size(),
+ required_type.alignment());
+ conversions_.convert(type, required_type, buffer, converted_buffer);
+ type.destruct(buffer);
+ return {required_type, converted_buffer};
+ }
+ void *default_buffer = allocator_.allocate(required_type.size(), required_type.alignment());
+ type.copy_to_uninitialized(type.default_value(), default_buffer);
+ return {required_type, default_buffer};
}
};
@@ -980,7 +994,7 @@ static void fill_data_handle_map(const NodesModifierSettings &settings,
{
Set<ID *> used_ids;
find_used_ids_from_settings(settings, used_ids);
- find_used_ids_from_nodes(*tree.btree(), used_ids);
+ find_used_ids_from_nodes(*tree.root_context().tree().btree(), used_ids);
int current_handle = 0;
for (ID *id : used_ids) {
@@ -1008,8 +1022,8 @@ static void reset_tree_ui_storage(Span<const blender::nodes::NodeTreeRef *> tree
* often than necessary. It's going to be replaced soon.
*/
static GeometrySet compute_geometry(const DerivedNodeTree &tree,
- Span<const DOutputSocket *> group_input_sockets,
- const DInputSocket &socket_to_compute,
+ Span<const OutputSocketRef *> group_input_sockets,
+ const InputSocketRef &socket_to_compute,
GeometrySet input_geometry_set,
NodesModifierData *nmd,
const ModifierEvalContext *ctx)
@@ -1021,32 +1035,33 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree,
PersistentDataHandleMap handle_map;
fill_data_handle_map(nmd->settings, tree, handle_map);
- Map<const DOutputSocket *, GMutablePointer> group_inputs;
+ Map<DOutputSocket, GMutablePointer> group_inputs;
+ const DTreeContext *root_context = &tree.root_context();
if (group_input_sockets.size() > 0) {
- Span<const DOutputSocket *> remaining_input_sockets = group_input_sockets;
+ Span<const OutputSocketRef *> remaining_input_sockets = group_input_sockets;
/* If the group expects a geometry as first input, use the geometry that has been passed to
* modifier. */
- const DOutputSocket *first_input_socket = group_input_sockets[0];
+ const OutputSocketRef *first_input_socket = group_input_sockets[0];
if (first_input_socket->bsocket()->type == SOCK_GEOMETRY) {
GeometrySet *geometry_set_in = allocator.construct<GeometrySet>(
std::move(input_geometry_set));
- group_inputs.add_new(first_input_socket, geometry_set_in);
+ group_inputs.add_new({root_context, first_input_socket}, geometry_set_in);
remaining_input_sockets = remaining_input_sockets.drop_front(1);
}
/* Initialize remaining group inputs. */
- for (const DOutputSocket *socket : remaining_input_sockets) {
+ for (const OutputSocketRef *socket : remaining_input_sockets) {
const CPPType &cpp_type = *blender::nodes::socket_cpp_type_get(*socket->typeinfo());
void *value_in = allocator.allocate(cpp_type.size(), cpp_type.alignment());
initialize_group_input(*nmd, handle_map, *socket->bsocket(), cpp_type, value_in);
- group_inputs.add_new(socket, {cpp_type, value_in});
+ group_inputs.add_new({root_context, socket}, {cpp_type, value_in});
}
}
- Vector<const DInputSocket *> group_outputs;
- group_outputs.append(&socket_to_compute);
+ Vector<DInputSocket> group_outputs;
+ group_outputs.append({root_context, &socket_to_compute});
GeometryNodesEvaluator evaluator{group_inputs,
group_outputs,
@@ -1121,16 +1136,17 @@ static void modifyGeometry(ModifierData *md,
check_property_socket_sync(ctx->object, md);
- blender::nodes::NodeTreeRefMap tree_refs;
- DerivedNodeTree tree{nmd->node_group, tree_refs};
+ NodeTreeRefMap tree_refs;
+ DerivedNodeTree tree{*nmd->node_group, tree_refs};
if (tree.has_link_cycles()) {
BKE_modifier_set_error(ctx->object, md, "Node group has cycles");
return;
}
- Span<const DNode *> input_nodes = tree.nodes_by_type("NodeGroupInput");
- Span<const DNode *> output_nodes = tree.nodes_by_type("NodeGroupOutput");
+ const NodeTreeRef &root_tree_ref = tree.root_context().tree();
+ Span<const NodeRef *> input_nodes = root_tree_ref.nodes_by_type("NodeGroupInput");
+ Span<const NodeRef *> output_nodes = root_tree_ref.nodes_by_type("NodeGroupOutput");
if (input_nodes.size() > 1) {
return;
@@ -1139,16 +1155,18 @@ static void modifyGeometry(ModifierData *md,
return;
}
- Span<const DOutputSocket *> group_inputs = (input_nodes.size() == 1) ?
- input_nodes[0]->outputs().drop_back(1) :
- Span<const DOutputSocket *>{};
- Span<const DInputSocket *> group_outputs = output_nodes[0]->inputs().drop_back(1);
+ Span<const OutputSocketRef *> group_inputs;
+ if (input_nodes.size() == 1) {
+ group_inputs = input_nodes[0]->outputs().drop_back(1);
+ }
+
+ Span<const InputSocketRef *> group_outputs = output_nodes[0]->inputs().drop_back(1);
if (group_outputs.size() == 0) {
return;
}
- const DInputSocket *group_output = group_outputs[0];
+ const InputSocketRef *group_output = group_outputs[0];
if (group_output->idname() != "NodeSocketGeometry") {
return;
}
@@ -1348,7 +1366,7 @@ ModifierTypeInfo modifierType_Nodes = {
/* dependsOnTime */ nullptr,
/* dependsOnNormals */ nullptr,
/* foreachIDLink */ foreachIDLink,
- /* foreachTexLink */ nullptr,
+ /* foreachTexLink */ foreachTexLink,
/* freeRuntimeData */ nullptr,
/* panelRegister */ panelRegister,
/* blendWrite */ blendWrite,
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 8122f4617c1..a6b83ed60ea 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -135,10 +135,11 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
return mesh;
}
- /* make sure there are UV Maps available */
-
+ /* Create a new layer if no UV Maps are available
+ * (e.g. if a preceding modifier could not preserve it). */
if (!CustomData_has_layer(&mesh->ldata, CD_MLOOPUV)) {
- return mesh;
+ CustomData_add_layer_named(
+ &mesh->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, mesh->totloop, umd->uvlayer_name);
}
/* make sure we're using an existing layer */
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 8c5081555fc..e21959d839c 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -62,7 +62,7 @@ set(SRC
composite/nodes/node_composite_composite.c
composite/nodes/node_composite_cornerpin.c
composite/nodes/node_composite_crop.c
- composite/nodes/node_composite_cryptomatte.c
+ composite/nodes/node_composite_cryptomatte.cc
composite/nodes/node_composite_curves.c
composite/nodes/node_composite_defocus.c
composite/nodes/node_composite_denoise.c
@@ -259,7 +259,7 @@ set(SRC
shader/nodes/node_shader_vectTransform.c
shader/nodes/node_shader_vector_displacement.c
shader/nodes/node_shader_vector_math.cc
- shader/nodes/node_shader_vector_rotate.c
+ shader/nodes/node_shader_vector_rotate.cc
shader/nodes/node_shader_vertex_color.c
shader/nodes/node_shader_volume_absorption.c
shader/nodes/node_shader_volume_info.c
diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh
index 62affe43895..f1dbb2caf29 100644
--- a/source/blender/nodes/NOD_derived_node_tree.hh
+++ b/source/blender/nodes/NOD_derived_node_tree.hh
@@ -19,546 +19,360 @@
/** \file
* \ingroup nodes
*
- * DerivedNodeTree provides a flattened view on a bNodeTree, i.e. node groups are inlined. It
- * builds on top of NodeTreeRef and supports similar queries efficiently.
- *
- * Every inlined node remembers its path to the parent ("call stack").
- *
- * Unlinked group node inputs are handled separately from other sockets.
- *
- * There is a dot graph exporter for debugging purposes.
+ * DerivedNodeTree builds on top of NodeTreeRef and makes working with (nested) node groups more
+ * convenient and safe. It does so by pairing nodes and sockets with a context. The context
+ * contains information about the current "instance" of the node or socket. A node might be
+ * "instanced" multiple times when it is in a node group that is used multiple times.
*/
-#include "NOD_node_tree_ref.hh"
-
+#include "BLI_function_ref.hh"
#include "BLI_vector_set.hh"
+#include "NOD_node_tree_ref.hh"
+
namespace blender::nodes {
+class DTreeContext;
+class DerivedNodeTree;
+
+class DNode;
class DSocket;
class DInputSocket;
class DOutputSocket;
-class DNode;
-class DParentNode;
-class DGroupInput;
-class DerivedNodeTree;
-class DSocket : NonCopyable, NonMovable {
- protected:
- DNode *node_;
- const SocketRef *socket_ref_;
- int id_;
+/**
+ * The context attached to every node or socket in a derived node tree. It can be used to determine
+ * the place of a node in a hierarchy of node groups.
+ *
+ * Contexts are organized in a tree data structure to avoid having to store the entire path to the
+ * root node group for every node/socket.
+ */
+class DTreeContext {
+ private:
+ /* Null when this context is for the root node group. Otherwise it points to the context one
+ * level up. */
+ DTreeContext *parent_context_;
+ /* Null when this context is for the root node group. Otherwise it points to the group node in
+ * the parent node group that contains this context. */
+ const NodeRef *parent_node_;
+ /* The current node tree. */
+ const NodeTreeRef *tree_;
+ /* All the children contexts of this context. */
+ Map<const NodeRef *, DTreeContext *> children_;
friend DerivedNodeTree;
public:
- const DNode &node() const;
-
- int id() const;
- int index() const;
-
- bool is_input() const;
- bool is_output() const;
-
- const DSocket &as_base() const;
- const DInputSocket &as_input() const;
- const DOutputSocket &as_output() const;
-
- PointerRNA *rna() const;
- StringRefNull idname() const;
- StringRefNull name() const;
- StringRefNull identifier() const;
- bNodeSocketType *typeinfo() const;
-
- const SocketRef &socket_ref() const;
- bNodeSocket *bsocket() const;
-
- bool is_available() const;
+ const NodeTreeRef &tree() const;
+ const DTreeContext *parent_context() const;
+ const NodeRef *parent_node() const;
+ const DTreeContext *child_context(const NodeRef &node) const;
+ bool is_root() const;
};
-class DInputSocket : public DSocket {
+/* A (nullable) reference to a node and the context it is in. It is unique within an entire nested
+ * node group hierarchy. This type is small and can be passed around by value. */
+class DNode {
private:
- Vector<DOutputSocket *> linked_sockets_;
- Vector<DGroupInput *> linked_group_inputs_;
- bool is_multi_input_socket_;
-
- friend DerivedNodeTree;
+ const DTreeContext *context_ = nullptr;
+ const NodeRef *node_ref_ = nullptr;
public:
- const InputSocketRef &socket_ref() const;
-
- Span<const DOutputSocket *> linked_sockets() const;
- Span<const DGroupInput *> linked_group_inputs() const;
-
- bool is_linked() const;
- bool is_multi_input_socket() const;
-};
+ DNode() = default;
+ DNode(const DTreeContext *context, const NodeRef *node);
-class DOutputSocket : public DSocket {
- private:
- Vector<DInputSocket *> linked_sockets_;
+ const DTreeContext *context() const;
+ const NodeRef *node_ref() const;
+ const NodeRef *operator->() const;
- friend DerivedNodeTree;
+ friend bool operator==(const DNode &a, const DNode &b);
+ friend bool operator!=(const DNode &a, const DNode &b);
+ operator bool() const;
- public:
- const OutputSocketRef &socket_ref() const;
- Span<const DInputSocket *> linked_sockets() const;
+ uint64_t hash() const;
};
-class DGroupInput : NonCopyable, NonMovable {
- private:
- const InputSocketRef *socket_ref_;
- DParentNode *parent_;
- Vector<DInputSocket *> linked_sockets_;
- int id_;
-
- friend DerivedNodeTree;
+/* A (nullable) reference to a socket and the context it is in. It is unique within an entire
+ * nested node group hierarchy. This type is small and can be passed around by value.
+ *
+ * A #DSocket can represent an input or an output socket. If the type of a socket is known at
+ * compile time is is preferable to use #DInputSocket or #DOutputSocket instead. */
+class DSocket {
+ protected:
+ const DTreeContext *context_ = nullptr;
+ const SocketRef *socket_ref_ = nullptr;
public:
- const InputSocketRef &socket_ref() const;
- bNodeSocket *bsocket() const;
- const DParentNode *parent() const;
- Span<const DInputSocket *> linked_sockets() const;
- int id() const;
- StringRefNull name() const;
-};
-
-class DNode : NonCopyable, NonMovable {
- private:
- const NodeRef *node_ref_;
- DParentNode *parent_;
+ DSocket() = default;
+ DSocket(const DTreeContext *context, const SocketRef *socket);
+ DSocket(const DInputSocket &input_socket);
+ DSocket(const DOutputSocket &output_socket);
- Span<DInputSocket *> inputs_;
- Span<DOutputSocket *> outputs_;
+ const DTreeContext *context() const;
+ const SocketRef *socket_ref() const;
+ const SocketRef *operator->() const;
- int id_;
+ friend bool operator==(const DSocket &a, const DSocket &b);
+ friend bool operator!=(const DSocket &a, const DSocket &b);
+ operator bool() const;
- friend DerivedNodeTree;
+ uint64_t hash() const;
+};
+/* A (nullable) reference to an input socket and the context it is in. */
+class DInputSocket : public DSocket {
public:
- const NodeRef &node_ref() const;
- const DParentNode *parent() const;
-
- Span<const DInputSocket *> inputs() const;
- Span<const DOutputSocket *> outputs() const;
-
- const DInputSocket &input(int index) const;
- const DOutputSocket &output(int index) const;
-
- const DInputSocket &input(int index, StringRef expected_name) const;
- const DOutputSocket &output(int index, StringRef expected_name) const;
+ DInputSocket() = default;
+ DInputSocket(const DTreeContext *context, const InputSocketRef *socket);
+ explicit DInputSocket(const DSocket &base_socket);
- int id() const;
+ const InputSocketRef *socket_ref() const;
+ const InputSocketRef *operator->() const;
- PointerRNA *rna() const;
- StringRefNull idname() const;
- StringRefNull name() const;
- bNode *bnode() const;
- bNodeType *typeinfo() const;
+ DOutputSocket get_corresponding_group_node_output() const;
+ Vector<DOutputSocket, 4> get_corresponding_group_input_sockets() const;
- private:
- void destruct_with_sockets();
+ void foreach_origin_socket(FunctionRef<void(DSocket)> callback) const;
};
-class DParentNode : NonCopyable, NonMovable {
- private:
- const NodeRef *node_ref_;
- DParentNode *parent_;
- int id_;
+/* A (nullable) reference to an output socket and the context it is in. */
+class DOutputSocket : public DSocket {
+ public:
+ DOutputSocket() = default;
+ DOutputSocket(const DTreeContext *context, const OutputSocketRef *socket);
+ explicit DOutputSocket(const DSocket &base_socket);
- friend DerivedNodeTree;
+ const OutputSocketRef *socket_ref() const;
+ const OutputSocketRef *operator->() const;
- public:
- const DParentNode *parent() const;
- const NodeRef &node_ref() const;
- int id() const;
-};
+ DInputSocket get_corresponding_group_node_input() const;
+ DInputSocket get_active_corresponding_group_output_socket() const;
-using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>;
+ void foreach_target_socket(FunctionRef<void(DInputSocket)> callback) const;
+};
-class DerivedNodeTree : NonCopyable, NonMovable {
+class DerivedNodeTree {
private:
LinearAllocator<> allocator_;
- Vector<DNode *> nodes_by_id_;
- Vector<DGroupInput *> group_inputs_;
- Vector<DParentNode *> parent_nodes_;
-
- Vector<DSocket *> sockets_by_id_;
- Vector<DInputSocket *> input_sockets_;
- Vector<DOutputSocket *> output_sockets_;
-
- MultiValueMap<const bNodeType *, DNode *> nodes_by_type_;
+ DTreeContext *root_context_;
VectorSet<const NodeTreeRef *> used_node_tree_refs_;
- bNodeTree *btree_;
public:
- DerivedNodeTree(bNodeTree *btree, NodeTreeRefMap &node_tree_refs);
+ DerivedNodeTree(bNodeTree &btree, NodeTreeRefMap &node_tree_refs);
~DerivedNodeTree();
- bNodeTree *btree() const;
-
- Span<const DNode *> nodes() const;
- Span<const DNode *> nodes_by_type(StringRefNull idname) const;
- Span<const DNode *> nodes_by_type(const bNodeType *nodetype) const;
-
- Span<const DSocket *> sockets() const;
- Span<const DInputSocket *> input_sockets() const;
- Span<const DOutputSocket *> output_sockets() const;
-
- Span<const DGroupInput *> group_inputs() const;
-
+ const DTreeContext &root_context() const;
Span<const NodeTreeRef *> used_node_tree_refs() const;
bool has_link_cycles() const;
-
- std::string to_dot() const;
+ void foreach_node(FunctionRef<void(DNode)> callback) const;
private:
- /* Utility functions used during construction. */
- void insert_nodes_and_links_in_id_order(const NodeTreeRef &tree_ref,
- DParentNode *parent,
- Vector<DNode *> &all_nodes);
- DNode &create_node(const NodeRef &node_ref,
- DParentNode *parent,
- MutableSpan<DSocket *> r_sockets_map);
- void expand_groups(Vector<DNode *> &all_nodes,
- Vector<DGroupInput *> &all_group_inputs,
- Vector<DParentNode *> &all_parent_nodes,
- NodeTreeRefMap &node_tree_refs);
- void expand_group_node(DNode &group_node,
- Vector<DNode *> &all_nodes,
- Vector<DGroupInput *> &all_group_inputs,
- Vector<DParentNode *> &all_parent_nodes,
- NodeTreeRefMap &node_tree_refs);
- void create_group_inputs_for_unlinked_inputs(DNode &node,
- Vector<DGroupInput *> &all_group_inputs);
- void relink_group_inputs(const NodeTreeRef &group_ref,
- Span<DNode *> nodes_by_id,
- DNode &group_node);
- void relink_group_outputs(const NodeTreeRef &group_ref,
- Span<DNode *> nodes_by_id,
- DNode &group_node);
- void remove_expanded_group_interfaces(Vector<DNode *> &all_nodes);
- void remove_unused_group_inputs(Vector<DGroupInput *> &all_group_inputs);
- void relink_and_remove_muted_nodes(Vector<DNode *> &all_nodes);
- void relink_muted_node(DNode &muted_node);
- void store_in_this_and_init_ids(Vector<DNode *> &&all_nodes,
- Vector<DGroupInput *> &&all_group_inputs,
- Vector<DParentNode *> &&all_parent_nodes);
+ DTreeContext &construct_context_recursively(DTreeContext *parent_context,
+ const NodeRef *parent_node,
+ bNodeTree &btree,
+ NodeTreeRefMap &node_tree_refs);
+ void destruct_context_recursively(DTreeContext *context);
+
+ void foreach_node_in_context_recursive(const DTreeContext &context,
+ FunctionRef<void(DNode)> callback) const;
};
namespace derived_node_tree_types {
+using namespace node_tree_ref_types;
using nodes::DerivedNodeTree;
-using nodes::DGroupInput;
using nodes::DInputSocket;
using nodes::DNode;
using nodes::DOutputSocket;
-using nodes::DParentNode;
-}; // namespace derived_node_tree_types
+using nodes::DSocket;
+using nodes::DTreeContext;
+} // namespace derived_node_tree_types
/* --------------------------------------------------------------------
- * DSocket inline methods.
+ * DTreeContext inline methods.
*/
-inline const DNode &DSocket::node() const
-{
- return *node_;
-}
-
-inline int DSocket::id() const
+inline const NodeTreeRef &DTreeContext::tree() const
{
- return id_;
+ return *tree_;
}
-inline int DSocket::index() const
+inline const DTreeContext *DTreeContext::parent_context() const
{
- return socket_ref_->index();
+ return parent_context_;
}
-inline bool DSocket::is_input() const
+inline const NodeRef *DTreeContext::parent_node() const
{
- return socket_ref_->is_input();
+ return parent_node_;
}
-inline bool DSocket::is_output() const
+inline const DTreeContext *DTreeContext::child_context(const NodeRef &node) const
{
- return socket_ref_->is_output();
+ return children_.lookup_default(&node, nullptr);
}
-inline const DSocket &DSocket::as_base() const
+inline bool DTreeContext::is_root() const
{
- return *this;
+ return parent_context_ == nullptr;
}
-inline const DInputSocket &DSocket::as_input() const
-{
- return static_cast<const DInputSocket &>(*this);
-}
-
-inline const DOutputSocket &DSocket::as_output() const
-{
- return static_cast<const DOutputSocket &>(*this);
-}
+/* --------------------------------------------------------------------
+ * DNode inline methods.
+ */
-inline PointerRNA *DSocket::rna() const
+inline DNode::DNode(const DTreeContext *context, const NodeRef *node_ref)
+ : context_(context), node_ref_(node_ref)
{
- return socket_ref_->rna();
+ BLI_assert(node_ref == nullptr || &node_ref->tree() == &context->tree());
}
-inline StringRefNull DSocket::idname() const
+inline const DTreeContext *DNode::context() const
{
- return socket_ref_->idname();
+ return context_;
}
-inline StringRefNull DSocket::name() const
+inline const NodeRef *DNode::node_ref() const
{
- return socket_ref_->name();
+ return node_ref_;
}
-inline StringRefNull DSocket::identifier() const
+inline bool operator==(const DNode &a, const DNode &b)
{
- return socket_ref_->identifier();
+ return a.context_ == b.context_ && a.node_ref_ == b.node_ref_;
}
-inline bNodeSocketType *DSocket::typeinfo() const
+inline bool operator!=(const DNode &a, const DNode &b)
{
- return socket_ref_->bsocket()->typeinfo;
+ return !(a == b);
}
-inline const SocketRef &DSocket::socket_ref() const
+inline DNode::operator bool() const
{
- return *socket_ref_;
+ return node_ref_ != nullptr;
}
-inline bNodeSocket *DSocket::bsocket() const
+inline const NodeRef *DNode::operator->() const
{
- return socket_ref_->bsocket();
+ return node_ref_;
}
-inline bool DSocket::is_available() const
+inline uint64_t DNode::hash() const
{
- return (socket_ref_->bsocket()->flag & SOCK_UNAVAIL) == 0;
+ return DefaultHash<const DTreeContext *>{}(context_) ^ DefaultHash<const NodeRef *>{}(node_ref_);
}
/* --------------------------------------------------------------------
- * DInputSocket inline methods.
+ * DSocket inline methods.
*/
-inline const InputSocketRef &DInputSocket::socket_ref() const
+inline DSocket::DSocket(const DTreeContext *context, const SocketRef *socket_ref)
+ : context_(context), socket_ref_(socket_ref)
{
- return socket_ref_->as_input();
+ BLI_assert(socket_ref == nullptr || &socket_ref->tree() == &context->tree());
}
-inline Span<const DOutputSocket *> DInputSocket::linked_sockets() const
+inline DSocket::DSocket(const DInputSocket &input_socket)
+ : DSocket(input_socket.context_, input_socket.socket_ref_)
{
- return linked_sockets_;
}
-inline Span<const DGroupInput *> DInputSocket::linked_group_inputs() const
+inline DSocket::DSocket(const DOutputSocket &output_socket)
+ : DSocket(output_socket.context_, output_socket.socket_ref_)
{
- return linked_group_inputs_;
}
-inline bool DInputSocket::is_linked() const
+inline const DTreeContext *DSocket::context() const
{
- return linked_sockets_.size() > 0 || linked_group_inputs_.size() > 0;
+ return context_;
}
-inline bool DInputSocket::is_multi_input_socket() const
+inline const SocketRef *DSocket::socket_ref() const
{
- return is_multi_input_socket_;
+ return socket_ref_;
}
-/* --------------------------------------------------------------------
- * DOutputSocket inline methods.
- */
-
-inline const OutputSocketRef &DOutputSocket::socket_ref() const
+inline bool operator==(const DSocket &a, const DSocket &b)
{
- return socket_ref_->as_output();
+ return a.context_ == b.context_ && a.socket_ref_ == b.socket_ref_;
}
-inline Span<const DInputSocket *> DOutputSocket::linked_sockets() const
+inline bool operator!=(const DSocket &a, const DSocket &b)
{
- return linked_sockets_;
+ return !(a == b);
}
-/* --------------------------------------------------------------------
- * DGroupInput inline methods.
- */
-
-inline const InputSocketRef &DGroupInput::socket_ref() const
+inline DSocket::operator bool() const
{
- return *socket_ref_;
+ return socket_ref_ != nullptr;
}
-inline bNodeSocket *DGroupInput::bsocket() const
+inline const SocketRef *DSocket::operator->() const
{
- return socket_ref_->bsocket();
+ return socket_ref_;
}
-inline const DParentNode *DGroupInput::parent() const
+inline uint64_t DSocket::hash() const
{
- return parent_;
-}
-
-inline Span<const DInputSocket *> DGroupInput::linked_sockets() const
-{
- return linked_sockets_;
-}
-
-inline int DGroupInput::id() const
-{
- return id_;
-}
-
-inline StringRefNull DGroupInput::name() const
-{
- return socket_ref_->name();
+ return DefaultHash<const DTreeContext *>{}(context_) ^
+ DefaultHash<const SocketRef *>{}(socket_ref_);
}
/* --------------------------------------------------------------------
- * DNode inline methods.
+ * DInputSocket inline methods.
*/
-inline const NodeRef &DNode::node_ref() const
-{
- return *node_ref_;
-}
-
-inline const DParentNode *DNode::parent() const
-{
- return parent_;
-}
-
-inline Span<const DInputSocket *> DNode::inputs() const
-{
- return inputs_;
-}
-
-inline Span<const DOutputSocket *> DNode::outputs() const
+inline DInputSocket::DInputSocket(const DTreeContext *context, const InputSocketRef *socket_ref)
+ : DSocket(context, socket_ref)
{
- return outputs_;
}
-inline const DInputSocket &DNode::input(int index) const
+inline DInputSocket::DInputSocket(const DSocket &base_socket) : DSocket(base_socket)
{
- return *inputs_[index];
+ BLI_assert(base_socket->is_input());
}
-inline const DOutputSocket &DNode::output(int index) const
+inline const InputSocketRef *DInputSocket::socket_ref() const
{
- return *outputs_[index];
+ return (const InputSocketRef *)socket_ref_;
}
-inline const DInputSocket &DNode::input(int index, StringRef expected_name) const
+inline const InputSocketRef *DInputSocket::operator->() const
{
- const DInputSocket &socket = *inputs_[index];
- BLI_assert(socket.name() == expected_name);
- UNUSED_VARS_NDEBUG(expected_name);
- return socket;
+ return (const InputSocketRef *)socket_ref_;
}
-inline const DOutputSocket &DNode::output(int index, StringRef expected_name) const
-{
- const DOutputSocket &socket = *outputs_[index];
- BLI_assert(socket.name() == expected_name);
- UNUSED_VARS_NDEBUG(expected_name);
- return socket;
-}
-
-inline int DNode::id() const
-{
- return id_;
-}
-
-inline PointerRNA *DNode::rna() const
-{
- return node_ref_->rna();
-}
-
-inline StringRefNull DNode::idname() const
-{
- return node_ref_->idname();
-}
-
-inline StringRefNull DNode::name() const
-{
- return node_ref_->name();
-}
-
-inline bNode *DNode::bnode() const
-{
- return node_ref_->bnode();
-}
+/* --------------------------------------------------------------------
+ * DOutputSocket inline methods.
+ */
-inline bNodeType *DNode::typeinfo() const
+inline DOutputSocket::DOutputSocket(const DTreeContext *context, const OutputSocketRef *socket_ref)
+ : DSocket(context, socket_ref)
{
- return node_ref_->bnode()->typeinfo;
}
-/* --------------------------------------------------------------------
- * DParentNode inline methods.
- */
-
-inline const DParentNode *DParentNode::parent() const
+inline DOutputSocket::DOutputSocket(const DSocket &base_socket) : DSocket(base_socket)
{
- return parent_;
+ BLI_assert(base_socket->is_output());
}
-inline const NodeRef &DParentNode::node_ref() const
+inline const OutputSocketRef *DOutputSocket::socket_ref() const
{
- return *node_ref_;
+ return (const OutputSocketRef *)socket_ref_;
}
-inline int DParentNode::id() const
+inline const OutputSocketRef *DOutputSocket::operator->() const
{
- return id_;
+ return (const OutputSocketRef *)socket_ref_;
}
/* --------------------------------------------------------------------
* DerivedNodeTree inline methods.
*/
-inline bNodeTree *DerivedNodeTree::btree() const
-{
- return btree_;
-}
-
-inline Span<const DNode *> DerivedNodeTree::nodes() const
-{
- return nodes_by_id_;
-}
-
-inline Span<const DNode *> DerivedNodeTree::nodes_by_type(StringRefNull idname) const
-{
- const bNodeType *nodetype = nodeTypeFind(idname.c_str());
- return this->nodes_by_type(nodetype);
-}
-
-inline Span<const DNode *> DerivedNodeTree::nodes_by_type(const bNodeType *nodetype) const
-{
- return nodes_by_type_.lookup(nodetype);
-}
-
-inline Span<const DSocket *> DerivedNodeTree::sockets() const
-{
- return sockets_by_id_;
-}
-
-inline Span<const DInputSocket *> DerivedNodeTree::input_sockets() const
-{
- return input_sockets_;
-}
-
-inline Span<const DOutputSocket *> DerivedNodeTree::output_sockets() const
-{
- return output_sockets_;
-}
-
-inline Span<const DGroupInput *> DerivedNodeTree::group_inputs() const
+inline const DTreeContext &DerivedNodeTree::root_context() const
{
- return group_inputs_;
+ return *root_context_;
}
inline Span<const NodeTreeRef *> DerivedNodeTree::used_node_tree_refs() const
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh
index e648d77337b..1772f92c4b6 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -59,7 +59,7 @@ using fn::GValueMap;
class GeoNodeExecParams {
private:
- const DNode &node_;
+ const DNode node_;
GValueMap<StringRef> &input_values_;
GValueMap<StringRef> &output_values_;
const PersistentDataHandleMap &handle_map_;
@@ -68,7 +68,7 @@ class GeoNodeExecParams {
Depsgraph *depsgraph_;
public:
- GeoNodeExecParams(const DNode &node,
+ GeoNodeExecParams(const DNode node,
GValueMap<StringRef> &input_values,
GValueMap<StringRef> &output_values,
const PersistentDataHandleMap &handle_map,
@@ -182,7 +182,7 @@ class GeoNodeExecParams {
*/
const bNode &node() const
{
- return *node_.bnode();
+ return *node_->bnode();
}
const PersistentDataHandleMap &handle_map() const
diff --git a/source/blender/nodes/NOD_node_tree_multi_function.hh b/source/blender/nodes/NOD_node_tree_multi_function.hh
index 552ef5509fa..df31ee18369 100644
--- a/source/blender/nodes/NOD_node_tree_multi_function.hh
+++ b/source/blender/nodes/NOD_node_tree_multi_function.hh
@@ -28,14 +28,15 @@
#include "NOD_derived_node_tree.hh"
#include "NOD_type_callbacks.hh"
+#include "BLI_multi_value_map.hh"
#include "BLI_resource_collector.hh"
namespace blender::nodes {
/**
- * A MFNetworkTreeMap maps various components of a DerivedNodeTree to components of a
- * fn::MFNetwork. This is necessary for further processing of a multi-function network that has
- * been generated from a node tree.
+ * A MFNetworkTreeMap maps various components of a node tree to components of a fn::MFNetwork. This
+ * is necessary for further processing of a multi-function network that has been generated from a
+ * node tree.
*/
class MFNetworkTreeMap {
private:
@@ -47,15 +48,11 @@ class MFNetworkTreeMap {
*/
const DerivedNodeTree &tree_;
fn::MFNetwork &network_;
- Array<Vector<fn::MFSocket *, 1>> sockets_by_dsocket_id_;
- Array<fn::MFOutputSocket *> socket_by_group_input_id_;
+ MultiValueMap<DSocket, fn::MFSocket *> sockets_by_dsocket_;
public:
MFNetworkTreeMap(const DerivedNodeTree &tree, fn::MFNetwork &network)
- : tree_(tree),
- network_(network),
- sockets_by_dsocket_id_(tree.sockets().size()),
- socket_by_group_input_id_(tree.group_inputs().size(), nullptr)
+ : tree_(tree), network_(network)
{
}
@@ -76,96 +73,95 @@ class MFNetworkTreeMap {
void add(const DSocket &dsocket, fn::MFSocket &socket)
{
- BLI_assert(dsocket.is_input() == socket.is_input());
- BLI_assert(dsocket.is_input() || sockets_by_dsocket_id_[dsocket.id()].size() == 0);
- sockets_by_dsocket_id_[dsocket.id()].append(&socket);
+ BLI_assert(dsocket->is_input() == socket.is_input());
+ BLI_assert(dsocket->is_input() || sockets_by_dsocket_.lookup(dsocket).is_empty());
+ sockets_by_dsocket_.add(dsocket, &socket);
}
void add(const DInputSocket &dsocket, fn::MFInputSocket &socket)
{
- sockets_by_dsocket_id_[dsocket.id()].append(&socket);
+ sockets_by_dsocket_.add(dsocket, &socket);
}
void add(const DOutputSocket &dsocket, fn::MFOutputSocket &socket)
{
/* There can be at most one matching output socket. */
- BLI_assert(sockets_by_dsocket_id_[dsocket.id()].size() == 0);
- sockets_by_dsocket_id_[dsocket.id()].append(&socket);
+ BLI_assert(sockets_by_dsocket_.lookup(dsocket).is_empty());
+ sockets_by_dsocket_.add(dsocket, &socket);
}
- void add(Span<const DInputSocket *> dsockets, Span<fn::MFInputSocket *> sockets)
+ void add(const DTreeContext &context,
+ Span<const InputSocketRef *> dsockets,
+ Span<fn::MFInputSocket *> sockets)
{
assert_same_size(dsockets, sockets);
for (int i : dsockets.index_range()) {
- this->add(*dsockets[i], *sockets[i]);
+ this->add(DInputSocket(&context, dsockets[i]), *sockets[i]);
}
}
- void add(Span<const DOutputSocket *> dsockets, Span<fn::MFOutputSocket *> sockets)
+ void add(const DTreeContext &context,
+ Span<const OutputSocketRef *> dsockets,
+ Span<fn::MFOutputSocket *> sockets)
{
assert_same_size(dsockets, sockets);
for (int i : dsockets.index_range()) {
- this->add(*dsockets[i], *sockets[i]);
+ this->add(DOutputSocket(&context, dsockets[i]), *sockets[i]);
}
}
- void add(const DGroupInput &group_input, fn::MFOutputSocket &socket)
- {
- BLI_assert(socket_by_group_input_id_[group_input.id()] == nullptr);
- socket_by_group_input_id_[group_input.id()] = &socket;
- }
-
void add_try_match(const DNode &dnode, fn::MFNode &node)
{
- this->add_try_match(dnode.inputs().cast<const DSocket *>(),
+ this->add_try_match(*dnode.context(),
+ dnode->inputs().cast<const SocketRef *>(),
node.inputs().cast<fn::MFSocket *>());
- this->add_try_match(dnode.outputs().cast<const DSocket *>(),
+ this->add_try_match(*dnode.context(),
+ dnode->outputs().cast<const SocketRef *>(),
node.outputs().cast<fn::MFSocket *>());
}
- void add_try_match(Span<const DInputSocket *> dsockets, Span<fn::MFInputSocket *> sockets)
+ void add_try_match(const DTreeContext &context,
+ Span<const InputSocketRef *> dsockets,
+ Span<fn::MFInputSocket *> sockets)
{
- this->add_try_match(dsockets.cast<const DSocket *>(), sockets.cast<fn::MFSocket *>());
+ this->add_try_match(
+ context, dsockets.cast<const SocketRef *>(), sockets.cast<fn::MFSocket *>());
}
- void add_try_match(Span<const DOutputSocket *> dsockets, Span<fn::MFOutputSocket *> sockets)
+ void add_try_match(const DTreeContext &context,
+ Span<const OutputSocketRef *> dsockets,
+ Span<fn::MFOutputSocket *> sockets)
{
- this->add_try_match(dsockets.cast<const DSocket *>(), sockets.cast<fn::MFSocket *>());
+ this->add_try_match(
+ context, dsockets.cast<const SocketRef *>(), sockets.cast<fn::MFSocket *>());
}
- void add_try_match(Span<const DSocket *> dsockets, Span<fn::MFSocket *> sockets)
+ void add_try_match(const DTreeContext &context,
+ Span<const SocketRef *> dsockets,
+ Span<fn::MFSocket *> sockets)
{
int used_sockets = 0;
- for (const DSocket *dsocket : dsockets) {
+ for (const SocketRef *dsocket : dsockets) {
if (!dsocket->is_available()) {
continue;
}
- if (!socket_is_mf_data_socket(*dsocket->bsocket()->typeinfo)) {
+ if (!socket_is_mf_data_socket(*dsocket->typeinfo())) {
continue;
}
fn::MFSocket *socket = sockets[used_sockets];
- this->add(*dsocket, *socket);
+ this->add(DSocket(&context, dsocket), *socket);
used_sockets++;
}
}
- fn::MFOutputSocket &lookup(const DGroupInput &group_input)
- {
- fn::MFOutputSocket *socket = socket_by_group_input_id_[group_input.id()];
- BLI_assert(socket != nullptr);
- return *socket;
- }
-
fn::MFOutputSocket &lookup(const DOutputSocket &dsocket)
{
- auto &sockets = sockets_by_dsocket_id_[dsocket.id()];
- BLI_assert(sockets.size() == 1);
- return sockets[0]->as_output();
+ return sockets_by_dsocket_.lookup(dsocket)[0]->as_output();
}
Span<fn::MFInputSocket *> lookup(const DInputSocket &dsocket)
{
- return sockets_by_dsocket_id_[dsocket.id()].as_span().cast<fn::MFInputSocket *>();
+ return sockets_by_dsocket_.lookup(dsocket).cast<fn::MFInputSocket *>();
}
fn::MFInputSocket &lookup_dummy(const DInputSocket &dsocket)
@@ -186,7 +182,7 @@ class MFNetworkTreeMap {
bool is_mapped(const DSocket &dsocket) const
{
- return sockets_by_dsocket_id_[dsocket.id()].size() >= 1;
+ return !sockets_by_dsocket_.lookup(dsocket).is_empty();
}
};
@@ -258,12 +254,7 @@ class SocketMFNetworkBuilder : public MFNetworkBuilderBase {
public:
SocketMFNetworkBuilder(CommonMFNetworkBuilderData &common, const DSocket &dsocket)
- : MFNetworkBuilderBase(common), bsocket_(dsocket.bsocket())
- {
- }
-
- SocketMFNetworkBuilder(CommonMFNetworkBuilderData &common, const DGroupInput &group_input)
- : MFNetworkBuilderBase(common), bsocket_(group_input.bsocket())
+ : MFNetworkBuilderBase(common), bsocket_(dsocket->bsocket())
{
}
@@ -331,10 +322,10 @@ class SocketMFNetworkBuilder : public MFNetworkBuilderBase {
*/
class NodeMFNetworkBuilder : public MFNetworkBuilderBase {
private:
- const DNode &dnode_;
+ DNode dnode_;
public:
- NodeMFNetworkBuilder(CommonMFNetworkBuilderData &common, const DNode &dnode)
+ NodeMFNetworkBuilder(CommonMFNetworkBuilderData &common, DNode dnode)
: MFNetworkBuilderBase(common), dnode_(dnode)
{
}
@@ -352,7 +343,7 @@ class NodeMFNetworkBuilder : public MFNetworkBuilderBase {
const fn::MultiFunction &get_not_implemented_fn()
{
- return this->get_default_fn("Not Implemented (" + dnode_.name() + ")");
+ return this->get_default_fn("Not Implemented (" + dnode_->name() + ")");
}
const fn::MultiFunction &get_default_fn(StringRef name);
@@ -377,7 +368,7 @@ class NodeMFNetworkBuilder : public MFNetworkBuilderBase {
*/
bNode &bnode()
{
- return *dnode_.node_ref().bnode();
+ return *dnode_->bnode();
}
/**
@@ -393,7 +384,7 @@ MFNetworkTreeMap insert_node_tree_into_mf_network(fn::MFNetwork &network,
const DerivedNodeTree &tree,
ResourceCollector &resources);
-using MultiFunctionByNode = Map<const DNode *, const fn::MultiFunction *>;
+using MultiFunctionByNode = Map<DNode, const fn::MultiFunction *>;
MultiFunctionByNode get_multi_function_per_node(const DerivedNodeTree &tree,
ResourceCollector &resources);
diff --git a/source/blender/nodes/NOD_node_tree_ref.hh b/source/blender/nodes/NOD_node_tree_ref.hh
index 7fcc117ba93..3c898aaf0ff 100644
--- a/source/blender/nodes/NOD_node_tree_ref.hh
+++ b/source/blender/nodes/NOD_node_tree_ref.hh
@@ -25,6 +25,7 @@
* The following queries are supported efficiently:
* - socket -> index of socket
* - socket -> directly linked sockets
+ * - socket -> directly linked links
* - socket -> linked sockets when skipping reroutes
* - socket -> node
* - socket/node -> rna pointer
@@ -65,6 +66,8 @@ class InputSocketRef;
class OutputSocketRef;
class NodeRef;
class NodeTreeRef;
+class LinkRef;
+class InternalLinkRef;
class SocketRef : NonCopyable, NonMovable {
protected:
@@ -76,12 +79,14 @@ class SocketRef : NonCopyable, NonMovable {
PointerRNA rna_;
Vector<SocketRef *> linked_sockets_;
Vector<SocketRef *> directly_linked_sockets_;
+ Vector<LinkRef *> directly_linked_links_;
friend NodeTreeRef;
public:
Span<const SocketRef *> linked_sockets() const;
Span<const SocketRef *> directly_linked_sockets() const;
+ Span<const LinkRef *> directly_linked_links() const;
bool is_linked() const;
const NodeRef &node() const;
@@ -102,16 +107,21 @@ class SocketRef : NonCopyable, NonMovable {
StringRefNull idname() const;
StringRefNull name() const;
StringRefNull identifier() const;
+ bNodeSocketType *typeinfo() const;
bNodeSocket *bsocket() const;
bNode *bnode() const;
bNodeTree *btree() const;
+
+ bool is_available() const;
};
class InputSocketRef final : public SocketRef {
public:
Span<const OutputSocketRef *> linked_sockets() const;
Span<const OutputSocketRef *> directly_linked_sockets() const;
+
+ bool is_multi_input_socket() const;
};
class OutputSocketRef final : public SocketRef {
@@ -128,6 +138,7 @@ class NodeRef : NonCopyable, NonMovable {
int id_;
Vector<InputSocketRef *> inputs_;
Vector<OutputSocketRef *> outputs_;
+ Vector<InternalLinkRef *> internal_links_;
friend NodeTreeRef;
@@ -136,6 +147,7 @@ class NodeRef : NonCopyable, NonMovable {
Span<const InputSocketRef *> inputs() const;
Span<const OutputSocketRef *> outputs() const;
+ Span<const InternalLinkRef *> internal_links() const;
const InputSocketRef &input(int index) const;
const OutputSocketRef &output(int index) const;
@@ -146,6 +158,7 @@ class NodeRef : NonCopyable, NonMovable {
PointerRNA *rna() const;
StringRefNull idname() const;
StringRefNull name() const;
+ bNodeType *typeinfo() const;
int id() const;
@@ -156,6 +169,36 @@ class NodeRef : NonCopyable, NonMovable {
bool is_muted() const;
};
+class LinkRef : NonCopyable, NonMovable {
+ private:
+ OutputSocketRef *from_;
+ InputSocketRef *to_;
+ bNodeLink *blink_;
+
+ friend NodeTreeRef;
+
+ public:
+ const OutputSocketRef &from() const;
+ const InputSocketRef &to() const;
+
+ bNodeLink *blink() const;
+};
+
+class InternalLinkRef : NonCopyable, NonMovable {
+ private:
+ InputSocketRef *from_;
+ OutputSocketRef *to_;
+ bNodeLink *blink_;
+
+ friend NodeTreeRef;
+
+ public:
+ const InputSocketRef &from() const;
+ const OutputSocketRef &to() const;
+
+ bNodeLink *blink() const;
+};
+
class NodeTreeRef : NonCopyable, NonMovable {
private:
LinearAllocator<> allocator_;
@@ -164,6 +207,7 @@ class NodeTreeRef : NonCopyable, NonMovable {
Vector<SocketRef *> sockets_by_id_;
Vector<InputSocketRef *> input_sockets_;
Vector<OutputSocketRef *> output_sockets_;
+ Vector<LinkRef *> links_;
MultiValueMap<const bNodeType *, NodeRef *> nodes_by_type_;
public:
@@ -178,6 +222,8 @@ class NodeTreeRef : NonCopyable, NonMovable {
Span<const InputSocketRef *> input_sockets() const;
Span<const OutputSocketRef *> output_sockets() const;
+ Span<const LinkRef *> links() const;
+
bool has_link_cycles() const;
bNodeTree *btree() const;
@@ -195,6 +241,19 @@ class NodeTreeRef : NonCopyable, NonMovable {
void find_targets_skipping_reroutes(OutputSocketRef &socket_ref, Vector<SocketRef *> &r_targets);
};
+using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>;
+
+const NodeTreeRef &get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree);
+
+namespace node_tree_ref_types {
+using nodes::InputSocketRef;
+using nodes::NodeRef;
+using nodes::NodeTreeRef;
+using nodes::NodeTreeRefMap;
+using nodes::OutputSocketRef;
+using nodes::SocketRef;
+} // namespace node_tree_ref_types
+
/* --------------------------------------------------------------------
* SocketRef inline methods.
*/
@@ -209,6 +268,11 @@ inline Span<const SocketRef *> SocketRef::directly_linked_sockets() const
return directly_linked_sockets_;
}
+inline Span<const LinkRef *> SocketRef::directly_linked_links() const
+{
+ return directly_linked_links_;
+}
+
inline bool SocketRef::is_linked() const
{
return linked_sockets_.size() > 0;
@@ -281,6 +345,11 @@ inline StringRefNull SocketRef::identifier() const
return bsocket_->identifier;
}
+inline bNodeSocketType *SocketRef::typeinfo() const
+{
+ return bsocket_->typeinfo;
+}
+
inline bNodeSocket *SocketRef::bsocket() const
{
return bsocket_;
@@ -296,6 +365,11 @@ inline bNodeTree *SocketRef::btree() const
return node_->btree();
}
+inline bool SocketRef::is_available() const
+{
+ return (bsocket_->flag & SOCK_UNAVAIL) == 0;
+}
+
/* --------------------------------------------------------------------
* InputSocketRef inline methods.
*/
@@ -310,6 +384,11 @@ inline Span<const OutputSocketRef *> InputSocketRef::directly_linked_sockets() c
return directly_linked_sockets_.as_span().cast<const OutputSocketRef *>();
}
+inline bool InputSocketRef::is_multi_input_socket() const
+{
+ return bsocket_->flag & SOCK_MULTI_INPUT;
+}
+
/* --------------------------------------------------------------------
* OutputSocketRef inline methods.
*/
@@ -343,6 +422,11 @@ inline Span<const OutputSocketRef *> NodeRef::outputs() const
return outputs_;
}
+inline Span<const InternalLinkRef *> NodeRef::internal_links() const
+{
+ return internal_links_;
+}
+
inline const InputSocketRef &NodeRef::input(int index) const
{
return *inputs_[index];
@@ -378,6 +462,11 @@ inline StringRefNull NodeRef::name() const
return bnode_->name;
}
+inline bNodeType *NodeRef::typeinfo() const
+{
+ return bnode_->typeinfo;
+}
+
inline int NodeRef::id() const
{
return id_;
@@ -409,7 +498,45 @@ inline bool NodeRef::is_muted() const
}
/* --------------------------------------------------------------------
- * NodeRef inline methods.
+ * LinkRef inline methods.
+ */
+
+inline const OutputSocketRef &LinkRef::from() const
+{
+ return *from_;
+}
+
+inline const InputSocketRef &LinkRef::to() const
+{
+ return *to_;
+}
+
+inline bNodeLink *LinkRef::blink() const
+{
+ return blink_;
+}
+
+/* --------------------------------------------------------------------
+ * InternalLinkRef inline methods.
+ */
+
+inline const InputSocketRef &InternalLinkRef::from() const
+{
+ return *from_;
+}
+
+inline const OutputSocketRef &InternalLinkRef::to() const
+{
+ return *to_;
+}
+
+inline bNodeLink *InternalLinkRef::blink() const
+{
+ return blink_;
+}
+
+/* --------------------------------------------------------------------
+ * NodeTreeRef inline methods.
*/
inline Span<const NodeRef *> NodeTreeRef::nodes() const
@@ -443,6 +570,11 @@ inline Span<const OutputSocketRef *> NodeTreeRef::output_sockets() const
return output_sockets_;
}
+inline Span<const LinkRef *> NodeTreeRef::links() const
+{
+ return links_;
+}
+
inline bNodeTree *NodeTreeRef::btree() const
{
return btree_;
diff --git a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc
index f5308fe2671..84cd84e41c7 100644
--- a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc
@@ -27,35 +27,36 @@
#include "BLI_utildefines.h"
#include "node_composite_util.h"
-static CryptomatteEntry *cryptomatte_find(NodeCryptomatte *n, float encoded_hash)
+extern "C" {
+static CryptomatteEntry *cryptomatte_find(const NodeCryptomatte &n, float encoded_hash)
{
- LISTBASE_FOREACH (CryptomatteEntry *, entry, &n->entries) {
+ LISTBASE_FOREACH (CryptomatteEntry *, entry, &n.entries) {
if (entry->encoded_hash == encoded_hash) {
return entry;
}
}
- return NULL;
+ return nullptr;
}
-static void cryptomatte_add(NodeCryptomatte *n, float f)
+static void cryptomatte_add(NodeCryptomatte &n, float f)
{
/* Check if entry already exist. */
- if (cryptomatte_find(n, f) != NULL) {
+ if (cryptomatte_find(n, f)) {
return;
}
- CryptomatteEntry *entry = MEM_callocN(sizeof(CryptomatteEntry), __func__);
+ CryptomatteEntry *entry = static_cast<CryptomatteEntry *>(
+ MEM_callocN(sizeof(CryptomatteEntry), __func__));
entry->encoded_hash = f;
- BLI_addtail(&n->entries, entry);
+ BLI_addtail(&n.entries, entry);
}
-static void cryptomatte_remove(NodeCryptomatte *n, float f)
+static void cryptomatte_remove(NodeCryptomatte &n, float f)
{
CryptomatteEntry *entry = cryptomatte_find(n, f);
- if (entry == NULL) {
+ if (!entry) {
return;
}
-
- BLI_remlink(&n->entries, entry);
+ BLI_remlink(&n.entries, entry);
MEM_freeN(entry);
}
@@ -68,44 +69,40 @@ static bNodeSocketTemplate outputs[] = {
void ntreeCompositCryptomatteSyncFromAdd(bNodeTree *UNUSED(ntree), bNode *node)
{
- NodeCryptomatte *n = node->storage;
+ NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
if (n->add[0] != 0.0f) {
- cryptomatte_add(n, n->add[0]);
- n->add[0] = 0.0f;
- n->add[1] = 0.0f;
- n->add[2] = 0.0f;
+ cryptomatte_add(*n, n->add[0]);
+ zero_v3(n->add);
}
}
void ntreeCompositCryptomatteSyncFromRemove(bNodeTree *UNUSED(ntree), bNode *node)
{
- NodeCryptomatte *n = node->storage;
+ NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
if (n->remove[0] != 0.0f) {
- cryptomatte_remove(n, n->remove[0]);
- n->remove[0] = 0.0f;
- n->remove[1] = 0.0f;
- n->remove[2] = 0.0f;
+ cryptomatte_remove(*n, n->remove[0]);
+ zero_v3(n->remove);
}
}
bNodeSocket *ntreeCompositCryptomatteAddSocket(bNodeTree *ntree, bNode *node)
{
- NodeCryptomatte *n = node->storage;
+ NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
char sockname[32];
n->num_inputs++;
BLI_snprintf(sockname, sizeof(sockname), "Crypto %.2d", n->num_inputs - 1);
bNodeSocket *sock = nodeAddStaticSocket(
- ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, NULL, sockname);
+ ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, nullptr, sockname);
return sock;
}
int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node)
{
- NodeCryptomatte *n = node->storage;
+ NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
if (n->num_inputs < 2) {
return 0;
}
- bNodeSocket *sock = node->inputs.last;
+ bNodeSocket *sock = static_cast<bNodeSocket *>(node->inputs.last);
nodeRemoveSocket(ntree, node, sock);
n->num_inputs--;
return 1;
@@ -113,7 +110,8 @@ int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node)
static void init(bNodeTree *ntree, bNode *node)
{
- NodeCryptomatte *user = MEM_callocN(sizeof(NodeCryptomatte), "cryptomatte user");
+ NodeCryptomatte *user = static_cast<NodeCryptomatte *>(
+ MEM_callocN(sizeof(NodeCryptomatte), __func__));
node->storage = user;
nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "image", "Image");
@@ -126,7 +124,7 @@ static void init(bNodeTree *ntree, bNode *node)
static void node_free_cryptomatte(bNode *node)
{
- NodeCryptomatte *nc = node->storage;
+ NodeCryptomatte *nc = static_cast<NodeCryptomatte *>(node->storage);
if (nc) {
BLI_freelistN(&nc->entries);
@@ -138,8 +136,8 @@ static void node_copy_cryptomatte(bNodeTree *UNUSED(dest_ntree),
bNode *dest_node,
const bNode *src_node)
{
- NodeCryptomatte *src_nc = src_node->storage;
- NodeCryptomatte *dest_nc = MEM_dupallocN(src_nc);
+ NodeCryptomatte *src_nc = static_cast<NodeCryptomatte *>(src_node->storage);
+ NodeCryptomatte *dest_nc = static_cast<NodeCryptomatte *>(MEM_dupallocN(src_nc));
BLI_duplicatelist(&dest_nc->entries, &src_nc->entries);
dest_node->storage = dest_nc;
@@ -150,8 +148,9 @@ void register_node_type_cmp_cryptomatte(void)
static bNodeType ntype;
cmp_node_type_base(&ntype, CMP_NODE_CRYPTOMATTE, "Cryptomatte", NODE_CLASS_CONVERTOR, 0);
- node_type_socket_templates(&ntype, NULL, outputs);
+ node_type_socket_templates(&ntype, nullptr, outputs);
node_type_init(&ntype, init);
node_type_storage(&ntype, "NodeCryptomatte", node_free_cryptomatte, node_copy_cryptomatte);
nodeRegisterType(&ntype);
}
+}
diff --git a/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc b/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc
index 1e22cde721d..3d0ea201239 100644
--- a/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc
+++ b/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc
@@ -26,9 +26,10 @@ static void fn_node_group_instance_id_expand_in_mf_network(
{
const blender::nodes::DNode &node = builder.dnode();
std::string id = "/";
- for (const blender::nodes::DParentNode *parent = node.parent(); parent;
- parent = parent->parent()) {
- id = "/" + parent->node_ref().name() + id;
+ for (const blender::nodes::DTreeContext *context = node.context();
+ context->parent_node() != nullptr;
+ context = context->parent_context()) {
+ id = "/" + context->parent_node()->name() + id;
}
builder.construct_and_set_matching_fn<blender::fn::CustomMF_Constant<std::string>>(
std::move(id));
diff --git a/source/blender/nodes/function/nodes/node_fn_random_float.cc b/source/blender/nodes/function/nodes/node_fn_random_float.cc
index f3401a2c00d..d0ecb5592da 100644
--- a/source/blender/nodes/function/nodes/node_fn_random_float.cc
+++ b/source/blender/nodes/function/nodes/node_fn_random_float.cc
@@ -67,12 +67,13 @@ static void fn_node_random_float_expand_in_mf_network(
blender::nodes::NodeMFNetworkBuilder &builder)
{
uint32_t function_seed = 1746872341u;
- const blender::nodes::DNode &node = builder.dnode();
+ blender::nodes::DNode node = builder.dnode();
const blender::DefaultHash<blender::StringRefNull> hasher;
- function_seed = 33 * function_seed + hasher(node.name());
- for (const blender::nodes::DParentNode *parent = node.parent(); parent != nullptr;
- parent = parent->parent()) {
- function_seed = 33 * function_seed + hasher(parent->node_ref().name());
+ function_seed = 33 * function_seed + hasher(node->name());
+ for (const blender::nodes::DTreeContext *context = node.context();
+ context->parent_node() != nullptr;
+ context = context->parent_context()) {
+ function_seed = 33 * function_seed + hasher(context->parent_node()->name());
}
builder.construct_and_set_matching_fn<RandomFloatFunction>(function_seed);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
index 2ab76540bdf..f09a9bf056e 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
@@ -32,7 +32,7 @@ static bNodeSocketTemplate geo_node_attribute_proximity_in[] = {
{SOCK_GEOMETRY, N_("Geometry")},
{SOCK_GEOMETRY, N_("Target")},
{SOCK_STRING, N_("Distance")},
- {SOCK_STRING, N_("Location")},
+ {SOCK_STRING, N_("Position")},
{-1, ""},
};
@@ -172,7 +172,7 @@ static void attribute_calc_proximity(GeometryComponent &component,
OutputAttributePtr distance_attribute = component.attribute_try_get_for_output(
distance_attribute_name, result_domain, CD_PROP_FLOAT);
- const std::string location_attribute_name = params.get_input<std::string>("Location");
+ const std::string location_attribute_name = params.get_input<std::string>("Position");
OutputAttributePtr location_attribute = component.attribute_try_get_for_output(
location_attribute_name, result_domain, CD_PROP_FLOAT3);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
index bb5b5073c32..27c35da7d37 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
@@ -224,7 +224,7 @@ static void randomize_attribute_on_component(GeometryComponent &component,
if (operation != GEO_NODE_ATTRIBUTE_RANDOMIZE_REPLACE_CREATE) {
if (!component.attribute_exists(attribute_name)) {
params.error_message_add(NodeWarningType::Error,
- "No attribute with name '" + attribute_name + "'.");
+ TIP_("No attribute with name \"") + attribute_name + "\"");
return;
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
index 4e15f232934..9dce52c072d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
@@ -222,8 +222,9 @@ static void join_components(Span<const MeshComponent *> src_components, Geometry
dst_component.replace(new_mesh);
/* Don't copy attributes that are stored directly in the mesh data structs. */
- join_attributes(
- to_base_components(src_components), dst_component, {"position", "material_index"});
+ join_attributes(to_base_components(src_components),
+ dst_component,
+ {"position", "material_index", "vertex_normal"});
}
static void join_components(Span<const PointCloudComponent *> src_components, GeometrySet &result)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
index d9878d54353..c40cb2bb0ae 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -429,7 +429,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
params.node().custom1);
if (!geometry_set.has_mesh()) {
- params.error_message_add(NodeWarningType::Error, "Geometry must contain a mesh.");
+ params.error_message_add(NodeWarningType::Error, TIP_("Geometry must contain a mesh"));
params.set_output("Geometry", std::move(geometry_set_out));
return;
}
@@ -446,7 +446,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
const Mesh *mesh_in = mesh_component.get_for_read();
if (mesh_in->mpoly == nullptr) {
- params.error_message_add(NodeWarningType::Error, "Mesh has no faces.");
+ params.error_message_add(NodeWarningType::Error, TIP_("Mesh has no faces"));
params.set_output("Geometry", std::move(geometry_set_out));
return;
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
index 669b5ee4614..dbbb73bd36d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
@@ -103,7 +103,7 @@ static void get_instanced_data__collection(
if (BLI_listbase_is_empty(&collection->children) &&
BLI_listbase_is_empty(&collection->gobject)) {
- params.error_message_add(NodeWarningType::Info, "Collection is empty.");
+ params.error_message_add(NodeWarningType::Info, TIP_("Collection is empty"));
return;
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_scale.cc b/source/blender/nodes/geometry/nodes/node_geo_point_scale.cc
index e28013a8bfc..9df103ff057 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_scale.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_scale.cc
@@ -47,6 +47,9 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
static const float3 scale_default = float3(1.0f);
OutputAttributePtr scale_attribute = component.attribute_try_get_for_output(
"scale", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, &scale_default);
+ if (!scale_attribute) {
+ return;
+ }
ReadAttributePtr attribute = params.get_input_attribute(
"Factor", component, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, nullptr);
if (!attribute) {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc
index 2a0cb727cd6..38560d277e3 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface_simple.cc
@@ -49,7 +49,7 @@ static void geo_node_subdivision_surface_simple_exec(GeoNodeExecParams params)
#ifndef WITH_OPENSUBDIV
params.error_message_add(NodeWarningType::Error,
- "Disabled, Blender was built without OpenSubdiv");
+ TIP_("Disabled, Blender was built without OpenSubdiv"));
params.set_output("Geometry", std::move(geometry_set));
return;
#endif
diff --git a/source/blender/nodes/intern/derived_node_tree.cc b/source/blender/nodes/intern/derived_node_tree.cc
index f5a0e14f18b..c20d6fa943e 100644
--- a/source/blender/nodes/intern/derived_node_tree.cc
+++ b/source/blender/nodes/intern/derived_node_tree.cc
@@ -16,523 +16,256 @@
#include "NOD_derived_node_tree.hh"
-#include "BLI_dot_export.hh"
-
-#define UNINITIALIZED_ID UINT32_MAX
-
namespace blender::nodes {
-static const NodeTreeRef &get_tree_ref(NodeTreeRefMap &node_tree_refs, bNodeTree *btree)
+/* Construct a new derived node tree for a given root node tree. The generated derived node tree
+ * does not own the used node tree refs (so that those can be used by others as well). The caller
+ * has to make sure that the node tree refs added to #node_tree_refs live at least as long as the
+ * derived node tree. */
+DerivedNodeTree::DerivedNodeTree(bNodeTree &btree, NodeTreeRefMap &node_tree_refs)
{
- return *node_tree_refs.lookup_or_add_cb(btree,
- [&]() { return std::make_unique<NodeTreeRef>(btree); });
+ /* Construct all possible contexts immediately. This is significantly cheaper than inlining all
+ * node groups. If it still becomes a performance issue in the future, contexts could be
+ * constructed lazily when they are needed. */
+ root_context_ = &this->construct_context_recursively(nullptr, nullptr, btree, node_tree_refs);
}
-DerivedNodeTree::DerivedNodeTree(bNodeTree *btree, NodeTreeRefMap &node_tree_refs) : btree_(btree)
+DTreeContext &DerivedNodeTree::construct_context_recursively(DTreeContext *parent_context,
+ const NodeRef *parent_node,
+ bNodeTree &btree,
+ NodeTreeRefMap &node_tree_refs)
{
- BLI_assert(btree != nullptr);
-
- const NodeTreeRef &main_tree_ref = get_tree_ref(node_tree_refs, btree);
- used_node_tree_refs_.add_new(&main_tree_ref);
-
- Vector<DNode *> all_nodes;
- Vector<DGroupInput *> all_group_inputs;
- Vector<DParentNode *> all_parent_nodes;
-
- this->insert_nodes_and_links_in_id_order(main_tree_ref, nullptr, all_nodes);
- this->expand_groups(all_nodes, all_group_inputs, all_parent_nodes, node_tree_refs);
- this->relink_and_remove_muted_nodes(all_nodes);
- this->remove_expanded_group_interfaces(all_nodes);
- this->remove_unused_group_inputs(all_group_inputs);
- this->store_in_this_and_init_ids(
- std::move(all_nodes), std::move(all_group_inputs), std::move(all_parent_nodes));
-}
-
-BLI_NOINLINE void DerivedNodeTree::insert_nodes_and_links_in_id_order(const NodeTreeRef &tree_ref,
- DParentNode *parent,
- Vector<DNode *> &all_nodes)
-{
- Array<DSocket *, 64> sockets_map(tree_ref.sockets().size());
-
- /* Insert nodes. */
- for (const NodeRef *node_ref : tree_ref.nodes()) {
- DNode &node = this->create_node(*node_ref, parent, sockets_map);
- all_nodes.append(&node);
- }
-
- /* Insert links. */
- for (const NodeRef *node_ref : tree_ref.nodes()) {
- for (const InputSocketRef *to_socket_ref : node_ref->inputs()) {
- DInputSocket *to_socket = static_cast<DInputSocket *>(sockets_map[to_socket_ref->id()]);
- for (const OutputSocketRef *from_socket_ref : to_socket_ref->linked_sockets()) {
- DOutputSocket *from_socket = static_cast<DOutputSocket *>(
- sockets_map[from_socket_ref->id()]);
- to_socket->linked_sockets_.append(from_socket);
- from_socket->linked_sockets_.append(to_socket);
+ DTreeContext &context = *allocator_.construct<DTreeContext>();
+ context.parent_context_ = parent_context;
+ context.parent_node_ = parent_node;
+ context.tree_ = &get_tree_ref_from_map(node_tree_refs, btree);
+ used_node_tree_refs_.add(context.tree_);
+
+ for (const NodeRef *node : context.tree_->nodes()) {
+ if (node->is_group_node()) {
+ bNode *bnode = node->bnode();
+ bNodeTree *child_btree = reinterpret_cast<bNodeTree *>(bnode->id);
+ if (child_btree != nullptr) {
+ DTreeContext &child = this->construct_context_recursively(
+ &context, node, *child_btree, node_tree_refs);
+ context.children_.add_new(node, &child);
}
}
}
+
+ return context;
}
-DNode &DerivedNodeTree::create_node(const NodeRef &node_ref,
- DParentNode *parent,
- MutableSpan<DSocket *> r_sockets_map)
+DerivedNodeTree::~DerivedNodeTree()
{
- DNode &node = *allocator_.construct<DNode>();
- node.node_ref_ = &node_ref;
- node.parent_ = parent;
- node.id_ = UNINITIALIZED_ID;
-
- node.inputs_ = allocator_.construct_elements_and_pointer_array<DInputSocket>(
- node_ref.inputs().size());
- node.outputs_ = allocator_.construct_elements_and_pointer_array<DOutputSocket>(
- node_ref.outputs().size());
-
- for (int i : node.inputs_.index_range()) {
- const InputSocketRef &socket_ref = node_ref.input(i);
- DInputSocket &socket = *node.inputs_[i];
- socket.is_multi_input_socket_ = socket_ref.bsocket()->flag & SOCK_MULTI_INPUT;
- socket.id_ = UNINITIALIZED_ID;
- socket.node_ = &node;
- socket.socket_ref_ = &socket_ref;
-
- r_sockets_map[socket_ref.id()] = &socket;
- }
-
- for (int i : node.outputs_.index_range()) {
- const OutputSocketRef &socket_ref = node_ref.output(i);
- DOutputSocket &socket = *node.outputs_[i];
-
- socket.id_ = UNINITIALIZED_ID;
- socket.node_ = &node;
- socket.socket_ref_ = &socket_ref;
-
- r_sockets_map[socket_ref.id()] = &socket;
- }
-
- return node;
+ /* Has to be destructed manually, because the context info is allocated in a linear allocator. */
+ this->destruct_context_recursively(root_context_);
}
-BLI_NOINLINE void DerivedNodeTree::expand_groups(Vector<DNode *> &all_nodes,
- Vector<DGroupInput *> &all_group_inputs,
- Vector<DParentNode *> &all_parent_nodes,
- NodeTreeRefMap &node_tree_refs)
+void DerivedNodeTree::destruct_context_recursively(DTreeContext *context)
{
- for (int i = 0; i < all_nodes.size(); i++) {
- DNode &node = *all_nodes[i];
- if (node.node_ref_->is_group_node()) {
- /* Muted nodes are relinked in a separate step. */
- if (!node.node_ref_->is_muted()) {
- this->expand_group_node(
- node, all_nodes, all_group_inputs, all_parent_nodes, node_tree_refs);
- }
- }
+ for (DTreeContext *child : context->children_.values()) {
+ this->destruct_context_recursively(child);
}
+ context->~DTreeContext();
}
-BLI_NOINLINE void DerivedNodeTree::expand_group_node(DNode &group_node,
- Vector<DNode *> &all_nodes,
- Vector<DGroupInput *> &all_group_inputs,
- Vector<DParentNode *> &all_parent_nodes,
- NodeTreeRefMap &node_tree_refs)
+/* Returns true if there are any cycles in the node tree. */
+bool DerivedNodeTree::has_link_cycles() const
{
- const NodeRef &group_node_ref = *group_node.node_ref_;
- BLI_assert(group_node_ref.is_group_node());
-
- bNodeTree *btree = reinterpret_cast<bNodeTree *>(group_node_ref.bnode()->id);
- if (btree == nullptr) {
- return;
+ for (const NodeTreeRef *tree_ref : used_node_tree_refs_) {
+ if (tree_ref->has_link_cycles()) {
+ return true;
+ }
}
-
- const NodeTreeRef &group_ref = get_tree_ref(node_tree_refs, btree);
- used_node_tree_refs_.add(&group_ref);
-
- DParentNode &parent = *allocator_.construct<DParentNode>();
- parent.id_ = all_parent_nodes.append_and_get_index(&parent);
- parent.parent_ = group_node.parent_;
- parent.node_ref_ = &group_node_ref;
-
- this->insert_nodes_and_links_in_id_order(group_ref, &parent, all_nodes);
- Span<DNode *> new_nodes_by_id = all_nodes.as_span().take_back(group_ref.nodes().size());
-
- this->create_group_inputs_for_unlinked_inputs(group_node, all_group_inputs);
- this->relink_group_inputs(group_ref, new_nodes_by_id, group_node);
- this->relink_group_outputs(group_ref, new_nodes_by_id, group_node);
+ return false;
}
-BLI_NOINLINE void DerivedNodeTree::create_group_inputs_for_unlinked_inputs(
- DNode &node, Vector<DGroupInput *> &all_group_inputs)
+/* Calls the given callback on all nodes in the (possibly nested) derived node tree. */
+void DerivedNodeTree::foreach_node(FunctionRef<void(DNode)> callback) const
{
- for (DInputSocket *input_socket : node.inputs_) {
- if (input_socket->is_linked()) {
- continue;
- }
-
- DGroupInput &group_input = *allocator_.construct<DGroupInput>();
- group_input.id_ = UNINITIALIZED_ID;
- group_input.socket_ref_ = &input_socket->socket_ref();
- group_input.parent_ = node.parent_;
-
- group_input.linked_sockets_.append(input_socket);
- input_socket->linked_group_inputs_.append(&group_input);
- all_group_inputs.append(&group_input);
- }
+ this->foreach_node_in_context_recursive(*root_context_, callback);
}
-BLI_NOINLINE void DerivedNodeTree::relink_group_inputs(const NodeTreeRef &group_ref,
- Span<DNode *> nodes_by_id,
- DNode &group_node)
+void DerivedNodeTree::foreach_node_in_context_recursive(const DTreeContext &context,
+ FunctionRef<void(DNode)> callback) const
{
- Span<const NodeRef *> node_refs = group_ref.nodes_by_type("NodeGroupInput");
- if (node_refs.size() == 0) {
- return;
+ for (const NodeRef *node_ref : context.tree_->nodes()) {
+ callback(DNode(&context, node_ref));
}
- /* TODO: Pick correct group input node if there are more than one. */
- const NodeRef &input_node_ref = *node_refs[0];
- DNode &input_node = *nodes_by_id[input_node_ref.id()];
-
- int input_amount = group_node.inputs().size();
- BLI_assert(input_amount == input_node_ref.outputs().size() - 1);
-
- for (int input_index : IndexRange(input_amount)) {
- DInputSocket *outside_group = group_node.inputs_[input_index];
- DOutputSocket *inside_group = input_node.outputs_[input_index];
-
- for (DOutputSocket *outside_connected : outside_group->linked_sockets_) {
- outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group);
- }
-
- for (DGroupInput *outside_connected : outside_group->linked_group_inputs_) {
- outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group);
- }
-
- for (DInputSocket *inside_connected : inside_group->linked_sockets_) {
- inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group);
-
- for (DOutputSocket *outside_connected : outside_group->linked_sockets_) {
- inside_connected->linked_sockets_.append(outside_connected);
- outside_connected->linked_sockets_.append(inside_connected);
- }
-
- for (DGroupInput *outside_connected : outside_group->linked_group_inputs_) {
- inside_connected->linked_group_inputs_.append(outside_connected);
- outside_connected->linked_sockets_.append(inside_connected);
- }
- }
-
- inside_group->linked_sockets_.clear();
- outside_group->linked_sockets_.clear();
- outside_group->linked_group_inputs_.clear();
+ for (const DTreeContext *child_context : context.children_.values()) {
+ this->foreach_node_in_context_recursive(*child_context, callback);
}
}
-BLI_NOINLINE void DerivedNodeTree::relink_group_outputs(const NodeTreeRef &group_ref,
- Span<DNode *> nodes_by_id,
- DNode &group_node)
+DOutputSocket DInputSocket::get_corresponding_group_node_output() const
{
- Span<const NodeRef *> node_refs = group_ref.nodes_by_type("NodeGroupOutput");
- if (node_refs.size() == 0) {
- return;
- }
- /* TODO: Pick correct group output node if there are more than one. */
- const NodeRef &output_node_ref = *node_refs[0];
- DNode &output_node = *nodes_by_id[output_node_ref.id()];
-
- int output_amount = group_node.outputs().size();
- BLI_assert(output_amount == output_node_ref.inputs().size() - 1);
+ BLI_assert(*this);
+ BLI_assert(socket_ref_->node().is_group_output_node());
+ BLI_assert(socket_ref_->index() < socket_ref_->node().inputs().size() - 1);
- for (int output_index : IndexRange(output_amount)) {
- DOutputSocket *outside_group = group_node.outputs_[output_index];
- DInputSocket *inside_group = output_node.inputs_[output_index];
-
- for (DInputSocket *outside_connected : outside_group->linked_sockets_) {
- outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group);
- }
+ const DTreeContext *parent_context = context_->parent_context();
+ const NodeRef *parent_node = context_->parent_node();
+ BLI_assert(parent_context != nullptr);
+ BLI_assert(parent_node != nullptr);
- for (DOutputSocket *inside_connected : inside_group->linked_sockets_) {
- inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group);
-
- for (DInputSocket *outside_connected : outside_group->linked_sockets_) {
- inside_connected->linked_sockets_.append(outside_connected);
- outside_connected->linked_sockets_.append(inside_connected);
- }
- }
-
- for (DGroupInput *inside_connected : inside_group->linked_group_inputs_) {
- inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group);
-
- for (DInputSocket *outside_connected : outside_group->linked_sockets_) {
- inside_connected->linked_sockets_.append(outside_connected);
- outside_connected->linked_group_inputs_.append(inside_connected);
- }
- }
-
- outside_group->linked_sockets_.clear();
- inside_group->linked_sockets_.clear();
- }
+ const int socket_index = socket_ref_->index();
+ return {parent_context, &parent_node->output(socket_index)};
}
-BLI_NOINLINE void DerivedNodeTree::remove_expanded_group_interfaces(Vector<DNode *> &all_nodes)
+Vector<DOutputSocket> DInputSocket::get_corresponding_group_input_sockets() const
{
- int index = 0;
- while (index < all_nodes.size()) {
- DNode &node = *all_nodes[index];
- const NodeRef &node_ref = *node.node_ref_;
- if (node_ref.is_group_node() ||
- (node.parent_ != nullptr &&
- (node_ref.is_group_input_node() || node_ref.is_group_output_node()))) {
- all_nodes.remove_and_reorder(index);
- node.destruct_with_sockets();
- }
- else {
- index++;
- }
+ BLI_assert(*this);
+ BLI_assert(socket_ref_->node().is_group_node());
+
+ const DTreeContext *child_context = context_->child_context(socket_ref_->node());
+ BLI_assert(child_context != nullptr);
+
+ const NodeTreeRef &child_tree = child_context->tree();
+ Span<const NodeRef *> group_input_nodes = child_tree.nodes_by_type("NodeGroupInput");
+ const int socket_index = socket_ref_->index();
+ Vector<DOutputSocket> sockets;
+ for (const NodeRef *group_input_node : group_input_nodes) {
+ sockets.append(DOutputSocket(child_context, &group_input_node->output(socket_index)));
}
+ return sockets;
}
-BLI_NOINLINE void DerivedNodeTree::remove_unused_group_inputs(
- Vector<DGroupInput *> &all_group_inputs)
+DInputSocket DOutputSocket::get_corresponding_group_node_input() const
{
- int index = 0;
- while (index < all_group_inputs.size()) {
- DGroupInput &group_input = *all_group_inputs[index];
- if (group_input.linked_sockets_.is_empty()) {
- all_group_inputs.remove_and_reorder(index);
- group_input.~DGroupInput();
- }
- else {
- index++;
- }
- }
+ BLI_assert(*this);
+ BLI_assert(socket_ref_->node().is_group_input_node());
+ BLI_assert(socket_ref_->index() < socket_ref_->node().outputs().size() - 1);
+
+ const DTreeContext *parent_context = context_->parent_context();
+ const NodeRef *parent_node = context_->parent_node();
+ BLI_assert(parent_context != nullptr);
+ BLI_assert(parent_node != nullptr);
+
+ const int socket_index = socket_ref_->index();
+ return {parent_context, &parent_node->input(socket_index)};
}
-BLI_NOINLINE void DerivedNodeTree::relink_and_remove_muted_nodes(Vector<DNode *> &all_nodes)
+DInputSocket DOutputSocket::get_active_corresponding_group_output_socket() const
{
- int index = 0;
- while (index < all_nodes.size()) {
- DNode &node = *all_nodes[index];
- const NodeRef &node_ref = *node.node_ref_;
- if (node_ref.is_muted()) {
- this->relink_muted_node(node);
- all_nodes.remove_and_reorder(index);
- node.destruct_with_sockets();
- }
- else {
- index++;
+ BLI_assert(*this);
+ BLI_assert(socket_ref_->node().is_group_node());
+
+ const DTreeContext *child_context = context_->child_context(socket_ref_->node());
+ BLI_assert(child_context != nullptr);
+
+ const NodeTreeRef &child_tree = child_context->tree();
+ Span<const NodeRef *> group_output_nodes = child_tree.nodes_by_type("NodeGroupOutput");
+ const int socket_index = socket_ref_->index();
+ for (const NodeRef *group_output_node : group_output_nodes) {
+ if (group_output_node->bnode()->flag & NODE_DO_OUTPUT || group_output_nodes.size() == 1) {
+ return {child_context, &group_output_node->input(socket_index)};
}
}
+ return {};
}
-BLI_NOINLINE void DerivedNodeTree::relink_muted_node(DNode &node)
+/* Call the given callback for every "real" origin socket. "Real" means that reroutes, muted nodes
+ * and node groups are handled by this function. Origin sockets are ones where a node gets its
+ * inputs from. */
+void DInputSocket::foreach_origin_socket(FunctionRef<void(DSocket)> callback) const
{
- const bNode &bnode = *node.bnode();
- LISTBASE_FOREACH (const bNodeLink *, internal_link, &bnode.internal_links) {
- BLI_assert(internal_link->fromnode == &bnode);
- BLI_assert(internal_link->tonode == &bnode);
- bNodeSocket *input_bsocket = internal_link->fromsock;
- bNodeSocket *output_bsocket = internal_link->tosock;
-
- /* Find internally linked sockets. */
- DInputSocket *input_socket = nullptr;
- DOutputSocket *output_socket = nullptr;
- for (DInputSocket *socket : node.inputs_) {
- if (socket->bsocket() == input_bsocket) {
- input_socket = socket;
- break;
+ BLI_assert(*this);
+ for (const OutputSocketRef *linked_socket : socket_ref_->as_input().linked_sockets()) {
+ const NodeRef &linked_node = linked_socket->node();
+ DOutputSocket linked_dsocket{context_, linked_socket};
+
+ if (linked_node.is_muted()) {
+ /* If the node is muted, follow the internal links of the node. */
+ for (const InternalLinkRef *internal_link : linked_node.internal_links()) {
+ if (&internal_link->to() == linked_socket) {
+ DInputSocket input_of_muted_node{context_, &internal_link->from()};
+ input_of_muted_node.foreach_origin_socket(callback);
+ }
}
}
- for (DOutputSocket *socket : node.outputs_) {
- if (socket->bsocket() == output_bsocket) {
- output_socket = socket;
- break;
+ else if (linked_node.is_group_input_node()) {
+ if (context_->is_root()) {
+ /* This is a group input in the root node group. */
+ callback(linked_dsocket);
}
- }
- BLI_assert(input_socket != nullptr);
- BLI_assert(output_socket != nullptr);
-
- /* Link sockets connected to the input to sockets that are connected to the internally linked
- * output. */
- for (DInputSocket *to_socket : output_socket->linked_sockets_) {
- for (DOutputSocket *from_socket : input_socket->linked_sockets_) {
- from_socket->linked_sockets_.append_non_duplicates(to_socket);
- to_socket->linked_sockets_.append_non_duplicates(from_socket);
- }
- for (DGroupInput *group_input : input_socket->linked_group_inputs_) {
- group_input->linked_sockets_.append_non_duplicates(to_socket);
- to_socket->linked_group_inputs_.append_non_duplicates(group_input);
+ else {
+ DInputSocket socket_in_parent_group = linked_dsocket.get_corresponding_group_node_input();
+ if (socket_in_parent_group->is_linked()) {
+ /* Follow the links coming into the corresponding socket on the parent group node. */
+ socket_in_parent_group.foreach_origin_socket(callback);
+ }
+ else {
+ /* The corresponding input on the parent group node is not connected. Therefore, we use
+ * the value of that input socket directly. */
+ callback(socket_in_parent_group);
+ }
}
}
- }
-
- /* Remove remaining links from muted node. */
- for (DInputSocket *to_socket : node.inputs_) {
- for (DOutputSocket *from_socket : to_socket->linked_sockets_) {
- from_socket->linked_sockets_.remove_first_occurrence_and_reorder(to_socket);
- }
- for (DGroupInput *from_group_input : to_socket->linked_group_inputs_) {
- from_group_input->linked_sockets_.remove_first_occurrence_and_reorder(to_socket);
- }
- to_socket->linked_sockets_.clear();
- to_socket->linked_group_inputs_.clear();
- }
- for (DOutputSocket *from_socket : node.outputs_) {
- for (DInputSocket *to_socket : from_socket->linked_sockets_) {
- to_socket->linked_sockets_.remove_first_occurrence_and_reorder(from_socket);
- }
- from_socket->linked_sockets_.clear();
- }
-}
-
-void DNode::destruct_with_sockets()
-{
- for (DInputSocket *socket : inputs_) {
- socket->~DInputSocket();
- }
- for (DOutputSocket *socket : outputs_) {
- socket->~DOutputSocket();
- }
- this->~DNode();
-}
-
-BLI_NOINLINE void DerivedNodeTree::store_in_this_and_init_ids(
- Vector<DNode *> &&all_nodes,
- Vector<DGroupInput *> &&all_group_inputs,
- Vector<DParentNode *> &&all_parent_nodes)
-{
- nodes_by_id_ = std::move(all_nodes);
- group_inputs_ = std::move(all_group_inputs);
- parent_nodes_ = std::move(all_parent_nodes);
-
- for (int node_index : nodes_by_id_.index_range()) {
- DNode *node = nodes_by_id_[node_index];
- node->id_ = node_index;
-
- const bNodeType *nodetype = node->node_ref_->bnode()->typeinfo;
- nodes_by_type_.add(nodetype, node);
-
- for (DInputSocket *socket : node->inputs_) {
- socket->id_ = sockets_by_id_.append_and_get_index(socket);
- input_sockets_.append(socket);
- }
- for (DOutputSocket *socket : node->outputs_) {
- socket->id_ = sockets_by_id_.append_and_get_index(socket);
- output_sockets_.append(socket);
+ else if (linked_node.is_group_node()) {
+ DInputSocket socket_in_group = linked_dsocket.get_active_corresponding_group_output_socket();
+ if (socket_in_group) {
+ if (socket_in_group->is_linked()) {
+ /* Follow the links coming into the group output node of the child node group. */
+ socket_in_group.foreach_origin_socket(callback);
+ }
+ else {
+ /* The output of the child node group is not connected, so we have to get the value from
+ * that socket. */
+ callback(socket_in_group);
+ }
+ }
}
- }
-
- for (int i : group_inputs_.index_range()) {
- group_inputs_[i]->id_ = i;
- }
-}
-
-DerivedNodeTree::~DerivedNodeTree()
-{
- for (DInputSocket *socket : input_sockets_) {
- socket->~DInputSocket();
- }
- for (DOutputSocket *socket : output_sockets_) {
- socket->~DOutputSocket();
- }
- for (DNode *node : nodes_by_id_) {
- node->~DNode();
- }
- for (DGroupInput *group_input : group_inputs_) {
- group_input->~DGroupInput();
- }
- for (DParentNode *parent : parent_nodes_) {
- parent->~DParentNode();
- }
-}
-
-bool DerivedNodeTree::has_link_cycles() const
-{
- for (const NodeTreeRef *tree : used_node_tree_refs_) {
- if (tree->has_link_cycles()) {
- return true;
+ else {
+ /* The normal case: just use the value of a linked output socket. */
+ callback(linked_dsocket);
}
}
- return false;
-}
-
-static dot::Cluster *get_cluster_for_parent(dot::DirectedGraph &graph,
- Map<const DParentNode *, dot::Cluster *> &clusters,
- const DParentNode *parent)
-{
- if (parent == nullptr) {
- return nullptr;
- }
- return clusters.lookup_or_add_cb(parent, [&]() {
- dot::Cluster *parent_cluster = get_cluster_for_parent(graph, clusters, parent->parent());
- bNodeTree *btree = reinterpret_cast<bNodeTree *>(parent->node_ref().bnode()->id);
- dot::Cluster *new_cluster = &graph.new_cluster(parent->node_ref().name() + " / " +
- StringRef(btree->id.name + 2));
- new_cluster->set_parent_cluster(parent_cluster);
- return new_cluster;
- });
}
-std::string DerivedNodeTree::to_dot() const
+/* Calls the given callback for every "real" target socket. "Real" means that reroutes, muted nodes
+ * and node groups are handled by this function. Target sockets are on the nodes that use the value
+ * from this socket. */
+void DOutputSocket::foreach_target_socket(FunctionRef<void(DInputSocket)> callback) const
{
- dot::DirectedGraph digraph;
- digraph.set_rankdir(dot::Attr_rankdir::LeftToRight);
-
- Map<const DNode *, dot::NodeWithSocketsRef> dot_nodes;
- Map<const DGroupInput *, dot::NodeWithSocketsRef> dot_group_inputs;
- Map<const DParentNode *, dot::Cluster *> dot_clusters;
-
- for (const DNode *node : nodes_by_id_) {
- dot::Node &dot_node = digraph.new_node("");
- dot_node.set_background_color("white");
-
- Vector<std::string> input_names;
- for (const DInputSocket *socket : node->inputs()) {
- input_names.append(socket->name());
- }
- Vector<std::string> output_names;
- for (const DOutputSocket *socket : node->outputs()) {
- output_names.append(socket->name());
+ for (const InputSocketRef *linked_socket : socket_ref_->as_output().linked_sockets()) {
+ const NodeRef &linked_node = linked_socket->node();
+ DInputSocket linked_dsocket{context_, linked_socket};
+
+ if (linked_node.is_muted()) {
+ /* If the target node is muted, follow its internal links. */
+ for (const InternalLinkRef *internal_link : linked_node.internal_links()) {
+ if (&internal_link->from() == linked_socket) {
+ DOutputSocket output_of_muted_node{context_, &internal_link->to()};
+ output_of_muted_node.foreach_target_socket(callback);
+ }
+ }
}
-
- dot_nodes.add_new(node,
- dot::NodeWithSocketsRef(dot_node, node->name(), input_names, output_names));
-
- dot::Cluster *cluster = get_cluster_for_parent(digraph, dot_clusters, node->parent());
- dot_node.set_parent_cluster(cluster);
- }
-
- for (const DGroupInput *group_input : group_inputs_) {
- dot::Node &dot_node = digraph.new_node("");
- dot_node.set_background_color("white");
-
- std::string group_input_name = group_input->name();
- dot_group_inputs.add_new(
- group_input, dot::NodeWithSocketsRef(dot_node, "Group Input", {}, {group_input_name}));
-
- dot::Cluster *cluster = get_cluster_for_parent(digraph, dot_clusters, group_input->parent());
- dot_node.set_parent_cluster(cluster);
- }
-
- for (const DNode *to_node : nodes_by_id_) {
- dot::NodeWithSocketsRef &to_dot_node = dot_nodes.lookup(to_node);
-
- for (const DInputSocket *to_socket : to_node->inputs()) {
- for (const DOutputSocket *from_socket : to_socket->linked_sockets()) {
- const DNode *from_node = &from_socket->node();
- dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(from_node);
-
- digraph.new_edge(from_dot_node.output(from_socket->index()),
- to_dot_node.input(to_socket->index()));
+ else if (linked_node.is_group_output_node()) {
+ if (context_->is_root()) {
+ /* This is a group output in the root node group. */
+ callback(linked_dsocket);
}
- for (const DGroupInput *group_input : to_socket->linked_group_inputs()) {
- dot::NodeWithSocketsRef &from_dot_node = dot_group_inputs.lookup(group_input);
-
- digraph.new_edge(from_dot_node.output(0), to_dot_node.input(to_socket->index()));
+ else {
+ /* Follow the links going out of the group node in the parent node group. */
+ DOutputSocket socket_in_parent_group =
+ linked_dsocket.get_corresponding_group_node_output();
+ socket_in_parent_group.foreach_target_socket(callback);
+ }
+ }
+ else if (linked_node.is_group_node()) {
+ /* Follow the links within the nested node group. */
+ Vector<DOutputSocket> sockets_in_group =
+ linked_dsocket.get_corresponding_group_input_sockets();
+ for (DOutputSocket socket_in_group : sockets_in_group) {
+ socket_in_group.foreach_target_socket(callback);
}
}
+ else {
+ /* The normal case: just use the linked input socket as target. */
+ callback(linked_dsocket);
+ }
}
-
- digraph.set_random_cluster_bgcolors();
- return digraph.to_dot_string();
}
} // namespace blender::nodes
diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c
index 0d46119ab60..6207a1bf024 100644
--- a/source/blender/nodes/intern/node_exec.c
+++ b/source/blender/nodes/intern/node_exec.c
@@ -218,7 +218,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
/* prepare all nodes for execution */
for (n = 0, nodeexec = exec->nodeexec; n < totnodes; n++, nodeexec++) {
node = nodeexec->node = nodelist[n];
- nodeexec->freeexecfunc = node->typeinfo->freeexecfunc;
+ nodeexec->free_exec_fn = node->typeinfo->free_exec_fn;
/* tag inputs */
for (sock = node->inputs.first; sock; sock = sock->next) {
@@ -242,8 +242,8 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
nodeexec->data.preview = context->previews ?
BKE_node_instance_hash_lookup(context->previews, nodekey) :
NULL;
- if (node->typeinfo->initexecfunc) {
- nodeexec->data.data = node->typeinfo->initexecfunc(context, node, nodekey);
+ if (node->typeinfo->init_exec_fn) {
+ nodeexec->data.data = node->typeinfo->init_exec_fn(context, node, nodekey);
}
}
@@ -264,8 +264,8 @@ void ntree_exec_end(bNodeTreeExec *exec)
}
for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
- if (nodeexec->freeexecfunc) {
- nodeexec->freeexecfunc(nodeexec->data.data);
+ if (nodeexec->free_exec_fn) {
+ nodeexec->free_exec_fn(nodeexec->data.data);
}
}
@@ -323,8 +323,8 @@ bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *call
* If the mute func is not set, assume the node should never be muted,
* and hence execute it!
*/
- if (node->typeinfo->execfunc && !(node->flag & NODE_MUTED)) {
- node->typeinfo->execfunc(callerdata, thread, node, &nodeexec->data, nsin, nsout);
+ if (node->typeinfo->exec_fn && !(node->flag & NODE_MUTED)) {
+ node->typeinfo->exec_fn(callerdata, thread, node, &nodeexec->data, nsin, nsout);
}
}
}
diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h
index 806dd10d9bf..de7cbb8cedb 100644
--- a/source/blender/nodes/intern/node_exec.h
+++ b/source/blender/nodes/intern/node_exec.h
@@ -48,7 +48,7 @@ typedef struct bNodeExec {
bNodeExecData data;
/** Free function, stored in exec itself to avoid dangling node pointer access. */
- NodeFreeExecFunction freeexecfunc;
+ NodeFreeExecFunction free_exec_fn;
} bNodeExec;
/* Execution Data for each instance of node tree execution */
diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc
index a2e0a4dd6a4..a4fb99a988e 100644
--- a/source/blender/nodes/intern/node_geometry_exec.cc
+++ b/source/blender/nodes/intern/node_geometry_exec.cc
@@ -20,7 +20,6 @@
#include "DEG_depsgraph_query.h"
-#include "NOD_derived_node_tree.hh"
#include "NOD_geometry_exec.hh"
#include "NOD_type_callbacks.hh"
@@ -30,7 +29,7 @@ namespace blender::nodes {
void GeoNodeExecParams::error_message_add(const NodeWarningType type, std::string message) const
{
- bNodeTree *btree_cow = node_.node_ref().tree().btree();
+ bNodeTree *btree_cow = node_->btree();
BLI_assert(btree_cow != nullptr);
if (btree_cow == nullptr) {
return;
@@ -40,12 +39,12 @@ void GeoNodeExecParams::error_message_add(const NodeWarningType type, std::strin
const NodeTreeEvaluationContext context(*self_object_, *modifier_);
BKE_nodetree_error_message_add(
- *btree_original, context, *node_.bnode(), type, std::move(message));
+ *btree_original, context, *node_->bnode(), type, std::move(message));
}
const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name) const
{
- for (const DSocket *socket : node_.inputs()) {
+ for (const InputSocketRef *socket : node_->inputs()) {
if (socket->is_available() && socket->name() == name) {
return socket->bsocket();
}
@@ -79,7 +78,7 @@ ReadAttributePtr GeoNodeExecParams::get_input_attribute(const StringRef name,
* the domain is empty and we don't expect an attribute anyway). */
if (!name.empty() && component.attribute_domain_size(domain) != 0) {
this->error_message_add(NodeWarningType::Error,
- std::string("No attribute with name '") + name + "'.");
+ TIP_("No attribute with name \"") + name + "\"");
}
return component.attribute_get_constant_for_read(domain, type, default_value);
}
@@ -176,7 +175,7 @@ void GeoNodeExecParams::check_extract_input(StringRef identifier,
const CPPType *requested_type) const
{
bNodeSocket *found_socket = nullptr;
- for (const DSocket *socket : node_.inputs()) {
+ for (const InputSocketRef *socket : node_->inputs()) {
if (socket->identifier() == identifier) {
found_socket = socket->bsocket();
break;
@@ -186,7 +185,7 @@ void GeoNodeExecParams::check_extract_input(StringRef identifier,
if (found_socket == nullptr) {
std::cout << "Did not find an input socket with the identifier '" << identifier << "'.\n";
std::cout << "Possible identifiers are: ";
- for (const DSocket *socket : node_.inputs()) {
+ for (const InputSocketRef *socket : node_->inputs()) {
if (socket->is_available()) {
std::cout << "'" << socket->identifier() << "', ";
}
@@ -218,7 +217,7 @@ void GeoNodeExecParams::check_extract_input(StringRef identifier,
void GeoNodeExecParams::check_set_output(StringRef identifier, const CPPType &value_type) const
{
bNodeSocket *found_socket = nullptr;
- for (const DSocket *socket : node_.outputs()) {
+ for (const OutputSocketRef *socket : node_->outputs()) {
if (socket->identifier() == identifier) {
found_socket = socket->bsocket();
break;
@@ -228,7 +227,7 @@ void GeoNodeExecParams::check_set_output(StringRef identifier, const CPPType &va
if (found_socket == nullptr) {
std::cout << "Did not find an output socket with the identifier '" << identifier << "'.\n";
std::cout << "Possible identifiers are: ";
- for (const DSocket *socket : node_.outputs()) {
+ for (const OutputSocketRef *socket : node_->outputs()) {
if (socket->is_available()) {
std::cout << "'" << socket->identifier() << "', ";
}
diff --git a/source/blender/nodes/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc
index c2391667e86..bb1367573f8 100644
--- a/source/blender/nodes/intern/node_tree_multi_function.cc
+++ b/source/blender/nodes/intern/node_tree_multi_function.cc
@@ -29,17 +29,17 @@ const fn::MultiFunction &NodeMFNetworkBuilder::get_default_fn(StringRef name)
Vector<fn::MFDataType, 10> input_types;
Vector<fn::MFDataType, 10> output_types;
- for (const DInputSocket *dsocket : dnode_.inputs()) {
+ for (const InputSocketRef *dsocket : dnode_->inputs()) {
if (dsocket->is_available()) {
- std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->bsocket()->typeinfo);
+ std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->typeinfo());
if (data_type.has_value()) {
input_types.append(*data_type);
}
}
}
- for (const DOutputSocket *dsocket : dnode_.outputs()) {
+ for (const OutputSocketRef *dsocket : dnode_->outputs()) {
if (dsocket->is_available()) {
- std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->bsocket()->typeinfo);
+ std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->typeinfo());
if (data_type.has_value()) {
output_types.append(*data_type);
}
@@ -57,9 +57,9 @@ static void insert_dummy_node(CommonMFNetworkBuilderData &common, const DNode &d
Vector<fn::MFDataType, stack_capacity> input_types;
Vector<StringRef, stack_capacity> input_names;
- Vector<const DInputSocket *, stack_capacity> input_dsockets;
+ Vector<const InputSocketRef *, stack_capacity> input_dsockets;
- for (const DInputSocket *dsocket : dnode.inputs()) {
+ for (const InputSocketRef *dsocket : dnode->inputs()) {
if (dsocket->is_available()) {
std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->bsocket()->typeinfo);
if (data_type.has_value()) {
@@ -72,9 +72,9 @@ static void insert_dummy_node(CommonMFNetworkBuilderData &common, const DNode &d
Vector<fn::MFDataType, stack_capacity> output_types;
Vector<StringRef, stack_capacity> output_names;
- Vector<const DOutputSocket *, stack_capacity> output_dsockets;
+ Vector<const OutputSocketRef *, stack_capacity> output_dsockets;
- for (const DOutputSocket *dsocket : dnode.outputs()) {
+ for (const OutputSocketRef *dsocket : dnode->outputs()) {
if (dsocket->is_available()) {
std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->bsocket()->typeinfo);
if (data_type.has_value()) {
@@ -86,20 +86,20 @@ static void insert_dummy_node(CommonMFNetworkBuilderData &common, const DNode &d
}
fn::MFDummyNode &dummy_node = common.network.add_dummy(
- dnode.name(), input_types, output_types, input_names, output_names);
+ dnode->name(), input_types, output_types, input_names, output_names);
- common.network_map.add(input_dsockets, dummy_node.inputs());
- common.network_map.add(output_dsockets, dummy_node.outputs());
+ common.network_map.add(*dnode.context(), input_dsockets, dummy_node.inputs());
+ common.network_map.add(*dnode.context(), output_dsockets, dummy_node.outputs());
}
static bool has_data_sockets(const DNode &dnode)
{
- for (const DInputSocket *socket : dnode.inputs()) {
+ for (const InputSocketRef *socket : dnode->inputs()) {
if (socket_is_mf_data_socket(*socket->bsocket()->typeinfo)) {
return true;
}
}
- for (const DOutputSocket *socket : dnode.outputs()) {
+ for (const OutputSocketRef *socket : dnode->outputs()) {
if (socket_is_mf_data_socket(*socket->bsocket()->typeinfo)) {
return true;
}
@@ -107,70 +107,39 @@ static bool has_data_sockets(const DNode &dnode)
return false;
}
+static void foreach_node_to_insert(CommonMFNetworkBuilderData &common,
+ FunctionRef<void(DNode)> callback)
+{
+ common.tree.foreach_node([&](const DNode dnode) {
+ if (dnode->is_group_node()) {
+ return;
+ }
+ /* Don't insert non-root group input/output nodes, because they will be inlined. */
+ if (!dnode.context()->is_root()) {
+ if (dnode->is_group_input_node() || dnode->is_group_output_node()) {
+ return;
+ }
+ }
+ callback(dnode);
+ });
+}
+
/**
* Expands all function nodes in the multi-function network. Nodes that don't have an expand
* function, but do have data sockets, will get corresponding dummy nodes.
*/
static void insert_nodes(CommonMFNetworkBuilderData &common)
{
- for (const DNode *dnode : common.tree.nodes()) {
- const bNodeType *node_type = dnode->node_ref().bnode()->typeinfo;
+ foreach_node_to_insert(common, [&](const DNode dnode) {
+ const bNodeType *node_type = dnode->typeinfo();
if (node_type->expand_in_mf_network != nullptr) {
- NodeMFNetworkBuilder builder{common, *dnode};
+ NodeMFNetworkBuilder builder{common, dnode};
node_type->expand_in_mf_network(builder);
}
- else if (has_data_sockets(*dnode)) {
- insert_dummy_node(common, *dnode);
- }
- }
-}
-
-static void insert_group_inputs(CommonMFNetworkBuilderData &common)
-{
- for (const DGroupInput *group_input : common.tree.group_inputs()) {
- bNodeSocket *bsocket = group_input->bsocket();
- if (socket_is_mf_data_socket(*bsocket->typeinfo)) {
- bNodeSocketType *socktype = bsocket->typeinfo;
- BLI_assert(socktype->expand_in_mf_network != nullptr);
-
- SocketMFNetworkBuilder builder{common, *group_input};
- socktype->expand_in_mf_network(builder);
-
- fn::MFOutputSocket *from_socket = builder.built_socket();
- BLI_assert(from_socket != nullptr);
- common.network_map.add(*group_input, *from_socket);
- }
- }
-}
-
-static fn::MFOutputSocket *try_find_origin(CommonMFNetworkBuilderData &common,
- const DInputSocket &to_dsocket)
-{
- Span<const DOutputSocket *> from_dsockets = to_dsocket.linked_sockets();
- Span<const DGroupInput *> from_group_inputs = to_dsocket.linked_group_inputs();
- int total_linked_amount = from_dsockets.size() + from_group_inputs.size();
- BLI_assert(total_linked_amount <= 1);
-
- if (total_linked_amount == 0) {
- return nullptr;
- }
-
- if (from_dsockets.size() == 1) {
- const DOutputSocket &from_dsocket = *from_dsockets[0];
- if (!from_dsocket.is_available()) {
- return nullptr;
- }
- if (socket_is_mf_data_socket(*from_dsocket.bsocket()->typeinfo)) {
- return &common.network_map.lookup(from_dsocket);
+ else if (has_data_sockets(dnode)) {
+ insert_dummy_node(common, dnode);
}
- return nullptr;
- }
-
- const DGroupInput &from_group_input = *from_group_inputs[0];
- if (socket_is_mf_data_socket(*from_group_input.bsocket()->typeinfo)) {
- return &common.network_map.lookup(from_group_input);
- }
- return nullptr;
+ });
}
template<typename From, typename To>
@@ -286,78 +255,82 @@ static fn::MFOutputSocket &insert_default_value_for_type(CommonMFNetworkBuilderD
return node.output(0);
}
-static void insert_links(CommonMFNetworkBuilderData &common)
+static fn::MFOutputSocket *insert_unlinked_input(CommonMFNetworkBuilderData &common,
+ const DInputSocket &dsocket)
{
- for (const DInputSocket *to_dsocket : common.tree.input_sockets()) {
- if (!to_dsocket->is_available()) {
- continue;
- }
- if (!to_dsocket->is_linked()) {
- continue;
- }
- if (!socket_is_mf_data_socket(*to_dsocket->bsocket()->typeinfo)) {
- continue;
- }
-
- Span<fn::MFInputSocket *> to_sockets = common.network_map.lookup(*to_dsocket);
- BLI_assert(to_sockets.size() >= 1);
- fn::MFDataType to_type = to_sockets[0]->data_type();
+ BLI_assert(socket_is_mf_data_socket(*dsocket->typeinfo()));
- fn::MFOutputSocket *from_socket = try_find_origin(common, *to_dsocket);
- if (from_socket == nullptr) {
- from_socket = &insert_default_value_for_type(common, to_type);
- }
-
- fn::MFDataType from_type = from_socket->data_type();
-
- if (from_type != to_type) {
- const fn::MultiFunction *conversion_fn = get_implicit_type_conversions().get_conversion(
- from_type, to_type);
- if (conversion_fn != nullptr) {
- fn::MFNode &node = common.network.add_function(*conversion_fn);
- common.network.add_link(*from_socket, node.input(0));
- from_socket = &node.output(0);
- }
- else {
- from_socket = &insert_default_value_for_type(common, to_type);
- }
- }
+ SocketMFNetworkBuilder builder{common, dsocket};
+ socket_expand_in_mf_network(builder);
- for (fn::MFInputSocket *to_socket : to_sockets) {
- common.network.add_link(*from_socket, *to_socket);
- }
- }
+ fn::MFOutputSocket *built_socket = builder.built_socket();
+ BLI_assert(built_socket != nullptr);
+ return built_socket;
}
-static void insert_unlinked_input(CommonMFNetworkBuilderData &common, const DInputSocket &dsocket)
+static void insert_links_and_unlinked_inputs(CommonMFNetworkBuilderData &common)
{
- bNodeSocket *bsocket = dsocket.bsocket();
- bNodeSocketType *socktype = bsocket->typeinfo;
- BLI_assert(socktype->expand_in_mf_network != nullptr);
-
- SocketMFNetworkBuilder builder{common, dsocket};
- socktype->expand_in_mf_network(builder);
-
- fn::MFOutputSocket *from_socket = builder.built_socket();
- BLI_assert(from_socket != nullptr);
+ foreach_node_to_insert(common, [&](const DNode dnode) {
+ for (const InputSocketRef *socket_ref : dnode->inputs()) {
+ const DInputSocket to_dsocket{dnode.context(), socket_ref};
+ if (!to_dsocket->is_available()) {
+ continue;
+ }
+ if (!socket_is_mf_data_socket(*to_dsocket->typeinfo())) {
+ continue;
+ }
- for (fn::MFInputSocket *to_socket : common.network_map.lookup(dsocket)) {
- common.network.add_link(*from_socket, *to_socket);
- }
-}
+ Span<fn::MFInputSocket *> to_sockets = common.network_map.lookup(to_dsocket);
+ BLI_assert(to_sockets.size() >= 1);
+ const fn::MFDataType to_type = to_sockets[0]->data_type();
-static void insert_unlinked_inputs(CommonMFNetworkBuilderData &common)
-{
- Vector<const DInputSocket *> unlinked_data_inputs;
- for (const DInputSocket *dsocket : common.tree.input_sockets()) {
- if (dsocket->is_available()) {
- if (socket_is_mf_data_socket(*dsocket->bsocket()->typeinfo)) {
- if (!dsocket->is_linked()) {
- insert_unlinked_input(common, *dsocket);
+ Vector<DSocket> from_dsockets;
+ to_dsocket.foreach_origin_socket([&](DSocket socket) { from_dsockets.append(socket); });
+ if (from_dsockets.size() > 1) {
+ fn::MFOutputSocket &from_socket = insert_default_value_for_type(common, to_type);
+ for (fn::MFInputSocket *to_socket : to_sockets) {
+ common.network.add_link(from_socket, *to_socket);
+ }
+ continue;
+ }
+ if (from_dsockets.is_empty()) {
+ /* The socket is not linked. Need to use the value of the socket itself. */
+ fn::MFOutputSocket *built_socket = insert_unlinked_input(common, to_dsocket);
+ for (fn::MFInputSocket *to_socket : to_sockets) {
+ common.network.add_link(*built_socket, *to_socket);
}
+ continue;
+ }
+ if (from_dsockets[0]->is_input()) {
+ DInputSocket from_dsocket{from_dsockets[0]};
+ fn::MFOutputSocket *built_socket = insert_unlinked_input(common, from_dsocket);
+ for (fn::MFInputSocket *to_socket : to_sockets) {
+ common.network.add_link(*built_socket, *to_socket);
+ }
+ continue;
+ }
+ DOutputSocket from_dsocket{from_dsockets[0]};
+ fn::MFOutputSocket *from_socket = &common.network_map.lookup(from_dsocket);
+ const fn::MFDataType from_type = from_socket->data_type();
+
+ if (from_type != to_type) {
+ const fn::MultiFunction *conversion_fn = get_implicit_type_conversions().get_conversion(
+ from_type, to_type);
+ if (conversion_fn != nullptr) {
+ fn::MFNode &node = common.network.add_function(*conversion_fn);
+ common.network.add_link(*from_socket, node.input(0));
+ from_socket = &node.output(0);
+ }
+ else {
+ from_socket = &insert_default_value_for_type(common, to_type);
+ }
+ }
+
+ for (fn::MFInputSocket *to_socket : to_sockets) {
+ common.network.add_link(*from_socket, *to_socket);
}
}
- }
+ });
}
/**
@@ -376,9 +349,7 @@ MFNetworkTreeMap insert_node_tree_into_mf_network(fn::MFNetwork &network,
CommonMFNetworkBuilderData common{resources, network, network_map, tree};
insert_nodes(common);
- insert_group_inputs(common);
- insert_links(common);
- insert_unlinked_inputs(common);
+ insert_links_and_unlinked_inputs(common);
return network_map;
}
@@ -420,16 +391,17 @@ static NodeExpandType get_node_expand_type(MFNetworkTreeMap &network_map,
}
};
- for (const DInputSocket *dsocket : dnode.inputs()) {
+ for (const InputSocketRef *dsocket : dnode->inputs()) {
if (dsocket->is_available()) {
- for (fn::MFInputSocket *mf_input : network_map.lookup(*dsocket)) {
+ for (fn::MFInputSocket *mf_input :
+ network_map.lookup(DInputSocket(dnode.context(), dsocket))) {
check_mf_node(mf_input->node());
}
}
}
- for (const DOutputSocket *dsocket : dnode.outputs()) {
+ for (const OutputSocketRef *dsocket : dnode->outputs()) {
if (dsocket->is_available()) {
- fn::MFOutputSocket &mf_output = network_map.lookup(*dsocket);
+ fn::MFOutputSocket &mf_output = network_map.lookup(DOutputSocket(dnode.context(), dsocket));
check_mf_node(mf_output.node());
}
}
@@ -451,20 +423,21 @@ static const fn::MultiFunction &create_function_for_node_that_expands_into_multi
ResourceCollector &resources)
{
Vector<const fn::MFOutputSocket *> dummy_fn_inputs;
- for (const DInputSocket *dsocket : dnode.inputs()) {
+ for (const InputSocketRef *dsocket : dnode->inputs()) {
if (dsocket->is_available()) {
MFDataType data_type = *socket_mf_type_get(*dsocket->typeinfo());
fn::MFOutputSocket &fn_input = network.add_input(data_type.to_string(), data_type);
- for (fn::MFInputSocket *mf_input : network_map.lookup(*dsocket)) {
+ for (fn::MFInputSocket *mf_input :
+ network_map.lookup(DInputSocket(dnode.context(), dsocket))) {
network.add_link(fn_input, *mf_input);
dummy_fn_inputs.append(&fn_input);
}
}
}
Vector<const fn::MFInputSocket *> dummy_fn_outputs;
- for (const DOutputSocket *dsocket : dnode.outputs()) {
+ for (const OutputSocketRef *dsocket : dnode->outputs()) {
if (dsocket->is_available()) {
- fn::MFOutputSocket &mf_output = network_map.lookup(*dsocket);
+ fn::MFOutputSocket &mf_output = network_map.lookup(DOutputSocket(dnode.context(), dsocket));
MFDataType data_type = mf_output.data_type();
fn::MFInputSocket &fn_output = network.add_output(data_type.to_string(), data_type);
network.add_link(mf_output, fn_output);
@@ -492,18 +465,18 @@ MultiFunctionByNode get_multi_function_per_node(const DerivedNodeTree &tree,
CommonMFNetworkBuilderData common{resources, network, network_map, tree};
- for (const DNode *dnode : tree.nodes()) {
+ tree.foreach_node([&](DNode dnode) {
const bNodeType *node_type = dnode->typeinfo();
if (node_type->expand_in_mf_network == nullptr) {
/* This node does not have a multi-function implementation. */
- continue;
+ return;
}
- NodeMFNetworkBuilder builder{common, *dnode};
+ NodeMFNetworkBuilder builder{common, dnode};
node_type->expand_in_mf_network(builder);
const fn::MultiFunction *single_function = nullptr;
- const NodeExpandType expand_type = get_node_expand_type(network_map, *dnode, &single_function);
+ const NodeExpandType expand_type = get_node_expand_type(network_map, dnode, &single_function);
switch (expand_type) {
case NodeExpandType::HasDummyNodes: {
@@ -519,12 +492,12 @@ MultiFunctionByNode get_multi_function_per_node(const DerivedNodeTree &tree,
/* If a node expanded into multiple functions, a new function has to be created that
* combines those. */
const fn::MultiFunction &fn = create_function_for_node_that_expands_into_multiple(
- *dnode, network, network_map, resources);
+ dnode, network, network_map, resources);
functions_by_node.add_new(dnode, &fn);
break;
}
}
- }
+ });
return functions_by_node;
}
diff --git a/source/blender/nodes/intern/node_tree_ref.cc b/source/blender/nodes/intern/node_tree_ref.cc
index 9dcd90f9f50..7fe21ec8582 100644
--- a/source/blender/nodes/intern/node_tree_ref.cc
+++ b/source/blender/nodes/intern/node_tree_ref.cc
@@ -52,6 +52,24 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree)
RNA_pointer_create(&btree->id, &RNA_NodeSocket, bsocket, &socket.rna_);
}
+ LISTBASE_FOREACH (bNodeLink *, blink, &bnode->internal_links) {
+ InternalLinkRef &internal_link = *allocator_.construct<InternalLinkRef>();
+ internal_link.blink_ = blink;
+ for (InputSocketRef *socket_ref : node.inputs_) {
+ if (socket_ref->bsocket_ == blink->fromsock) {
+ internal_link.from_ = socket_ref;
+ break;
+ }
+ }
+ for (OutputSocketRef *socket_ref : node.outputs_) {
+ if (socket_ref->bsocket_ == blink->tosock) {
+ internal_link.to_ = socket_ref;
+ break;
+ }
+ }
+ node.internal_links_.append(&internal_link);
+ }
+
input_sockets_.extend(node.inputs_.as_span());
output_sockets_.extend(node.outputs_.as_span());
@@ -64,8 +82,16 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree)
InputSocketRef &to_socket = this->find_input_socket(
node_mapping, blink->tonode, blink->tosock);
+ LinkRef &link = *allocator_.construct<LinkRef>();
+ link.from_ = &from_socket;
+ link.to_ = &to_socket;
+ link.blink_ = blink;
+
+ links_.append(&link);
from_socket.directly_linked_sockets_.append(&to_socket);
to_socket.directly_linked_sockets_.append(&from_socket);
+ from_socket.directly_linked_links_.append(&link);
+ to_socket.directly_linked_links_.append(&link);
}
for (OutputSocketRef *socket : output_sockets_) {
@@ -85,6 +111,8 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree)
NodeTreeRef::~NodeTreeRef()
{
+ /* The destructor has to be called manually, because these types are allocated in a linear
+ * allocator. */
for (NodeRef *node : nodes_by_id_) {
node->~NodeRef();
}
@@ -94,6 +122,9 @@ NodeTreeRef::~NodeTreeRef()
for (OutputSocketRef *socket : output_sockets_) {
socket->~OutputSocketRef();
}
+ for (LinkRef *link : links_) {
+ link->~LinkRef();
+ }
}
InputSocketRef &NodeTreeRef::find_input_socket(Map<bNode *, NodeRef *> &node_mapping,
@@ -216,4 +247,10 @@ std::string NodeTreeRef::to_dot() const
return digraph.to_dot_string();
}
+const NodeTreeRef &get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree)
+{
+ return *node_tree_refs.lookup_or_add_cb(&btree,
+ [&]() { return std::make_unique<NodeTreeRef>(&btree); });
+}
+
} // namespace blender::nodes
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 25d6aef69e5..1a2405e021f 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -257,11 +257,11 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node
}
if (do_it) {
- if (node->typeinfo->gpufunc) {
+ if (node->typeinfo->gpu_fn) {
node_get_stack(node, stack, nsin, nsout);
gpu_stack_from_data_list(gpuin, &node->inputs, nsin);
gpu_stack_from_data_list(gpuout, &node->outputs, nsout);
- if (node->typeinfo->gpufunc(mat, node, &nodeexec->data, gpuin, gpuout)) {
+ if (node->typeinfo->gpu_fn(mat, node, &nodeexec->data, gpuin, gpuout)) {
data_from_gpu_stack_list(&node->outputs, nsout, gpuout);
}
}
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 7ce085d2c82..499f62da683 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
@@ -55,8 +55,13 @@ static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat,
float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f;
- return GPU_stack_link(
- mat, node, "node_bsdf_anisotropic", in, out, GPU_constant(&use_multi_scatter));
+ return GPU_stack_link(mat,
+ node,
+ "node_bsdf_anisotropic",
+ in,
+ out,
+ GPU_constant(&use_multi_scatter),
+ GPU_constant(&node->ssr_id));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc
index f54914ceba9..7a846031456 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_math.cc
@@ -116,7 +116,7 @@ static void sh_node_math_expand_in_mf_network(blender::nodes::NodeMFNetworkBuild
blender::fn::MFNetwork &network = builder.network();
blender::fn::MFFunctionNode &base_node = network.add_function(base_function);
- builder.network_map().add_try_match(dnode.inputs(), base_node.inputs());
+ builder.network_map().add_try_match(*dnode.context(), dnode->inputs(), base_node.inputs());
const bool clamp_output = builder.bnode().custom2 != 0;
if (clamp_output) {
@@ -126,10 +126,12 @@ static void sh_node_math_expand_in_mf_network(blender::nodes::NodeMFNetworkBuild
}};
blender::fn::MFFunctionNode &clamp_node = network.add_function(clamp_fn);
network.add_link(base_node.output(0), clamp_node.input(0));
- builder.network_map().add(dnode.output(0), clamp_node.output(0));
+ builder.network_map().add(blender::nodes::DOutputSocket(dnode.context(), &dnode->output(0)),
+ clamp_node.output(0));
}
else {
- builder.network_map().add(dnode.output(0), base_node.output(0));
+ builder.network_map().add(blender::nodes::DOutputSocket(dnode.context(), &dnode->output(0)),
+ base_node.output(0));
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index 41c978e75ba..26a1db1f3a6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -90,7 +90,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
sampler &= ~GPU_SAMPLER_REPEAT;
}
- const char *gpufunc;
+ const char *gpu_fn;
static const char *names[] = {
"node_tex_image_linear",
"node_tex_image_cubic",
@@ -98,19 +98,19 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
switch (tex->interpolation) {
case SHD_INTERP_LINEAR:
- gpufunc = names[0];
+ gpu_fn = names[0];
break;
case SHD_INTERP_CLOSEST:
sampler &= ~(GPU_SAMPLER_FILTER | GPU_SAMPLER_MIPMAP);
- gpufunc = names[0];
+ gpu_fn = names[0];
break;
default:
- gpufunc = names[1];
+ gpu_fn = names[1];
break;
}
/* Sample texture with correct interpolation. */
- GPU_link(mat, gpufunc, in[0].link, GPU_image(mat, ima, iuser, sampler), &out[0].link, &outalpha);
+ GPU_link(mat, gpu_fn, in[0].link, GPU_image(mat, ima, iuser, sampler), &out[0].link, &outalpha);
if (out[0].hasoutput) {
if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) ||
diff --git a/source/blender/nodes/shader/nodes/node_shader_value.cc b/source/blender/nodes/shader/nodes/node_shader_value.cc
index 5a8a1b847cc..495c8d12824 100644
--- a/source/blender/nodes/shader/nodes/node_shader_value.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_value.cc
@@ -41,7 +41,7 @@ static int gpu_shader_value(GPUMaterial *mat,
static void sh_node_value_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
- const bNodeSocket *bsocket = builder.dnode().output(0).bsocket();
+ const bNodeSocket *bsocket = builder.dnode()->output(0).bsocket();
const bNodeSocketValueFloat *value = (const bNodeSocketValueFloat *)bsocket->default_value;
builder.construct_and_set_matching_fn<blender::fn::CustomMF_Constant<float>>(value->value);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc
index b2132c59cde..d6ead5a8b99 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc
@@ -32,7 +32,28 @@ static bNodeSocketTemplate sh_node_vector_rotate_in[] = {
{SOCK_VECTOR, N_("Rotation"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_EULER},
{-1, ""}};
-static bNodeSocketTemplate sh_node_vector_rotate_out[] = {{SOCK_VECTOR, N_("Vector")}, {-1, ""}};
+static bNodeSocketTemplate sh_node_vector_rotate_out[] = {
+ {SOCK_VECTOR, N_("Vector")},
+ {-1, ""},
+};
+
+static const char *gpu_shader_get_name(int mode)
+{
+ switch (mode) {
+ case NODE_VECTOR_ROTATE_TYPE_AXIS:
+ return "node_vector_rotate_axis_angle";
+ case NODE_VECTOR_ROTATE_TYPE_AXIS_X:
+ return "node_vector_rotate_axis_x";
+ case NODE_VECTOR_ROTATE_TYPE_AXIS_Y:
+ return "node_vector_rotate_axis_y";
+ case NODE_VECTOR_ROTATE_TYPE_AXIS_Z:
+ return "node_vector_rotate_axis_z";
+ case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ:
+ return "node_vector_rotate_euler_xyz";
+ }
+
+ return nullptr;
+}
static int gpu_shader_vector_rotate(GPUMaterial *mat,
bNode *node,
@@ -40,18 +61,11 @@ static int gpu_shader_vector_rotate(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
+ const char *name = gpu_shader_get_name(node->custom1);
- static const char *names[] = {
- [NODE_VECTOR_ROTATE_TYPE_AXIS] = "node_vector_rotate_axis_angle",
- [NODE_VECTOR_ROTATE_TYPE_AXIS_X] = "node_vector_rotate_axis_x",
- [NODE_VECTOR_ROTATE_TYPE_AXIS_Y] = "node_vector_rotate_axis_y",
- [NODE_VECTOR_ROTATE_TYPE_AXIS_Z] = "node_vector_rotate_axis_z",
- [NODE_VECTOR_ROTATE_TYPE_EULER_XYZ] = "node_vector_rotate_euler_xyz",
- };
-
- if (node->custom1 < ARRAY_SIZE(names) && names[node->custom1]) {
+ if (name != nullptr) {
float invert = (node->custom2) ? -1.0 : 1.0;
- return GPU_stack_link(mat, node, names[node->custom1], in, out, GPU_constant(&invert));
+ return GPU_stack_link(mat, node, name, in, out, GPU_constant(&invert));
}
return 0;
diff --git a/source/blender/python/gpu/gpu_py_api.c b/source/blender/python/gpu/gpu_py_api.c
index 68f7eb9816c..0bc18e73d0c 100644
--- a/source/blender/python/gpu/gpu_py_api.c
+++ b/source/blender/python/gpu/gpu_py_api.c
@@ -73,6 +73,9 @@ PyObject *BPyInit_gpu(void)
PyModule_AddObject(mod, "state", (submodule = bpygpu_state_init()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
+ PyModule_AddObject(mod, "texture", (submodule = bpygpu_texture_init()));
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
+
return mod;
}
diff --git a/source/blender/python/gpu/gpu_py_batch.c b/source/blender/python/gpu/gpu_py_batch.c
index ef795268158..8e803350b53 100644
--- a/source/blender/python/gpu/gpu_py_batch.c
+++ b/source/blender/python/gpu/gpu_py_batch.c
@@ -279,8 +279,8 @@ static void pygpu_batch__tp_dealloc(BPyGPUBatch *self)
GPU_batch_discard(self->batch);
#ifdef USE_GPU_PY_REFERENCES
+ PyObject_GC_UnTrack(self);
if (self->references) {
- PyObject_GC_UnTrack(self);
pygpu_batch__tp_clear(self);
Py_XDECREF(self->references);
}
diff --git a/source/blender/python/gpu/gpu_py_buffer.c b/source/blender/python/gpu/gpu_py_buffer.c
index b89d2c6a69f..420a7873517 100644
--- a/source/blender/python/gpu/gpu_py_buffer.c
+++ b/source/blender/python/gpu/gpu_py_buffer.c
@@ -202,8 +202,7 @@ static void pygpu_buffer__tp_dealloc(BPyGPUBuffer *self)
{
if (self->parent) {
PyObject_GC_UnTrack(self);
- pygpu_buffer__tp_clear(self);
- Py_XDECREF(self->parent);
+ Py_CLEAR(self->parent);
}
else {
MEM_freeN(self->buf.as_void);
diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c
index 9d5671ff702..dff4b169f9a 100644
--- a/source/blender/python/gpu/gpu_py_offscreen.c
+++ b/source/blender/python/gpu/gpu_py_offscreen.c
@@ -336,8 +336,8 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar
region,
GPU_offscreen_width(self->ofs),
GPU_offscreen_height(self->ofs),
- (float(*)[4])py_mat_view->matrix,
- (float(*)[4])py_mat_projection->matrix,
+ (const float(*)[4])py_mat_view->matrix,
+ (const float(*)[4])py_mat_projection->matrix,
true,
true,
"",
diff --git a/source/blender/python/gpu/gpu_py_texture.c b/source/blender/python/gpu/gpu_py_texture.c
index 12855b8dbcc..14f901624fe 100644
--- a/source/blender/python/gpu/gpu_py_texture.c
+++ b/source/blender/python/gpu/gpu_py_texture.c
@@ -27,9 +27,13 @@
#include "BLI_string.h"
+#include "DNA_image_types.h"
+
#include "GPU_context.h"
#include "GPU_texture.h"
+#include "BKE_image.h"
+
#include "../generic/py_capi_utils.h"
#include "gpu_py.h"
@@ -510,6 +514,53 @@ PyTypeObject BPyGPUTexture_Type = {
/** \} */
/* -------------------------------------------------------------------- */
+/** \name GPU Texture module
+ * \{ */
+PyDoc_STRVAR(pygpu_texture_from_image_doc,
+ ".. function:: from_image(image)\n"
+ "\n"
+ " Get GPUTexture corresponding to an Image datablock. The GPUTexture memory is "
+ "shared with Blender.\n"
+ " Note: Colors read from the texture will be in scene linear color space and have "
+ "premultiplied or straight alpha matching the image alpha mode.\n"
+ "\n"
+ " :arg image: The Image datablock.\n"
+ " :type image: `bpy.types.Image`\n"
+ " :return: The GPUTexture used by the image.\n"
+ " :rtype: :class:`gpu.types.GPUTexture`\n");
+static PyObject *pygpu_texture_from_image(PyObject *UNUSED(self), PyObject *arg)
+{
+ Image *ima = PyC_RNA_AsPointer(arg, "Image");
+ if (ima == NULL) {
+ return NULL;
+ }
+
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
+ GPUTexture *tex = BKE_image_get_gpu_texture(ima, &iuser, NULL);
+
+ /* Increase the texture reference count. */
+ GPU_texture_ref(tex);
+
+ return BPyGPUTexture_CreatePyObject(tex);
+}
+
+static struct PyMethodDef pygpu_texture__m_methods[] = {
+ {"from_image", (PyCFunction)pygpu_texture_from_image, METH_O, pygpu_texture_from_image_doc},
+ {NULL, NULL, 0, NULL},
+};
+
+PyDoc_STRVAR(pygpu_texure__m_doc, "This module provides utils for textures.");
+static PyModuleDef pygpu_texture_module_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "gpu.texture",
+ .m_doc = pygpu_texure__m_doc,
+ .m_methods = pygpu_texture__m_methods,
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Local API
* \{ */
@@ -534,6 +585,14 @@ int bpygpu_ParseTexture(PyObject *o, void *p)
return 1;
}
+PyObject *bpygpu_texture_init(void)
+{
+ PyObject *submodule;
+ submodule = PyModule_Create(&pygpu_texture_module_def);
+
+ return submodule;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/python/gpu/gpu_py_texture.h b/source/blender/python/gpu/gpu_py_texture.h
index be7348b2bd4..5130273f971 100644
--- a/source/blender/python/gpu/gpu_py_texture.h
+++ b/source/blender/python/gpu/gpu_py_texture.h
@@ -31,4 +31,6 @@ typedef struct BPyGPUTexture {
} BPyGPUTexture;
int bpygpu_ParseTexture(PyObject *o, void *p);
+PyObject *bpygpu_texture_init(void);
+
PyObject *BPyGPUTexture_CreatePyObject(struct GPUTexture *tex) ATTR_NONNULL(1);
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index c7e195b586d..927ec11c376 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -216,7 +216,7 @@ static PyObject *make_app_info(void)
#undef SetObjItem
if (PyErr_Occurred()) {
- Py_CLEAR(app_info);
+ Py_DECREF(app_info);
return NULL;
}
return app_info;
diff --git a/source/blender/python/intern/bpy_app_alembic.c b/source/blender/python/intern/bpy_app_alembic.c
index d5640045977..bb218c57d06 100644
--- a/source/blender/python/intern/bpy_app_alembic.c
+++ b/source/blender/python/intern/bpy_app_alembic.c
@@ -79,8 +79,8 @@ static PyObject *make_alembic_info(void)
SetStrItem("Unknown");
#endif
- if (PyErr_Occurred()) {
- Py_CLEAR(alembic_info);
+ if (UNLIKELY(PyErr_Occurred())) {
+ Py_DECREF(alembic_info);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c
index 4e396668450..d2261ee7311 100644
--- a/source/blender/python/intern/bpy_app_ffmpeg.c
+++ b/source/blender/python/intern/bpy_app_ffmpeg.c
@@ -116,8 +116,8 @@ static PyObject *make_ffmpeg_info(void)
#undef FFMPEG_LIB_VERSION
- if (PyErr_Occurred()) {
- Py_CLEAR(ffmpeg_info);
+ if (UNLIKELY(PyErr_Occurred())) {
+ Py_DECREF(ffmpeg_info);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_app_ocio.c b/source/blender/python/intern/bpy_app_ocio.c
index 3a36e90018f..8ce87bd0150 100644
--- a/source/blender/python/intern/bpy_app_ocio.c
+++ b/source/blender/python/intern/bpy_app_ocio.c
@@ -81,8 +81,8 @@ static PyObject *make_ocio_info(void)
SetStrItem("Unknown");
#endif
- if (PyErr_Occurred()) {
- Py_CLEAR(ocio_info);
+ if (UNLIKELY(PyErr_Occurred())) {
+ Py_DECREF(ocio_info);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_app_oiio.c b/source/blender/python/intern/bpy_app_oiio.c
index 0038f982170..8436296680b 100644
--- a/source/blender/python/intern/bpy_app_oiio.c
+++ b/source/blender/python/intern/bpy_app_oiio.c
@@ -77,8 +77,8 @@ static PyObject *make_oiio_info(void)
SetStrItem("Unknown");
#endif
- if (PyErr_Occurred()) {
- Py_CLEAR(oiio_info);
+ if (UNLIKELY(PyErr_Occurred())) {
+ Py_DECREF(oiio_info);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_app_opensubdiv.c b/source/blender/python/intern/bpy_app_opensubdiv.c
index 90aab2a4500..635013a1f9e 100644
--- a/source/blender/python/intern/bpy_app_opensubdiv.c
+++ b/source/blender/python/intern/bpy_app_opensubdiv.c
@@ -74,8 +74,8 @@ static PyObject *make_opensubdiv_info(void)
SetStrItem("Unknown");
#endif
- if (PyErr_Occurred()) {
- Py_CLEAR(opensubdiv_info);
+ if (UNLIKELY(PyErr_Occurred())) {
+ Py_DECREF(opensubdiv_info);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_app_openvdb.c b/source/blender/python/intern/bpy_app_openvdb.c
index c98c6ec0137..20a61ba170a 100644
--- a/source/blender/python/intern/bpy_app_openvdb.c
+++ b/source/blender/python/intern/bpy_app_openvdb.c
@@ -81,8 +81,8 @@ static PyObject *make_openvdb_info(void)
SetStrItem("Unknown");
#endif
- if (PyErr_Occurred()) {
- Py_CLEAR(openvdb_info);
+ if (UNLIKELY(PyErr_Occurred())) {
+ Py_DECREF(openvdb_info);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_app_sdl.c b/source/blender/python/intern/bpy_app_sdl.c
index 645119c1c5d..e45e73fb4de 100644
--- a/source/blender/python/intern/bpy_app_sdl.c
+++ b/source/blender/python/intern/bpy_app_sdl.c
@@ -114,8 +114,8 @@ static PyObject *make_sdl_info(void)
SetObjItem(PyBool_FromLong(0));
#endif
- if (PyErr_Occurred()) {
- Py_CLEAR(sdl_info);
+ if (UNLIKELY(PyErr_Occurred())) {
+ Py_DECREF(sdl_info);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_app_usd.c b/source/blender/python/intern/bpy_app_usd.c
index 4a0ee96061a..72287d45b93 100644
--- a/source/blender/python/intern/bpy_app_usd.c
+++ b/source/blender/python/intern/bpy_app_usd.c
@@ -80,8 +80,8 @@ static PyObject *make_usd_info(void)
SetStrItem("Unknown");
#endif
- if (PyErr_Occurred()) {
- Py_CLEAR(usd_info);
+ if (UNLIKELY(PyErr_Occurred())) {
+ Py_DECREF(usd_info);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index 020c8f7ea49..03771a8c294 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -34,7 +34,6 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "BKE_context.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
@@ -68,9 +67,11 @@ typedef struct {
BlendHandle *blo_handle;
int flag;
PyObject *dict;
+ /* Borrowed reference to the `bmain`, taken from the RNA instance of #RNA_BlendDataLibraries. */
+ Main *bmain;
} BPy_Library;
-static PyObject *bpy_lib_load(PyObject *self, PyObject *args, PyObject *kwds);
+static PyObject *bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *kwds);
static PyObject *bpy_lib_enter(BPy_Library *self);
static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *args);
static PyObject *bpy_lib_dir(BPy_Library *self);
@@ -182,9 +183,9 @@ PyDoc_STRVAR(
" :type relative: bool\n"
" :arg assets_only: If True, only list data-blocks marked as assets.\n"
" :type assets_only: bool\n");
-static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+static PyObject *bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *kw)
{
- Main *bmain = CTX_data_main(BPY_context_get());
+ Main *bmain = self->ptr.data; /* Typically #G_MAIN */
BPy_Library *ret;
const char *filename = NULL;
bool is_rel = false, is_link = false, use_assets_only = false;
@@ -210,11 +211,13 @@ static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *
BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath));
BLI_path_abs(ret->abspath, BKE_main_blendfile_path(bmain));
+ ret->bmain = bmain;
+
ret->blo_handle = NULL;
ret->flag = ((is_link ? FILE_LINK : 0) | (is_rel ? FILE_RELPATH : 0) |
(use_assets_only ? FILE_ASSETS_ONLY : 0));
- ret->dict = _PyDict_NewPresized(MAX_LIBARRAY);
+ ret->dict = _PyDict_NewPresized(INDEX_ID_MAX);
return (PyObject *)ret;
}
@@ -245,7 +248,7 @@ static PyObject *bpy_lib_enter(BPy_Library *self)
{
PyObject *ret;
BPy_Library *self_from;
- PyObject *from_dict = _PyDict_NewPresized(MAX_LIBARRAY);
+ PyObject *from_dict = _PyDict_NewPresized(INDEX_ID_MAX);
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);
@@ -333,7 +336,7 @@ static void bpy_lib_exit_warn_type(BPy_Library *self, PyObject *item)
static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
{
- Main *bmain = CTX_data_main(BPY_context_get());
+ Main *bmain = self->bmain;
Main *mainl = NULL;
const int err = 0;
const bool do_append = ((self->flag & FILE_LINK) == 0);
@@ -477,7 +480,7 @@ static PyObject *bpy_lib_dir(BPy_Library *self)
PyMethodDef BPY_library_load_method_def = {
"load",
(PyCFunction)bpy_lib_load,
- METH_STATIC | METH_VARARGS | METH_KEYWORDS,
+ METH_VARARGS | METH_KEYWORDS,
bpy_lib_load_doc,
};
diff --git a/source/blender/python/intern/bpy_library_write.c b/source/blender/python/intern/bpy_library_write.c
index 66d20dd357f..f26f305cca8 100644
--- a/source/blender/python/intern/bpy_library_write.c
+++ b/source/blender/python/intern/bpy_library_write.c
@@ -71,7 +71,7 @@ PyDoc_STRVAR(
" :type fake_user: bool\n"
" :arg compress: When True, write a compressed blend file.\n"
" :type compress: bool\n");
-static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+static PyObject *bpy_lib_write(BPy_PropertyRNA *self, PyObject *args, PyObject *kw)
{
/* args */
const char *filepath;
@@ -114,7 +114,7 @@ static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject
return NULL;
}
- Main *bmain_src = G_MAIN;
+ Main *bmain_src = self->ptr.data; /* Typically #G_MAIN */
int write_flags = 0;
if (use_compress) {
@@ -220,6 +220,6 @@ finally:
PyMethodDef BPY_library_write_method_def = {
"write",
(PyCFunction)bpy_lib_write,
- METH_STATIC | METH_VARARGS | METH_KEYWORDS,
+ METH_VARARGS | METH_KEYWORDS,
bpy_lib_write_doc,
};
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index b2812e0eba7..246387486be 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -203,10 +203,8 @@ static const EnumPropertyItem property_subtype_array_items[] = {
static void bpy_prop_deferred_dealloc(BPy_PropDeferred *self)
{
- if (self->kw) {
- PyObject_GC_UnTrack(self);
- Py_CLEAR(self->kw);
- }
+ PyObject_GC_UnTrack(self);
+ Py_CLEAR(self->kw);
PyObject_GC_Del(self);
}
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 189d8308c14..ecaa5791e38 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -1204,15 +1204,15 @@ static void pyrna_struct_dealloc(BPy_StructRNA *self)
static void pyrna_struct_reference_set(BPy_StructRNA *self, PyObject *reference)
{
if (self->reference) {
- // PyObject_GC_UnTrack(self); /* INITIALIZED TRACKED ? */
- pyrna_struct_clear(self);
+ PyObject_GC_UnTrack(self);
+ Py_CLEAR(self->reference);
}
/* Reference is now NULL. */
if (reference) {
self->reference = reference;
Py_INCREF(reference);
- // PyObject_GC_Track(self); /* INITIALIZED TRACKED ? */
+ PyObject_GC_Track(self);
}
}
#endif /* !USE_PYRNA_STRUCT_REFERENCE */
@@ -2022,45 +2022,54 @@ static int pyrna_py_to_prop(
}
}
- if (!BPy_StructRNA_Check(value) && value != Py_None) {
- PyErr_Format(PyExc_TypeError,
- "%.200s %.200s.%.200s expected a %.200s type, not %.200s",
- error_prefix,
- RNA_struct_identifier(ptr->type),
- RNA_property_identifier(prop),
- RNA_struct_identifier(ptr_type),
- Py_TYPE(value)->tp_name);
- Py_XDECREF(value_new);
- return -1;
- }
- if ((flag & PROP_NEVER_NULL) && value == Py_None) {
- PyErr_Format(PyExc_TypeError,
- "%.200s %.200s.%.200s does not support a 'None' assignment %.200s type",
- error_prefix,
- RNA_struct_identifier(ptr->type),
- RNA_property_identifier(prop),
- RNA_struct_identifier(ptr_type));
- Py_XDECREF(value_new);
- return -1;
+ BPy_StructRNA *param;
+ if (value == Py_None) {
+ if (flag & PROP_NEVER_NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s %.200s.%.200s does not support a 'None' assignment %.200s type",
+ error_prefix,
+ RNA_struct_identifier(ptr->type),
+ RNA_property_identifier(prop),
+ RNA_struct_identifier(ptr_type));
+ Py_XDECREF(value_new);
+ return -1;
+ }
+ param = NULL;
}
- if ((value != Py_None) && ((flag & PROP_ID_SELF_CHECK) &&
- ptr->owner_id == ((BPy_StructRNA *)value)->ptr.owner_id)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s %.200s.%.200s ID type does not support assignment to itself",
- error_prefix,
- RNA_struct_identifier(ptr->type),
- RNA_property_identifier(prop));
- Py_XDECREF(value_new);
- return -1;
+ else {
+ if (!BPy_StructRNA_Check(value)) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s %.200s.%.200s expected a %.200s type, not %.200s",
+ error_prefix,
+ RNA_struct_identifier(ptr->type),
+ RNA_property_identifier(prop),
+ RNA_struct_identifier(ptr_type),
+ Py_TYPE(value)->tp_name);
+ Py_XDECREF(value_new);
+ return -1;
+ }
+ param = (BPy_StructRNA *)value;
+
+ const ID *value_owner_id = ((BPy_StructRNA *)value)->ptr.owner_id;
+ if (value_owner_id != NULL) {
+ if ((flag & PROP_ID_SELF_CHECK) && (ptr->owner_id == value_owner_id)) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s %.200s.%.200s ID type does not support assignment to itself",
+ error_prefix,
+ RNA_struct_identifier(ptr->type),
+ RNA_property_identifier(prop));
+ Py_XDECREF(value_new);
+ return -1;
+ }
+ }
}
- BPy_StructRNA *param = (BPy_StructRNA *)value;
bool raise_error = false;
if (data) {
if (flag_parameter & PARM_RNAPTR) {
if (flag & PROP_THICK_WRAP) {
- if (value == Py_None) {
+ if (param == NULL) {
memset(data, 0, sizeof(PointerRNA));
}
else if (RNA_struct_is_a(param->ptr.type, ptr_type)) {
@@ -2075,7 +2084,7 @@ static int pyrna_py_to_prop(
* but watch out that it remains valid!
* We could possibly support this later if needed. */
BLI_assert(value_new == NULL);
- if (value == Py_None) {
+ if (param == NULL) {
*((void **)data) = NULL;
}
else if (RNA_struct_is_a(param->ptr.type, ptr_type)) {
@@ -2086,7 +2095,7 @@ static int pyrna_py_to_prop(
}
}
}
- else if (value == Py_None) {
+ else if (param == NULL) {
*((void **)data) = NULL;
}
else if (RNA_struct_is_a(param->ptr.type, ptr_type)) {
@@ -2098,11 +2107,11 @@ static int pyrna_py_to_prop(
}
else {
/* Data == NULL, assign to RNA. */
- if (value == Py_None || RNA_struct_is_a(param->ptr.type, ptr_type)) {
+ if ((param == NULL) || RNA_struct_is_a(param->ptr.type, ptr_type)) {
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);
RNA_property_pointer_set(
- ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr, &reports);
+ ptr, prop, (param == NULL) ? PointerRNA_NULL : param->ptr, &reports);
const int err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true));
if (err == -1) {
Py_XDECREF(value_new);
@@ -4589,13 +4598,12 @@ static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject
#else
{
/* Could just do this except for 1 awkward case.
- * PyObject_GenericGetAttr((PyObject *)self, pyname);
- * so as to support 'bpy.data.library.load()'
- * note, this _only_ supports static methods */
+ * `PyObject_GenericGetAttr((PyObject *)self, pyname);`
+ * so as to support `bpy.data.library.load()` */
PyObject *ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
- if (ret == NULL && name[0] != '_') { /* Avoid inheriting __call__ and similar. */
+ if (ret == NULL && name[0] != '_') { /* Avoid inheriting `__call__` and similar. */
/* Since this is least common case, handle it last. */
PointerRNA r_ptr;
if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) {
@@ -4613,6 +4621,19 @@ static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject
if (ret == NULL) {
PyErr_Restore(error_type, error_value, error_traceback);
}
+ else {
+ if (Py_TYPE(ret) == &PyMethodDescr_Type) {
+ PyMethodDef *m = ((PyMethodDescrObject *)ret)->d_method;
+ /* TODO: #METH_CLASS */
+ if (m->ml_flags & METH_STATIC) {
+ /* Keep 'ret' as-is. */
+ }
+ else {
+ Py_DECREF(ret);
+ ret = PyCMethod_New(m, (PyObject *)self, NULL, NULL);
+ }
+ }
+ }
}
}
@@ -5813,6 +5834,11 @@ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject *
BPy_StructRNA *ret;
if ((ret = (BPy_StructRNA *)type->tp_alloc(type, 0))) {
ret->ptr = base->ptr;
+#ifdef USE_PYRNA_STRUCT_REFERENCE
+ /* #PyType_GenericAlloc will have set tracking.
+ * We only want tracking when `StructRNA.reference` has been set. */
+ PyObject_GC_UnTrack(ret);
+#endif
}
/* Pass on exception & NULL if tp_alloc fails. */
return (PyObject *)ret;
@@ -6516,7 +6542,11 @@ PyTypeObject pyrna_struct_Type = {
NULL, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
+#ifdef USE_PYRNA_STRUCT_REFERENCE
+ | Py_TPFLAGS_HAVE_GC
+#endif
+ , /* long tp_flags; */
NULL, /* char *tp_doc; Documentation string */
/*** Assigned meaning in release 2.0 ***/
@@ -7453,13 +7483,28 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
if (tp) {
pyrna = (BPy_StructRNA *)tp->tp_alloc(tp, 0);
+#ifdef USE_PYRNA_STRUCT_REFERENCE
+ /* #PyType_GenericAlloc will have set tracking.
+ * We only want tracking when `StructRNA.reference` has been set. */
+ if (pyrna != NULL) {
+ PyObject_GC_UnTrack(pyrna);
+ }
+#endif
Py_DECREF(tp); /* srna owns, can't hold a reference. */
}
else {
CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type));
+
+#ifdef USE_PYRNA_STRUCT_REFERENCE
pyrna = (BPy_StructRNA *)PyObject_GC_New(BPy_StructRNA, &pyrna_struct_Type);
+#else
+ pyrna = (BPy_StructRNA *)PyObject_New(BPy_StructRNA, &pyrna_struct_Type);
+#endif
+
#ifdef USE_WEAKREFS
- pyrna->in_weakreflist = NULL;
+ if (pyrna != NULL) {
+ pyrna->in_weakreflist = NULL;
+ }
#endif
}
}
@@ -8961,7 +9006,7 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
#if 0
if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna) == NULL) {
- PWM_cursor_wait(0);
+ PWM_cursor_wait(false);
PyErr_SetString(PyExc_ValueError, "unregister_class(): not a registered as a subclass");
return NULL;
}
diff --git a/source/blender/sequencer/SEQ_add.h b/source/blender/sequencer/SEQ_add.h
index b136cb35e09..7d728b25a30 100644
--- a/source/blender/sequencer/SEQ_add.h
+++ b/source/blender/sequencer/SEQ_add.h
@@ -30,50 +30,74 @@ extern "C" {
struct ListBase;
struct Scene;
struct Sequence;
-struct bContext;
-/* api for adding new sequence strips */
-typedef struct SeqLoadInfo {
+/* SeqLoadData.flags */
+typedef enum eSeqLoadFlags {
+ SEQ_LOAD_SOUND_CACHE = (1 << 1),
+ SEQ_LOAD_SOUND_MONO = (1 << 2),
+ SEQ_LOAD_MOVIE_SYNC_FPS = (1 << 3),
+} eSeqLoadFlags;
+
+/* Api for adding new sequence strips. */
+typedef struct SeqLoadData {
int start_frame;
- int end_frame;
int channel;
- int flag; /* use sound, replace sel */
- int type;
- int len; /* only for image strips */
+ char name[64]; /* Strip name. */
char path[1024]; /* 1024 = FILE_MAX */
+ struct {
+ int len;
+ int end_frame;
+ } image; /* Only for image strips. */
+ struct Scene *scene; /* Only for scene strips. */
+ struct MovieClip *clip; /* Only for clip strips. */
+ struct Mask *mask; /* Only for mask strips. */
+ struct {
+ int type;
+ int end_frame;
+ struct Sequence *seq1;
+ struct Sequence *seq2;
+ struct Sequence *seq3;
+ } effect; /* Only for effect strips. */
+ eSeqLoadFlags flags;
eSeqImageFitMethod fit_method;
-
- /* multiview */
+ bool use_multiview;
char views_format;
struct Stereo3dFormat *stereo3d_format;
+ bool allow_invalid_file; /* Used by RNA API to create placeholder strips. */
+} SeqLoadData;
- /* return values */
- char name[64];
- struct Sequence *seq_sound; /* for movie's */
- int tot_success;
- int tot_error;
-} SeqLoadInfo;
-
-/* SeqLoadInfo.flag */
-#define SEQ_LOAD_REPLACE_SEL (1 << 0)
-#define SEQ_LOAD_FRAME_ADVANCE (1 << 1)
-#define SEQ_LOAD_MOVIE_SOUND (1 << 2)
-#define SEQ_LOAD_SOUND_CACHE (1 << 3)
-#define SEQ_LOAD_SYNC_FPS (1 << 4)
-#define SEQ_LOAD_SOUND_MONO (1 << 5)
-
-/* use as an api function */
-typedef struct Sequence *(*SeqLoadFn)(struct bContext *, ListBase *, struct SeqLoadInfo *);
-
-struct Sequence *SEQ_add_image_strip(struct bContext *C,
- ListBase *seqbasep,
- struct SeqLoadInfo *seq_load);
-struct Sequence *SEQ_add_sound_strip(struct bContext *C,
- ListBase *seqbasep,
- struct SeqLoadInfo *seq_load);
-struct Sequence *SEQ_add_movie_strip(struct bContext *C,
- ListBase *seqbasep,
- struct SeqLoadInfo *seq_load);
+void SEQ_add_load_data_init(struct SeqLoadData *load_data,
+ const char *name,
+ const char *path,
+ const int start_frame,
+ const int channel);
+struct Sequence *SEQ_add_image_strip(struct Main *bmain,
+ struct Scene *scene,
+ struct ListBase *seqbase,
+ struct SeqLoadData *load_data);
+struct Sequence *SEQ_add_sound_strip(struct Main *bmain,
+ struct Scene *scene,
+ struct ListBase *seqbase,
+ struct SeqLoadData *load_data);
+struct Sequence *SEQ_add_movie_strip(struct Main *bmain,
+ struct Scene *scene,
+ struct ListBase *seqbase,
+ struct SeqLoadData *load_data);
+struct Sequence *SEQ_add_scene_strip(struct Scene *scene,
+ struct ListBase *seqbase,
+ struct SeqLoadData *load_data);
+struct Sequence *SEQ_add_movieclip_strip(struct Scene *scene,
+ struct ListBase *seqbase,
+ struct SeqLoadData *load_data);
+struct Sequence *SEQ_add_mask_strip(struct Scene *scene,
+ struct ListBase *seqbase,
+ struct SeqLoadData *load_data);
+struct Sequence *SEQ_add_effect_strip(struct Scene *scene,
+ struct ListBase *seqbase,
+ struct SeqLoadData *load_data);
+void SEQ_add_image_set_directory(struct Sequence *seq, char *path);
+void SEQ_add_image_load_file(struct Sequence *seq, size_t strip_frame, char *filename);
+void SEQ_add_image_init_alpha_mode(struct Sequence *seq);
void SEQ_add_reload_new_file(struct Main *bmain,
struct Scene *scene,
struct Sequence *seq,
diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h
index ccadfc54e1d..85513faf3e6 100644
--- a/source/blender/sequencer/SEQ_sequencer.h
+++ b/source/blender/sequencer/SEQ_sequencer.h
@@ -62,8 +62,12 @@ struct Editing *SEQ_editing_get(struct Scene *scene, bool alloc);
struct Editing *SEQ_editing_ensure(struct Scene *scene);
void SEQ_editing_free(struct Scene *scene, const bool do_id_user);
struct ListBase *SEQ_active_seqbase_get(const struct Editing *ed);
+void SEQ_seqbase_active_set(struct Editing *ed, struct ListBase *seqbase);
struct Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type);
void SEQ_sequence_free(struct Scene *scene, struct Sequence *seq, const bool do_clean_animdata);
+struct MetaStack *SEQ_meta_stack_alloc(struct Editing *ed, struct Sequence *seq_meta);
+struct MetaStack *SEQ_meta_stack_active_get(const struct Editing *ed);
+void SEQ_meta_stack_free(struct Editing *ed, struct MetaStack *ms);
void SEQ_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs);
void SEQ_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst);
struct Sequence *SEQ_sequence_dupli_recursive(const struct Scene *scene_src,
diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c
index e9de73bc093..cf07fc7bc19 100644
--- a/source/blender/sequencer/intern/render.c
+++ b/source/blender/sequencer/intern/render.c
@@ -203,34 +203,6 @@ void SEQ_render_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4
}
}
-void SEQ_render_init_colorspace(Sequence *seq)
-{
- if (seq->strip && seq->strip->stripdata) {
- char name[FILE_MAX];
- ImBuf *ibuf;
-
- BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name);
- BLI_path_abs(name, BKE_main_blendfile_path_from_global());
-
- /* initialize input color space */
- if (seq->type == SEQ_TYPE_IMAGE) {
- ibuf = IMB_loadiffname(
- name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name);
-
- /* byte images are default to straight alpha, however sequencer
- * works in premul space, so mark strip to be premultiplied first
- */
- seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
- if (ibuf) {
- if (ibuf->flags & IB_alphamode_premul) {
- seq->alpha_mode = IMA_ALPHA_PREMUL;
- }
-
- IMB_freeImBuf(ibuf);
- }
- }
- }
-}
/** \} */
/* -------------------------------------------------------------------- */
@@ -611,6 +583,7 @@ static bool seq_need_scale_to_render_size(const Sequence *seq, bool is_proxy_ima
return true;
}
if ((seq->type & SEQ_TYPE_EFFECT) != 0 || seq->type == SEQ_TYPE_MASK ||
+ seq->type == SEQ_TYPE_META ||
(seq->type == SEQ_TYPE_SCENE && ((seq->flag & SEQ_SCENE_STRIPS) != 0))) {
return true;
}
diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c
index 4a0e4f1d9ad..4db7350544b 100644
--- a/source/blender/sequencer/intern/sequencer.c
+++ b/source/blender/sequencer/intern/sequencer.c
@@ -344,6 +344,58 @@ ListBase *SEQ_active_seqbase_get(const Editing *ed)
return ed->seqbasep;
}
+
+/**
+ * Set seqbase that is being viewed currently. This can be main seqbase or meta strip seqbase
+ *
+ * \param ed: sequence editor data
+ * \param seqbase: ListBase with strips
+ */
+void SEQ_seqbase_active_set(Editing *ed, ListBase *seqbase)
+{
+ ed->seqbasep = seqbase;
+}
+
+/**
+ * Create and initialize #MetaStack, append it to `ed->metastack` ListBase
+ *
+ * \param ed: sequence editor data
+ * \param seq_meta: meta strip
+ * \return pointer to created meta stack
+ */
+MetaStack *SEQ_meta_stack_alloc(Editing *ed, Sequence *seq_meta)
+{
+ MetaStack *ms = MEM_mallocN(sizeof(MetaStack), "metastack");
+ BLI_addtail(&ed->metastack, ms);
+ ms->parseq = seq_meta;
+ ms->oldbasep = ed->seqbasep;
+ copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp);
+ return ms;
+}
+
+/**
+ * Free #MetaStack and remove it from `ed->metastack` ListBase.
+ *
+ * \param ed: sequence editor data
+ * \param ms: meta stack
+ */
+void SEQ_meta_stack_free(Editing *ed, MetaStack *ms)
+{
+ BLI_remlink(&ed->metastack, ms);
+ MEM_freeN(ms);
+}
+
+/**
+ * Get #MetaStack that corresponds to current level that is being viewed
+ *
+ * \param ed: sequence editor data
+ * \return pointer to meta stack
+ */
+MetaStack *SEQ_meta_stack_active_get(const Editing *ed)
+{
+ return ed->metastack.last;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c
index ba080a07879..54e71ff0698 100644
--- a/source/blender/sequencer/intern/strip_add.c
+++ b/source/blender/sequencer/intern/strip_add.c
@@ -29,6 +29,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
@@ -54,7 +55,9 @@
#include "IMB_metadata.h"
#include "SEQ_add.h"
+#include "SEQ_effects.h"
#include "SEQ_relations.h"
+#include "SEQ_render.h"
#include "SEQ_select.h"
#include "SEQ_sequencer.h"
#include "SEQ_time.h"
@@ -65,168 +68,372 @@
#include "proxy.h"
#include "utils.h"
-static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo *seq_load)
+/**
+ * Initialize common SeqLoadData members
+ *
+ * \param load_data: SeqLoadData to be initialized
+ * \param name: strip name (can be NULL)
+ * \param path: path to file that is used as strip input (can be NULL)
+ * \param start_frame: timeline frame where strip will be created
+ * \param channel: timeline channel where strip will be created
+ *
+ */
+void SEQ_add_load_data_init(SeqLoadData *load_data,
+ const char *name,
+ const char *path,
+ const int start_frame,
+ const int channel)
{
- if (seq) {
- BLI_strncpy_utf8(seq->name + 2, seq_load->name, sizeof(seq->name) - 2);
- BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2));
- SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
+ memset(load_data, 0, sizeof(SeqLoadData));
+ if (name != NULL) {
+ BLI_strncpy(load_data->name, name, sizeof(load_data->name));
+ }
+ if (path != NULL) {
+ BLI_strncpy(load_data->path, path, sizeof(load_data->path));
+ }
+ load_data->start_frame = start_frame;
+ load_data->channel = channel;
+}
- if (seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) {
- seq_load->start_frame += (seq->enddisp - seq->startdisp);
- }
+static void seq_add_generic_update(Scene *scene, ListBase *seqbase, Sequence *seq)
+{
+ SEQ_sequence_base_unique_name_recursive(seqbase, seq);
+ SEQ_time_update_sequence_bounds(scene, seq);
+ SEQ_sort(scene);
+ SEQ_relations_invalidate_cache_composite(scene, seq);
+}
- if (seq_load->flag & SEQ_LOAD_REPLACE_SEL) {
- seq_load->flag |= SELECT;
- SEQ_select_active_set(scene, seq);
+static void seq_add_set_name(Sequence *seq, SeqLoadData *load_data)
+{
+ if (load_data->name != NULL) {
+ BLI_strncpy(seq->name + 2, load_data->name, sizeof(seq->name) - 2);
+ }
+ else {
+ if (seq->type == SEQ_TYPE_SCENE) {
+ BLI_strncpy(seq->name + 2, load_data->scene->id.name + 2, sizeof(seq->name) - 2);
}
-
- if (seq_load->flag & SEQ_LOAD_SOUND_MONO) {
- seq->sound->flags |= SOUND_FLAGS_MONO;
- BKE_sound_load(bmain, seq->sound);
+ else if (seq->type == SEQ_TYPE_MOVIECLIP) {
+ BLI_strncpy(seq->name + 2, load_data->clip->id.name + 2, sizeof(seq->name) - 2);
}
-
- if (seq_load->flag & SEQ_LOAD_SOUND_CACHE) {
- if (seq->sound) {
- seq->sound->flags |= SOUND_FLAGS_CACHING;
- }
+ else if (seq->type == SEQ_TYPE_MASK) {
+ BLI_strncpy(seq->name + 2, load_data->mask->id.name + 2, sizeof(seq->name) - 2);
+ }
+ else if ((seq->type & SEQ_TYPE_EFFECT) != 0) {
+ BLI_strncpy(seq->name + 2, SEQ_sequence_give_name(seq), sizeof(seq->name) - 2);
+ }
+ else { /* Image, sound and movie. */
+ BLI_strncpy_utf8(seq->name + 2, load_data->name, sizeof(seq->name) - 2);
+ BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2));
}
-
- seq_load->tot_success++;
- }
- else {
- seq_load->tot_error++;
}
}
-/* NOTE: this function doesn't fill in image names */
-Sequence *SEQ_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
+/**
+ * Add scene strip.
+ *
+ * \param scene: Scene where strips will be added
+ * \param seqbase: ListBase where strips will be added
+ * \param load_data: SeqLoadData with information necessary to create strip
+ * \return created strip
+ */
+Sequence *SEQ_add_scene_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
{
- Scene *scene = CTX_data_scene(C); /* only for active seq */
- Sequence *seq;
- Strip *strip;
+ Sequence *seq = SEQ_sequence_alloc(
+ seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SCENE);
+ seq->blend_mode = SEQ_TYPE_CROSS;
+ seq->scene = load_data->scene;
+ seq->len = load_data->scene->r.efra - load_data->scene->r.sfra + 1;
+ id_us_ensure_real((ID *)load_data->scene);
+ seq_add_set_name(seq, load_data);
+ seq_add_generic_update(scene, seqbase, seq);
+ return seq;
+}
- seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_IMAGE);
- seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
+/**
+ * Add movieclip strip.
+ *
+ * \param scene: Scene where strips will be added
+ * \param seqbase: ListBase where strips will be added
+ * \param load_data: SeqLoadData with information necessary to create strip
+ * \return created strip
+ */
+Sequence *SEQ_add_movieclip_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
+{
+ Sequence *seq = SEQ_sequence_alloc(
+ seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIECLIP);
+ seq->blend_mode = SEQ_TYPE_CROSS;
+ seq->clip = load_data->clip;
+ seq->len = BKE_movieclip_get_duration(load_data->clip);
+ id_us_ensure_real((ID *)load_data->clip);
+ seq_add_set_name(seq, load_data);
+ seq_add_generic_update(scene, seqbase, seq);
+ return seq;
+}
- /* basic defaults */
- seq->len = seq_load->len ? seq_load->len : 1;
+/**
+ * Add mask strip.
+ *
+ * \param scene: Scene where strips will be added
+ * \param seqbase: ListBase where strips will be added
+ * \param load_data: SeqLoadData with information necessary to create strip
+ * \return created strip
+ */
+Sequence *SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
+{
+ Sequence *seq = SEQ_sequence_alloc(
+ seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MASK);
+ seq->blend_mode = SEQ_TYPE_CROSS;
+ seq->mask = load_data->mask;
+ seq->len = BKE_mask_get_duration(load_data->mask);
+ id_us_ensure_real((ID *)load_data->mask);
+ seq_add_set_name(seq, load_data);
+ seq_add_generic_update(scene, seqbase, seq);
+ return seq;
+}
- strip = seq->strip;
- strip->stripdata = MEM_callocN(seq->len * sizeof(StripElem), "stripelem");
- BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir));
+/**
+ * Add effect strip.
+ *
+ * \param scene: Scene where strips will be added
+ * \param seqbase: ListBase where strips will be added
+ * \param load_data: SeqLoadData with information necessary to create strip
+ * \return created strip
+ */
+Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
+{
+ Sequence *seq = SEQ_sequence_alloc(
+ seqbase, load_data->start_frame, load_data->channel, load_data->effect.type);
+
+ seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
+ struct SeqEffectHandle sh = SEQ_effect_handle_get(seq);
+ sh.init(seq);
+ seq->seq1 = load_data->effect.seq1;
+ seq->seq2 = load_data->effect.seq2;
+ seq->seq3 = load_data->effect.seq3;
+
+ if (seq->type == SEQ_TYPE_COLOR) {
+ seq->blend_mode = SEQ_TYPE_CROSS;
+ }
+ else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
+ seq->blend_mode = SEQ_TYPE_CROSS;
+ }
+ else if (seq->type == SEQ_TYPE_TEXT) {
+ seq->blend_mode = SEQ_TYPE_ALPHAOVER;
+ }
+ else if (SEQ_effect_get_num_inputs(seq->type) == 1) {
+ seq->blend_mode = seq->seq1->blend_mode;
+ }
- if (seq_load->stereo3d_format) {
- *seq->stereo3d_format = *seq_load->stereo3d_format;
+ if (!load_data->effect.seq1) {
+ seq->len = 1; /* Effect is generator, set non zero length. */
+ SEQ_transform_set_right_handle_frame(seq, load_data->image.end_frame);
}
+ SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */
+ seq_add_set_name(seq, load_data);
+ seq_add_generic_update(scene, seqbase, seq);
+
+ return seq;
+}
+
+/**
+ * Set directory used by image strip.
+ *
+ * \param seq: image strip to be changed
+ * \param path: directory path
+ */
+void SEQ_add_image_set_directory(Sequence *seq, char *path)
+{
+ BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
+}
- seq->views_format = seq_load->views_format;
- seq->flag |= seq_load->flag & SEQ_USE_VIEWS;
+/**
+ * Set directory used by image strip.
+ *
+ * \param seq: image strip to be changed
+ * \param strip_frame: frame index of strip to be changed
+ * \param filename: image filename (only filename, not complete path)
+ */
+void SEQ_add_image_load_file(Sequence *seq, size_t strip_frame, char *filename)
+{
+ StripElem *se = SEQ_render_give_stripelem(seq, seq->start + strip_frame);
+ BLI_strncpy(se->name, filename, sizeof(se->name));
+}
- seq_load_apply(CTX_data_main(C), scene, seq, seq_load);
+/**
+ * Set image strip alpha mode
+ *
+ * \param seq: image strip to be changed
+ */
+void SEQ_add_image_init_alpha_mode(Sequence *seq)
+{
+ if (seq->strip && seq->strip->stripdata) {
+ char name[FILE_MAX];
+ ImBuf *ibuf;
+
+ BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name);
+ BLI_path_abs(name, BKE_main_blendfile_path_from_global());
+
+ /* Initialize input color space. */
+ if (seq->type == SEQ_TYPE_IMAGE) {
+ ibuf = IMB_loadiffname(
+ name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name);
+
+ /* Byte images are default to straight alpha, however sequencer
+ * works in premul space, so mark strip to be premultiplied first.
+ */
+ seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
+ if (ibuf) {
+ if (ibuf->flags & IB_alphamode_premul) {
+ seq->alpha_mode = IMA_ALPHA_PREMUL;
+ }
+ IMB_freeImBuf(ibuf);
+ }
+ }
+ }
+}
+
+/**
+ * Add image strip.
+ * NOTE: Use SEQ_add_image_set_directory() and SEQ_add_image_load_file() to load image sequences
+ *
+ * \param main: Main reference
+ * \param scene: Scene where strips will be added
+ * \param seqbase: ListBase where strips will be added
+ * \param load_data: SeqLoadData with information necessary to create strip
+ * \return created strip
+ */
+Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
+{
+ Sequence *seq = SEQ_sequence_alloc(
+ seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_IMAGE);
+ seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
+ seq->len = load_data->image.len;
+ Strip *strip = seq->strip;
+ strip->stripdata = MEM_callocN(load_data->image.len * sizeof(StripElem), "stripelem");
+
+ /* Multiview settings. */
+ if (load_data->use_multiview) {
+ seq->flag |= SEQ_USE_VIEWS;
+ seq->views_format = load_data->views_format;
+ }
+ if (load_data->stereo3d_format) {
+ seq->stereo3d_format = load_data->stereo3d_format;
+ }
+
+ /* Set initial scale based on load_data->fit_method. */
char file_path[FILE_MAX];
- BLI_join_dirfile(file_path, sizeof(file_path), seq_load->path, seq_load->name);
- BLI_path_abs(file_path, BKE_main_blendfile_path(CTX_data_main(C)));
+ BLI_join_dirfile(file_path, sizeof(file_path), load_data->path, load_data->name);
+ BLI_path_abs(file_path, BKE_main_blendfile_path(bmain));
ImBuf *ibuf = IMB_loadiffname(file_path, IB_rect, seq->strip->colorspace_settings.name);
if (ibuf != NULL) {
SEQ_set_scale_to_fit(
- seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, seq_load->fit_method);
+ seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, load_data->fit_method);
IMB_freeImBuf(ibuf);
}
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ /* Set Last active directory. */
+ BLI_strncpy(scene->ed->act_imagedir, seq->strip->dir, sizeof(scene->ed->act_imagedir));
+ seq_add_set_name(seq, load_data);
+ seq_add_generic_update(scene, seqbase, seq);
return seq;
}
#ifdef WITH_AUDASPACE
-Sequence *SEQ_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C); /* only for sound */
- Editing *ed = SEQ_editing_get(scene, false);
- bSound *sound;
-
- Sequence *seq; /* generic strip vars */
- Strip *strip;
- StripElem *se;
-
- sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */
+/**
+ * Add sound strip.
+ * NOTE: Use SEQ_add_image_set_directory() and SEQ_add_image_load_file() to load image sequences
+ *
+ * \param main: Main reference
+ * \param scene: Scene where strips will be added
+ * \param seqbase: ListBase where strips will be added
+ * \param load_data: SeqLoadData with information necessary to create strip
+ * \return created strip
+ */
+Sequence *SEQ_add_sound_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
+{
+ bSound *sound = BKE_sound_new_file(bmain, load_data->path); /* Handles relative paths. */
SoundInfo info;
- if (!BKE_sound_info_get(bmain, sound, &info)) {
+ bool sound_loaded = BKE_sound_info_get(bmain, sound, &info);
+
+ if (!sound_loaded && !load_data->allow_invalid_file) {
BKE_id_free(bmain, sound);
return NULL;
}
- if (info.specs.channels == SOUND_CHANNELS_INVALID) {
+ if (info.specs.channels == SOUND_CHANNELS_INVALID && !load_data->allow_invalid_file) {
BKE_id_free(bmain, sound);
return NULL;
}
- seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_SOUND_RAM);
+ Sequence *seq = SEQ_sequence_alloc(
+ seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SOUND_RAM);
seq->sound = sound;
- BLI_strncpy(seq->name + 2, "Sound", SEQ_NAME_MAXSTR - 2);
- SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
+ seq->scene_sound = NULL;
- /* basic defaults */
/* We add a very small negative offset here, because
* ceil(132.0) == 133.0, not nice with videos, see T47135. */
- seq->len = (int)ceil((double)info.length * FPS - 1e-4);
- strip = seq->strip;
-
- /* we only need 1 element to store the filename */
- strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
-
- BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
+ seq->len = MAX2(1, (int)ceil((double)info.length * FPS - 1e-4));
- seq->scene_sound = NULL;
-
- SEQ_time_update_sequence_bounds(scene, seq);
+ Strip *strip = seq->strip;
+ /* We only need 1 element to store the filename. */
+ StripElem *se = strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
+ BLI_split_dirfile(load_data->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
- /* last active name */
- BLI_strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR);
+ if (seq != NULL && seq->sound != NULL) {
+ if (load_data->flags & SEQ_LOAD_SOUND_MONO) {
+ seq->sound->flags |= SOUND_FLAGS_MONO;
+ }
- seq_load_apply(bmain, scene, seq, seq_load);
+ if (load_data->flags & SEQ_LOAD_SOUND_CACHE) {
+ if (seq->sound) {
+ seq->sound->flags |= SOUND_FLAGS_CACHING;
+ }
+ }
+ }
- /* TODO(sergey): Shall we tag here or in the operator? */
- DEG_relations_tag_update(bmain);
+ /* Set Last active directory. */
+ BLI_strncpy(scene->ed->act_sounddir, strip->dir, FILE_MAXDIR);
+ seq_add_set_name(seq, load_data);
+ seq_add_generic_update(scene, seqbase, seq);
return seq;
}
+
#else // WITH_AUDASPACE
-Sequence *SEQ_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
+Sequence *SEQ_add_sound_strip(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ ListBase *UNUSED(seqbase),
+ SeqLoadData *UNUSED(load_data))
{
- (void)C;
- (void)seqbasep;
- (void)seq_load;
return NULL;
}
#endif // WITH_AUDASPACE
-Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
+/**
+ * Add movie strip.
+ *
+ * \param main: Main reference
+ * \param scene: Scene where strips will be added
+ * \param seqbase: ListBase where strips will be added
+ * \param load_data: SeqLoadData with information necessary to create strip
+ * \return created strip
+ */
+Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C); /* only for sound */
- char path[sizeof(seq_load->path)];
+ char path[sizeof(load_data->path)];
+ BLI_strncpy(path, load_data->path, sizeof(path));
+ BLI_path_abs(path, BKE_main_blendfile_path(bmain));
- Sequence *seq; /* generic strip vars */
- Strip *strip;
- StripElem *se;
char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */
bool is_multiview_loaded = false;
- const bool is_multiview = (seq_load->flag & SEQ_USE_VIEWS) != 0;
- const int totfiles = seq_num_files(scene, seq_load->views_format, is_multiview);
- struct anim **anim_arr;
+ const int totfiles = seq_num_files(scene, load_data->views_format, load_data->use_multiview);
+ struct anim **anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files");
int i;
- BLI_strncpy(path, seq_load->path, sizeof(path));
- BLI_path_abs(path, BKE_main_blendfile_path(bmain));
-
- anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files");
-
- if (is_multiview && (seq_load->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
+ if (load_data->use_multiview && (load_data->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
char prefix[FILE_MAX];
const char *ext = NULL;
size_t j = 0;
@@ -245,38 +452,30 @@ Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_
j++;
}
}
-
- if (j == 0) {
- MEM_freeN(anim_arr);
- return NULL;
- }
is_multiview_loaded = true;
}
}
if (is_multiview_loaded == false) {
anim_arr[0] = openanim(path, IB_rect, 0, colorspace);
-
- if (anim_arr[0] == NULL) {
- MEM_freeN(anim_arr);
- return NULL;
- }
}
- if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) {
- seq_load->channel++;
+ if (anim_arr[0] == NULL && !load_data->allow_invalid_file) {
+ MEM_freeN(anim_arr);
+ return NULL;
}
- seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_MOVIE);
- /* multiview settings */
- if (seq_load->stereo3d_format) {
- *seq->stereo3d_format = *seq_load->stereo3d_format;
- seq->views_format = seq_load->views_format;
- }
- seq->flag |= seq_load->flag & SEQ_USE_VIEWS;
+ Sequence *seq = SEQ_sequence_alloc(
+ seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIE);
- seq->type = SEQ_TYPE_MOVIE;
- seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
+ /* Multiview settings. */
+ if (load_data->use_multiview) {
+ seq->flag |= SEQ_USE_VIEWS;
+ seq->views_format = load_data->views_format;
+ }
+ if (load_data->stereo3d_format) {
+ seq->stereo3d_format = load_data->stereo3d_format;
+ }
for (i = 0; i < totfiles; i++) {
if (anim_arr[i]) {
@@ -289,51 +488,38 @@ Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_
}
}
- IMB_anim_load_metadata(anim_arr[0]);
+ seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
- seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]);
+ if (anim_arr[0] != NULL) {
+ seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]);
+ seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
- const float width = IMB_anim_get_image_width(anim_arr[0]);
- const float height = IMB_anim_get_image_height(anim_arr[0]);
- SEQ_set_scale_to_fit(seq, width, height, scene->r.xsch, scene->r.ysch, seq_load->fit_method);
+ IMB_anim_load_metadata(anim_arr[0]);
- BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2);
- SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
+ /* Adjust scene's frame rate settings to match. */
+ if (load_data->flags & SEQ_LOAD_MOVIE_SYNC_FPS) {
+ IMB_anim_get_fps(anim_arr[0], &scene->r.frs_sec, &scene->r.frs_sec_base, true);
+ }
- /* adjust scene's frame rate settings to match */
- if (seq_load->flag & SEQ_LOAD_SYNC_FPS) {
- IMB_anim_get_fps(anim_arr[0], &scene->r.frs_sec, &scene->r.frs_sec_base, true);
+ /* Set initial scale based on load_data->fit_method. */
+ const float width = IMB_anim_get_image_width(anim_arr[0]);
+ const float height = IMB_anim_get_image_height(anim_arr[0]);
+ SEQ_set_scale_to_fit(seq, width, height, scene->r.xsch, scene->r.ysch, load_data->fit_method);
}
- /* basic defaults */
- seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
- strip = seq->strip;
-
+ seq->len = MAX2(1, seq->len);
BLI_strncpy(seq->strip->colorspace_settings.name,
colorspace,
sizeof(seq->strip->colorspace_settings.name));
- /* we only need 1 element for MOVIE strips */
+ Strip *strip = seq->strip;
+ /* We only need 1 element for MOVIE strips. */
+ StripElem *se;
strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
+ BLI_split_dirfile(load_data->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
- BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
-
- SEQ_time_update_sequence_bounds(scene, seq);
-
- if (seq_load->name[0] == '\0') {
- BLI_strncpy(seq_load->name, se->name, sizeof(seq_load->name));
- }
-
- if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) {
- int start_frame_back = seq_load->start_frame;
- seq_load->channel--;
- seq_load->seq_sound = SEQ_add_sound_strip(C, seqbasep, seq_load);
- seq_load->start_frame = start_frame_back;
- }
-
- /* can be NULL */
- seq_load_apply(CTX_data_main(C), scene, seq, seq_load);
- SEQ_relations_invalidate_cache_composite(scene, seq);
+ seq_add_set_name(seq, load_data);
+ seq_add_generic_update(scene, seqbase, seq);
MEM_freeN(anim_arr);
return seq;
@@ -525,9 +711,9 @@ void SEQ_add_movie_reload_if_needed(struct Main *bmain,
bool must_reload = false;
- /* The Sequence struct allows for multiple anim structs to be associated with one strip. This
- * function will return true only if there is at least one 'anim' AND all anims can produce
- * frames. */
+ /* The Sequence struct allows for multiple anim structs to be associated with one strip.
+ * This function will return true only if there is at least one 'anim' AND all anims can
+ * produce frames. */
if (BLI_listbase_is_empty(&seq->anims)) {
/* No anim present, so reloading is always necessary. */
diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c
index c495ad6d8f1..21dc9aa2cdd 100644
--- a/source/blender/sequencer/intern/strip_time.c
+++ b/source/blender/sequencer/intern/strip_time.c
@@ -164,7 +164,6 @@ void SEQ_time_update_sequence_bounds(Scene *scene, Sequence *seq)
void SEQ_time_update_sequence(Scene *scene, Sequence *seq)
{
Sequence *seqm;
- int min, max;
/* check all metas recursively */
seqm = seq->seqbase.first;
@@ -212,27 +211,6 @@ void SEQ_time_update_sequence(Scene *scene, Sequence *seq)
}
}
else {
- if (seq->type == SEQ_TYPE_META) {
- seqm = seq->seqbase.first;
- if (seqm) {
- min = MAXFRAME * 2;
- max = -MAXFRAME * 2;
- while (seqm) {
- if (seqm->startdisp < min) {
- min = seqm->startdisp;
- }
- if (seqm->enddisp > max) {
- max = seqm->enddisp;
- }
- seqm = seqm->next;
- }
- seq->start = min + seq->anim_startofs;
- seq->len = max - min;
- seq->len -= seq->anim_startofs;
- seq->len -= seq->anim_endofs;
- }
- seq_update_sound_bounds_recursive(scene, seq);
- }
SEQ_time_update_sequence_bounds(scene, seq);
}
}
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index d40c0715a09..084ca2d2df5 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -461,6 +461,7 @@ typedef struct wmNotifier {
#define NA_SELECTED 6
#define NA_ACTIVATED 7
#define NA_PAINTING 8
+#define NA_JOB_FINISHED 9
/* ************** Gesture Manager data ************** */
@@ -543,17 +544,36 @@ typedef struct wmTabletData {
/**
* Each event should have full modifier state.
* event comes from event manager and from keymap.
+ *
+ *
+ * Previous State
+ * ==============
+ *
+ * Events hold information about the previous event,
+ * this is used for detecting click and double-click events (the timer is needed for double-click).
+ * See #wm_event_add_ghostevent for implementation details.
+ *
+ * Notes:
+ *
+ * - The previous values are only set for mouse button and keyboard events.
+ * See: #ISMOUSE_BUTTON & #ISKEYBOARD macros.
+ *
+ * - Previous x/y are exceptions: #wmEvent.prevx & #wmEvent.prevy
+ * these are set on mouse motion, see #MOUSEMOVE & track-pad events.
+ *
+ * - Modal key-map handling sets `prevval` & `prevtype` to `val` & `type`,
+ * this allows modal keys-maps to check the original values (needed in some cases).
*/
typedef struct wmEvent {
struct wmEvent *next, *prev;
- /** Event code itself (short, is also in keymap). */
+ /** Event code itself (short, is also in key-map). */
short type;
/** Press, release, scroll-value. */
short val;
/** Mouse pointer position, screen coord. */
int x, y;
- /** Region mouse position, name convention pre 2.5 :). */
+ /** Region relative mouse position (name convention before Blender 2.5). */
int mval[2];
/**
* From, ghost if utf8 is enabled for the platform,
@@ -572,37 +592,43 @@ typedef struct wmEvent {
*/
char is_repeat;
- /** Previous state, used for double click and the 'click'. */
+ /** The previous value of `type`. */
short prevtype;
+ /** The previous value of `val`. */
short prevval;
- int prevx, prevy;
+ /** The time when the key is pressed, see #PIL_check_seconds_timer. */
double prevclicktime;
+ /** The location when the key is pressed (used to enforce drag thresholds). */
int prevclickx, prevclicky;
+ /**
+ * The previous value of #wmEvent.x #wmEvent.y,
+ * Unlike other previous state variables, this is set on any mouse motion.
+ * Use `prevclickx` & `prevclicky` for the value at time of pressing.
+ */
+ int prevx, prevy;
/** Modifier states. */
/** 'oskey' is apple or windows-key, value denotes order of pressed. */
short shift, ctrl, alt, oskey;
- /** rawkey modifier. */
+ /** Raw-key modifier (allow using any key as a modifier). */
short keymodifier;
- /** Set in case a #KM_PRESS went by unhandled. */
- char check_click;
- char check_drag;
-
/** Tablet info, available for mouse move and button events. */
wmTabletData tablet;
- /* custom data */
+ /* Custom data. */
/** Custom data type, stylus, 6dof, see wm_event_types.h */
short custom;
short customdatafree;
int pad2;
- /** Ascii, unicode, mouse coords, angles, vectors, dragdrop info. */
+ /** Ascii, unicode, mouse-coords, angles, vectors, NDOF data, drag-drop info. */
void *customdata;
- /* True if the operating system inverted the delta x/y values and resulting
- * prev x/y values, for natural scroll direction. For absolute scroll direction,
- * the delta must be negated again. */
+ /**
+ * True if the operating system inverted the delta x/y values and resulting
+ * `prevx`, `prevy` values, for natural scroll direction.
+ * For absolute scroll direction, the delta must be negated again.
+ */
char is_direction_inverted;
} wmEvent;
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index a9c0d1dd8fe..c5a429d7839 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -172,7 +172,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id)
win->ime_data = NULL;
#endif
- BLI_listbase_clear(&win->queue);
+ BLI_listbase_clear(&win->event_queue);
BLI_listbase_clear(&win->handlers);
BLI_listbase_clear(&win->modalhandlers);
BLI_listbase_clear(&win->gesture);
@@ -184,6 +184,8 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id)
win->modalcursor = 0;
win->grabcursor = 0;
win->addmousemove = true;
+ win->event_queue_check_click = 0;
+ win->event_queue_check_drag = 0;
BLO_read_data_address(reader, &win->stereo3d_format);
/* Multi-view always fallback to anaglyph at file opening
@@ -198,7 +200,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id)
BLI_listbase_clear(&wm->timers);
BLI_listbase_clear(&wm->operators);
BLI_listbase_clear(&wm->paintcursors);
- BLI_listbase_clear(&wm->queue);
+ BLI_listbase_clear(&wm->notifier_queue);
BKE_reports_init(&wm->reports, RPT_STORE);
BLI_listbase_clear(&wm->keyconfigs);
@@ -590,7 +592,7 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
WM_keyconfig_free(keyconf);
}
- BLI_freelistN(&wm->queue);
+ BLI_freelistN(&wm->notifier_queue);
if (wm->message_bus != NULL) {
WM_msgbus_destroy(wm->message_bus);
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index e32552063af..d6e4a93f6a6 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -303,7 +303,7 @@ static void wm_cursor_warp_relative(wmWindow *win, int x, int y)
{
/* note: don't use wmEvent coords because of continuous grab T36409. */
int cx, cy;
- wm_get_cursor_position(win, &cx, &cy);
+ wm_cursor_position_get(win, &cx, &cy);
WM_cursor_warp(win, cx + x, cy + y);
}
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 85611a0be93..071bce822a5 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -117,7 +117,7 @@ static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region)
if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) {
int x = 0, y = 0;
- wm_get_cursor_position(win, &x, &y);
+ wm_cursor_position_get(win, &x, &y);
pc->draw(C, x, y, pc->customdata);
}
else {
diff --git a/source/blender/windowmanager/intern/wm_event_query.c b/source/blender/windowmanager/intern/wm_event_query.c
index ab8f37548b7..9b9be6bb497 100644
--- a/source/blender/windowmanager/intern/wm_event_query.c
+++ b/source/blender/windowmanager/intern/wm_event_query.c
@@ -281,6 +281,10 @@ int WM_event_drag_threshold(const struct wmEvent *event)
drag_threshold = U.drag_threshold_tablet;
}
else if (ISMOUSE(event->prevtype)) {
+ BLI_assert(event->prevtype != MOUSEMOVE);
+ /* Using the previous type is important is we want to check the last pressed/released button,
+ * The `event->type` would include #MOUSEMOVE which is always the case when dragging
+ * and does not help us know which threshold to use. */
drag_threshold = U.drag_threshold_mouse;
}
else {
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index dc38bd79b7d..4c4523c80bc 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -126,12 +126,12 @@ wmEvent *wm_event_add_ex(wmWindow *win,
*event = *event_to_add;
if (event_to_add_after == NULL) {
- BLI_addtail(&win->queue, event);
+ BLI_addtail(&win->event_queue, event);
}
else {
/* Note: strictly speaking this breaks const-correctness,
* however we're only changing 'next' member. */
- BLI_insertlinkafter(&win->queue, (void *)event_to_add_after, event);
+ BLI_insertlinkafter(&win->event_queue, (void *)event_to_add_after, event);
}
return event;
}
@@ -149,23 +149,25 @@ wmEvent *WM_event_add_simulate(wmWindow *win, const wmEvent *event_to_add)
}
wmEvent *event = wm_event_add(win, event_to_add);
+ /* Logic for setting previous value is documented on the #wmEvent struct,
+ * see #wm_event_add_ghostevent for the implementation of logic this follows. */
+
win->eventstate->x = event->x;
win->eventstate->y = event->y;
- win->eventstate->prevval = event->prevval = win->eventstate->val;
- win->eventstate->prevtype = event->prevtype = win->eventstate->type;
- win->eventstate->prevx = event->prevx = win->eventstate->x;
- win->eventstate->prevy = event->prevy = win->eventstate->y;
-
if (event->type == MOUSEMOVE) {
- /* Pass. */
+ win->eventstate->prevx = event->prevx = win->eventstate->x;
+ win->eventstate->prevy = event->prevy = win->eventstate->y;
}
- else {
+ else if (ISMOUSE_BUTTON(event->type) || ISKEYBOARD(event->type)) {
+ win->eventstate->prevval = event->prevval = win->eventstate->val;
+ win->eventstate->prevtype = event->prevtype = win->eventstate->type;
+
win->eventstate->val = event->val;
win->eventstate->type = event->type;
- if (ISMOUSE_BUTTON(event->type)) {
- if (event->val == KM_PRESS) {
+ if (event->val == KM_PRESS) {
+ if (event->is_repeat == false) {
win->eventstate->prevclickx = event->x;
win->eventstate->prevclicky = event->y;
}
@@ -203,7 +205,7 @@ void wm_event_free(wmEvent *event)
static void wm_event_free_last(wmWindow *win)
{
- wmEvent *event = BLI_poptail(&win->queue);
+ wmEvent *event = BLI_poptail(&win->event_queue);
if (event != NULL) {
wm_event_free(event);
}
@@ -212,7 +214,7 @@ static void wm_event_free_last(wmWindow *win)
void wm_event_free_all(wmWindow *win)
{
wmEvent *event;
- while ((event = BLI_pophead(&win->queue))) {
+ while ((event = BLI_pophead(&win->event_queue))) {
wm_event_free(event);
}
}
@@ -230,7 +232,7 @@ void wm_event_init_from_window(wmWindow *win, wmEvent *event)
static bool wm_test_duplicate_notifier(const wmWindowManager *wm, uint type, void *reference)
{
- LISTBASE_FOREACH (wmNotifier *, note, &wm->queue) {
+ LISTBASE_FOREACH (wmNotifier *, note, &wm->notifier_queue) {
if ((note->category | note->data | note->subtype | note->action) == type &&
note->reference == reference) {
return true;
@@ -248,7 +250,7 @@ void WM_event_add_notifier_ex(wmWindowManager *wm, const wmWindow *win, uint typ
wmNotifier *note = MEM_callocN(sizeof(wmNotifier), "notifier");
- BLI_addtail(&wm->queue, note);
+ BLI_addtail(&wm->notifier_queue, note);
note->window = win;
@@ -277,7 +279,7 @@ void WM_main_add_notifier(unsigned int type, void *reference)
wmNotifier *note = MEM_callocN(sizeof(wmNotifier), "notifier");
- BLI_addtail(&wm->queue, note);
+ BLI_addtail(&wm->notifier_queue, note);
note->category = type & NOTE_CATEGORY;
note->data = type & NOTE_DATA;
@@ -296,7 +298,7 @@ void WM_main_remove_notifier_reference(const void *reference)
wmWindowManager *wm = bmain->wm.first;
if (wm) {
- LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->queue) {
+ LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->notifier_queue) {
if (note->reference == reference) {
/* Don't remove because this causes problems for #wm_event_do_notifiers
* which may be looping on the data (deleting screens). */
@@ -448,7 +450,7 @@ void wm_event_do_notifiers(bContext *C)
CTX_wm_window_set(C, win);
- LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->queue) {
+ LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->notifier_queue) {
if (note->category == NC_WM) {
if (ELEM(note->data, ND_FILEREAD, ND_FILESAVE)) {
wm->file_saved = 1;
@@ -537,7 +539,7 @@ void wm_event_do_notifiers(bContext *C)
/* The notifiers are sent without context, to keep it clean. */
wmNotifier *note;
- while ((note = BLI_pophead(&wm->queue))) {
+ while ((note = BLI_pophead(&wm->notifier_queue))) {
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
Scene *scene = WM_window_get_active_scene(win);
bScreen *screen = WM_window_get_active_screen(win);
@@ -1957,6 +1959,13 @@ static wmKeyMapItem *wm_eventmatch_modal_keymap_items(const wmKeyMap *keymap,
return NULL;
}
+struct wmEvent_ModalMapStore {
+ short prevtype;
+ short prevval;
+
+ bool dbl_click_disabled;
+};
+
/**
* This function prepares events for use with #wmOperatorType.modal by:
*
@@ -1970,7 +1979,7 @@ static wmKeyMapItem *wm_eventmatch_modal_keymap_items(const wmKeyMap *keymap,
static void wm_event_modalkeymap_begin(const bContext *C,
wmOperator *op,
wmEvent *event,
- bool *dbl_click_disabled)
+ struct wmEvent_ModalMapStore *event_backup)
{
BLI_assert(event->type != EVT_MODAL_MAP);
@@ -1979,6 +1988,8 @@ static void wm_event_modalkeymap_begin(const bContext *C,
op = op->opm;
}
+ event_backup->dbl_click_disabled = false;
+
if (op->type->modalkeymap) {
wmKeyMap *keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap);
wmKeyMapItem *kmi = NULL;
@@ -1998,6 +2009,9 @@ static void wm_event_modalkeymap_begin(const bContext *C,
}
if (event_match != NULL) {
+ event_backup->prevtype = event->prevtype;
+ event_backup->prevval = event->prevval;
+
event->prevtype = event_match->type;
event->prevval = event_match->val;
event->type = EVT_MODAL_MAP;
@@ -2008,7 +2022,7 @@ static void wm_event_modalkeymap_begin(const bContext *C,
* which would break when modal functions expect press/release. */
if (event->prevtype == KM_DBL_CLICK) {
event->prevtype = KM_PRESS;
- *dbl_click_disabled = true;
+ event_backup->dbl_click_disabled = true;
}
}
}
@@ -2017,7 +2031,7 @@ static void wm_event_modalkeymap_begin(const bContext *C,
/* This bypass just disables support for double-click in modal handlers. */
if (event->val == KM_DBL_CLICK) {
event->val = KM_PRESS;
- *dbl_click_disabled = true;
+ event_backup->dbl_click_disabled = true;
}
}
}
@@ -2029,16 +2043,18 @@ static void wm_event_modalkeymap_begin(const bContext *C,
* better restore event type for checking of #KM_CLICK for example.
* Modal maps could use different method (ton).
*/
-static void wm_event_modalkeymap_end(wmEvent *event, bool dbl_click_disabled)
+static void wm_event_modalkeymap_end(wmEvent *event,
+ const struct wmEvent_ModalMapStore *event_backup)
{
if (event->type == EVT_MODAL_MAP) {
event->type = event->prevtype;
- event->prevtype = 0;
event->val = event->prevval;
- event->prevval = 0;
+
+ event->prevtype = event_backup->prevtype;
+ event->prevval = event_backup->prevval;
}
- if (dbl_click_disabled) {
+ if (event_backup->dbl_click_disabled) {
event->val = KM_DBL_CLICK;
}
}
@@ -2070,11 +2086,12 @@ static int wm_handler_operator_call(bContext *C,
wmWindowManager *wm = CTX_wm_manager(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- bool dbl_click_disabled = false;
wm_handler_op_context(C, handler, event);
wm_region_mouse_co(C, event);
- wm_event_modalkeymap_begin(C, op, event, &dbl_click_disabled);
+
+ struct wmEvent_ModalMapStore event_backup;
+ wm_event_modalkeymap_begin(C, op, event, &event_backup);
if (ot->flag & OPTYPE_UNDO) {
wm->op_undo_depth++;
@@ -2089,7 +2106,7 @@ static int wm_handler_operator_call(bContext *C,
* the event, operator etc have all been freed. - campbell */
if (CTX_wm_manager(C) == wm) {
- wm_event_modalkeymap_end(event, dbl_click_disabled);
+ wm_event_modalkeymap_end(event, &event_backup);
if (ot->flag & OPTYPE_UNDO) {
wm->op_undo_depth--;
@@ -2326,7 +2343,7 @@ static int wm_handler_fileselect_do(bContext *C,
wm_window_make_drawable(wm, ctx_win);
/* Ensure correct cursor position, otherwise, popups may close immediately after
* opening (UI_BLOCK_MOVEMOUSE_QUIT). */
- wm_get_cursor_position(ctx_win, &ctx_win->eventstate->x, &ctx_win->eventstate->y);
+ wm_cursor_position_get(ctx_win, &ctx_win->eventstate->x, &ctx_win->eventstate->y);
wm->winactive = ctx_win; /* Reports use this... */
if (handler->context.win == win) {
handler->context.win = NULL;
@@ -2934,27 +2951,26 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
{
int action = wm_handlers_do_intern(C, event, handlers);
- /* Fileread case. */
- if (CTX_wm_window(C) == NULL) {
+ /* Will be NULL in the file read case. */
+ wmWindow *win = CTX_wm_window(C);
+ if (win == NULL) {
return action;
}
if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
-
/* Test for CLICK_DRAG events. */
if (wm_action_not_handled(action)) {
- if (event->check_drag) {
- wmWindow *win = CTX_wm_window(C);
- if (WM_event_drag_test(event, &win->eventstate->prevclickx)) {
+ if (win->event_queue_check_drag) {
+ if (WM_event_drag_test(event, &event->prevclickx)) {
int x = event->x;
int y = event->y;
short val = event->val;
short type = event->type;
- event->x = win->eventstate->prevclickx;
- event->y = win->eventstate->prevclicky;
+ event->x = event->prevclickx;
+ event->y = event->prevclicky;
event->val = KM_CLICK_DRAG;
- event->type = win->eventstate->type;
+ event->type = event->prevtype;
CLOG_INFO(WM_LOG_HANDLERS, 1, "handling PRESS_DRAG");
@@ -2965,16 +2981,16 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
event->x = x;
event->y = y;
- win->eventstate->check_click = false;
- win->eventstate->check_drag = false;
+ win->event_queue_check_click = false;
+ if (!wm_action_not_handled(action)) {
+ /* Only disable when handled as other handlers may use this drag event. */
+ win->event_queue_check_drag = false;
+ }
}
}
}
else {
- wmWindow *win = CTX_wm_window(C);
- if (win) {
- win->eventstate->check_drag = false;
- }
+ win->event_queue_check_drag = false;
}
}
else if (ISMOUSE_BUTTON(event->type) || ISKEYBOARD(event->type)) {
@@ -2982,46 +2998,47 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
/* Test for CLICK events. */
if (wm_action_not_handled(action)) {
- wmWindow *win = CTX_wm_window(C);
-
/* eventstate stores if previous event was a KM_PRESS, in case that
* wasn't handled, the KM_RELEASE will become a KM_CLICK */
- if (win != NULL) {
- if (event->val == KM_PRESS) {
- win->eventstate->check_click = true;
- win->eventstate->check_drag = true;
- }
- else if (event->val == KM_RELEASE) {
- win->eventstate->check_drag = false;
+ if (event->val == KM_PRESS) {
+ if (event->prevval != KM_PRESS) {
+ win->event_queue_check_click = true;
+ win->event_queue_check_drag = true;
}
}
+ else if (event->val == KM_RELEASE) {
+ win->event_queue_check_drag = false;
+ }
- if (win && win->eventstate->prevtype == event->type) {
+ if (event->prevtype == event->type) {
- if ((event->val == KM_RELEASE) && (win->eventstate->prevval == KM_PRESS) &&
- (win->eventstate->check_click == true)) {
- if (WM_event_drag_test(event, &win->eventstate->prevclickx)) {
- win->eventstate->check_click = 0;
- win->eventstate->check_drag = 0;
- }
- else {
- /* Position is where the actual click happens, for more
- * accurate selecting in case the mouse drifts a little. */
- int x = event->x;
- int y = event->y;
+ if (event->val == KM_RELEASE) {
+ if (event->prevval == KM_PRESS) {
+ if (win->event_queue_check_click == true) {
+ if (WM_event_drag_test(event, &event->prevclickx)) {
+ win->event_queue_check_click = false;
+ win->event_queue_check_drag = false;
+ }
+ else {
+ /* Position is where the actual click happens, for more
+ * accurate selecting in case the mouse drifts a little. */
+ int x = event->x;
+ int y = event->y;
- event->x = win->eventstate->prevclickx;
- event->y = win->eventstate->prevclicky;
- event->val = KM_CLICK;
+ event->x = event->prevclickx;
+ event->y = event->prevclicky;
+ event->val = KM_CLICK;
- CLOG_INFO(WM_LOG_HANDLERS, 1, "handling CLICK");
+ CLOG_INFO(WM_LOG_HANDLERS, 1, "handling CLICK");
- action |= wm_handlers_do_intern(C, event, handlers);
+ action |= wm_handlers_do_intern(C, event, handlers);
- event->val = KM_RELEASE;
- event->x = x;
- event->y = y;
+ event->val = KM_RELEASE;
+ event->x = x;
+ event->y = y;
+ }
+ }
}
}
else if (event->val == KM_DBL_CLICK) {
@@ -3037,11 +3054,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
}
}
else {
- wmWindow *win = CTX_wm_window(C);
- if (win) {
- win->eventstate->check_click = 0;
- win->eventstate->check_drag = 0;
- }
+ win->event_queue_check_click = false;
+ win->event_queue_check_drag = false;
}
}
else if (ISMOUSE_WHEEL(event->type) || ISMOUSE_GESTURE(event->type)) {
@@ -3051,11 +3065,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
/* pass */
}
else {
- wmWindow *win = CTX_wm_window(C);
- if (win) {
- if (ISKEYMODIFIER(win->eventstate->type)) {
- win->eventstate->check_click = 0;
- }
+ if (ISKEYMODIFIER(event->prevtype)) {
+ win->event_queue_check_click = false;
}
}
}
@@ -3201,9 +3212,9 @@ static void wm_event_drag_and_drop_test(wmWindowManager *wm, wmWindow *win, wmEv
/* Filter out all events of the pie that spawned the last pie unless it's a release event. */
static bool wm_event_pie_filter(wmWindow *win, const wmEvent *event)
{
- if (win->lock_pie_event && win->lock_pie_event == event->type) {
+ if (win->pie_event_type_lock && win->pie_event_type_lock == event->type) {
if (event->val == KM_RELEASE) {
- win->lock_pie_event = EVENT_NONE;
+ win->pie_event_type_lock = EVENT_NONE;
return false;
}
return true;
@@ -3214,7 +3225,7 @@ static bool wm_event_pie_filter(wmWindow *win, const wmEvent *event)
/**
* Account for the special case when events are being handled and a file is loaded.
* In this case event handling exits early, however when "Load UI" is disabled
- * the even will still be in #wmWindow.queue.
+ * the even will still be in #wmWindow.event_queue.
*
* Without this it's possible to continuously handle the same event, see: T76484.
*/
@@ -3222,7 +3233,7 @@ static void wm_event_free_and_remove_from_queue_if_valid(wmEvent *event)
{
LISTBASE_FOREACH (wmWindowManager *, wm, &G_MAIN->wm) {
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
- if (BLI_remlink_safe(&win->queue, event)) {
+ if (BLI_remlink_safe(&win->event_queue, event)) {
wm_event_free(event);
return;
}
@@ -3311,7 +3322,7 @@ void wm_event_do_handlers(bContext *C)
}
wmEvent *event;
- while ((event = win->queue.first)) {
+ while ((event = win->event_queue.first)) {
int action = WM_HANDLER_CONTINUE;
/* Active screen might change during handlers, update pointer. */
@@ -3328,7 +3339,7 @@ void wm_event_do_handlers(bContext *C)
if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
CLOG_INFO(WM_LOG_HANDLERS, 1, "event filtered due to pie button pressed");
}
- BLI_remlink(&win->queue, event);
+ BLI_remlink(&win->event_queue, event);
wm_event_free(event);
continue;
}
@@ -3477,7 +3488,7 @@ void wm_event_do_handlers(bContext *C)
* press in tool keymap can override click in editor keymap.*/
if (ISMOUSE_BUTTON(event->type) && event->val == KM_PRESS &&
!wm_action_not_handled(action)) {
- win->eventstate->check_click = false;
+ win->event_queue_check_click = false;
}
/* Update previous mouse position for following events to use. */
@@ -3485,11 +3496,11 @@ void wm_event_do_handlers(bContext *C)
win->eventstate->prevy = event->y;
/* Unlink and free here, blender-quit then frees all. */
- BLI_remlink(&win->queue, event);
+ BLI_remlink(&win->event_queue, event);
wm_event_free(event);
}
- /* Only add mousemove when queue was read entirely. */
+ /* Only add mouse-move when the event queue was read entirely. */
if (win->addmousemove && win->eventstate) {
wmEvent tevent = *(win->eventstate);
// printf("adding MOUSEMOVE %d %d\n", tevent.x, tevent.y);
@@ -4330,25 +4341,25 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
}
}
- wmWindow *owin;
- if (WM_window_find_under_cursor(wm, win, win, mval, &owin, mval)) {
+ wmWindow *win_other;
+ if (WM_window_find_under_cursor(wm, win, win, mval, &win_other, mval)) {
event->x = mval[0];
event->y = mval[1];
- return owin;
+ return win_other;
}
}
return NULL;
}
-static bool wm_event_is_double_click(const wmEvent *event, const wmEvent *event_state)
+static bool wm_event_is_double_click(const wmEvent *event)
{
- if ((event->type == event_state->prevtype) && (event_state->prevval == KM_RELEASE) &&
+ if ((event->type == event->prevtype) && (event->prevval == KM_RELEASE) &&
(event->val == KM_PRESS)) {
- if (ISMOUSE(event->type) && WM_event_drag_test(event, &event_state->prevclickx)) {
+ if (ISMOUSE(event->type) && WM_event_drag_test(event, &event->prevclickx)) {
/* Pass. */
}
else {
- if ((PIL_check_seconds_timer() - event_state->prevclicktime) * 1000 < U.dbl_click_time) {
+ if ((PIL_check_seconds_timer() - event->prevclicktime) * 1000 < U.dbl_click_time) {
return true;
}
}
@@ -4357,9 +4368,25 @@ static bool wm_event_is_double_click(const wmEvent *event, const wmEvent *event_
return false;
}
+/**
+ * Copy the current state to the previous event state.
+ */
+static void wm_event_prev_values_set(wmEvent *event, wmEvent *event_state)
+{
+ event->prevval = event_state->prevval = event_state->val;
+ event->prevtype = event_state->prevtype = event_state->type;
+}
+
+static void wm_event_prev_click_set(wmEvent *event, wmEvent *event_state)
+{
+ event->prevclicktime = event_state->prevclicktime = PIL_check_seconds_timer();
+ event->prevclickx = event_state->prevclickx = event_state->x;
+ event->prevclicky = event_state->prevclicky = event_state->y;
+}
+
static wmEvent *wm_event_add_mousemove(wmWindow *win, const wmEvent *event)
{
- wmEvent *event_last = win->queue.last;
+ wmEvent *event_last = win->event_queue.last;
/* Some painting operators want accurate mouse events, they can
* handle in between mouse move moves, others can happily ignore
@@ -4381,7 +4408,7 @@ static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int d
{
/* Ignore in between trackpad events for performance, we only need high accuracy
* for painting with mouse moves, for navigation using the accumulated value is ok. */
- wmEvent *event_last = win->queue.last;
+ wmEvent *event_last = win->event_queue.last;
if (event_last && event_last->type == event->type) {
deltax += event_last->x - event_last->prevx;
deltay += event_last->y - event_last->prevy;
@@ -4397,8 +4424,9 @@ static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int d
return event_new;
}
-/* Windows store own event queues, no bContext here. */
-/* Time is in 1000s of seconds, from Ghost. */
+/**
+ * Windows store own event queues #wmWindow.event_queue (no #bContext here).
+ */
void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void *customdata)
{
if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) {
@@ -4406,21 +4434,50 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
}
/**
- * Having both, \a event and \a evt, can be highly confusing to work with,
+ * Having both, \a event and \a event_state, can be highly confusing to work with,
* but is necessary for our current event system, so let's clear things up a bit:
*
* - Data added to event only will be handled immediately,
* but will not be copied to the next event.
- * - Data added to \a evt only stays,
+ * - Data added to \a event_state only stays,
* but is handled with the next event -> execution delay.
- * - Data added to event and \a evt stays and is handled immediately.
+ * - Data added to event and \a event_state stays and is handled immediately.
*/
- wmEvent event, *evt = win->eventstate;
+ wmEvent event, *event_state = win->eventstate;
/* Initialize and copy state (only mouse x y and modifiers). */
- event = *evt;
+ event = *event_state;
event.is_repeat = false;
+ /**
+ * Always support accessing the last key press/release. This is set from `win->eventstate`,
+ * so it will always be a valid event type to store in the previous state.
+ *
+ * Note that these values are intentionally _not_ set in the `win->eventstate`,
+ * as copying these values only makes sense when `win->eventstate->{val/type}` would be
+ * written to (which only happens for some kinds of events).
+ * If this was done it could leave `win->eventstate` previous and current value
+ * set to the same key press/release state which doesn't make sense.
+ */
+ event.prevtype = event.type;
+ event.prevval = event.val;
+
+ /* Ensure the event state is correct, any deviation from this may cause bugs. */
+#ifndef NDEBUG
+ if ((event_state->type || event_state->val) && /* Ignore cleared event state. */
+ !(ISMOUSE_BUTTON(event_state->type) || ISKEYBOARD(event_state->type))) {
+ CLOG_WARN(WM_LOG_HANDLERS,
+ "Non-keyboard/mouse button found in 'win->eventstate->type = %d'",
+ event_state->type);
+ }
+ if ((event_state->prevtype || event_state->prevval) && /* Ignore cleared event state. */
+ !(ISMOUSE_BUTTON(event_state->prevtype) || ISKEYBOARD(event_state->prevtype))) {
+ CLOG_WARN(WM_LOG_HANDLERS,
+ "Non-keyboard/mouse button found in 'win->eventstate->prevtype = %d'",
+ event_state->prevtype);
+ }
+#endif
+
switch (type) {
/* Mouse move, also to inactive window (X11 does this). */
case GHOST_kEventCursorMove: {
@@ -4430,31 +4487,29 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
wm_stereo3d_mouse_offset_apply(win, &event.x);
wm_tablet_data_from_ghost(&cd->tablet, &event.tablet);
- event.prevtype = event.type;
- event.prevval = event.val;
event.type = MOUSEMOVE;
{
wmEvent *event_new = wm_event_add_mousemove(win, &event);
- copy_v2_v2_int(&evt->x, &event_new->x);
- evt->tablet.is_motion_absolute = event_new->tablet.is_motion_absolute;
+ copy_v2_v2_int(&event_state->x, &event_new->x);
+ event_state->tablet.is_motion_absolute = event_new->tablet.is_motion_absolute;
}
/* Also add to other window if event is there, this makes overdraws disappear nicely. */
/* It remaps mousecoord to other window in event. */
- wmWindow *owin = wm_event_cursor_other_windows(wm, win, &event);
- if (owin) {
- wmEvent oevent, *oevt = owin->eventstate;
+ wmWindow *win_other = wm_event_cursor_other_windows(wm, win, &event);
+ if (win_other) {
+ wmEvent event_other = *win_other->eventstate;
- oevent = *oevt;
+ /* See comment for this operation on `event` for details. */
+ event_other.prevtype = event_other.type;
+ event_other.prevval = event_other.val;
- copy_v2_v2_int(&oevent.x, &event.x);
- oevent.prevtype = oevent.type;
- oevent.prevval = oevent.val;
- oevent.type = MOUSEMOVE;
+ copy_v2_v2_int(&event_other.x, &event.x);
+ event_other.type = MOUSEMOVE;
{
- wmEvent *event_new = wm_event_add_mousemove(owin, &oevent);
- copy_v2_v2_int(&oevt->x, &event_new->x);
- oevt->tablet.is_motion_absolute = event_new->tablet.is_motion_absolute;
+ wmEvent *event_new = wm_event_add_mousemove(win_other, &event_other);
+ copy_v2_v2_int(&win_other->eventstate->x, &event_new->x);
+ win_other->eventstate->tablet.is_motion_absolute = event_new->tablet.is_motion_absolute;
}
}
@@ -4480,8 +4535,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
break;
}
- event.x = evt->x = pd->x;
- event.y = evt->y = pd->y;
+ event.x = event_state->x = pd->x;
+ event.y = event_state->y = pd->y;
event.val = KM_NOTHING;
/* The direction is inverted from the device due to system preferences. */
@@ -4524,38 +4579,37 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
wm_tablet_data_from_ghost(&bd->tablet, &event.tablet);
wm_eventemulation(&event, false);
-
- /* Copy previous state to prev event state (two old!). */
- evt->prevval = evt->val;
- evt->prevtype = evt->type;
+ wm_event_prev_values_set(&event, event_state);
/* Copy to event state. */
- evt->val = event.val;
- evt->type = event.type;
+ event_state->val = event.val;
+ event_state->type = event.type;
/* Double click test. */
- if (wm_event_is_double_click(&event, evt)) {
+ if (wm_event_is_double_click(&event)) {
CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click");
event.val = KM_DBL_CLICK;
}
if (event.val == KM_PRESS) {
- evt->prevclicktime = PIL_check_seconds_timer();
- evt->prevclickx = event.x;
- evt->prevclicky = event.y;
+ wm_event_prev_click_set(&event, event_state);
}
/* Add to other window if event is there (not to both!). */
- wmWindow *owin = wm_event_cursor_other_windows(wm, win, &event);
- if (owin) {
- wmEvent oevent = *(owin->eventstate);
+ wmWindow *win_other = wm_event_cursor_other_windows(wm, win, &event);
+ if (win_other) {
+ wmEvent event_other = *win_other->eventstate;
- oevent.x = event.x;
- oevent.y = event.y;
- oevent.type = event.type;
- oevent.val = event.val;
- oevent.tablet = event.tablet;
+ /* See comment for this operation on `event` for details. */
+ event_other.prevtype = event_other.type;
+ event_other.prevval = event_other.val;
- wm_event_add(owin, &oevent);
+ copy_v2_v2_int(&event_other.x, &event.x);
+
+ event_other.type = event.type;
+ event_other.val = event.val;
+ event_other.tablet = event.tablet;
+
+ wm_event_add(win_other, &event_other);
}
else {
wm_event_add(win, &event);
@@ -4576,15 +4630,12 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE;
wm_eventemulation(&event, false);
-
- /* Copy previous state to prev event state (two old!). */
- evt->prevval = evt->val;
- evt->prevtype = evt->type;
+ wm_event_prev_values_set(&event, event_state);
/* Copy to event state. */
- evt->val = event.val;
- evt->type = event.type;
- evt->is_repeat = event.is_repeat;
+ event_state->val = event.val;
+ event_state->type = event.type;
+ event_state->is_repeat = event.is_repeat;
/* Exclude arrow keys, esc, etc from text input. */
if (type == GHOST_kEventKeyUp) {
@@ -4620,64 +4671,64 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
case EVT_LEFTSHIFTKEY:
case EVT_RIGHTSHIFTKEY:
if (event.val == KM_PRESS) {
- if (evt->ctrl || evt->alt || evt->oskey) {
+ if (event_state->ctrl || event_state->alt || event_state->oskey) {
keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
}
else {
keymodifier = KM_MOD_FIRST;
}
}
- event.shift = evt->shift = keymodifier;
+ event.shift = event_state->shift = keymodifier;
break;
case EVT_LEFTCTRLKEY:
case EVT_RIGHTCTRLKEY:
if (event.val == KM_PRESS) {
- if (evt->shift || evt->alt || evt->oskey) {
+ if (event_state->shift || event_state->alt || event_state->oskey) {
keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
}
else {
keymodifier = KM_MOD_FIRST;
}
}
- event.ctrl = evt->ctrl = keymodifier;
+ event.ctrl = event_state->ctrl = keymodifier;
break;
case EVT_LEFTALTKEY:
case EVT_RIGHTALTKEY:
if (event.val == KM_PRESS) {
- if (evt->ctrl || evt->shift || evt->oskey) {
+ if (event_state->ctrl || event_state->shift || event_state->oskey) {
keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
}
else {
keymodifier = KM_MOD_FIRST;
}
}
- event.alt = evt->alt = keymodifier;
+ event.alt = event_state->alt = keymodifier;
break;
case EVT_OSKEY:
if (event.val == KM_PRESS) {
- if (evt->ctrl || evt->alt || evt->shift) {
+ if (event_state->ctrl || event_state->alt || event_state->shift) {
keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
}
else {
keymodifier = KM_MOD_FIRST;
}
}
- event.oskey = evt->oskey = keymodifier;
+ event.oskey = event_state->oskey = keymodifier;
break;
default:
if (event.val == KM_PRESS && event.keymodifier == 0) {
/* Only set in eventstate, for next event. */
- evt->keymodifier = event.type;
+ event_state->keymodifier = event.type;
}
else if (event.val == KM_RELEASE && event.keymodifier == event.type) {
- event.keymodifier = evt->keymodifier = 0;
+ event.keymodifier = event_state->keymodifier = 0;
}
break;
}
/* Double click test. */
/* If previous event was same type, and previous was release, and now it presses... */
- if (wm_event_is_double_click(&event, evt)) {
+ if (wm_event_is_double_click(&event)) {
CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click");
event.val = KM_DBL_CLICK;
}
@@ -4693,7 +4744,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
* Since it's impossible to map a key modifier to an unknown key,
* it shouldn't harm to clear it. */
if (event.keymodifier == EVT_UNKNOWNKEY) {
- evt->keymodifier = event.keymodifier = 0;
+ event_state->keymodifier = event.keymodifier = 0;
}
/* If test_break set, it catches this. Do not set with modifier presses.
@@ -4707,10 +4758,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
/* Double click test - only for press. */
if (event.val == KM_PRESS) {
/* Don't reset timer & location when holding the key generates repeat events. */
- if ((evt->prevtype != event.type) || (evt->prevval != KM_PRESS)) {
- evt->prevclicktime = PIL_check_seconds_timer();
- evt->prevclickx = event.x;
- evt->prevclicky = event.y;
+ if (event.is_repeat == false) {
+ wm_event_prev_click_set(&event, event_state);
}
}
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index d2d080a9a68..13f3afdfc4c 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -711,7 +711,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* so we can get the error message */
errno = 0;
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
wm_file_read_pre(C, use_data, use_userdef);
@@ -809,7 +809,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
}
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
return success;
}
@@ -1498,7 +1498,7 @@ static bool wm_file_write(bContext *C,
}
/* don't forget not to return without! */
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
ED_editors_flush_edits(bmain);
@@ -1560,7 +1560,7 @@ static bool wm_file_write(bContext *C,
MEM_freeN(thumb);
}
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
return ok;
}
@@ -1776,7 +1776,12 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
filepath,
fileflags,
&(const struct BlendFileWriteParams){
- .remap_mode = BLO_WRITE_PATH_REMAP_RELATIVE,
+ /* Make all paths absolute when saving the startup file.
+ * On load the `G.relbase_valid` will be false so the paths
+ * wont have a base for resolving the relative paths. */
+ .remap_mode = BLO_WRITE_PATH_REMAP_ABSOLUTE,
+ /* Don't apply any path changes to the current blend file. */
+ .use_save_as_copy = true,
},
op->reports) == 0) {
printf("fail\n");
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index d4495821672..6a1fc84774c 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -804,7 +804,7 @@ static void lib_relocate_do(Main *bmain,
ReportList *reports,
const bool do_reload)
{
- ListBase *lbarray[MAX_LIBARRAY];
+ ListBase *lbarray[INDEX_ID_MAX];
int lba_idx;
LinkNode *itemlink;
diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c
index aeab1ee6fca..ba236988c1d 100644
--- a/source/blender/windowmanager/intern/wm_operator_props.c
+++ b/source/blender/windowmanager/intern/wm_operator_props.c
@@ -291,7 +291,7 @@ void WM_operator_properties_select_random(wmOperatorType *ot)
1.0f,
"Ratio",
"Portion of items to select randomly",
- 0.f,
+ 0.0f,
1.0f);
RNA_def_int(ot->srna,
"seed",
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index f96c45f8a05..660e502a3d7 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1809,7 +1809,7 @@ static void WM_OT_call_menu(wmOperatorType *ot)
{
ot->name = "Call Menu";
ot->idname = "WM_OT_call_menu";
- ot->description = "Call (draw) a predefined menu";
+ ot->description = "Open a predefined menu";
ot->exec = wm_call_menu_exec;
ot->poll = WM_operator_winactive;
@@ -1840,7 +1840,7 @@ static void WM_OT_call_menu_pie(wmOperatorType *ot)
{
ot->name = "Call Pie Menu";
ot->idname = "WM_OT_call_menu_pie";
- ot->description = "Call (draw) a predefined pie menu";
+ ot->description = "Open a predefined pie menu";
ot->invoke = wm_call_pie_menu_invoke;
ot->exec = wm_call_pie_menu_exec;
@@ -1874,7 +1874,7 @@ static void WM_OT_call_panel(wmOperatorType *ot)
{
ot->name = "Call Panel";
ot->idname = "WM_OT_call_panel";
- ot->description = "Call (draw) a predefined panel";
+ ot->description = "Open a predefined panel";
ot->exec = wm_call_panel_exec;
ot->poll = WM_operator_winactive;
@@ -2046,7 +2046,7 @@ wmPaintCursor *WM_paint_cursor_activate(short space_type,
bool WM_paint_cursor_end(wmPaintCursor *handle)
{
wmWindowManager *wm = G_MAIN->wm.first;
- for (wmPaintCursor *pc = wm->paintcursors.first; pc; pc = pc->next) {
+ LISTBASE_FOREACH (wmPaintCursor *, pc, &wm->paintcursors) {
if (pc == (wmPaintCursor *)handle) {
BLI_remlink(&wm->paintcursors, pc);
MEM_freeN(pc);
@@ -2058,9 +2058,7 @@ bool WM_paint_cursor_end(wmPaintCursor *handle)
void WM_paint_cursor_remove_by_type(wmWindowManager *wm, void *draw_fn, void (*free)(void *))
{
- wmPaintCursor *pc = wm->paintcursors.first;
- while (pc) {
- wmPaintCursor *pc_next = pc->next;
+ LISTBASE_FOREACH_MUTABLE (wmPaintCursor *, pc, &wm->paintcursors) {
if (pc->draw == draw_fn) {
if (free) {
free(pc->customdata);
@@ -2068,7 +2066,6 @@ void WM_paint_cursor_remove_by_type(wmWindowManager *wm, void *draw_fn, void (*f
BLI_remlink(&wm->paintcursors, pc);
MEM_freeN(pc);
}
- pc = pc_next;
}
}
@@ -3237,7 +3234,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
*/
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- WM_cursor_wait(1);
+ WM_cursor_wait(true);
double time_start = PIL_check_seconds_timer();
@@ -3260,7 +3257,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
RNA_enum_description(redraw_timer_type_items, type, &infostr);
- WM_cursor_wait(0);
+ WM_cursor_wait(false);
BKE_reportf(op->reports,
RPT_WARNING,
diff --git a/source/blender/windowmanager/intern/wm_platform_support.c b/source/blender/windowmanager/intern/wm_platform_support.c
index 65e1cd45e02..45618e9d6d3 100644
--- a/source/blender/windowmanager/intern/wm_platform_support.c
+++ b/source/blender/windowmanager/intern/wm_platform_support.c
@@ -43,7 +43,9 @@
#define WM_PLATFORM_SUPPORT_TEXT_SIZE 1024
-/* Check if user has already approved the given platform_support_key. */
+/**
+ * Check if user has already approved the given `platform_support_key`.
+ */
static bool wm_platform_support_check_approval(const char *platform_support_key, bool update)
{
const char *const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
@@ -120,11 +122,11 @@ bool WM_platform_support_perform_checks()
eGPUSupportLevel support_level = GPU_platform_support_level();
const char *platform_key = GPU_platform_support_level_key();
- /* check if previous check matches the current check. Don't update the approval when running in
- * `background`. this could have been triggered by installing addons via installers. */
+ /* Check if previous check matches the current check. Don't update the approval when running in
+ * `background`. this could have been triggered by installing add-ons via installers. */
if (support_level != GPU_SUPPORT_LEVEL_UNSUPPORTED && !G.factory_startup &&
wm_platform_support_check_approval(platform_key, !G.background)) {
- /* if it matches the user has confirmed and whishes to use it */
+ /* If it matches the user has confirmed and wishes to use it. */
return result;
}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index ada4093080c..2fc941c3d6b 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -520,7 +520,7 @@ void WM_window_set_dpi(const wmWindow *win)
static void wm_window_update_eventstate(wmWindow *win)
{
/* Update mouse position when a window is activated. */
- wm_get_cursor_position(win, &win->eventstate->x, &win->eventstate->y);
+ wm_cursor_position_get(win, &win->eventstate->x, &win->eventstate->y);
}
static void wm_window_ensure_eventstate(wmWindow *win)
@@ -983,15 +983,15 @@ void wm_cursor_position_to_ghost(wmWindow *win, int *x, int *y)
GHOST_ClientToScreen(win->ghostwin, *x, *y, x, y);
}
-void wm_get_cursor_position(wmWindow *win, int *x, int *y)
+void wm_cursor_position_get(wmWindow *win, int *r_x, int *r_y)
{
if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) {
- *x = win->eventstate->x;
- *y = win->eventstate->y;
+ *r_x = win->eventstate->x;
+ *r_y = win->eventstate->y;
return;
}
- GHOST_GetCursorPosition(g_system, x, y);
- wm_cursor_position_from_ghost(win, x, y);
+ GHOST_GetCursorPosition(g_system, r_x, r_y);
+ wm_cursor_position_from_ghost(win, r_x, r_y);
}
typedef enum {
@@ -1691,7 +1691,7 @@ void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *
/* there might be events in queue with this timer as customdata */
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
- LISTBASE_FOREACH (wmEvent *, event, &win->queue) {
+ LISTBASE_FOREACH (wmEvent *, event, &win->event_queue) {
if (event->customdata == wt) {
event->customdata = NULL;
event->type = EVENT_NONE; /* timer users customdata, dont want NULL == NULL */
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index 0ac67b987d7..f205f923ec8 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -69,8 +69,8 @@ void wm_window_swap_buffers(wmWindow *win);
void wm_window_set_swap_interval(wmWindow *win, int interval);
bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut);
-void wm_get_cursor_position(wmWindow *win, int *x, int *y);
-void wm_cursor_position_from_ghost(wmWindow *win, int *x, int *y);
+void wm_cursor_position_get(wmWindow *win, int *r_x, int *r_y);
+void wm_cursor_position_from_ghost(wmWindow *win, int *r_x, int *r_y);
void wm_cursor_position_to_ghost(wmWindow *win, int *x, int *y);
#ifdef WITH_INPUT_IME
diff --git a/source/creator/creator.c b/source/creator/creator.c
index fbc97028d35..b40718d1f7c 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -47,7 +47,7 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-/* Mostly init functions. */
+/* Mostly initialization functions. */
#include "BKE_appdir.h"
#include "BKE_blender.h"
#include "BKE_brush.h"
@@ -109,8 +109,6 @@
#include "creator_intern.h" /* Own include. */
-/* Local Function prototypes. */
-
/* -------------------------------------------------------------------- */
/** \name Local Application State
* \{ */
@@ -264,7 +262,7 @@ int main(int argc,
# endif
/* Win32 Unicode Arguments. */
- /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
+ /* NOTE: cannot use `guardedalloc` allocation here, as it's not yet initialized
* (it depends on the arguments passed in, which is what we're getting here!)
*/
{
@@ -453,8 +451,8 @@ int main(int argc,
/* Background render uses this font too. */
BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);
- /* Initialize ffmpeg if built in, also needed for background-mode if videos are
- * rendered via ffmpeg. */
+ /* Initialize FFMPEG if built in, also needed for background-mode if videos are
+ * rendered via FFMPEG. */
BKE_sound_init_once();
BKE_materials_init();
@@ -524,7 +522,7 @@ int main(int argc,
#endif /* WITH_PYTHON_MODULE */
return 0;
-} /* End of int main(...) function. */
+} /* End of `int main(...)` function. */
#ifdef WITH_PYTHON_MODULE
void main_python_exit(void)
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index e31be24ec7b..0e0d66d40a9 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -84,6 +84,8 @@
# include "DEG_depsgraph_build.h"
# include "DEG_depsgraph_debug.h"
+# include "WM_types.h"
+
# include "creator_intern.h" /* own include */
/* -------------------------------------------------------------------- */
@@ -608,6 +610,7 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
printf("\n");
printf("Misc Options:\n");
+ BLI_args_print_arg_doc(ba, "--open-last");
BLI_args_print_arg_doc(ba, "--app-template");
BLI_args_print_arg_doc(ba, "--factory-startup");
BLI_args_print_arg_doc(ba, "--enable-event-simulate");
@@ -1146,7 +1149,7 @@ static const char arg_handle_env_system_set_doc_python[] =
static int arg_handle_env_system_set(int argc, const char **argv, void *UNUSED(data))
{
- /* "--env-system-scripts" --> "BLENDER_SYSTEM_SCRIPTS" */
+ /* `--env-system-scripts` -> `BLENDER_SYSTEM_SCRIPTS` */
char env[64] = "BLENDER";
char *ch_dst = env + 7; /* skip BLENDER */
@@ -1994,6 +1997,21 @@ static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
return 0;
}
+static const char arg_handle_load_last_file_doc[] =
+ "\n\t"
+ "Open the most recently opened blend file, instead of the default startup file.";
+static int arg_handle_load_last_file(int UNUSED(argc), const char **UNUSED(argv), void *data)
+{
+ if (BLI_listbase_is_empty(&G.recent_files)) {
+ printf("Warning: no recent files known, opening default startup file instead.\n");
+ return -1;
+ }
+
+ const RecentFile *recent_file = G.recent_files.first;
+ const char *fake_argv[] = {recent_file->filepath};
+ return arg_handle_load_file(ARRAY_SIZE(fake_argv), fake_argv, data);
+}
+
void main_args_setup(bContext *C, bArgs *ba)
{
@@ -2217,6 +2235,8 @@ void main_args_setup(bContext *C, bArgs *ba)
BLI_args_add(ba, "-F", "--render-format", CB(arg_handle_image_type_set), C);
BLI_args_add(ba, "-x", "--use-extension", CB(arg_handle_extension_set), C);
+ BLI_args_add(ba, NULL, "--open-last", CB(arg_handle_load_last_file), C);
+
# undef CB
# undef CB_EX
}
diff --git a/tests/gtests/runner/CMakeLists.txt b/tests/gtests/runner/CMakeLists.txt
index 1fe8cf21810..b18eff59016 100644
--- a/tests/gtests/runner/CMakeLists.txt
+++ b/tests/gtests/runner/CMakeLists.txt
@@ -82,6 +82,7 @@ elseif(APPLE)
# are used as dependencies of other test libraries.
foreach(_lib ${_test_libs})
list(REMOVE_ITEM _test_libs_dependencies ${_lib})
+ add_dependencies(blender_test ${_lib})
target_link_options(blender_test PRIVATE "LINKER:-force_load,$<TARGET_FILE:${_lib}>")
endforeach()
diff --git a/tests/python/bl_blendfile_io.py b/tests/python/bl_blendfile_io.py
index 2c27b60f34e..38b3a93bbbc 100644
--- a/tests/python/bl_blendfile_io.py
+++ b/tests/python/bl_blendfile_io.py
@@ -15,7 +15,8 @@ class TestBlendFileSaveLoadBasic(TestHelper):
self.args = args
def test_save_load(self):
- bpy.ops.wm.read_factory_settings()
+ bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
+
bpy.data.meshes.new("OrphanedMesh")
output_dir = self.args.output_dir
@@ -71,6 +72,9 @@ def argparse_create():
def main():
args = argparse_create().parse_args()
+ # Don't write thumbnails into the home directory.
+ bpy.context.preferences.filepaths.use_save_preview_images = False
+
for Test in TESTS:
Test(args).run_all_tests()
diff --git a/tests/python/bl_blendfile_liblink.py b/tests/python/bl_blendfile_liblink.py
index fc618314216..a5f2571c902 100644
--- a/tests/python/bl_blendfile_liblink.py
+++ b/tests/python/bl_blendfile_liblink.py
@@ -15,7 +15,9 @@ class TestBlendLibLinkSaveLoadBasic(TestHelper):
self.args = args
def test_link_save_load(self):
- bpy.ops.wm.read_factory_settings()
+
+ bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
+
me = bpy.data.meshes.new("LibMesh")
me.use_fake_user = True
@@ -26,7 +28,7 @@ class TestBlendLibLinkSaveLoadBasic(TestHelper):
bpy.ops.wm.save_as_mainfile(filepath=output_path, check_existing=False, compress=False)
- bpy.ops.wm.read_factory_settings()
+ bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True)
bpy.data.orphans_purge()
link_dir = os.path.join(output_path, "Mesh")
@@ -68,6 +70,9 @@ def argparse_create():
def main():
args = argparse_create().parse_args()
+ # Don't write thumbnails into the home directory.
+ bpy.context.preferences.filepaths.use_save_preview_images = False
+
for Test in TESTS:
Test(args).run_all_tests()