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:
authorJoshua Leung <aligorith@gmail.com>2015-12-12 07:43:00 +0300
committerJoshua Leung <aligorith@gmail.com>2015-12-12 07:43:00 +0300
commit50fde02b422a1a1dbc71a7bc95a061e46ce73b33 (patch)
tree631d2de1db5a6321241685f8015f740da64c7a85
parent85bbf7e04f2694a160219e07fb44711f157e6237 (diff)
parentdc98a3b0a74b0e91ad424195ce488a9b14f13e73 (diff)
Merge branch 'master' into GPencil_Editing_Stage3
Conflicts: source/blender/editors/transform/transform_manipulator.c
-rw-r--r--CMakeLists.txt63
-rw-r--r--SConstruct5
-rwxr-xr-xbuild_files/build_environment/install_deps.sh63
-rw-r--r--build_files/buildbot/config/blender_linux.cmake102
-rw-r--r--build_files/buildbot/config/blender_linux_player.cmake12
-rw-r--r--build_files/buildbot/config/user-config-cuda-glibc211-i686.py6
-rw-r--r--build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py5
-rw-r--r--build_files/buildbot/config/user-config-glibc211-i686.py185
-rw-r--r--build_files/buildbot/config/user-config-glibc211-x86_64.py185
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-i686.py126
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-x86_64.py126
-rw-r--r--build_files/buildbot/master.cfg11
-rw-r--r--build_files/buildbot/slave_compile.py252
-rw-r--r--build_files/buildbot/slave_pack.py252
-rw-r--r--build_files/buildbot/slave_test.py20
-rw-r--r--build_files/cmake/Modules/FindPythonLibsUnix.cmake4
-rw-r--r--build_files/cmake/cmake_consistency_check_config.py3
-rw-r--r--build_files/cmake/cmake_static_check_clang_array.py1
-rw-r--r--build_files/cmake/cmake_static_check_cppcheck.py1
-rw-r--r--build_files/cmake/cmake_static_check_smatch.py1
-rw-r--r--build_files/cmake/cmake_static_check_sparse.py1
-rw-r--r--build_files/cmake/cmake_static_check_splint.py1
-rw-r--r--build_files/cmake/config/blender_full.cmake2
-rw-r--r--build_files/cmake/config/blender_lite.cmake1
-rw-r--r--build_files/cmake/macros.cmake29
-rw-r--r--build_files/scons/Modules/FindPython.py2
-rw-r--r--build_files/scons/config/win32-mingw-config.py2
-rw-r--r--build_files/scons/config/win64-mingw-config.py2
-rw-r--r--doc/doxygen/doxygen.intern.h2
-rw-r--r--doc/python_api/rst/bge.logic.rst70
-rw-r--r--extern/CMakeLists.txt5
-rw-r--r--extern/Eigen3/Eigen/Core6
-rw-r--r--extern/Eigen3/Eigen/SparseCore2
-rw-r--r--extern/Eigen3/Eigen/src/Cholesky/LDLT.h61
-rw-r--r--extern/Eigen3/Eigen/src/Cholesky/LLT.h10
-rw-r--r--extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h2
-rw-r--r--extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h10
-rw-r--r--extern/Eigen3/Eigen/src/Core/Array.h15
-rw-r--r--extern/Eigen3/Eigen/src/Core/ArrayBase.h4
-rw-r--r--extern/Eigen3/Eigen/src/Core/ArrayWrapper.h10
-rw-r--r--extern/Eigen3/Eigen/src/Core/Assign.h15
-rw-r--r--extern/Eigen3/Eigen/src/Core/Block.h7
-rw-r--r--extern/Eigen3/Eigen/src/Core/CommaInitializer.h11
-rw-r--r--extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h3
-rw-r--r--extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h2
-rw-r--r--extern/Eigen3/Eigen/src/Core/DenseBase.h28
-rw-r--r--extern/Eigen3/Eigen/src/Core/DenseStorage.h271
-rw-r--r--extern/Eigen3/Eigen/src/Core/Diagonal.h8
-rw-r--r--extern/Eigen3/Eigen/src/Core/DiagonalProduct.h5
-rw-r--r--extern/Eigen3/Eigen/src/Core/Functors.h45
-rw-r--r--extern/Eigen3/Eigen/src/Core/GeneralProduct.h14
-rw-r--r--extern/Eigen3/Eigen/src/Core/MapBase.h13
-rw-r--r--extern/Eigen3/Eigen/src/Core/MathFunctions.h2
-rw-r--r--extern/Eigen3/Eigen/src/Core/Matrix.h15
-rw-r--r--extern/Eigen3/Eigen/src/Core/MatrixBase.h27
-rw-r--r--extern/Eigen3/Eigen/src/Core/PermutationMatrix.h34
-rw-r--r--extern/Eigen3/Eigen/src/Core/PlainObjectBase.h32
-rw-r--r--extern/Eigen3/Eigen/src/Core/ProductBase.h14
-rw-r--r--extern/Eigen3/Eigen/src/Core/Redux.h5
-rw-r--r--extern/Eigen3/Eigen/src/Core/Ref.h38
-rw-r--r--extern/Eigen3/Eigen/src/Core/Replicate.h4
-rw-r--r--extern/Eigen3/Eigen/src/Core/ReturnByValue.h11
-rw-r--r--extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h10
-rw-r--r--extern/Eigen3/Eigen/src/Core/TriangularMatrix.h29
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h2
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h20
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h14
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h79
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h6
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/Parallelizer.h17
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h4
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h9
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/Constants.h13
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h3
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/MKL_support.h51
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/Macros.h40
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/Memory.h27
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/StaticAssert.h4
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/XprHelper.h10
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h1
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h8
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h9
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h9
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/RealQZ.h14
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h12
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h227
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/AlignedBox.h85
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/AngleAxis.h6
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Homogeneous.h2
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Hyperplane.h12
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Quaternion.h34
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Rotation2D.h7
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Transform.h33
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Umeyama.h10
-rw-r--r--extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h2
-rw-r--r--extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h4
-rw-r--r--extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h24
-rw-r--r--extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h33
-rw-r--r--extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h25
-rw-r--r--extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h48
-rw-r--r--extern/Eigen3/Eigen/src/LU/FullPivLU.h21
-rw-r--r--extern/Eigen3/Eigen/src/LU/PartialPivLU.h8
-rw-r--r--extern/Eigen3/Eigen/src/OrderingMethods/Amd.h19
-rw-r--r--extern/Eigen3/Eigen/src/OrderingMethods/Ordering.h12
-rw-r--r--extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h2
-rw-r--r--extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h35
-rw-r--r--extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h8
-rw-r--r--extern/Eigen3/Eigen/src/QR/HouseholderQR.h98
-rw-r--r--extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h30
-rw-r--r--extern/Eigen3/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h64
-rw-r--r--extern/Eigen3/Eigen/src/SVD/JacobiSVD.h130
-rw-r--r--extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h42
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h4
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h8
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h136
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h7
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h44
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h17
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h44
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h2
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h10
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h7
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/SparseVector.h1
-rw-r--r--extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h2
-rw-r--r--extern/Eigen3/Eigen/src/SparseLU/SparseLU.h90
-rw-r--r--extern/Eigen3/Eigen/src/SparseLU/SparseLUImpl.h2
-rw-r--r--extern/Eigen3/Eigen/src/SparseLU/SparseLU_Memory.h4
-rw-r--r--extern/Eigen3/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h12
-rw-r--r--extern/Eigen3/Eigen/src/SparseLU/SparseLU_column_bmod.h4
-rw-r--r--extern/Eigen3/Eigen/src/SparseLU/SparseLU_kernel_bmod.h4
-rw-r--r--extern/Eigen3/Eigen/src/SparseLU/SparseLU_panel_bmod.h8
-rw-r--r--extern/Eigen3/Eigen/src/SparseLU/SparseLU_pivotL.h13
-rw-r--r--extern/Eigen3/Eigen/src/SparseQR/SparseQR.h191
-rw-r--r--extern/Eigen3/Eigen/src/StlSupport/StdDeque.h2
-rw-r--r--extern/Eigen3/Eigen/src/StlSupport/StdList.h2
-rw-r--r--extern/Eigen3/Eigen/src/StlSupport/StdVector.h2
-rw-r--r--extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h112
-rw-r--r--extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h54
-rw-r--r--extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h16
-rw-r--r--extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h17
-rw-r--r--extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h15
-rwxr-xr-xextern/Eigen3/eigen-update.sh2
-rw-r--r--extern/SConscript2
-rw-r--r--extern/colamd/CMakeLists.txt41
-rw-r--r--extern/colamd/Doc/ChangeLog129
-rw-r--r--extern/colamd/Doc/lesser.txt504
-rw-r--r--extern/colamd/Include/UFconfig.h118
-rw-r--r--extern/colamd/Include/colamd.h255
-rw-r--r--extern/colamd/README.txt127
-rw-r--r--extern/colamd/SConscript14
-rw-r--r--extern/colamd/Source/colamd.c3611
-rw-r--r--extern/colamd/Source/colamd_global.c24
-rw-r--r--extern/cuew/auto/cuda_extra.py2
-rw-r--r--extern/cuew/auto/cuew_gen.py9
-rw-r--r--extern/cuew/include/cuew.h66
-rw-r--r--extern/cuew/src/cuew.c99
-rw-r--r--extern/libmv/libmv/simple_pipeline/camera_intrinsics.h4
-rw-r--r--intern/CMakeLists.txt5
-rw-r--r--intern/SConscript2
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp4
-rw-r--r--intern/cycles/blender/blender_shader.cpp71
-rw-r--r--intern/cycles/blender/blender_util.h50
-rw-r--r--intern/cycles/device/device_cuda.cpp7
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh.h2
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h6
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h17
-rw-r--r--intern/cycles/kernel/kernel_bake.h5
-rw-r--r--intern/cycles/kernel/kernel_emission.h20
-rw-r--r--intern/cycles/kernel/kernel_path.h107
-rw-r--r--intern/cycles/kernel/kernel_shader.h46
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h8
-rw-r--r--intern/cycles/kernel/kernel_types.h9
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel.cu4
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt2
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_curves.osl25
-rw-r--r--intern/cycles/kernel/svm/svm_ramp.h49
-rw-r--r--intern/cycles/render/graph.cpp93
-rw-r--r--intern/cycles/render/graph.h13
-rw-r--r--intern/cycles/render/nodes.cpp144
-rw-r--r--intern/cycles/render/nodes.h14
-rw-r--r--intern/cycles/render/scene.h3
-rw-r--r--intern/cycles/render/svm.cpp10
-rw-r--r--intern/cycles/util/CMakeLists.txt1
-rw-r--r--intern/cycles/util/util_math.h6
-rw-r--r--intern/cycles/util/util_math_fast.h2
-rw-r--r--intern/cycles/util/util_queue.h29
-rw-r--r--intern/eigen/CMakeLists.txt (renamed from extern/Eigen3/CMakeLists.txt)7
-rw-r--r--intern/eigen/SConscript (renamed from extern/Eigen3/SConscript)4
-rw-r--r--intern/eigen/eigen_capi.h (renamed from extern/Eigen3/eigen3_capi.h)7
-rw-r--r--intern/eigen/intern/eigenvalues.cc (renamed from extern/Eigen3/intern/eigenvalues.cc)2
-rw-r--r--intern/eigen/intern/eigenvalues.h (renamed from extern/Eigen3/intern/eigenvalues.h)2
-rw-r--r--intern/eigen/intern/linear_solver.cc354
-rw-r--r--intern/eigen/intern/linear_solver.h71
-rw-r--r--intern/eigen/intern/svd.cc (renamed from extern/Eigen3/intern/svd.cc)5
-rw-r--r--intern/eigen/intern/svd.h (renamed from extern/Eigen3/intern/svd.h)2
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp18
-rw-r--r--intern/iksolver/CMakeLists.txt28
-rw-r--r--intern/iksolver/SConscript2
-rw-r--r--intern/iksolver/intern/IK_Math.h261
-rw-r--r--intern/iksolver/intern/IK_QJacobian.cpp208
-rw-r--r--intern/iksolver/intern/IK_QJacobian.h62
-rw-r--r--intern/iksolver/intern/IK_QJacobianSolver.cpp102
-rw-r--r--intern/iksolver/intern/IK_QJacobianSolver.h28
-rw-r--r--intern/iksolver/intern/IK_QSegment.cpp398
-rw-r--r--intern/iksolver/intern/IK_QSegment.h171
-rw-r--r--intern/iksolver/intern/IK_QTask.cpp71
-rw-r--r--intern/iksolver/intern/IK_QTask.h56
-rw-r--r--intern/iksolver/intern/IK_Solver.cpp70
-rw-r--r--intern/iksolver/intern/MT_ExpMap.cpp250
-rw-r--r--intern/iksolver/intern/MT_ExpMap.h213
-rw-r--r--intern/iksolver/intern/TNT/cholesky.h98
-rw-r--r--intern/iksolver/intern/TNT/cmat.h614
-rw-r--r--intern/iksolver/intern/TNT/fcscmat.h167
-rw-r--r--intern/iksolver/intern/TNT/fmat.h569
-rw-r--r--intern/iksolver/intern/TNT/fortran.h69
-rw-r--r--intern/iksolver/intern/TNT/fspvec.h171
-rw-r--r--intern/iksolver/intern/TNT/index.h87
-rw-r--r--intern/iksolver/intern/TNT/lapack.h189
-rw-r--r--intern/iksolver/intern/TNT/lu.h208
-rw-r--r--intern/iksolver/intern/TNT/qr.h233
-rw-r--r--intern/iksolver/intern/TNT/region1d.h375
-rw-r--r--intern/iksolver/intern/TNT/region2d.h471
-rw-r--r--intern/iksolver/intern/TNT/stopwatch.h83
-rw-r--r--intern/iksolver/intern/TNT/subscript.h63
-rw-r--r--intern/iksolver/intern/TNT/svd.h435
-rw-r--r--intern/iksolver/intern/TNT/tnt.h93
-rw-r--r--intern/iksolver/intern/TNT/tntmath.h154
-rw-r--r--intern/iksolver/intern/TNT/tntreqs.h73
-rw-r--r--intern/iksolver/intern/TNT/transv.h164
-rw-r--r--intern/iksolver/intern/TNT/triang.h637
-rw-r--r--intern/iksolver/intern/TNT/trisolve.h188
-rw-r--r--intern/iksolver/intern/TNT/vec.h491
-rw-r--r--intern/iksolver/intern/TNT/vecadaptor.h284
-rw-r--r--intern/iksolver/intern/TNT/version.h25
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp91
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutDrawer.h95
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp84
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h101
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp99
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h111
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h375
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h80
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h206
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/main.cpp321
-rw-r--r--intern/memutil/CMakeLists.txt3
-rw-r--r--intern/memutil/MEM_NonCopyable.h62
-rw-r--r--intern/memutil/MEM_RefCountPtr.h297
-rw-r--r--intern/memutil/MEM_SmartPtr.h245
-rw-r--r--intern/moto/CMakeLists.txt6
-rw-r--r--intern/moto/include/GEN_List.h87
-rw-r--r--intern/moto/include/GEN_Map.h181
-rw-r--r--intern/moto/include/MT_Plane3.h137
-rw-r--r--intern/moto/include/MT_Plane3.inl128
-rw-r--r--intern/moto/include/MT_Scalar.h1
-rw-r--r--intern/moto/include/NM_Scalar.h159
-rw-r--r--intern/moto/intern/MT_Plane3.cpp37
-rw-r--r--intern/opennl/CMakeLists.txt58
-rw-r--r--intern/opennl/SConscript35
-rw-r--r--intern/opennl/extern/ONL_opennl.h113
-rw-r--r--intern/opennl/intern/opennl.cpp479
-rw-r--r--intern/opensubdiv/gpu_shader_opensubd_display.glsl3
-rw-r--r--intern/opensubdiv/opensubdiv_capi.cc7
-rw-r--r--intern/opensubdiv/opensubdiv_capi.h2
-rw-r--r--intern/opensubdiv/opensubdiv_gpu_capi.cc49
-rw-r--r--intern/opensubdiv/opensubdiv_utils_capi.cc3
-rw-r--r--release/scripts/modules/bpy_extras/keyconfig_utils.py31
-rw-r--r--release/scripts/modules/bpy_types.py4
-rw-r--r--release/scripts/modules/rna_prop_ui.py3
-rw-r--r--release/scripts/startup/bl_operators/presets.py16
-rw-r--r--release/scripts/startup/bl_operators/rigidbody.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py9
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py8
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py1
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py1
-rw-r--r--release/scripts/templates_py/operator_modal_view3d_raycast.py15
-rw-r--r--source/blender/blenfont/intern/blf.c38
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c6
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h3
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_image.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h2
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h4
-rw-r--r--source/blender/blenkernel/BKE_screen.h1
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h1
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c6
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c7
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c8
-rw-r--r--source/blender/blenkernel/intern/icons.c2
-rw-r--r--source/blender/blenkernel/intern/image.c17
-rw-r--r--source/blender/blenkernel/intern/library.c4
-rw-r--r--source/blender/blenkernel/intern/library_query.c10
-rw-r--r--source/blender/blenkernel/intern/multires.c4
-rw-r--r--source/blender/blenkernel/intern/ocean.c470
-rw-r--r--source/blender/blenkernel/intern/pbvh.c271
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c378
-rw-r--r--source/blender/blenkernel/intern/sequencer.c117
-rw-r--r--source/blender/blenkernel/intern/softbody.c9
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c5
-rw-r--r--source/blender/blenlib/BLI_ghash.h24
-rw-r--r--source/blender/blenlib/BLI_kdtree.h4
-rw-r--r--source/blender/blenlib/BLI_linklist.h6
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h2
-rw-r--r--source/blender/blenlib/BLI_math_geom.h8
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h4
-rw-r--r--source/blender/blenlib/BLI_task.h4
-rw-r--r--source/blender/blenlib/BLI_winstuff.h4
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/SConscript2
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c69
-rw-r--r--source/blender/blenlib/intern/BLI_kdtree.c155
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c4
-rw-r--r--source/blender/blenlib/intern/edgehash.c180
-rw-r--r--source/blender/blenlib/intern/math_geom.c70
-rw-r--r--source/blender/blenlib/intern/math_geom_inline.c11
-rw-r--r--source/blender/blenlib/intern/math_matrix.c6
-rw-r--r--source/blender/blenlib/intern/math_solvers.c6
-rw-r--r--source/blender/blenlib/intern/path_util.c2
-rw-r--r--source/blender/blenlib/intern/task.c60
-rw-r--r--source/blender/blenloader/intern/readfile.c3
-rw-r--r--source/blender/blenloader/intern/versioning_260.c2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c2
-rw-r--r--source/blender/bmesh/CMakeLists.txt12
-rw-r--r--source/blender/bmesh/SConscript2
-rw-r--r--source/blender/bmesh/bmesh.h1
-rw-r--r--source/blender/bmesh/bmesh_class.h14
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c60
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h22
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c551
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h10
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c52
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c1257
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.h (renamed from source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.h)35
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c15
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h4
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c4
-rw-r--r--source/blender/bmesh/operators/bmo_normals.c13
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c473
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c15
-rw-r--r--source/blender/bmesh/operators/bmo_smooth_laplacian.c95
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c7
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c428
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.h11
-rw-r--r--source/blender/bmesh/tools/bmesh_path.c4
-rw-r--r--source/blender/collada/DocumentExporter.cpp60
-rw-r--r--source/blender/compositor/operations/COM_AntiAliasOperation.cpp136
-rw-r--r--source/blender/compositor/operations/COM_AntiAliasOperation.h1
-rw-r--r--source/blender/editors/armature/CMakeLists.txt8
-rw-r--r--source/blender/editors/armature/SConscript2
-rw-r--r--source/blender/editors/armature/armature_edit.c2
-rw-r--r--source/blender/editors/armature/armature_skinning.c10
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c6
-rw-r--r--source/blender/editors/armature/meshlaplacian.c118
-rw-r--r--source/blender/editors/armature/reeb.c46
-rw-r--r--source/blender/editors/curve/editcurve.c131
-rw-r--r--source/blender/editors/include/BIF_glutil.h6
-rw-r--r--source/blender/editors/include/ED_armature.h2
-rw-r--r--source/blender/editors/include/ED_mesh.h2
-rw-r--r--source/blender/editors/include/ED_object.h1
-rw-r--r--source/blender/editors/include/ED_transform.h61
-rw-r--r--source/blender/editors/include/ED_util.h2
-rw-r--r--source/blender/editors/include/UI_interface.h6
-rw-r--r--source/blender/editors/include/UI_resources.h3
-rw-r--r--source/blender/editors/interface/interface.c4
-rw-r--r--source/blender/editors/interface/interface_align.c12
-rw-r--r--source/blender/editors/interface/interface_draw.c56
-rw-r--r--source/blender/editors/interface/interface_handlers.c51
-rw-r--r--source/blender/editors/interface/interface_icons.c13
-rw-r--r--source/blender/editors/interface/interface_panel.c2
-rw-r--r--source/blender/editors/interface/interface_regions.c29
-rw-r--r--source/blender/editors/interface/interface_style.c14
-rw-r--r--source/blender/editors/interface/resources.c10
-rw-r--r--source/blender/editors/mesh/editface.c28
-rw-r--r--source/blender/editors/mesh/editmesh_add.c108
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c2
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c2
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c6
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c163
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c41
-rw-r--r--source/blender/editors/mesh/editmesh_select.c2
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c24
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c2
-rw-r--r--source/blender/editors/mesh/mesh_intern.h1
-rw-r--r--source/blender/editors/mesh/mesh_ops.c1
-rw-r--r--source/blender/editors/metaball/mball_edit.c68
-rw-r--r--source/blender/editors/object/object_add.c10
-rw-r--r--source/blender/editors/object/object_hook.c2
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/object/object_transform.c32
-rw-r--r--source/blender/editors/render/render_internal.c4
-rw-r--r--source/blender/editors/render/render_opengl.c4
-rw-r--r--source/blender/editors/screen/glutil.c105
-rw-r--r--source/blender/editors/screen/screen_ops.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c20
-rw-r--r--source/blender/editors/space_action/space_action.c42
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c24
-rw-r--r--source/blender/editors/space_clip/clip_draw.c12
-rw-r--r--source/blender/editors/space_clip/clip_ops.c2
-rw-r--r--source/blender/editors/space_clip/space_clip.c94
-rw-r--r--source/blender/editors/space_console/console_draw.c15
-rw-r--r--source/blender/editors/space_console/space_console.c24
-rw-r--r--source/blender/editors/space_file/filelist.c15
-rw-r--r--source/blender/editors/space_file/space_file.c90
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2
-rw-r--r--source/blender/editors/space_graph/space_graph.c40
-rw-r--r--source/blender/editors/space_image/image_buttons.c2
-rw-r--r--source/blender/editors/space_image/image_draw.c2
-rw-r--r--source/blender/editors/space_image/image_intern.h2
-rw-r--r--source/blender/editors/space_image/image_ops.c26
-rw-r--r--source/blender/editors/space_image/space_image.c52
-rw-r--r--source/blender/editors/space_info/space_info.c24
-rw-r--r--source/blender/editors/space_info/textview.c27
-rw-r--r--source/blender/editors/space_logic/space_logic.c28
-rw-r--r--source/blender/editors/space_nla/nla_channels.c2
-rw-r--r--source/blender/editors/space_nla/space_nla.c46
-rw-r--r--source/blender/editors/space_node/node_edit.c2
-rw-r--r--source/blender/editors/space_node/node_ops.c2
-rw-r--r--source/blender/editors/space_node/node_relationships.c93
-rw-r--r--source/blender/editors/space_node/space_node.c40
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c97
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h7
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c100
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c36
-rw-r--r--source/blender/editors/space_script/space_script.c24
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c48
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c56
-rw-r--r--source/blender/editors/space_text/space_text.c28
-rw-r--r--source/blender/editors/space_text/text_draw.c149
-rw-r--r--source/blender/editors/space_text/text_format.c2
-rw-r--r--source/blender/editors/space_text/text_format.h2
-rw-r--r--source/blender/editors/space_text/text_intern.h12
-rw-r--r--source/blender/editors/space_time/space_time.c28
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c24
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c38
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c213
-rw-r--r--source/blender/editors/space_view3d/drawobject.c188
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c31
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c80
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c66
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c17
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h4
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c22
-rw-r--r--source/blender/editors/transform/transform.c18
-rw-r--r--source/blender/editors/transform/transform_conversions.c55
-rw-r--r--source/blender/editors/transform/transform_generics.c18
-rw-r--r--source/blender/editors/transform/transform_input.c28
-rw-r--r--source/blender/editors/transform/transform_manipulator.c31
-rw-r--r--source/blender/editors/transform/transform_orientations.c8
-rw-r--r--source/blender/editors/transform/transform_snap.c399
-rw-r--r--source/blender/editors/util/ed_util.c20
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt8
-rw-r--r--source/blender/editors/uvedit/SConscript2
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c167
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c10
-rw-r--r--source/blender/gpu/CMakeLists.txt26
-rw-r--r--source/blender/gpu/GPU_basic_shader.h (renamed from source/blender/gpu/GPU_simple_shader.h)45
-rw-r--r--source/blender/gpu/GPU_buffers.h2
-rw-r--r--source/blender/gpu/GPU_draw.h9
-rw-r--r--source/blender/gpu/GPU_extensions.h192
-rw-r--r--source/blender/gpu/GPU_framebuffer.h84
-rw-r--r--source/blender/gpu/GPU_shader.h127
-rw-r--r--source/blender/gpu/GPU_texture.h104
-rw-r--r--source/blender/gpu/SConscript4
-rw-r--r--source/blender/gpu/intern/gpu_basic_shader.c (renamed from source/blender/gpu/intern/gpu_simple_shader.c)175
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c64
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c16
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c18
-rw-r--r--source/blender/gpu/intern/gpu_draw.c219
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c2236
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c633
-rw-r--r--source/blender/gpu/intern/gpu_material.c12
-rw-r--r--source/blender/gpu/intern/gpu_shader.c783
-rw-r--r--source/blender/gpu/intern/gpu_texture.c762
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_frag.glsl (renamed from source/blender/gpu/shaders/gpu_shader_simple_frag.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_vert.glsl (renamed from source/blender/gpu/shaders/gpu_shader_simple_vert.glsl)0
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h14
-rw-r--r--source/blender/makesdna/DNA_node_types.h1
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h3
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h17
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/RNA_define.h2
-rw-r--r--source/blender/makesrna/intern/makesrna.c10
-rw-r--r--source/blender/makesrna/intern/rna_access.c31
-rw-r--r--source/blender/makesrna/intern/rna_define.c14
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c1
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c28
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c100
-rw-r--r--source/blender/makesrna/intern/rna_object.c3
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c80
-rw-r--r--source/blender/makesrna/intern/rna_scene.c7
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c45
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c7
-rw-r--r--source/blender/makesrna/intern/rna_space.c36
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c10
-rw-r--r--source/blender/modifiers/CMakeLists.txt8
-rw-r--r--source/blender/modifiers/SConscript2
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c225
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c153
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c84
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c4
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c303
-rw-r--r--source/blender/modifiers/intern/MOD_util.c21
-rw-r--r--source/blender/modifiers/intern/MOD_util.h17
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c120
-rw-r--r--source/blender/nodes/composite/node_composite_util.c1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_common.c1
-rw-r--r--source/blender/nodes/intern/node_util.c90
-rw-r--r--source/blender/nodes/intern/node_util.h3
-rw-r--r--source/blender/nodes/shader/node_shader_util.c1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_common.c1
-rw-r--r--source/blender/nodes/texture/node_texture_util.c1
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_common.c1
-rw-r--r--source/blender/physics/CMakeLists.txt3
-rw-r--r--source/blender/python/generic/py_capi_utils.c58
-rw-r--r--source/blender/python/intern/bpy.c3
-rw-r--r--source/blender/python/intern/bpy_rna.c15
-rw-r--r--source/blender/python/intern/bpy_util.h4
-rw-r--r--source/blender/python/intern/gpu_offscreen.c2
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c4
-rw-r--r--source/blender/python/mathutils/mathutils_kdtree.c82
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h4
-rw-r--r--source/blender/render/intern/source/pipeline.c25
-rw-r--r--source/blender/render/intern/source/pointdensity.c25
-rw-r--r--source/blender/windowmanager/WM_keymap.h2
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c204
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c11
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c7
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c138
-rw-r--r--source/blender/windowmanager/wm_draw.h8
-rw-r--r--source/blenderplayer/CMakeLists.txt10
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c12
-rw-r--r--source/creator/CMakeLists.txt2
-rw-r--r--source/creator/blender.map1
-rw-r--r--source/creator/creator.c10
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp18
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp16
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp2
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp1
-rw-r--r--source/gameengine/Ketsji/BL_Texture.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp77
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h47
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp139
-rw-r--r--source/gameengine/Rasterizer/RAS_IRasterizer.h6
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.cpp12
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt4
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp73
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h1
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp28
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h3
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp185
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h10
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp310
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h69
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp63
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h1
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp71
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h5
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp6
-rw-r--r--source/gameengine/VideoTexture/blendVideoTex.cpp2
-rw-r--r--tests/gtests/blenlib/CMakeLists.txt4
-rw-r--r--tests/python/bl_pyapi_mathutils.py72
576 files changed, 15019 insertions, 25455 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f7be4ebdb61..354e4adb0d7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -267,6 +267,10 @@ if(NOT WITH_AUDASPACE)
endif()
option(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" ON)
+if(UNIX AND NOT APPLE)
+ option(WITH_OPENMP_STATIC "Link OpenMP statically (only used by the release environment)" OFF)
+ mark_as_advanced(WITH_OPENMP_STATIC)
+endif()
if(WITH_X11)
option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON)
@@ -358,7 +362,6 @@ if(WIN32)
endif()
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ${_init_INPUT_NDOF})
option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
-option(WITH_OPENNL "Enable use of Open Numerical Library" ON)
if(UNIX AND NOT APPLE)
option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON)
option(WITH_STATIC_LIBS "Try to link with static libraries, as much as possible, to make blender more portable across distributions" OFF)
@@ -810,14 +813,14 @@ set(PLATFORM_LINKFLAGS_DEBUG "")
# For alternate Python locations the commandline can be used to override detected/default cache settings, e.g:
# On Unix:
# cmake ../blender \
-# -D PYTHON_VERSION=3.4 \
-# -D PYTHON_INCLUDE_DIR=/opt/py34/include/python3.4d \
-# -D PYTHON_LIBRARY=/opt/py34/lib/libpython3.4d.so
+# -D PYTHON_VERSION=3.5 \
+# -D PYTHON_INCLUDE_DIR=/opt/py35/include/python3.5d \
+# -D PYTHON_LIBRARY=/opt/py35/lib/libpython3.5d.so
#
# On Macs:
# cmake ../blender \
-# -D PYTHON_INCLUDE_DIR=/System/Library/Frameworks/Python.framework/Versions/3.4/include/python3.4 \
-# -D PYTHON_LIBPATH=/System/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/config \
+# -D PYTHON_INCLUDE_DIR=/System/Library/Frameworks/Python.framework/Versions/3.5/include/python3.5 \
+# -D PYTHON_LIBPATH=/System/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/config \
# -G Xcode
#
# When changing any of this remember to update the notes in doc/build_systems/cmake.txt
@@ -865,13 +868,9 @@ endif()
if(UNIX AND NOT APPLE)
macro(find_package_wrapper)
if(WITH_STATIC_LIBS)
- set(_cmake_find_library_suffixes_back ${CMAKE_FIND_LIBRARY_SUFFIXES})
- set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
- endif()
- find_package(${ARGV})
- if(WITH_STATIC_LIBS)
- set(CMAKE_FIND_LIBRARY_SUFFIXES ${_cmake_find_library_suffixes_back})
- unset(_cmake_find_library_suffixes_back)
+ find_package_static(${ARGV})
+ else()
+ find_package(${ARGV})
endif()
endmacro()
@@ -896,10 +895,10 @@ if(UNIX AND NOT APPLE)
# else values are set below for all platforms
if(WITH_PYTHON)
- # No way to set py34. remove for now.
+ # No way to set py35, remove for now.
# find_package(PythonLibs)
- # Use our own instead, since wothout py is such a rare case,
+ # Use our own instead, since without py is such a rare case,
# require this package
# XXX Linking errors with debian static python :/
# find_package_wrapper(PythonLibsUnix REQUIRED)
@@ -1292,13 +1291,22 @@ elseif(WIN32)
set(PLATFORM_LINKFLAGS_DEBUG "/IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib")
if(NOT DEFINED LIBDIR)
+
# Setup 64bit and 64bit windows systems
if(CMAKE_CL_64)
message(STATUS "64 bit compiler detected.")
- set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/win64_vc12)
+ set(LIBDIR_BASE "win64")
else()
message(STATUS "32 bit compiler detected.")
- set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/windows_vc12)
+ set(LIBDIR_BASE "windows")
+ endif()
+
+ if(MSVC_VERSION EQUAL 1900)
+ message(STATUS "Visual Studio 2015 detected.")
+ set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc14)
+ else()
+ message(STATUS "Visual Studio 2013 detected.")
+ set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc12)
endif()
else()
message(STATUS using LIBDIR ${LIBDIR})
@@ -1734,7 +1742,7 @@ elseif(WIN32)
if(WITH_PYTHON)
# normally cached but not since we include them with blender
- set(PYTHON_VERSION 3.4) # CACHE STRING)
+ set(PYTHON_VERSION 3.5) # CACHE STRING)
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") # CACHE PATH)
set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}mw.lib") # CACHE FILEPATH)
@@ -1939,7 +1947,7 @@ elseif(APPLE)
endif()
if(WITH_PYTHON)
- # we use precompiled libraries for py 3.4 and up by default
+ # we use precompiled libraries for py 3.5 and up by default
set(PYTHON_VERSION 3.5)
if(NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
# normally cached but not since we include them with blender
@@ -2458,8 +2466,18 @@ endif()
if(WITH_OPENMP)
find_package(OpenMP)
if(OPENMP_FOUND)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+ if(NOT WITH_OPENMP_STATIC)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+ else()
+ # Typically avoid adding flags as defines but we can't
+ # ass OpenMP flags to the linker for static builds, meaning
+ # we can't add any OpenMP related flags to CFLAGS variables
+ # since they're passed to the linker as well.
+ add_definitions("${OpenMP_C_FLAGS}")
+
+ find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
+ endif()
else()
set(WITH_OPENMP OFF)
endif()
@@ -2973,9 +2991,6 @@ if(FIRST_RUN)
info_cfg_option(WITH_GL_ANGLE)
endif()
- info_cfg_text("Other:")
- info_cfg_option(WITH_OPENNL)
-
# debug
message(STATUS "HAVE_STDBOOL_H = ${HAVE_STDBOOL_H}")
diff --git a/SConstruct b/SConstruct
index 29f539236c2..de265df5b02 100644
--- a/SConstruct
+++ b/SConstruct
@@ -555,7 +555,6 @@ else:
# TODO, make optional (as with CMake)
env['CPPFLAGS'].append('-DWITH_AVI')
-env['CPPFLAGS'].append('-DWITH_OPENNL')
if env['OURPLATFORM'] not in ('win32-vc', 'win64-vc'):
env['CPPFLAGS'].append('-DHAVE_STDBOOL_H')
@@ -797,8 +796,8 @@ if B.targets != ['cudakernels']:
data_to_c_simple("source/blender/gpu/shaders/gpu_program_smoke_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl")
- data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_frag.glsl")
- data_to_c_simple("source/blender/gpu/shaders/gpu_shader_simple_vert.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_basic_frag.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_basic_vert.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl")
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 8c38a766002..e98a84f8888 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -249,19 +249,19 @@ DO_SHOW_DEPS=false
SUDO="sudo"
-PYTHON_VERSION="3.4.0"
-PYTHON_VERSION_MIN="3.4"
+PYTHON_VERSION="3.5.1"
+PYTHON_VERSION_MIN="3.5"
PYTHON_FORCE_BUILD=false
PYTHON_FORCE_REBUILD=false
PYTHON_SKIP=false
-NUMPY_VERSION="1.9.1"
+NUMPY_VERSION="1.10.1"
NUMPY_VERSION_MIN="1.8"
NUMPY_FORCE_BUILD=false
NUMPY_FORCE_REBUILD=false
NUMPY_SKIP=false
-BOOST_VERSION="1.51.0"
+BOOST_VERSION="1.55.0"
BOOST_VERSION_MIN="1.49"
BOOST_FORCE_BUILD=false
BOOST_FORCE_REBUILD=false
@@ -731,7 +731,7 @@ download() {
done
if [ $error -eq 1 ]; then
- ERROR "wget could not find $1, or could not write it to $2, exiting"
+ ERROR "wget could not find ${sources[@]}, or could not write it to $2, exiting"
exit 1
fi
}
@@ -1527,7 +1527,7 @@ clean_LLVM() {
compile_LLVM() {
# To be changed each time we make edits that would modify the compiled result!
- llvm_magic=2
+ llvm_magic=3
_init_llvm
# Clean install if needed!
@@ -1700,7 +1700,7 @@ compile_OSL() {
if [ ! -z $LLVM_VERSION_FOUND ]; then
cmake_d="$cmake_d -D LLVM_VERSION=$LLVM_VERSION_FOUND"
if [ -d $INST/llvm ]; then
- cmake_d="$cmake_d -D LLVM_ROOT_DIR=$INST/llvm"
+ cmake_d="$cmake_d -D LLVM_DIRECTORY=$INST/llvm"
cmake_d="$cmake_d -D LLVM_STATIC=ON"
fi
fi
@@ -2209,6 +2209,13 @@ install_DEB() {
PRINT ""
install_packages_DEB $_packages
+ PRINT""
+ SNDFILE_DEV="libsndfile1-dev"
+ check_package_DEB $SNDFILE_DEV
+ if [ $? -eq 0 ]; then
+ install_packages_DEB $SNDFILE_DEV
+ fi
+
PRINT ""
X264_DEV="libx264-dev"
check_package_version_ge_DEB $X264_DEV $X264_VERSION_MIN
@@ -2762,6 +2769,13 @@ install_RPM() {
fi
fi
+ PRINT""
+ SNDFILE_DEV="libsndfile-devel"
+ check_package_RPM $SNDFILE_DEV
+ if [ $? -eq 0 ]; then
+ install_packages_RMP $SNDFILE_DEV
+ fi
+
if [ "$WITH_ALL" = true ]; then
PRINT ""
VPX_DEV="libvpx-devel"
@@ -2924,7 +2938,7 @@ install_RPM() {
PRINT ""
- _do_compile_osl=true
+ _do_compile_osl=false
if [ "$OSL_SKIP" = true ]; then
WARNING "Skipping OpenShadingLanguage installation, as requested..."
elif [ "$OSL_FORCE_BUILD" = true ]; then
@@ -3125,6 +3139,13 @@ install_ARCH() {
PRINT ""
install_packages_ARCH $_packages
+ PRINT""
+ SNDFILE_DEV="libsndfile"
+ check_package_ARCH $SNDFILE_DEV
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH $SNDFILE_DEV
+ fi
+
PRINT ""
X264_DEV="x264"
check_package_version_ge_ARCH $X264_DEV $X264_VERSION_MIN
@@ -3664,6 +3685,13 @@ print_info() {
_buildargs=""
+ _1="-D WITH_CODEC_SNDFILE=ON"
+ PRINT " $_1"
+ _buildargs="$_buildargs -U *SNDFILE* $_1"
+
+ _1="-D PYTHON_VERSION=$PYTHON_VERSION_MIN"
+ PRINT " $_1"
+ _buildargs="$_buildargs -U *PYTHON* $_1"
if [ -d $INST/python-$PYTHON_VERSION_MIN ]; then
_1="-D PYTHON_ROOT_DIR=$INST/python-$PYTHON_VERSION_MIN"
PRINT " $_1"
@@ -3675,25 +3703,25 @@ print_info() {
_2="-D Boost_NO_SYSTEM_PATHS=ON"
PRINT " $_1"
PRINT " $_2"
- _buildargs="$_buildargs $_1 $_2"
+ _buildargs="$_buildargs -U *BOOST* -U *Boost* $_1 $_2"
fi
if [ -d $INST/ocio ]; then
_1="-D OPENCOLORIO_ROOT_DIR=$INST/ocio"
PRINT " $_1"
- _buildargs="$_buildargs $_1"
+ _buildargs="$_buildargs -U *OPENCOLORIO* $_1"
fi
if [ -d $INST/openexr ]; then
_1="-D OPENEXR_ROOT_DIR=$INST/openexr"
PRINT " $_1"
- _buildargs="$_buildargs $_1"
+ _buildargs="$_buildargs -U *OPENEXR* $_1"
fi
if [ -d $INST/oiio ]; then
_1="-D OPENIMAGEIO_ROOT_DIR=$INST/oiio"
PRINT " $_1"
- _buildargs="$_buildargs $_1"
+ _buildargs="$_buildargs -U *OPENIMAGEIO* $_1"
fi
if [ "$OSL_SKIP" = false ]; then
@@ -3703,7 +3731,7 @@ print_info() {
PRINT " $_1"
PRINT " $_2"
PRINT " $_3"
- _buildargs="$_buildargs $_1 $_2 $_3"
+ _buildargs="$_buildargs -U *LLVM* -U *CYCLES* $_1 $_2 $_3"
if [ -d $INST/osl ]; then
_1="-D CYCLES_OSL=$INST/osl"
PRINT " $_1"
@@ -3729,13 +3757,13 @@ print_info() {
_2="-D OPENSUBDIV_ROOT_DIR=$INST/osd"
PRINT " $_1"
PRINT " $_2"
- _buildargs="$_buildargs $_1 $_2"
+ _buildargs="$_buildargs -U *OPENSUBDIV* $_1 $_2"
fi
if [ "$WITH_OPENCOLLADA" = true ]; then
_1="-D WITH_OPENCOLLADA=ON"
PRINT " $_1"
- _buildargs="$_buildargs $_1"
+ _buildargs="$_buildargs -U *COLLADA* $_1"
fi
if [ "$FFMPEG_SKIP" = false ]; then
@@ -3743,7 +3771,7 @@ print_info() {
_2="-D FFMPEG_LIBRARIES='avformat;avcodec;avutil;avdevice;swscale;rt;`print_info_ffmpeglink`'"
PRINT " $_1"
PRINT " $_2"
- _buildargs="$_buildargs $_1 $_2"
+ _buildargs="$_buildargs -U *FFMPEG* $_1 $_2"
if [ -d $INST/ffmpeg ]; then
_1="-D FFMPEG=$INST/ffmpeg"
PRINT " $_1"
@@ -3758,6 +3786,9 @@ print_info() {
PRINT ""
PRINT "If you're using SCons add this to your user-config:"
+ PRINT "WITH_BF_SNDFILE = True"
+
+ PRINT "BF_PYTHON_VERSION = '$PYTHON_VERSION_MIN'"
if [ -d $INST/python-$PYTHON_VERSION_MIN ]; then
PRINT "BF_PYTHON = '$INST/python-$PYTHON_VERSION_MIN'"
PRINT "BF_PYTHON_ABI_FLAGS = 'm'"
diff --git a/build_files/buildbot/config/blender_linux.cmake b/build_files/buildbot/config/blender_linux.cmake
new file mode 100644
index 00000000000..d4895ce26d7
--- /dev/null
+++ b/build_files/buildbot/config/blender_linux.cmake
@@ -0,0 +1,102 @@
+# ######## Global feature set settings ########
+
+include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/config/blender_full.cmake")
+
+# Default to only build Blender, not the player
+set(WITH_BLENDER ON CACHE BOOL "" FORCE)
+set(WITH_PLAYER OFF CACHE BOOL "" FORCE)
+
+# ######## Linux-specific build options ########
+# Options which are specific to Linux-only platforms
+set(WITH_DOC_MANPAGE OFF CACHE BOOL "" FORCE)
+
+# ######## Official release-specific build options ########
+# Options which are specific to Linux release builds only
+set(WITH_JACK_DYNLOAD ON CACHE BOOL "" FORCE)
+set(WITH_SDL_DYNLOAD ON CACHE BOOL "" FORCE)
+set(WITH_SYSTEM_GLEW OFF CACHE BOOL "" FORCE)
+
+set(WITH_OPENMP_STATIC ON CACHE BOOL "" FORCE)
+
+set(WITH_PYTHON_INSTALL_NUMPY ON CACHE BOOL "" FORCE)
+set(WITH_PYTHON_INSTALL_REQUESTS ON CACHE BOOL "" FORCE)
+
+# ######## Release environment specific settings ########
+# All the hardcoded libraru paths and such
+
+# LLVM libraries
+set(LLVM_VERSION "3.4" CACHE STRING "" FORCE)
+set(LLVM_ROOT_DIR "/opt/lib/llvm-${LLVM_VERSION}" CACHE STRING "" FORCE)
+set(LLVM_STATIC ON CACHE BOOL "" FORCE)
+
+# BOOST libraries
+set(BOOST_ROOT "/opt/lib/boost" CACHE STRING "" FORCE)
+set(Boost_USE_STATIC_LIBS ON CACHE BOOL "" FORCE)
+
+# FFmpeg libraries
+set(FFMPEG "/opt/lib/ffmpeg" CACHE STRING "" FORCE)
+set(FFMPEG_LIBRARIES
+ avdevice avformat avcodec avutil avfilter swscale swresample
+ /usr/lib/libxvidcore.a
+ /usr/lib/libx264.a
+ /usr/lib/libmp3lame.a
+ /usr/lib/libvpx.a
+ /usr/lib/libvorbis.a
+ /usr/lib/libogg.a
+ /usr/lib/libvorbisenc.a
+ /usr/lib/libtheora.a
+ /usr/lib/libschroedinger-1.0.a
+ /usr/lib/liborc-0.4.a
+ CACHE STRING "" FORCE
+)
+
+# SndFile libraries
+set(SNDFILE_LIBRARY "/usr/lib/libsndfile.a;/usr/lib/libFLAC.a" CACHE STRING "" FORCE)
+
+# OpenAL libraries
+set(OPENAL_ROOT_DIR "/opt/lib/openal" CACHE STRING "" FORCE)
+set(OPENAL_INCLUDE_DIR "${OPENAL_ROOT_DIR}/include" CACHE STRING "" FORCE)
+set(OPENAL_LIBRARY
+ ${OPENAL_ROOT_DIR}/lib/libopenal.a
+ ${OPENAL_ROOT_DIR}/lib/libcommon.a
+ CACHE STRING "" FORCE
+)
+
+# OpenCollada libraries
+set(OPENCOLLADA_UTF_LIBRARY "" CACHE STRING "" FORCE)
+set(PCRE_INCLUDE_DIR "/usr/include" CACHE STRING "" FORCE)
+set(PCRE_LIBRARY "/usr/lib/libpcre.a" CACHE STRING "" FORCE)
+set(XML2_INCLUDE_DIR "/usr/include" CACHE STRING "" FORCE)
+set(XML2_LIBRARY "/usr/lib/libxml2.a" CACHE STRING "" FORCE)
+
+# OpenColorIO libraries
+set(OPENCOLORIO_ROOT_DIR "/opt/lib/ocio" CACHE STRING "" FORCE)
+set(OPENCOLORIO_OPENCOLORIO_LIBRARY "${OPENCOLORIO_ROOT_DIR}/lib/libOpenColorIO.a" CACHE STRING "" FORCE)
+set(OPENCOLORIO_TINYXML_LIBRARY "${OPENCOLORIO_ROOT_DIR}/lib/libtinyxml.a" CACHE STRING "" FORCE)
+set(OPENCOLORIO_YAML-CPP_LIBRARY "${OPENCOLORIO_ROOT_DIR}/lib/libyaml-cpp.a" CACHE STRING "" FORCE)
+
+# OpenSubdiv libraries
+set(OPENSUBDIV_ROOT_DIR "/opt/lib/opensubdiv" CACHE STRING "" FORCE)
+set(OPENSUBDIV_OSDCPU_LIBRARY "${OPENSUBDIV_ROOT_DIR}/lib/libosdCPU.a" CACHE STRING "" FORCE)
+set(OPENSUBDIV_OSDGPU_LIBRARY "${OPENSUBDIV_ROOT_DIR}/lib/libosdGPU.a" CACHE STRING "" FORCE)
+
+# OpenEXR libraries
+set(OPENEXR_ROOT_DIR "/opt/lib/openexr" CACHE STRING "" FORCE)
+set(OPENEXR_HALF_LIBRARY "/opt/lib/openexr/lib/libHalf.a" CACHE STRING "" FORCE)
+set(OPENEXR_IEX_LIBRARY "/opt/lib/openexr/lib/libIex.a" CACHE STRING "" FORCE)
+set(OPENEXR_ILMIMF_LIBRARY "/opt/lib/openexr/lib/libIlmImf.a" CACHE STRING "" FORCE)
+set(OPENEXR_ILMTHREAD_LIBRARY "/opt/lib/openexr/lib/libIlmThread.a" CACHE STRING "" FORCE)
+set(OPENEXR_IMATH_LIBRARY "/opt/lib/openexr/lib/libImath.a" CACHE STRING "" FORCE)
+
+# JeMalloc library
+set(JEMALLOC_LIBRARY "/opt/lib/jemalloc/lib/libjemalloc.a" CACHE STRING "" FORCE)
+
+# Foce some system libraries to be static
+set(FFTW3_LIBRARY "/usr/lib/libfftw3.a" CACHE STRING "" FORCE)
+set(JPEG_LIBRARY "/usr/lib/libjpeg.a" CACHE STRING "" FORCE)
+set(PNG_LIBRARY "/usr/lib/libpng.a" CACHE STRING "" FORCE)
+set(TIFF_LIBRARY "/usr/lib/libtiff.a" CACHE STRING "" FORCE)
+set(ZLIB_LIBRARY "/usr/lib/libz.a" CACHE STRING "" FORCE)
+
+# Additional linking libraries
+set(CMAKE_EXE_LINKER_FLAGS "-lrt" CACHE STRING "" FORCE)
diff --git a/build_files/buildbot/config/blender_linux_player.cmake b/build_files/buildbot/config/blender_linux_player.cmake
new file mode 100644
index 00000000000..2fb31192002
--- /dev/null
+++ b/build_files/buildbot/config/blender_linux_player.cmake
@@ -0,0 +1,12 @@
+# This is applied as an ovveride on top of blender_linux.config
+# Disables all the areas which are not needed for the player.
+set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
+set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
+set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE)
+set(WITH_GHOST_XDND OFF CACHE BOOL "" FORCE)
+set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
+set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
+set(WITH_LIBMV OFF CACHE BOOL "" FORCE)
+
+set(WITH_BLENDER OFF CACHE BOOL "" FORCE)
+set(WITH_PLAYER ON CACHE BOOL "" FORCE)
diff --git a/build_files/buildbot/config/user-config-cuda-glibc211-i686.py b/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
deleted file mode 100644
index 580e67ee7e3..00000000000
--- a/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
+++ /dev/null
@@ -1,6 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc211-i686'
-BF_INSTALLDIR = '../blender-install/linux-glibc211-i686'
-BF_NUMJOBS = 1
-
-#BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
-BF_CYCLES_CUDA_BINARIES_ARCH = []
diff --git a/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py b/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py
deleted file mode 100644
index 29b1b9f1ad7..00000000000
--- a/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py
+++ /dev/null
@@ -1,5 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc211-x86_64'
-BF_INSTALLDIR = '../blender-install/linux-glibc211-x86_64'
-BF_NUMJOBS = 1
-
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30', 'sm_35', 'sm_50', 'sm_52']
diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py
deleted file mode 100644
index 88eae57431a..00000000000
--- a/build_files/buildbot/config/user-config-glibc211-i686.py
+++ /dev/null
@@ -1,185 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc211-i686'
-BF_INSTALLDIR = '../blender-install/linux-glibc211-i686'
-BF_NUMJOBS = 4
-WITHOUT_BF_OVERWRITE_INSTALL = True
-
-# Python configuration
-BF_PYTHON_VERSION = '3.5'
-BF_PYTHON_ABI_FLAGS = 'm'
-BF_PYTHON = '/opt/lib/python-3.5'
-WITH_BF_PYTHON_INSTALL_NUMPY = True
-WITH_BF_PYTHON_INSTALL_REQUESTS = True
-
-WITH_BF_STATICPYTHON = True
-
-# OpenCollada configuration
-WITH_BF_COLLADA = True
-WITH_BF_STATICOPENCOLLADA=True
-BF_OPENCOLLADA = '/opt/lib/opencollada'
-BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
-BF_OPENCOLLADA_LIB_STATIC = '${BF_OPENCOLLADA}/lib/libOpenCOLLADAStreamWriter.a ' + \
- '${BF_OPENCOLLADA}/lib/libOpenCOLLADASaxFrameworkLoader.a ' + \
- '${BF_OPENCOLLADA}/lib/libOpenCOLLADAFramework.a ' + \
- '${BF_OPENCOLLADA}/lib/libOpenCOLLADABaseUtils.a ' + \
- '${BF_OPENCOLLADA}/lib/libGeneratedSaxParser.a ' + \
- '${BF_OPENCOLLADA}/lib/libMathMLSolver.a ' + \
- '${BF_OPENCOLLADA}/lib/libbuffer.a ${BF_OPENCOLLADA}/lib/libftoa.a ' + \
- '/usr/lib/libxml2.a /usr/lib/libexpat.a /usr/lib/libpcre.a'
-BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib /home/sources/staticlibs/lib64'
-BF_PCRE_LIB = ''
-BF_EXPAT_LIB = ''
-
-# FFMPEG configuration
-WITH_BF_FFMPEG = True
-WITH_BF_STATICFFMPEG = True
-
-BF_FFMPEG = '/opt/lib/ffmpeg'
-BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib'
-BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ' + \
- '${BF_FFMPEG_LIBPATH}/libavfilter.a ${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
- '${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \
- '/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \
- '/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \
- '/usr/lib/liborc-0.4.a'
-
-# Don't depend on system's libstdc++
-WITH_BF_STATICCXX = True
-BF_CXX_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7.1/libstdc++.a'
-
-WITH_BF_OPENAL = True
-WITH_BF_STATICOPENAL = True
-BF_OPENAL = '/opt/lib/openal'
-BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a /opt/lib/openal/lib/libcommon.a'
-
-WITH_BF_GETTEXT_STATIC = True
-
-WITH_BF_FREETYPE_STATIC = False
-
-WITH_BF_OPENEXR = True
-BF_OPENEXR = '/opt/lib/openexr'
-BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include'
-WITH_BF_STATICOPENEXR = True
-
-WITH_BF_TIFF = True
-WITH_BF_STATICTIFF = True
-BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a'
-
-WITH_BF_JPEG = True
-WITH_BF_STATICJPEG = True
-BF_JPEG_LIB_STATIC= '${BF_JPEG}/lib/libjpeg.a'
-
-WITH_BF_PNG = True
-WITH_BF_STATICPNG = True
-BF_PNG_LIB_STATIC = '${BF_PNG}/lib/libpng.a'
-
-WITH_BF_STATICLIBSAMPLERATE = True
-
-WITH_BF_ZLIB = True
-WITH_BF_STATICZLIB = True
-BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
-
-WITH_BF_SDL = True
-WITH_BF_SDL_DYNLOAD = True
-
-WITH_BF_OGG = True
-
-WITH_BF_OPENMP = True
-WITH_BF_STATICOPENMP = True
-BF_OPENMP_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7/libgomp.a'
-
-WITH_BF_GAMEENGINE = True
-WITH_BF_BULLET = True
-
-# Blender player (would be enabled in it's own config)
-WITH_BF_PLAYER = False
-
-# Use jemalloc memory manager
-WITH_BF_JEMALLOC = True
-WITH_BF_STATICJEMALLOC = True
-BF_JEMALLOC = '/opt/lib/jemalloc'
-BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib'
-
-# Use 3d mouse library
-WITH_BF_3DMOUSE = True
-WITH_BF_STATIC3DMOUSE = True
-BF_3DMOUSE = '/opt/lib/libspnav'
-BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib'
-
-# FFT
-WITH_BF_FFTW3 = True
-WITH_BF_STATICFFTW3 = True
-
-# JACK
-WITH_BF_JACK = True
-WITH_BF_JACK_DYNLOAD = True
-
-# Cycles
-WITH_BF_CYCLES = True
-WITH_BF_CYCLES_CUDA_BINARIES = False
-
-WITH_BF_OIIO = True
-WITH_BF_STATICOIIO = True
-BF_OIIO = '/opt/lib/oiio'
-BF_OIIO_INC = '${BF_OIIO}/include'
-BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a'
-BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
-
-BF_IS_NEW_OSL = False
-WITH_BF_CYCLES_OSL = True
-WITH_BF_STATICOSL = BF_IS_NEW_OSL
-BF_OSL = '/opt/lib/osl'
-BF_OSL_INC = '${BF_OSL}/include'
-# note oslexec would passed via program linkflags, which is needed to
-# make llvm happy with osl_allocate_closure_component
-BF_OSL_LIB = 'oslcomp oslexec oslquery'
-BF_OSL_LIB_STATIC = '${BF_OSL}/lib/liboslcomp.a ${BF_OSL}/lib/liboslexec.a ${BF_OSL}/lib/liboslquery.a'
-BF_OSL_LIBPATH = '${BF_OSL}/lib'
-BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
-
-WITH_BF_LLVM = True
-WITH_BF_STATICLLVM = False
-BF_LLVM = '/opt/lib/llvm-3.4.2'
-BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMObject LLVMX86Info LLVMX86AsmPrinter ' + \
- 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \
- 'LLVMTarget LLVMMC LLVMCore LLVMSupport'
-BF_LLVM_LIBPATH = '${BF_LLVM}/lib'
-
-# Color management
-WITH_BF_OCIO = True
-WITH_BF_STATICOCIO = True
-BF_OCIO = '/opt/lib/ocio'
-BF_OCIO_INC = '${BF_OCIO}/include'
-BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
-BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
-
-WITH_BF_BOOST = True
-WITH_BF_STATICBOOST = True
-BF_BOOST = '/opt/lib/boost'
-BF_BOOST_INC = '${BF_BOOST}/include'
-BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \
- '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \
- ${BF_BOOST_LIBPATH}/libboost_thread.a'
-if BF_IS_NEW_OSL:
- BF_BOOST_LIB_STATIC += ' ${BF_BOOST_LIBPATH}/libboost_wave.a'
-BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
-
-# Ocean Simulation
-WITH_BF_OCEANSIM = True
-
-# OpenSubdiv
-WITH_BF_OPENSUBDIV = True
-WITH_BF_STATICOPENSUBDIV = True
-BF_OPENSUBDIV = '/opt/lib/opensubdiv'
-BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
-BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
-BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
-BF_OPENSUBDIV_LIB_STATIC = '${BF_OPENSUBDIV}/lib/libosdCPU.a ${BF_OPENSUBDIV}/lib/libosdGPU.a'
-
-# Compilation and optimization
-BF_DEBUG = False
-REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
-PLATFORM_LINKFLAGS = ['-lrt']
-if BF_IS_NEW_OSL:
- BF_PROGRAM_LINKFLAGS = ['-Wl,--version-script=source/creator/blender.map']
-else:
- BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']
diff --git a/build_files/buildbot/config/user-config-glibc211-x86_64.py b/build_files/buildbot/config/user-config-glibc211-x86_64.py
deleted file mode 100644
index 7059d50f208..00000000000
--- a/build_files/buildbot/config/user-config-glibc211-x86_64.py
+++ /dev/null
@@ -1,185 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc211-x86_64'
-BF_INSTALLDIR = '../blender-install/linux-glibc211-x86_64'
-BF_NUMJOBS = 4
-WITHOUT_BF_OVERWRITE_INSTALL = True
-
-# Python configuration
-BF_PYTHON_VERSION = '3.5'
-BF_PYTHON_ABI_FLAGS = 'm'
-BF_PYTHON = '/opt/lib/python-3.5'
-WITH_BF_PYTHON_INSTALL_NUMPY = True
-WITH_BF_PYTHON_INSTALL_REQUESTS = True
-
-WITH_BF_STATICPYTHON = True
-
-# OpenCollada configuration
-WITH_BF_COLLADA = True
-WITH_BF_STATICOPENCOLLADA=True
-BF_OPENCOLLADA = '/opt/lib/opencollada'
-BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
-BF_OPENCOLLADA_LIB_STATIC = '${BF_OPENCOLLADA}/lib/libOpenCOLLADAStreamWriter.a ' + \
- '${BF_OPENCOLLADA}/lib/libOpenCOLLADASaxFrameworkLoader.a ' + \
- '${BF_OPENCOLLADA}/lib/libOpenCOLLADAFramework.a ' + \
- '${BF_OPENCOLLADA}/lib/libOpenCOLLADABaseUtils.a ' + \
- '${BF_OPENCOLLADA}/lib/libGeneratedSaxParser.a ' + \
- '${BF_OPENCOLLADA}/lib/libMathMLSolver.a ' + \
- '${BF_OPENCOLLADA}/lib/libbuffer.a ${BF_OPENCOLLADA}/lib/libftoa.a ' + \
- '/usr/lib/libxml2.a /usr/lib/libexpat.a /usr/lib/libpcre.a'
-BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib /home/sources/staticlibs/lib64'
-BF_PCRE_LIB = ''
-BF_EXPAT_LIB = ''
-
-# FFMPEG configuration
-WITH_BF_FFMPEG = True
-WITH_BF_STATICFFMPEG = True
-
-BF_FFMPEG = '/opt/lib/ffmpeg'
-BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib'
-BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ' + \
- '${BF_FFMPEG_LIBPATH}/libavfilter.a ${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
- '${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \
- '/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \
- '/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \
- '/usr/lib/liborc-0.4.a'
-
-# Don't depend on system's libstdc++
-WITH_BF_STATICCXX = True
-BF_CXX_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7.1/libstdc++.a'
-
-WITH_BF_OPENAL = True
-WITH_BF_STATICOPENAL = True
-BF_OPENAL = '/opt/lib/openal'
-BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a /opt/lib/openal/lib/libcommon.a'
-
-WITH_BF_GETTEXT_STATIC = True
-
-WITH_BF_FREETYPE_STATIC = False
-
-WITH_BF_OPENEXR = True
-BF_OPENEXR = '/opt/lib/openexr'
-BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include'
-WITH_BF_STATICOPENEXR = True
-
-WITH_BF_TIFF = True
-WITH_BF_STATICTIFF = True
-BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a'
-
-WITH_BF_JPEG = True
-WITH_BF_STATICJPEG = True
-BF_JPEG_LIB_STATIC= '${BF_JPEG}/lib/libjpeg.a'
-
-WITH_BF_PNG = True
-WITH_BF_STATICPNG = True
-BF_PNG_LIB_STATIC = '${BF_PNG}/lib/libpng.a'
-
-WITH_BF_STATICLIBSAMPLERATE = True
-
-WITH_BF_ZLIB = True
-WITH_BF_STATICZLIB = True
-BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
-
-WITH_BF_SDL = True
-WITH_BF_SDL_DYNLOAD = True
-
-WITH_BF_OGG = True
-
-WITH_BF_OPENMP = True
-WITH_BF_STATICOPENMP = True
-BF_OPENMP_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7/libgomp.a'
-
-WITH_BF_GAMEENGINE = True
-WITH_BF_BULLET = True
-
-# Blender player (would be enabled in it's own config)
-WITH_BF_PLAYER = False
-
-# Use jemalloc memory manager
-WITH_BF_JEMALLOC = True
-WITH_BF_STATICJEMALLOC = True
-BF_JEMALLOC = '/opt/lib/jemalloc'
-BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib'
-
-# Use 3d mouse library
-WITH_BF_3DMOUSE = True
-WITH_BF_STATIC3DMOUSE = True
-BF_3DMOUSE = '/opt/lib/libspnav'
-BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib'
-
-# FFT
-WITH_BF_FFTW3 = True
-WITH_BF_STATICFFTW3 = True
-
-# JACK
-WITH_BF_JACK = True
-WITH_BF_JACK_DYNLOAD = True
-
-# Cycles
-WITH_BF_CYCLES = True
-WITH_BF_CYCLES_CUDA_BINARIES = False
-
-WITH_BF_OIIO = True
-WITH_BF_STATICOIIO = True
-BF_OIIO = '/opt/lib/oiio'
-BF_OIIO_INC = '${BF_OIIO}/include'
-BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a'
-BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
-
-BF_IS_NEW_OSL = False
-WITH_BF_CYCLES_OSL = True
-WITH_BF_STATICOSL = BF_IS_NEW_OSL
-BF_OSL = '/opt/lib/osl'
-BF_OSL_INC = '${BF_OSL}/include'
-# note oslexec would passed via program linkflags, which is needed to
-# make llvm happy with osl_allocate_closure_component
-BF_OSL_LIB = 'oslcomp oslexec oslquery'
-BF_OSL_LIB_STATIC = '${BF_OSL}/lib/liboslcomp.a ${BF_OSL}/lib/liboslexec.a ${BF_OSL}/lib/liboslquery.a'
-BF_OSL_LIBPATH = '${BF_OSL}/lib'
-BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
-
-WITH_BF_LLVM = True
-WITH_BF_STATICLLVM = False
-BF_LLVM = '/opt/lib/llvm-3.4.2'
-BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMObject LLVMX86Info LLVMX86AsmPrinter ' + \
- 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \
- 'LLVMTarget LLVMMC LLVMCore LLVMSupport'
-BF_LLVM_LIBPATH = '${BF_LLVM}/lib'
-
-# Color management
-WITH_BF_OCIO = True
-WITH_BF_STATICOCIO = True
-BF_OCIO = '/opt/lib/ocio'
-BF_OCIO_INC = '${BF_OCIO}/include'
-BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
-BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
-
-WITH_BF_BOOST = True
-WITH_BF_STATICBOOST = True
-BF_BOOST = '/opt/lib/boost'
-BF_BOOST_INC = '${BF_BOOST}/include'
-BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \
- '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \
- ${BF_BOOST_LIBPATH}/libboost_thread.a'
-if BF_IS_NEW_OSL:
- BF_BOOST_LIB_STATIC += ' ${BF_BOOST_LIBPATH}/libboost_wave.a'
-BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
-
-# Ocean Simulation
-WITH_BF_OCEANSIM = True
-
-# OpenSubdiv
-WITH_BF_OPENSUBDIV = True
-WITH_BF_STATICOPENSUBDIV = True
-BF_OPENSUBDIV = '/opt/lib/opensubdiv'
-BF_OPENSUBDIV_INC = '${BF_OPENSUBDIV}/include'
-BF_OPENSUBDIV_LIB = 'osdCPU osdGPU'
-BF_OPENSUBDIV_LIBPATH = '${BF_OPENSUBDIV}/lib'
-BF_OPENSUBDIV_LIB_STATIC = '${BF_OPENSUBDIV}/lib/libosdCPU.a ${BF_OPENSUBDIV}/lib/libosdGPU.a'
-
-# Compilation and optimization
-BF_DEBUG = False
-REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
-PLATFORM_LINKFLAGS = ['-lrt']
-if BF_IS_NEW_OSL:
- BF_PROGRAM_LINKFLAGS = ['-Wl,--version-script=source/creator/blender.map']
-else:
- BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']
diff --git a/build_files/buildbot/config/user-config-player-glibc211-i686.py b/build_files/buildbot/config/user-config-player-glibc211-i686.py
deleted file mode 100644
index 47898002ae6..00000000000
--- a/build_files/buildbot/config/user-config-player-glibc211-i686.py
+++ /dev/null
@@ -1,126 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc211-i686'
-BF_INSTALLDIR = '../blender-install/linux-glibc211-i686'
-BF_NUMJOBS = 4
-
-# Python configuration
-BF_PYTHON_VERSION = '3.5'
-BF_PYTHON_ABI_FLAGS = 'm'
-BF_PYTHON = '/opt/lib/python-3.5'
-WITH_BF_PYTHON_INSTALL_NUMPY = True
-WITH_BF_PYTHON_INSTALL_REQUESTS = True
-
-WITH_BF_STATICPYTHON = True
-
-# OpenCollada configuration
-WITH_BF_COLLADA = False
-
-# FFMPEG configuration
-WITH_BF_FFMPEG = True
-WITH_BF_STATICFFMPEG = True
-
-BF_FFMPEG = '/opt/lib/ffmpeg'
-BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib'
-BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ' + \
- '${BF_FFMPEG_LIBPATH}/libavfilter.a ${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
- '${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \
- '/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \
- '/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \
- '/usr/lib/liborc-0.4.a'
-
-# Don't depend on system's libstdc++
-WITH_BF_STATICCXX = True
-BF_CXX_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7.1/libstdc++.a'
-
-WITH_BF_OPENAL = True
-WITH_BF_STATICOPENAL = True
-BF_OPENAL = '/opt/lib/openal'
-BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a /opt/lib/openal/lib/libcommon.a'
-
-WITH_BF_GETTEXT_STATIC = True
-
-WITH_BF_FREETYPE_STATIC = False
-
-WITH_BF_OPENEXR = True
-BF_OPENEXR = '/opt/lib/openexr'
-BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include'
-WITH_BF_STATICOPENEXR = True
-
-WITH_BF_TIFF = True
-WITH_BF_STATICTIFF = True
-BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a'
-
-WITH_BF_JPEG = True
-WITH_BF_STATICJPEG = True
-BF_JPEG_LIB_STATIC= '${BF_JPEG}/lib/libjpeg.a'
-
-WITH_BF_STATICLIBSAMPLERATE = True
-
-WITH_BF_PNG = True
-WITH_BF_STATICPNG = True
-BF_PNG_LIB_STATIC = '${BF_PNG}/lib/libpng.a'
-
-WITH_BF_ZLIB = True
-WITH_BF_STATICZLIB = True
-BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
-
-WITH_BF_SDL = True
-WITH_BF_SDL_DYNLOAD = True
-
-WITH_BF_OGG = False
-
-WITH_BF_OPENMP = True
-WITH_BF_STATICOPENMP = True
-BF_OPENMP_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7/libgomp.a'
-
-WITH_BF_GAMEENGINE = True
-WITH_BF_BULLET = True
-
-# Do not build blender when building blenderplayer
-WITH_BF_NOBLENDER = True
-WITH_BF_PLAYER = True
-
-# Use jemalloc memory manager
-WITH_BF_JEMALLOC = True
-WITH_BF_STATICJEMALLOC = True
-BF_JEMALLOC = '/opt/lib/jemalloc'
-BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib'
-
-# Use 3d mouse library
-WITH_BF_3DMOUSE = True
-WITH_BF_STATIC3DMOUSE = True
-BF_3DMOUSE = '/opt/lib/libspnav'
-BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib'
-
-# Color management
-WITH_BF_OCIO = True
-WITH_BF_STATICOCIO = True
-BF_OCIO = '/opt/lib/ocio'
-BF_OCIO_INC = '${BF_OCIO}/include'
-BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
-BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
-
-WITH_BF_BOOST = True
-WITH_BF_STATICBOOST = True
-BF_BOOST = '/opt/lib/boost'
-BF_BOOST_INC = '${BF_BOOST}/include'
-BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \
- '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \
- ${BF_BOOST_LIBPATH}/libboost_thread.a'
-BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
-
-# JACK
-WITH_BF_JACK = True
-WITH_BF_JACK_DYNLOAD = True
-
-# Motion Tracking
-WITH_BF_LIBMV = False
-
-# Ocean Simulation
-WITH_BF_FFTW3 = True
-WITH_BF_STATICFFTW3 = True
-WITH_BF_OCEANSIM = True
-
-# Compilation and optimization
-BF_DEBUG = False
-REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
-PLATFORM_LINKFLAGS = ['-lrt']
diff --git a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
deleted file mode 100644
index 42068834879..00000000000
--- a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
+++ /dev/null
@@ -1,126 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc211-x86_64'
-BF_INSTALLDIR = '../blender-install/linux-glibc211-x86_64'
-BF_NUMJOBS = 4
-
-# Python configuration
-BF_PYTHON_VERSION = '3.5'
-BF_PYTHON_ABI_FLAGS = 'm'
-BF_PYTHON = '/opt/lib/python-3.5'
-WITH_BF_PYTHON_INSTALL_NUMPY = True
-WITH_BF_PYTHON_INSTALL_REQUESTS = True
-
-WITH_BF_STATICPYTHON = True
-
-# OpenCollada configuration
-WITH_BF_COLLADA = False
-
-# FFMPEG configuration
-WITH_BF_FFMPEG = True
-WITH_BF_STATICFFMPEG = True
-
-BF_FFMPEG = '/opt/lib/ffmpeg'
-BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib'
-BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ' + \
- '${BF_FFMPEG_LIBPATH}/libavfilter.a ${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
- '${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \
- '/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \
- '/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \
- '/usr/lib/liborc-0.4.a'
-
-# Don't depend on system's libstdc++
-WITH_BF_STATICCXX = True
-BF_CXX_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7.1/libstdc++.a'
-
-WITH_BF_OPENAL = True
-WITH_BF_STATICOPENAL = True
-BF_OPENAL = '/opt/lib/openal'
-BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a /opt/lib/openal/lib/libcommon.a'
-
-WITH_BF_GETTEXT_STATIC = True
-
-WITH_BF_FREETYPE_STATIC = False
-
-WITH_BF_OPENEXR = True
-BF_OPENEXR = '/opt/lib/openexr'
-BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include'
-WITH_BF_STATICOPENEXR = True
-
-WITH_BF_TIFF = True
-WITH_BF_STATICTIFF = True
-BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a'
-
-WITH_BF_JPEG = True
-WITH_BF_STATICJPEG = True
-BF_JPEG_LIB_STATIC= '${BF_JPEG}/lib/libjpeg.a'
-
-WITH_BF_STATICLIBSAMPLERATE = True
-
-WITH_BF_PNG = True
-WITH_BF_STATICPNG = True
-BF_PNG_LIB_STATIC = '${BF_PNG}/lib/libpng.a'
-
-WITH_BF_ZLIB = True
-WITH_BF_STATICZLIB = True
-BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
-
-WITH_BF_SDL = True
-WITH_BF_SDL_DYNLOAD = True
-
-WITH_BF_OGG = False
-
-WITH_BF_OPENMP = True
-WITH_BF_STATICOPENMP = True
-BF_OPENMP_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7/libgomp.a'
-
-WITH_BF_GAMEENGINE = True
-WITH_BF_BULLET = True
-
-# Do not build blender when building blenderplayer
-WITH_BF_NOBLENDER = True
-WITH_BF_PLAYER = True
-
-# Use jemalloc memory manager
-WITH_BF_JEMALLOC = True
-WITH_BF_STATICJEMALLOC = True
-BF_JEMALLOC = '/opt/lib/jemalloc'
-BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib'
-
-# Use 3d mouse library
-WITH_BF_3DMOUSE = True
-WITH_BF_STATIC3DMOUSE = True
-BF_3DMOUSE = '/opt/lib/libspnav'
-BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib'
-
-# Color management
-WITH_BF_OCIO = True
-WITH_BF_STATICOCIO = True
-BF_OCIO = '/opt/lib/ocio'
-BF_OCIO_INC = '${BF_OCIO}/include'
-BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
-BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
-
-WITH_BF_BOOST = True
-WITH_BF_STATICBOOST = True
-BF_BOOST = '/opt/lib/boost'
-BF_BOOST_INC = '${BF_BOOST}/include'
-BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \
- '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \
- ${BF_BOOST_LIBPATH}/libboost_thread.a'
-BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
-
-# JACK
-WITH_BF_JACK = True
-WITH_BF_JACK_DYNLOAD = True
-
-# Motion Tracking
-WITH_BF_LIBMV = False
-
-# Ocean Simulation
-WITH_BF_FFTW3 = True
-WITH_BF_STATICFFTW3 = True
-WITH_BF_OCEANSIM = True
-
-# Compilation and optimization
-BF_DEBUG = False
-REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
-PLATFORM_LINKFLAGS = ['-lrt']
diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg
index 7b8dd175453..b506f12b21b 100644
--- a/build_files/buildbot/master.cfg
+++ b/build_files/buildbot/master.cfg
@@ -282,11 +282,6 @@ def generic_builder(id, libdir='', branch='', rsync=False):
descriptionDone='packaged'))
if rsync:
f.addStep(rsync_step(id, branch, rsync_script))
- elif id.find('cmake') != -1:
- f.addStep(FileUpload(name='upload',
- slavesrc='buildbot_upload.zip',
- masterdest=filename,
- maxsize=150 * 1024 * 1024))
else:
f.addStep(FileUpload(name='upload',
slavesrc='buildbot_upload.zip',
@@ -303,8 +298,10 @@ def generic_builder(id, libdir='', branch='', rsync=False):
add_builder(c, 'mac_x86_64_10_6_scons', 'darwin-9.x.universal', generic_builder, hour=5)
add_builder(c, 'mac_i386_10_6_scons', 'darwin-9.x.universal', generic_builder, hour=11)
-add_builder(c, 'linux_glibc211_i386_scons', '', generic_builder, hour=1)
-add_builder(c, 'linux_glibc211_x86_64_scons', '', generic_builder, hour=2)
+#add_builder(c, 'linux_glibc211_i386_scons', '', generic_builder, hour=1)
+#add_builder(c, 'linux_glibc211_x86_64_scons', '', generic_builder, hour=2)
+add_builder(c, 'linux_glibc211_i386_cmake', '', generic_builder, hour=1)
+add_builder(c, 'linux_glibc211_x86_64_cmake', '', generic_builder, hour=2)
#add_builder(c, 'win32_scons_vc2013', 'windows_vc12', generic_builder, hour=1)
#add_builder(c, 'win64_scons_vc2013', 'win64_vc12', generic_builder, hour=2)
add_builder(c, 'win32_cmake_vc2013', 'windows_vc12', generic_builder, hour=3)
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index ee89bc90225..0afbd9f372e 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -31,47 +31,125 @@ if len(sys.argv) < 2:
builder = sys.argv[1]
# we run from build/ directory
-blender_dir = '../blender.git'
+blender_dir = os.path.join('..', 'blender.git')
if 'cmake' in builder:
# cmake
- # set build options
+ # Some fine-tuning configuration
+ blender_dir = os.path.join('..', blender_dir)
+ build_dir = os.path.abspath(os.path.join('..', 'build', builder))
+ install_dir = os.path.abspath(os.path.join('..', 'install', builder))
+ targets = ['blender']
+
+ chroot_name = None # If not None command will be delegated to that chroot
+ build_cubins = True # Whether to build Cycles CUDA kernels
+ remove_cache = False # Remove CMake cache to be sure config is totally up-to-date
+ remove_install_dir = False # Remove installation folder before building
+
+ # Config file to be used (relative to blender's sources root)
+ cmake_config_file = "build_files/cmake/config/blender_full.cmake"
+ cmake_player_config_file = None
+ cmake_cuda_config_file = None
+
+ # Set build options.
cmake_options = ['-DCMAKE_BUILD_TYPE:STRING=Release']
- if builder.endswith('mac_x86_64_cmake'):
- cmake_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=x86_64')
- elif builder.endswith('mac_i386_cmake'):
- cmake_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=i386')
- elif builder.endswith('mac_ppc_cmake'):
- cmake_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=ppc')
-
- if 'win64' in builder:
- cmake_options.append(['-G', '"Visual Studio 12 2013 Win64"'])
- elif 'win32' in builder:
- cmake_options.append(['-G', '"Visual Studio 12 2013"'])
-
- cmake_options.append("-C../blender.git/build_files/cmake/config/blender_full.cmake")
- if 'win32' not in builder:
- cmake_options.append("-DWITH_CYCLES_CUDA_BINARIES=1")
- else:
- cmake_options.append("-DWITH_CYCLES_CUDA_BINARIES=0")
- # configure and make
- retcode = subprocess.call(['cmake', blender_dir] + cmake_options)
- if retcode != 0:
- sys.exit(retcode)
-
- if 'win32' in builder:
- retcode = subprocess.call(['msbuild', 'INSTALL.vcxproj', '/Property:PlatformToolset=v120_xp', '/p:Configuration=Release'])
- elif 'win64' in builder:
- retcode = subprocess.call(['msbuild', 'INSTALL.vcxproj', '/p:Configuration=Release'])
+ if builder.startswith('mac'):
+ # Set up OSX architecture
+ if builder.endswith('x86_64_cmake'):
+ cmake_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=x86_64')
+ elif builder.endswith('i386_cmake'):
+ cmake_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=i386')
+ elif builder.endswith('ppc_cmake'):
+ cmake_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=ppc')
+
+ elif builder.startswith('win'):
+ install_dir = None
+ if builder.startswith('win64'):
+ cmake_options.append(['-G', '"Visual Studio 12 2013 Win64"'])
+ elif builder.startswith('win32'):
+ cmake_options.append(['-G', '"Visual Studio 12 2013"'])
+ build_cubins = False
+
+ elif builder.startswith('linux'):
+ remove_cache = True
+ remove_install_dir = True
+ cmake_config_file = "build_files/buildbot/config/blender_linux.cmake"
+ cmake_player_config_file = "build_files/buildbot/config/blender_linux_player.cmake"
+ # Currently unused
+ # cmake_cuda_config_file = "build_files/buildbot/config/blender_linux_cuda.cmake"
+ if builder.endswith('x86_64_cmake'):
+ chroot_name = 'buildbot_squeeze_x86_64'
+ build_cubins = True
+ targets = ['player', 'blender']
+ elif builder.endswith('i386_cmake'):
+ chroot_name = 'buildbot_squeeze_i686'
+ build_cubins = False
+ targets = ['player', 'blender']
+
+ cmake_options.append("-DWITH_CYCLES_CUDA_BINARIES=%d" % (build_cubins))
+
+ if install_dir:
+ cmake_options.append("-DCMAKE_INSTALL_PREFIX=%s" % (install_dir))
+
+ cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file))
+
+ # Prepare chroot command prefix if needed
+
+ if chroot_name:
+ chroot_prefix = ['schroot', '-c', chroot_name, '--']
else:
- retcode = subprocess.call(['make', '-s', '-j4', 'install'])
- sys.exit(retcode)
+ chroot_prefix = []
+
+ # Make sure no garbage remained from the previous run
+ # (only do it if builder requested this)
+ if remove_install_dir:
+ if os.path.isdir(install_dir):
+ shutil.rmtree(install_dir)
+
+ for target in targets:
+ print("Building target %s" % (target))
+ # Construct build directory name based on the target
+ target_build_dir = build_dir
+ if target != 'blender':
+ target_build_dir += '_' + target
+ # Make sure build directory exists and enter it
+ if not os.path.isdir(target_build_dir):
+ os.mkdir(target_build_dir)
+ os.chdir(target_build_dir)
+ # Tweaking CMake options to respect the target
+ target_cmake_options = cmake_options[:]
+ if target == 'player':
+ target_cmake_options.append("-C" + os.path.join(blender_dir, cmake_player_config_file))
+ elif target == 'cuda':
+ target_cmake_options.append("-C" + os.path.join(blender_dir, cmake_cuda_config_file))
+ # Configure the build
+ print("CMake options:")
+ print(target_cmake_options)
+ if remove_cache and os.path.exists('CMakeCache.txt'):
+ print("Removing CMake cache")
+ os.remove('CMakeCache.txt')
+ retcode = subprocess.call(chroot_prefix + ['cmake', blender_dir] + target_cmake_options)
+ if retcode != 0:
+ print('Condifuration FAILED!')
+ sys.exit(retcode)
+
+ if 'win32' in builder:
+ command = ['msbuild', 'INSTALL.vcxproj', '/Property:PlatformToolset=v120_xp', '/p:Configuration=Release']
+ elif 'win64' in builder:
+ command = ['msbuild', 'INSTALL.vcxproj', '/p:Configuration=Release']
+ else:
+ command = chroot_prefix + ['make', '-s', '-j2', 'install']
+
+ print("Executing command:")
+ print(command)
+ retcode = subprocess.call(command)
+
+ if retcode != 0:
+ sys.exit(retcode)
else:
python_bin = 'python'
- if builder.find('linux') != -1:
- python_bin = '/opt/lib/python-2.7/bin/python2.7'
# scons
os.chdir(blender_dir)
@@ -91,108 +169,14 @@ else:
buildbot_dir = os.path.dirname(os.path.realpath(__file__))
config_dir = os.path.join(buildbot_dir, 'config')
- if builder.find('linux') != -1:
- configs = []
- if builder.endswith('linux_glibc211_x86_64_scons'):
- configs = ['user-config-player-glibc211-x86_64.py',
- 'user-config-cuda-glibc211-x86_64.py',
- 'user-config-glibc211-x86_64.py'
- ]
- chroot_name = 'buildbot_squeeze_x86_64'
- cuda_chroot = 'buildbot_squeeze_x86_64'
- elif builder.endswith('linux_glibc211_i386_scons'):
- configs = ['user-config-player-glibc211-i686.py',
- 'user-config-cuda-glibc211-i686.py',
- 'user-config-glibc211-i686.py']
- chroot_name = 'buildbot_squeeze_i686'
-
- # use 64bit cuda toolkit, so there'll be no memory limit issues
- cuda_chroot = 'buildbot_squeeze_x86_64'
-
- # Compilation will happen inside of chroot environment
- prog_scons_cmd = ['schroot', '-c', chroot_name, '--'] + scons_cmd
- cuda_scons_cmd = ['schroot', '-c', cuda_chroot, '--'] + scons_cmd
-
- common_options = ['BF_INSTALLDIR=' + install_dir] + scons_options
-
- for config in configs:
- config_fpath = os.path.join(config_dir, config)
-
- scons_options = []
+ if builder.find('mac') != -1:
+ if builder.find('x86_64') != -1:
+ config = 'user-config-mac-x86_64.py'
+ else:
+ config = 'user-config-mac-i386.py'
- if config.find('player') != -1:
- scons_options.append('BF_BUILDDIR=%s_player' % (build_dir))
- elif config.find('cuda') != -1:
- scons_options.append('BF_BUILDDIR=%s_cuda' % (build_dir))
- else:
- scons_options.append('BF_BUILDDIR=%s' % (build_dir))
+ scons_options.append('BF_CONFIG=' + os.path.join(config_dir, config))
- scons_options += common_options
+ retcode = subprocess.call([python_bin, 'scons/scons.py'] + scons_options)
- if config.find('player') != -1:
- scons_options.append('blenderplayer')
- cur_scons_cmd = prog_scons_cmd
- elif config.find('cuda') != -1:
- scons_options.append('cudakernels')
- cur_scons_cmd = cuda_scons_cmd
-
- if config.find('i686') != -1:
- scons_options.append('BF_BITNESS=32')
- elif config.find('x86_64') != -1:
- scons_options.append('BF_BITNESS=64')
- else:
- scons_options.append('blender')
- cur_scons_cmd = prog_scons_cmd
-
- scons_options.append('BF_CONFIG=' + config_fpath)
-
- retcode = subprocess.call(cur_scons_cmd + scons_options)
- if retcode != 0:
- print('Error building rules with config ' + config)
- sys.exit(retcode)
-
- sys.exit(0)
- else:
- if builder.find('win') != -1:
- bitness = '32'
-
- if builder.find('win64') != -1:
- bitness = '64'
-
- scons_options.append('BF_INSTALLDIR=' + install_dir)
- scons_options.append('BF_BUILDDIR=' + build_dir)
- scons_options.append('BF_BITNESS=' + bitness)
- scons_options.append('WITH_BF_CYCLES_CUDA_BINARIES=True')
- scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe')
- if builder.find('mingw') != -1:
- scons_options.append('BF_TOOLSET=mingw')
- if builder.endswith('vc2013'):
- scons_options.append('MSVS_VERSION=12.0')
- scons_options.append('MSVC_VERSION=12.0')
- scons_options.append('WITH_BF_CYCLES_CUDA_BINARIES=1')
- scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe')
- scons_options.append('BF_NUMJOBS=1')
-
- elif builder.find('mac') != -1:
- if builder.find('x86_64') != -1:
- config = 'user-config-mac-x86_64.py'
- else:
- config = 'user-config-mac-i386.py'
-
- scons_options.append('BF_CONFIG=' + os.path.join(config_dir, config))
-
- if builder.find('win') != -1:
- if not os.path.exists(install_dir):
- os.makedirs(install_dir)
- if builder.endswith('vc2013'):
- dlls = ('msvcp120.dll', 'msvcr120.dll', 'vcomp120.dll')
- if builder.find('win64') == -1:
- dlls_path = '..\\..\\..\\redist\\x86'
- else:
- dlls_path = '..\\..\\..\\redist\\amd64'
- for dll in dlls:
- shutil.copyfile(os.path.join(dlls_path, dll), os.path.join(install_dir, dll))
-
- retcode = subprocess.call([python_bin, 'scons/scons.py'] + scons_options)
-
- sys.exit(retcode)
+ sys.exit(retcode)
diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py
index aec7cdca80a..c0f9a84ea18 100644
--- a/build_files/buildbot/slave_pack.py
+++ b/build_files/buildbot/slave_pack.py
@@ -36,95 +36,83 @@ builder = sys.argv[1]
# Never write branch if it is master.
branch = sys.argv[2] if (len(sys.argv) >= 3 and sys.argv[2] != 'master') else ''
+blender_dir = os.path.join('..', 'blender.git')
+build_dir = os.path.join('..', 'build', builder)
+install_dir = os.path.join('..', 'install', builder)
+buildbot_upload_zip = os.path.abspath(os.path.join(os.path.dirname(install_dir), "buildbot_upload.zip"))
+
+upload_filename = None # Name of the archive to be uploaded
+ # (this is the name of archive which will appear on the
+ # download page)
+upload_filepath = None # Filepath to be uploaded to the server
+ # (this folder will be packed)
+
+
+def parse_header_file(filename, define):
+ import re
+ regex = re.compile("^#\s*define\s+%s\s+(.*)" % define)
+ with open(filename, "r") as file:
+ for l in file:
+ match = regex.match(l)
+ if match:
+ return match.group(1)
+ return None
+
+
+# Make sure install directory always exists
+if not os.path.exists(install_dir):
+ os.makedirs(install_dir)
+
+
+def create_tar_bz2(src, dest, package_name):
+ # One extra to remove leading os.sep when cleaning root for package_root
+ ln = len(src) + 1
+ flist = list()
+
+ # Create list of tuples containing file and archive name
+ for root, dirs, files in os.walk(src):
+ package_root = os.path.join(package_name, root[ln:])
+ flist.extend([(os.path.join(root, file), os.path.join(package_root, file)) for file in files])
+
+ import tarfile
+ package = tarfile.open(dest, 'w:bz2')
+ for entry in flist:
+ package.add(entry[0], entry[1], recursive=False)
+ package.close()
+
+
# scons does own packaging
if builder.find('scons') != -1:
python_bin = 'python'
- if builder.find('linux') != -1:
- python_bin = '/opt/lib/python-2.7/bin/python2.7'
os.chdir('../blender.git')
scons_options = ['BF_QUICK=slnt', 'BUILDBOT_BRANCH=' + branch, 'buildslave', 'BF_FANCY=False']
buildbot_dir = os.path.dirname(os.path.realpath(__file__))
config_dir = os.path.join(buildbot_dir, 'config')
- build_dir = os.path.join('..', 'build', builder)
- install_dir = os.path.join('..', 'install', builder)
-
- if builder.find('linux') != -1:
- scons_options += ['WITH_BF_NOBLENDER=True', 'WITH_BF_PLAYER=False',
- 'BF_BUILDDIR=' + build_dir,
- 'BF_INSTALLDIR=' + install_dir,
- 'WITHOUT_BF_INSTALL=True']
-
- config = None
- bits = None
-
- if builder.endswith('linux_glibc211_x86_64_scons'):
- config = 'user-config-glibc211-x86_64.py'
- chroot_name = 'buildbot_squeeze_x86_64'
- bits = 64
- elif builder.endswith('linux_glibc211_i386_scons'):
- config = 'user-config-glibc211-i686.py'
- chroot_name = 'buildbot_squeeze_i686'
- bits = 32
-
- if config is not None:
- config_fpath = os.path.join(config_dir, config)
- scons_options.append('BF_CONFIG=' + config_fpath)
- blender = os.path.join(install_dir, 'blender')
- blenderplayer = os.path.join(install_dir, 'blenderplayer')
- subprocess.call(['schroot', '-c', chroot_name, '--', 'strip', '--strip-all', blender, blenderplayer])
+ if builder.find('mac') != -1:
+ if builder.find('x86_64') != -1:
+ config = 'user-config-mac-x86_64.py'
+ else:
+ config = 'user-config-mac-i386.py'
- extra = '/' + os.path.join('home', 'sources', 'release-builder', 'extra')
- mesalibs = os.path.join(extra, 'mesalibs' + str(bits) + '.tar.bz2')
- software_gl = os.path.join(extra, 'blender-softwaregl')
+ scons_options.append('BF_CONFIG=' + os.path.join(config_dir, config))
- os.system('tar -xpf %s -C %s' % (mesalibs, install_dir))
- os.system('cp %s %s' % (software_gl, install_dir))
- os.system('chmod 755 %s' % (os.path.join(install_dir, 'blender-softwaregl')))
-
- retcode = subprocess.call(['schroot', '-c', chroot_name, '--', python_bin, 'scons/scons.py'] + scons_options)
-
- sys.exit(retcode)
- else:
- if builder.find('win') != -1:
- bitness = '32'
-
- if builder.find('win64') != -1:
- bitness = '64'
-
- scons_options.append('BF_INSTALLDIR=' + install_dir)
- scons_options.append('BF_BUILDDIR=' + build_dir)
- scons_options.append('BF_BITNESS=' + bitness)
- scons_options.append('WITH_BF_CYCLES_CUDA_BINARIES=True')
- scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe')
- if builder.find('mingw') != -1:
- scons_options.append('BF_TOOLSET=mingw')
- if builder.endswith('vc2013'):
- scons_options.append('MSVS_VERSION=12.0')
- scons_options.append('MSVC_VERSION=12.0')
-
- elif builder.find('mac') != -1:
- if builder.find('x86_64') != -1:
- config = 'user-config-mac-x86_64.py'
- else:
- config = 'user-config-mac-i386.py'
-
- scons_options.append('BF_CONFIG=' + os.path.join(config_dir, config))
-
- retcode = subprocess.call([python_bin, 'scons/scons.py'] + scons_options)
- sys.exit(retcode)
+ retcode = subprocess.call([python_bin, 'scons/scons.py'] + scons_options)
+ sys.exit(retcode)
else:
# CMake
if 'win' in builder:
+ os.chdir(build_dir)
+
files = [f for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.zip')]
for f in files:
os.remove(f)
retcode = subprocess.call(['cpack', '-G', 'ZIP'])
result_file = [f for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.zip')][0]
- # TODO(sergey): Such magic usually happens in SCon's packaging bu we don't have it
+ # TODO(sergey): Such magic usually happens in SCon's packaging but we don't have it
# in the CMake yet. For until then we do some magic here.
tokens = result_file.split('-')
blender_version = tokens[1].split('.')
@@ -138,10 +126,9 @@ else:
os.rename(result_file, "{}.zip".format(builderified_name))
# create zip file
try:
- upload_zip = "buildbot_upload.zip"
- if os.path.exists(upload_zip):
- os.remove(upload_zip)
- z = zipfile.ZipFile(upload_zip, "w", compression=zipfile.ZIP_STORED)
+ if os.path.exists(buildbot_upload_zip):
+ os.remove(buildbot_upload_zip)
+ z = zipfile.ZipFile(buildbot_upload_zip, "w", compression=zipfile.ZIP_STORED)
z.write("{}.zip".format(builderified_name))
z.close()
sys.exit(retcode)
@@ -149,48 +136,111 @@ else:
sys.stderr.write('Create buildbot_upload.zip failed' + str(ex) + '\n')
sys.exit(1)
+ elif builder.startswith('linux_'):
+ blender = os.path.join(install_dir, 'blender')
+ blenderplayer = os.path.join(install_dir, 'blenderplayer')
+
+ buildinfo_h = os.path.join(build_dir, "source", "creator", "buildinfo.h")
+ blender_h = os.path.join(blender_dir, "source", "blender", "blenkernel", "BKE_blender.h")
-# clean release directory if it already exists
-release_dir = 'release'
+ # Get version information
+ blender_version = int(parse_header_file(blender_h, 'BLENDER_VERSION'))
+ blender_version = "%d.%d" % (blender_version // 100, blender_version % 100)
+ blender_hash = parse_header_file(buildinfo_h, 'BUILD_HASH')[1:-1]
+ blender_glibc = builder.split('_')[1]
-if os.path.exists(release_dir):
- for f in os.listdir(release_dir):
- if os.path.isfile(os.path.join(release_dir, f)):
- os.remove(os.path.join(release_dir, f))
+ if builder.endswith('x86_64_cmake'):
+ chroot_name = 'buildbot_squeeze_x86_64'
+ bits = 64
+ blender_arch = 'x86_64'
+ elif builder.endswith('i386_cmake'):
+ chroot_name = 'buildbot_squeeze_i686'
+ bits = 32
+ blender_arch = 'i686'
-# create release package
-try:
- subprocess.call(['make', 'package_archive'])
-except Exception as ex:
- sys.stderr.write('Make package release failed' + str(ex) + '\n')
- sys.exit(1)
+ # Strip all unused symbols from the binaries
+ print("Stripping binaries...")
+ chroot_prefix = ['schroot', '-c', chroot_name, '--']
+ subprocess.call(chroot_prefix + ['strip', '--strip-all', blender, blenderplayer])
-# find release directory, must exist this time
-if not os.path.exists(release_dir):
- sys.stderr.write("Failed to find release directory %r.\n" % release_dir)
- sys.exit(1)
+ print("Stripping python...")
+ py_target = os.path.join(install_dir, blender_version)
+ subprocess.call(chroot_prefix + ['find', py_target, '-iname', '*.so', '-exec', 'strip', '-s', '{}', ';'])
-# find release package
-file = None
-filepath = None
+ # Copy all specific files which are too specific to be copied by
+ # the CMake rules themselves
+ print("Copying extra scripts and libs...")
-for f in os.listdir(release_dir):
- rf = os.path.join(release_dir, f)
- if os.path.isfile(rf) and f.startswith('blender'):
- file = f
- filepath = rf
+ extra = '/' + os.path.join('home', 'sources', 'release-builder', 'extra')
+ mesalibs = os.path.join(extra, 'mesalibs' + str(bits) + '.tar.bz2')
+ software_gl = os.path.join(blender_dir, 'release', 'bin', 'blender-softwaregl')
+ icons = os.path.join(blender_dir, 'release', 'freedesktop', 'icons')
-if not file:
- sys.stderr.write("Failed to find release package.\n")
- sys.exit(1)
+ os.system('tar -xpf %s -C %s' % (mesalibs, install_dir))
+ os.system('cp %s %s' % (software_gl, install_dir))
+ os.system('cp -r %s %s' % (icons, install_dir))
+ os.system('chmod 755 %s' % (os.path.join(install_dir, 'blender-softwaregl')))
+
+ # Construct archive name
+ package_name = 'blender-%s-%s-linux-%s-%s' % (blender_version,
+ blender_hash,
+ blender_glibc,
+ blender_arch)
+ if branch != '':
+ package_name = branch + "-" + package_name
+
+ upload_filename = package_name + ".tar.bz2"
+
+ print("Creating .tar.bz2 archive")
+ upload_filepath = install_dir + '.tar.bz2'
+ create_tar_bz2(install_dir, upload_filepath, package_name)
+
+
+if upload_filepath is None:
+ # clean release directory if it already exists
+ release_dir = 'release'
+
+ if os.path.exists(release_dir):
+ for f in os.listdir(release_dir):
+ if os.path.isfile(os.path.join(release_dir, f)):
+ os.remove(os.path.join(release_dir, f))
+
+ # create release package
+ try:
+ subprocess.call(['make', 'package_archive'])
+ except Exception as ex:
+ sys.stderr.write('Make package release failed' + str(ex) + '\n')
+ sys.exit(1)
+
+ # find release directory, must exist this time
+ if not os.path.exists(release_dir):
+ sys.stderr.write("Failed to find release directory %r.\n" % release_dir)
+ sys.exit(1)
+
+ # find release package
+ file = None
+ filepath = None
+
+ for f in os.listdir(release_dir):
+ rf = os.path.join(release_dir, f)
+ if os.path.isfile(rf) and f.startswith('blender'):
+ file = f
+ filepath = rf
+
+ if not file:
+ sys.stderr.write("Failed to find release package.\n")
+ sys.exit(1)
+
+ upload_filename = file
+ upload_filepath = filepath
# create zip file
try:
- upload_zip = "buildbot_upload.zip"
+ upload_zip = os.path.join(buildbot_upload_zip)
if os.path.exists(upload_zip):
os.remove(upload_zip)
z = zipfile.ZipFile(upload_zip, "w", compression=zipfile.ZIP_STORED)
- z.write(filepath, arcname=file)
+ z.write(upload_filepath, arcname=upload_filename)
z.close()
except Exception as ex:
sys.stderr.write('Create buildbot_upload.zip failed' + str(ex) + '\n')
diff --git a/build_files/buildbot/slave_test.py b/build_files/buildbot/slave_test.py
index ef7a4b23d04..973e17a1f3b 100644
--- a/build_files/buildbot/slave_test.py
+++ b/build_files/buildbot/slave_test.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import subprocess
+import os
import sys
# get builder name
@@ -33,7 +34,24 @@ blender_dir = '../blender.git'
if "cmake" in builder:
# cmake
- retcode = subprocess.call(['ctest', '.' '--output-on-failure'])
+
+ if "linux" in builder:
+ print("Automated tests are still DISABLED!")
+ sys.exit(0)
+
+ build_dir = os.path.abspath(os.path.join('..', 'build', builder))
+ chroot_name = None
+ chroot_prefix = []
+
+ if builder.endswith('x86_64_cmake'):
+ chroot_name = 'buildbot_squeeze_x86_64'
+ elif builder.endswith('i386_cmake'):
+ chroot_name = 'buildbot_squeeze_i686'
+ if chroot_name:
+ chroot_prefix = ['schroot', '-c', chroot_name, '--']
+
+ os.chdir(build_dir)
+ retcode = subprocess.call(chroot_prefix + ['ctest', '--output-on-failure'])
sys.exit(retcode)
else:
# scons
diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake
index e4236fb4c24..9d79bdd778d 100644
--- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake
+++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake
@@ -38,7 +38,7 @@ IF(NOT PYTHON_ROOT_DIR AND NOT $ENV{PYTHON_ROOT_DIR} STREQUAL "")
SET(PYTHON_ROOT_DIR $ENV{PYTHON_ROOT_DIR})
ENDIF()
-SET(PYTHON_VERSION 3.4 CACHE STRING "Python Version (major and minor only)")
+SET(PYTHON_VERSION 3.5 CACHE STRING "Python Version (major and minor only)")
MARK_AS_ADVANCED(PYTHON_VERSION)
@@ -199,7 +199,7 @@ IF(PYTHONLIBSUNIX_FOUND)
)
# we need this for installation
- # XXX No more valid with debian-like py3.4 packages...
+ # XXX No more valid with debian-like py3.5 packages...
# GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH)
# not required for build, just used when bundling Python.
diff --git a/build_files/cmake/cmake_consistency_check_config.py b/build_files/cmake/cmake_consistency_check_config.py
index 1f75b9884bc..5345f682f58 100644
--- a/build_files/cmake/cmake_consistency_check_config.py
+++ b/build_files/cmake/cmake_consistency_check_config.py
@@ -10,9 +10,6 @@ IGNORE = (
"/ik_glut_test/",
# specific source files
- "extern/Eigen2/Eigen/src/Cholesky/CholeskyInstantiations.cpp",
- "extern/Eigen2/Eigen/src/Core/CoreInstantiations.cpp",
- "extern/Eigen2/Eigen/src/QR/QrInstantiations.cpp",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp",
diff --git a/build_files/cmake/cmake_static_check_clang_array.py b/build_files/cmake/cmake_static_check_clang_array.py
index 45b262a13ce..597d1d2b980 100644
--- a/build_files/cmake/cmake_static_check_clang_array.py
+++ b/build_files/cmake/cmake_static_check_clang_array.py
@@ -32,7 +32,6 @@ USE_QUIET = (os.environ.get("QUIET", None) is not None)
CHECKER_IGNORE_PREFIX = [
"extern",
"intern/moto",
- "blender/intern/opennl",
]
CHECKER_BIN = "python2"
diff --git a/build_files/cmake/cmake_static_check_cppcheck.py b/build_files/cmake/cmake_static_check_cppcheck.py
index 9f012cb7f6d..3504b005adc 100644
--- a/build_files/cmake/cmake_static_check_cppcheck.py
+++ b/build_files/cmake/cmake_static_check_cppcheck.py
@@ -32,7 +32,6 @@ USE_QUIET = (os.environ.get("QUIET", None) is not None)
CHECKER_IGNORE_PREFIX = [
"extern",
"intern/moto",
- "blender/intern/opennl",
]
CHECKER_BIN = "cppcheck"
diff --git a/build_files/cmake/cmake_static_check_smatch.py b/build_files/cmake/cmake_static_check_smatch.py
index de13d141276..f525187e22c 100644
--- a/build_files/cmake/cmake_static_check_smatch.py
+++ b/build_files/cmake/cmake_static_check_smatch.py
@@ -25,7 +25,6 @@
CHECKER_IGNORE_PREFIX = [
"extern",
"intern/moto",
- "blender/intern/opennl",
]
CHECKER_BIN = "smatch"
diff --git a/build_files/cmake/cmake_static_check_sparse.py b/build_files/cmake/cmake_static_check_sparse.py
index 2ee99925adb..6d1c4e3d6a2 100644
--- a/build_files/cmake/cmake_static_check_sparse.py
+++ b/build_files/cmake/cmake_static_check_sparse.py
@@ -25,7 +25,6 @@
CHECKER_IGNORE_PREFIX = [
"extern",
"intern/moto",
- "blender/intern/opennl",
]
CHECKER_BIN = "sparse"
diff --git a/build_files/cmake/cmake_static_check_splint.py b/build_files/cmake/cmake_static_check_splint.py
index 5a967ecc7a3..46d8808e89d 100644
--- a/build_files/cmake/cmake_static_check_splint.py
+++ b/build_files/cmake/cmake_static_check_splint.py
@@ -25,7 +25,6 @@
CHECKER_IGNORE_PREFIX = [
"extern",
"intern/moto",
- "blender/intern/opennl",
]
CHECKER_BIN = "splint"
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
index 881dc515499..ad8a6815675 100644
--- a/build_files/cmake/config/blender_full.cmake
+++ b/build_files/cmake/config/blender_full.cmake
@@ -10,6 +10,7 @@ set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
+set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
set(WITH_LIBMV ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
@@ -42,7 +43,6 @@ set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
set(WITH_OPENMP ON CACHE BOOL "" FORCE)
-set(WITH_OPENNL ON CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index 9e7b4dcf39b..99e90caf793 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -47,7 +47,6 @@ set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
-set(WITH_OPENNL OFF CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 90c4fbd5674..4ba15c72677 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -103,6 +103,23 @@ macro(file_list_suffix
endmacro()
+if(UNIX AND NOT APPLE)
+ macro(find_package_static)
+ set(_cmake_find_library_suffixes_back ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ find_package(${ARGV})
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${_cmake_find_library_suffixes_back})
+ unset(_cmake_find_library_suffixes_back)
+ endmacro()
+
+ macro(find_library_static)
+ set(_cmake_find_library_suffixes_back ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ find_library(${ARGV})
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${_cmake_find_library_suffixes_back})
+ unset(_cmake_find_library_suffixes_back)
+ endmacro()
+endif()
function(target_link_libraries_optimized
TARGET
@@ -452,6 +469,11 @@ function(setup_liblinks
if(WIN32 AND NOT UNIX)
target_link_libraries(${target} ${PTHREADS_LIBRARIES})
endif()
+ if(UNIX AND NOT APPLE)
+ if(WITH_OPENMP_STATIC)
+ target_link_libraries(${target} ${OpenMP_LIBRARIES})
+ endif()
+ endif()
# We put CLEW and CUEW here because OPENSUBDIV_LIBRARIES dpeends on them..
if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
@@ -574,7 +596,6 @@ function(SETUP_BLENDER_SORTED_LIBS)
ge_phys_bullet
bf_intern_smoke
extern_lzma
- extern_colamd
ge_logic_ketsji
extern_recastnavigation
ge_logic
@@ -604,12 +625,12 @@ function(SETUP_BLENDER_SORTED_LIBS)
cycles_subd
bf_intern_raskter
bf_intern_opencolorio
+ bf_intern_eigen
extern_rangetree
extern_wcwidth
extern_libmv
extern_glog
extern_sdlew
- extern_eigen3
bf_intern_glew_mx
)
@@ -676,10 +697,6 @@ function(SETUP_BLENDER_SORTED_LIBS)
list(APPEND BLENDER_SORTED_LIBS bf_intern_locale)
endif()
- if(WITH_OPENNL)
- list_insert_after(BLENDER_SORTED_LIBS "bf_render" "bf_intern_opennl")
- endif()
-
if(WITH_BULLET)
list_insert_after(BLENDER_SORTED_LIBS "bf_blenkernel" "bf_intern_rigidbody")
endif()
diff --git a/build_files/scons/Modules/FindPython.py b/build_files/scons/Modules/FindPython.py
index a0ead88ebb4..9f652b73585 100644
--- a/build_files/scons/Modules/FindPython.py
+++ b/build_files/scons/Modules/FindPython.py
@@ -6,7 +6,7 @@ def FindPython():
python = "/usr"
abi_flags = "m" # Most common for linux distros
- version = "3.4"
+ version = "3.5"
_arch = platform.uname()[4] + "-linux-gnu"
diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py
index f4b709dda81..bb28deaade2 100644
--- a/build_files/scons/config/win32-mingw-config.py
+++ b/build_files/scons/config/win32-mingw-config.py
@@ -2,7 +2,7 @@ LCGDIR = '#../lib/mingw32'
LIBDIR = "${LCGDIR}"
BF_PYTHON = LIBDIR + '/python'
-BF_PYTHON_VERSION = '3.4'
+BF_PYTHON_VERSION = '3.5'
WITH_BF_STATICPYTHON = False
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = 'python'
diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py
index 6106f2ac631..f5659a99ff5 100644
--- a/build_files/scons/config/win64-mingw-config.py
+++ b/build_files/scons/config/win64-mingw-config.py
@@ -2,7 +2,7 @@ LCGDIR = '#../lib/mingw64'
LIBDIR = "${LCGDIR}"
BF_PYTHON = LIBDIR + '/python'
-BF_PYTHON_VERSION = '3.4'
+BF_PYTHON_VERSION = '3.5'
WITH_BF_STATICPYTHON = False
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = 'python'
diff --git a/doc/doxygen/doxygen.intern.h b/doc/doxygen/doxygen.intern.h
index 2c8ecae0ead..e3cc11b3404 100644
--- a/doc/doxygen/doxygen.intern.h
+++ b/doc/doxygen/doxygen.intern.h
@@ -38,7 +38,7 @@
* \ingroup intern
*/
-/** \defgroup opennl opennl
+/** \defgroup eigen eigen
* \ingroup intern
*/
diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst
index b119bdd1ba1..3f35901234a 100644
--- a/doc/python_api/rst/bge.logic.rst
+++ b/doc/python_api/rst/bge.logic.rst
@@ -378,6 +378,76 @@ General functions
Render next frame (if Python has control)
+**********************
+Time related functions
+**********************
+
+.. function:: getClockTime()
+
+ Get the current BGE render time, in seconds. The BGE render time is the
+ simulation time corresponding to the next scene that will be rendered.
+
+ :rtype: double
+
+.. function:: getFrameTime()
+
+ Get the current BGE frame time, in seconds. The BGE frame time is the
+ simulation time corresponding to the current call of the logic system.
+ Generally speaking, it is what the user is interested in.
+
+ :rtype: double
+
+.. function:: getRealTime()
+
+ Get the number of real (system-clock) seconds elapsed since the beginning
+ of the simulation.
+
+ :rtype: double
+
+.. function:: getTimeScale()
+
+ Get the time multiplier between real-time and simulation time. The default
+ value is 1.0. A value greater than 1.0 means that the simulation is going
+ faster than real-time, a value lower than 1.0 means that the simulation is
+ going slower than real-time.
+
+ :rtype: double
+
+.. function:: setTimeScale(time_scale)
+
+ Set the time multiplier between real-time and simulation time. A value
+ greater than 1.0 means that the simulation is going faster than real-time,
+ a value lower than 1.0 means that the simulation is going slower than
+ real-time. Note that a too large value may lead to some physics
+ instabilities.
+
+ :arg time_scale: The new time multiplier.
+
+.. function:: getUseExternalClock()
+
+ Get if the BGE use the inner BGE clock, or rely or on an external
+ clock. The default is to use the inner BGE clock.
+
+ :rtype: bool
+
+.. function:: setUseExternalClock(use_external_clock)
+
+ Set if the BGE use the inner BGE clock, or rely or on an external
+ clock. If the user selects the use of an external clock, he should call
+ regularly the setClockTime method.
+
+ :arg use_external_clock: the new setting
+
+.. function:: setClockTime(new_time)
+
+ Set the next value of the simulation clock. It is preferable to use this
+ method from a custom main function in python, as calling it in the logic
+ block can easily lead to a blocked system (if the time does not advance
+ enough to run at least the next logic step).
+
+ :arg new_time: the next value of the BGE clock (in second).
+
+
*****************
Utility functions
*****************
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 93f57b04d4e..640de9d80e7 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -29,11 +29,6 @@ remove_strict_flags()
add_subdirectory(rangetree)
add_subdirectory(wcwidth)
add_subdirectory(libmv)
-add_subdirectory(Eigen3)
-
-if(WITH_OPENNL)
- add_subdirectory(colamd)
-endif()
if(WITH_BULLET)
if(NOT WITH_SYSTEM_BULLET)
diff --git a/extern/Eigen3/Eigen/Core b/extern/Eigen3/Eigen/Core
index 9131cc3fc9d..509c529e13d 100644
--- a/extern/Eigen3/Eigen/Core
+++ b/extern/Eigen3/Eigen/Core
@@ -95,7 +95,7 @@
extern "C" {
// In theory we should only include immintrin.h and not the other *mmintrin.h header files directly.
// Doing so triggers some issues with ICC. However old gcc versions seems to not have this file, thus:
- #ifdef __INTEL_COMPILER
+ #if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1110
#include <immintrin.h>
#else
#include <emmintrin.h>
@@ -123,7 +123,7 @@
#undef bool
#undef vector
#undef pixel
- #elif defined __ARM_NEON__
+ #elif defined __ARM_NEON
#define EIGEN_VECTORIZE
#define EIGEN_VECTORIZE_NEON
#include <arm_neon.h>
@@ -165,7 +165,7 @@
#endif
// required for __cpuid, needs to be included after cmath
-#if defined(_MSC_VER) && (defined(_M_IX86)||defined(_M_X64))
+#if defined(_MSC_VER) && (defined(_M_IX86)||defined(_M_X64)) && (!defined(_WIN32_WCE))
#include <intrin.h>
#endif
diff --git a/extern/Eigen3/Eigen/SparseCore b/extern/Eigen3/Eigen/SparseCore
index 9b5be5e15a9..24bcf0156b3 100644
--- a/extern/Eigen3/Eigen/SparseCore
+++ b/extern/Eigen3/Eigen/SparseCore
@@ -14,7 +14,7 @@
/**
* \defgroup SparseCore_Module SparseCore module
*
- * This module provides a sparse matrix representation, and basic associatd matrix manipulations
+ * This module provides a sparse matrix representation, and basic associated matrix manipulations
* and operations.
*
* See the \ref TutorialSparse "Sparse tutorial"
diff --git a/extern/Eigen3/Eigen/src/Cholesky/LDLT.h b/extern/Eigen3/Eigen/src/Cholesky/LDLT.h
index d026418f8a9..abd30bd916d 100644
--- a/extern/Eigen3/Eigen/src/Cholesky/LDLT.h
+++ b/extern/Eigen3/Eigen/src/Cholesky/LDLT.h
@@ -235,6 +235,11 @@ template<typename _MatrixType, int _UpLo> class LDLT
}
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
/** \internal
* Used to compute and store the Cholesky decomposition A = L D L^* = U^* D U.
@@ -274,30 +279,13 @@ template<> struct ldlt_inplace<Lower>
return true;
}
- RealScalar cutoff(0), biggest_in_corner;
-
for (Index k = 0; k < size; ++k)
{
// Find largest diagonal element
Index index_of_biggest_in_corner;
- biggest_in_corner = mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
+ mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
index_of_biggest_in_corner += k;
- if(k == 0)
- {
- // The biggest overall is the point of reference to which further diagonals
- // are compared; if any diagonal is negligible compared
- // to the largest overall, the algorithm bails.
- cutoff = abs(NumTraits<Scalar>::epsilon() * biggest_in_corner);
- }
-
- // Finish early if the matrix is not full rank.
- if(biggest_in_corner < cutoff)
- {
- for(Index i = k; i < size; i++) transpositions.coeffRef(i) = i;
- break;
- }
-
transpositions.coeffRef(k) = index_of_biggest_in_corner;
if(k != index_of_biggest_in_corner)
{
@@ -328,15 +316,20 @@ template<> struct ldlt_inplace<Lower>
if(k>0)
{
- temp.head(k) = mat.diagonal().head(k).asDiagonal() * A10.adjoint();
+ temp.head(k) = mat.diagonal().real().head(k).asDiagonal() * A10.adjoint();
mat.coeffRef(k,k) -= (A10 * temp.head(k)).value();
if(rs>0)
A21.noalias() -= A20 * temp.head(k);
}
- if((rs>0) && (abs(mat.coeffRef(k,k)) > cutoff))
- A21 /= mat.coeffRef(k,k);
-
+
+ // In some previous versions of Eigen (e.g., 3.2.1), the scaling was omitted if the pivot
+ // was smaller than the cutoff value. However, soince LDLT is not rank-revealing
+ // we should only make sure we do not introduce INF or NaN values.
+ // LAPACK also uses 0 as the cutoff value.
RealScalar realAkk = numext::real(mat.coeffRef(k,k));
+ if((rs>0) && (abs(realAkk) > RealScalar(0)))
+ A21 /= realAkk;
+
if (sign == PositiveSemiDef) {
if (realAkk < 0) sign = Indefinite;
} else if (sign == NegativeSemiDef) {
@@ -446,6 +439,8 @@ template<typename MatrixType> struct LDLT_Traits<MatrixType,Upper>
template<typename MatrixType, int _UpLo>
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
{
+ check_template_parameters();
+
eigen_assert(a.rows()==a.cols());
const Index size = a.rows();
@@ -454,6 +449,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
m_transpositions.resize(size);
m_isInitialized = false;
m_temporary.resize(size);
+ m_sign = internal::ZeroSign;
internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, m_sign);
@@ -468,7 +464,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
*/
template<typename MatrixType, int _UpLo>
template<typename Derived>
-LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename NumTraits<typename MatrixType::Scalar>::Real& sigma)
+LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename LDLT<MatrixType,_UpLo>::RealScalar& sigma)
{
const Index size = w.rows();
if (m_isInitialized)
@@ -514,16 +510,21 @@ struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs>
using std::abs;
using std::max;
typedef typename LDLTType::MatrixType MatrixType;
- typedef typename LDLTType::Scalar Scalar;
typedef typename LDLTType::RealScalar RealScalar;
- const Diagonal<const MatrixType> vectorD = dec().vectorD();
- RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() * NumTraits<Scalar>::epsilon(),
- RealScalar(1) / NumTraits<RealScalar>::highest()); // motivated by LAPACK's xGELSS
+ const typename Diagonal<const MatrixType>::RealReturnType vectorD(dec().vectorD());
+ // In some previous versions, tolerance was set to the max of 1/highest and the maximal diagonal entry * epsilon
+ // as motivated by LAPACK's xGELSS:
+ // RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() *NumTraits<RealScalar>::epsilon(),RealScalar(1) / NumTraits<RealScalar>::highest());
+ // However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the highest
+ // diagonal element is not well justified and to numerical issues in some cases.
+ // Moreover, Lapack's xSYTRS routines use 0 for the tolerance.
+ RealScalar tolerance = RealScalar(1) / NumTraits<RealScalar>::highest();
+
for (Index i = 0; i < vectorD.size(); ++i) {
if(abs(vectorD(i)) > tolerance)
- dst.row(i) /= vectorD(i);
+ dst.row(i) /= vectorD(i);
else
- dst.row(i).setZero();
+ dst.row(i).setZero();
}
// dst = L^-T (D^-1 L^-1 P b)
@@ -576,7 +577,7 @@ MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
// L^* P
res = matrixU() * res;
// D(L^*P)
- res = vectorD().asDiagonal() * res;
+ res = vectorD().real().asDiagonal() * res;
// L(DL^*P)
res = matrixL() * res;
// P^T (LDL^*P)
diff --git a/extern/Eigen3/Eigen/src/Cholesky/LLT.h b/extern/Eigen3/Eigen/src/Cholesky/LLT.h
index 2e6189f7dab..7c11a2dc29a 100644
--- a/extern/Eigen3/Eigen/src/Cholesky/LLT.h
+++ b/extern/Eigen3/Eigen/src/Cholesky/LLT.h
@@ -174,6 +174,12 @@ template<typename _MatrixType, int _UpLo> class LLT
LLT rankUpdate(const VectorType& vec, const RealScalar& sigma = 1);
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
+
/** \internal
* Used to compute and store L
* The strict upper part is not used and even not initialized.
@@ -283,7 +289,7 @@ template<typename Scalar> struct llt_inplace<Scalar, Lower>
return k;
mat.coeffRef(k,k) = x = sqrt(x);
if (k>0 && rs>0) A21.noalias() -= A20 * A10.adjoint();
- if (rs>0) A21 *= RealScalar(1)/x;
+ if (rs>0) A21 /= x;
}
return -1;
}
@@ -384,6 +390,8 @@ template<typename MatrixType> struct LLT_Traits<MatrixType,Upper>
template<typename MatrixType, int _UpLo>
LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const MatrixType& a)
{
+ check_template_parameters();
+
eigen_assert(a.rows()==a.cols());
const Index size = a.rows();
m_matrix.resize(size, size);
diff --git a/extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h b/extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h
index 64daa445cf7..66675d7476d 100644
--- a/extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h
+++ b/extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h
@@ -60,7 +60,7 @@ template<> struct mkl_llt<EIGTYPE> \
lda = m.outerStride(); \
\
info = LAPACKE_##MKLPREFIX##potrf( matrix_order, uplo, size, (MKLTYPE*)a, lda ); \
- info = (info==0) ? Success : NumericalIssue; \
+ info = (info==0) ? -1 : info>0 ? info-1 : size; \
return info; \
} \
}; \
diff --git a/extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h b/extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h
index c449960de4a..99dbe171c36 100644
--- a/extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h
+++ b/extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h
@@ -78,7 +78,7 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
{
res.itype = CHOLMOD_INT;
}
- else if (internal::is_same<_Index,UF_long>::value)
+ else if (internal::is_same<_Index,SuiteSparse_long>::value)
{
res.itype = CHOLMOD_LONG;
}
@@ -395,7 +395,7 @@ class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimpl
CholmodSimplicialLLT(const MatrixType& matrix) : Base()
{
init();
- compute(matrix);
+ Base::compute(matrix);
}
~CholmodSimplicialLLT() {}
@@ -442,7 +442,7 @@ class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimp
CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
{
init();
- compute(matrix);
+ Base::compute(matrix);
}
~CholmodSimplicialLDLT() {}
@@ -487,7 +487,7 @@ class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSuper
CholmodSupernodalLLT(const MatrixType& matrix) : Base()
{
init();
- compute(matrix);
+ Base::compute(matrix);
}
~CholmodSupernodalLLT() {}
@@ -534,7 +534,7 @@ class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecom
CholmodDecomposition(const MatrixType& matrix) : Base()
{
init();
- compute(matrix);
+ Base::compute(matrix);
}
~CholmodDecomposition() {}
diff --git a/extern/Eigen3/Eigen/src/Core/Array.h b/extern/Eigen3/Eigen/src/Core/Array.h
index 0ab03eff0f0..0b9c38c8219 100644
--- a/extern/Eigen3/Eigen/src/Core/Array.h
+++ b/extern/Eigen3/Eigen/src/Core/Array.h
@@ -124,6 +124,21 @@ class Array
}
#endif
+#ifdef EIGEN_HAVE_RVALUE_REFERENCES
+ Array(Array&& other)
+ : Base(std::move(other))
+ {
+ Base::_check_template_params();
+ if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic)
+ Base::_set_noalias(other);
+ }
+ Array& operator=(Array&& other)
+ {
+ other.swap(*this);
+ return *this;
+ }
+#endif
+
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
*
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors,
diff --git a/extern/Eigen3/Eigen/src/Core/ArrayBase.h b/extern/Eigen3/Eigen/src/Core/ArrayBase.h
index 38852600dc2..33ff553712e 100644
--- a/extern/Eigen3/Eigen/src/Core/ArrayBase.h
+++ b/extern/Eigen3/Eigen/src/Core/ArrayBase.h
@@ -46,9 +46,6 @@ template<typename Derived> class ArrayBase
typedef ArrayBase Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl;
- using internal::special_scalar_op_base<Derived,typename internal::traits<Derived>::Scalar,
- typename NumTraits<typename internal::traits<Derived>::Scalar>::Real>::operator*;
-
typedef typename internal::traits<Derived>::StorageKind StorageKind;
typedef typename internal::traits<Derived>::Index Index;
typedef typename internal::traits<Derived>::Scalar Scalar;
@@ -56,6 +53,7 @@ template<typename Derived> class ArrayBase
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef DenseBase<Derived> Base;
+ using Base::operator*;
using Base::RowsAtCompileTime;
using Base::ColsAtCompileTime;
using Base::SizeAtCompileTime;
diff --git a/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h b/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h
index a791bc3581a..b4641e2a01f 100644
--- a/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h
+++ b/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h
@@ -29,6 +29,11 @@ struct traits<ArrayWrapper<ExpressionType> >
: public traits<typename remove_all<typename ExpressionType::Nested>::type >
{
typedef ArrayXpr XprKind;
+ // Let's remove NestByRefBit
+ enum {
+ Flags0 = traits<typename remove_all<typename ExpressionType::Nested>::type >::Flags,
+ Flags = Flags0 & ~NestByRefBit
+ };
};
}
@@ -149,6 +154,11 @@ struct traits<MatrixWrapper<ExpressionType> >
: public traits<typename remove_all<typename ExpressionType::Nested>::type >
{
typedef MatrixXpr XprKind;
+ // Let's remove NestByRefBit
+ enum {
+ Flags0 = traits<typename remove_all<typename ExpressionType::Nested>::type >::Flags,
+ Flags = Flags0 & ~NestByRefBit
+ };
};
}
diff --git a/extern/Eigen3/Eigen/src/Core/Assign.h b/extern/Eigen3/Eigen/src/Core/Assign.h
index 1dccc2f4212..f4817317279 100644
--- a/extern/Eigen3/Eigen/src/Core/Assign.h
+++ b/extern/Eigen3/Eigen/src/Core/Assign.h
@@ -439,19 +439,26 @@ struct assign_impl<Derived1, Derived2, SliceVectorizedTraversal, NoUnrolling, Ve
typedef typename Derived1::Index Index;
static inline void run(Derived1 &dst, const Derived2 &src)
{
- typedef packet_traits<typename Derived1::Scalar> PacketTraits;
+ typedef typename Derived1::Scalar Scalar;
+ typedef packet_traits<Scalar> PacketTraits;
enum {
packetSize = PacketTraits::size,
alignable = PacketTraits::AlignedOnScalar,
- dstAlignment = alignable ? Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) ,
+ dstIsAligned = assign_traits<Derived1,Derived2>::DstIsAligned,
+ dstAlignment = alignable ? Aligned : int(dstIsAligned),
srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
};
+ const Scalar *dst_ptr = &dst.coeffRef(0,0);
+ if((!bool(dstIsAligned)) && (size_t(dst_ptr) % sizeof(Scalar))>0)
+ {
+ // the pointer is not aligend-on scalar, so alignment is not possible
+ return assign_impl<Derived1,Derived2,DefaultTraversal,NoUnrolling>::run(dst, src);
+ }
const Index packetAlignedMask = packetSize - 1;
const Index innerSize = dst.innerSize();
const Index outerSize = dst.outerSize();
const Index alignedStep = alignable ? (packetSize - dst.outerStride() % packetSize) & packetAlignedMask : 0;
- Index alignedStart = ((!alignable) || assign_traits<Derived1,Derived2>::DstIsAligned) ? 0
- : internal::first_aligned(&dst.coeffRef(0,0), innerSize);
+ Index alignedStart = ((!alignable) || bool(dstIsAligned)) ? 0 : internal::first_aligned(dst_ptr, innerSize);
for(Index outer = 0; outer < outerSize; ++outer)
{
diff --git a/extern/Eigen3/Eigen/src/Core/Block.h b/extern/Eigen3/Eigen/src/Core/Block.h
index 358b3188b38..82789444327 100644
--- a/extern/Eigen3/Eigen/src/Core/Block.h
+++ b/extern/Eigen3/Eigen/src/Core/Block.h
@@ -66,8 +66,9 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
: ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
: int(traits<XprType>::MaxColsAtCompileTime),
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
- IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
- : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
+ IsDense = is_same<StorageKind,Dense>::value,
+ IsRowMajor = (IsDense&&MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
+ : (IsDense&&MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
: XprTypeIsRowMajor,
HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
@@ -81,7 +82,7 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
&& (InnerStrideAtCompileTime == 1)
? PacketAccessBit : 0,
MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
- FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
+ FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (traits<XprType>::Flags&LinearAccessBit))) ? LinearAccessBit : 0,
FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
diff --git a/extern/Eigen3/Eigen/src/Core/CommaInitializer.h b/extern/Eigen3/Eigen/src/Core/CommaInitializer.h
index a96867af4d5..a036d8c3bc9 100644
--- a/extern/Eigen3/Eigen/src/Core/CommaInitializer.h
+++ b/extern/Eigen3/Eigen/src/Core/CommaInitializer.h
@@ -43,6 +43,17 @@ struct CommaInitializer
m_xpr.block(0, 0, other.rows(), other.cols()) = other;
}
+ /* Copy/Move constructor which transfers ownership. This is crucial in
+ * absence of return value optimization to avoid assertions during destruction. */
+ // FIXME in C++11 mode this could be replaced by a proper RValue constructor
+ inline CommaInitializer(const CommaInitializer& o)
+ : m_xpr(o.m_xpr), m_row(o.m_row), m_col(o.m_col), m_currentBlockRows(o.m_currentBlockRows) {
+ // Mark original object as finished. In absence of R-value references we need to const_cast:
+ const_cast<CommaInitializer&>(o).m_row = m_xpr.rows();
+ const_cast<CommaInitializer&>(o).m_col = m_xpr.cols();
+ const_cast<CommaInitializer&>(o).m_currentBlockRows = 0;
+ }
+
/* inserts a scalar value in the target matrix */
CommaInitializer& operator,(const Scalar& s)
{
diff --git a/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h b/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h
index 586f77aaf32..519a866e605 100644
--- a/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h
+++ b/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h
@@ -81,7 +81,8 @@ struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
)
),
Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
- CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + functor_traits<BinaryOp>::Cost
+ Cost0 = EIGEN_ADD_COST(LhsCoeffReadCost,RhsCoeffReadCost),
+ CoeffReadCost = EIGEN_ADD_COST(Cost0,functor_traits<BinaryOp>::Cost)
};
};
} // end namespace internal
diff --git a/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h b/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h
index f2de749f92b..f7ee60e9879 100644
--- a/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h
+++ b/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h
@@ -47,7 +47,7 @@ struct traits<CwiseUnaryOp<UnaryOp, XprType> >
Flags = _XprTypeNested::Flags & (
HereditaryBits | LinearAccessBit | AlignedBit
| (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)),
- CoeffReadCost = _XprTypeNested::CoeffReadCost + functor_traits<UnaryOp>::Cost
+ CoeffReadCost = EIGEN_ADD_COST(_XprTypeNested::CoeffReadCost, functor_traits<UnaryOp>::Cost)
};
};
}
diff --git a/extern/Eigen3/Eigen/src/Core/DenseBase.h b/extern/Eigen3/Eigen/src/Core/DenseBase.h
index c5800f6c8c8..4b371b075b8 100644
--- a/extern/Eigen3/Eigen/src/Core/DenseBase.h
+++ b/extern/Eigen3/Eigen/src/Core/DenseBase.h
@@ -40,15 +40,14 @@ static inline void check_DenseIndex_is_signed() {
*/
template<typename Derived> class DenseBase
#ifndef EIGEN_PARSED_BY_DOXYGEN
- : public internal::special_scalar_op_base<Derived,typename internal::traits<Derived>::Scalar,
- typename NumTraits<typename internal::traits<Derived>::Scalar>::Real>
+ : public internal::special_scalar_op_base<Derived, typename internal::traits<Derived>::Scalar,
+ typename NumTraits<typename internal::traits<Derived>::Scalar>::Real,
+ DenseCoeffsBase<Derived> >
#else
: public DenseCoeffsBase<Derived>
#endif // not EIGEN_PARSED_BY_DOXYGEN
{
public:
- using internal::special_scalar_op_base<Derived,typename internal::traits<Derived>::Scalar,
- typename NumTraits<typename internal::traits<Derived>::Scalar>::Real>::operator*;
class InnerIterator;
@@ -63,8 +62,9 @@ template<typename Derived> class DenseBase
typedef typename internal::traits<Derived>::Scalar Scalar;
typedef typename internal::packet_traits<Scalar>::type PacketScalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
+ typedef internal::special_scalar_op_base<Derived,Scalar,RealScalar, DenseCoeffsBase<Derived> > Base;
- typedef DenseCoeffsBase<Derived> Base;
+ using Base::operator*;
using Base::derived;
using Base::const_cast_derived;
using Base::rows;
@@ -183,10 +183,6 @@ template<typename Derived> class DenseBase
/** \returns the number of nonzero coefficients which is in practice the number
* of stored coefficients. */
inline Index nonZeros() const { return size(); }
- /** \returns true if either the number of rows or the number of columns is equal to 1.
- * In other words, this function returns
- * \code rows()==1 || cols()==1 \endcode
- * \sa rows(), cols(), IsVectorAtCompileTime. */
/** \returns the outer size.
*
@@ -266,11 +262,13 @@ template<typename Derived> class DenseBase
template<typename OtherDerived>
Derived& operator=(const ReturnByValue<OtherDerived>& func);
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- /** Copies \a other into *this without evaluating other. \returns a reference to *this. */
+ /** \internal Copies \a other into *this without evaluating other. \returns a reference to *this. */
template<typename OtherDerived>
Derived& lazyAssign(const DenseBase<OtherDerived>& other);
-#endif // not EIGEN_PARSED_BY_DOXYGEN
+
+ /** \internal Evaluates \a other into *this. \returns a reference to *this. */
+ template<typename OtherDerived>
+ Derived& lazyAssign(const ReturnByValue<OtherDerived>& other);
CommaInitializer<Derived> operator<< (const Scalar& s);
@@ -462,8 +460,10 @@ template<typename Derived> class DenseBase
template<int p> RealScalar lpNorm() const;
template<int RowFactor, int ColFactor>
- const Replicate<Derived,RowFactor,ColFactor> replicate() const;
- const Replicate<Derived,Dynamic,Dynamic> replicate(Index rowFacor,Index colFactor) const;
+ inline const Replicate<Derived,RowFactor,ColFactor> replicate() const;
+
+ typedef Replicate<Derived,Dynamic,Dynamic> ReplicateReturnType;
+ inline const ReplicateReturnType replicate(Index rowFacor,Index colFactor) const;
typedef Reverse<Derived, BothDirections> ReverseReturnType;
typedef const Reverse<const Derived, BothDirections> ConstReverseReturnType;
diff --git a/extern/Eigen3/Eigen/src/Core/DenseStorage.h b/extern/Eigen3/Eigen/src/Core/DenseStorage.h
index 3e7f9c1b7a7..568493cbae0 100644
--- a/extern/Eigen3/Eigen/src/Core/DenseStorage.h
+++ b/extern/Eigen3/Eigen/src/Core/DenseStorage.h
@@ -24,6 +24,14 @@ namespace internal {
struct constructor_without_unaligned_array_assert {};
+template<typename T, int Size> void check_static_allocation_size()
+{
+ // if EIGEN_STACK_ALLOCATION_LIMIT is defined to 0, then no limit
+ #if EIGEN_STACK_ALLOCATION_LIMIT
+ EIGEN_STATIC_ASSERT(Size * sizeof(T) <= EIGEN_STACK_ALLOCATION_LIMIT, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
+ #endif
+}
+
/** \internal
* Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned:
* to 16 bytes boundary if the total size is a multiple of 16 bytes.
@@ -38,12 +46,12 @@ struct plain_array
plain_array()
{
- EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
+ check_static_allocation_size<T,Size>();
}
plain_array(constructor_without_unaligned_array_assert)
{
- EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
+ check_static_allocation_size<T,Size>();
}
};
@@ -76,12 +84,12 @@ struct plain_array<T, Size, MatrixOrArrayOptions, 16>
plain_array()
{
EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf);
- EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
+ check_static_allocation_size<T,Size>();
}
plain_array(constructor_without_unaligned_array_assert)
{
- EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
+ check_static_allocation_size<T,Size>();
}
};
@@ -114,33 +122,41 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
{
internal::plain_array<T,Size,_Options> m_data;
public:
- inline DenseStorage() {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert)
+ DenseStorage() {}
+ DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(internal::constructor_without_unaligned_array_assert()) {}
- inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
- inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
- static inline DenseIndex rows(void) {return _Rows;}
- static inline DenseIndex cols(void) {return _Cols;}
- inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
- inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
- inline const T *data() const { return m_data.array; }
- inline T *data() { return m_data.array; }
+ DenseStorage(const DenseStorage& other) : m_data(other.m_data) {}
+ DenseStorage& operator=(const DenseStorage& other)
+ {
+ if (this != &other) m_data = other.m_data;
+ return *this;
+ }
+ DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
+ void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
+ static DenseIndex rows(void) {return _Rows;}
+ static DenseIndex cols(void) {return _Cols;}
+ void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
+ void resize(DenseIndex,DenseIndex,DenseIndex) {}
+ const T *data() const { return m_data.array; }
+ T *data() { return m_data.array; }
};
// null matrix
template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
{
public:
- inline DenseStorage() {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert) {}
- inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
- inline void swap(DenseStorage& ) {}
- static inline DenseIndex rows(void) {return _Rows;}
- static inline DenseIndex cols(void) {return _Cols;}
- inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
- inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
- inline const T *data() const { return 0; }
- inline T *data() { return 0; }
+ DenseStorage() {}
+ DenseStorage(internal::constructor_without_unaligned_array_assert) {}
+ DenseStorage(const DenseStorage&) {}
+ DenseStorage& operator=(const DenseStorage&) { return *this; }
+ DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
+ void swap(DenseStorage& ) {}
+ static DenseIndex rows(void) {return _Rows;}
+ static DenseIndex cols(void) {return _Cols;}
+ void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
+ void resize(DenseIndex,DenseIndex,DenseIndex) {}
+ const T *data() const { return 0; }
+ T *data() { return 0; }
};
// more specializations for null matrices; these are necessary to resolve ambiguities
@@ -160,18 +176,29 @@ template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic
DenseIndex m_rows;
DenseIndex m_cols;
public:
- inline DenseStorage() : m_rows(0), m_cols(0) {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert)
+ DenseStorage() : m_rows(0), m_cols(0) {}
+ DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
- inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) : m_rows(nbRows), m_cols(nbCols) {}
- inline void swap(DenseStorage& other)
+ DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows), m_cols(other.m_cols) {}
+ DenseStorage& operator=(const DenseStorage& other)
+ {
+ if (this != &other)
+ {
+ m_data = other.m_data;
+ m_rows = other.m_rows;
+ m_cols = other.m_cols;
+ }
+ return *this;
+ }
+ DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) : m_rows(nbRows), m_cols(nbCols) {}
+ void swap(DenseStorage& other)
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
- inline DenseIndex rows() const {return m_rows;}
- inline DenseIndex cols() const {return m_cols;}
- inline void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
- inline void resize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
- inline const T *data() const { return m_data.array; }
- inline T *data() { return m_data.array; }
+ DenseIndex rows() const {return m_rows;}
+ DenseIndex cols() const {return m_cols;}
+ void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
+ void resize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
+ const T *data() const { return m_data.array; }
+ T *data() { return m_data.array; }
};
// dynamic-size matrix with fixed-size storage and fixed width
@@ -180,17 +207,27 @@ template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Si
internal::plain_array<T,Size,_Options> m_data;
DenseIndex m_rows;
public:
- inline DenseStorage() : m_rows(0) {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert)
+ DenseStorage() : m_rows(0) {}
+ DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
- inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex) : m_rows(nbRows) {}
- inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
- inline DenseIndex rows(void) const {return m_rows;}
- inline DenseIndex cols(void) const {return _Cols;}
- inline void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
- inline void resize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
- inline const T *data() const { return m_data.array; }
- inline T *data() { return m_data.array; }
+ DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows) {}
+ DenseStorage& operator=(const DenseStorage& other)
+ {
+ if (this != &other)
+ {
+ m_data = other.m_data;
+ m_rows = other.m_rows;
+ }
+ return *this;
+ }
+ DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex) : m_rows(nbRows) {}
+ void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
+ DenseIndex rows(void) const {return m_rows;}
+ DenseIndex cols(void) const {return _Cols;}
+ void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
+ void resize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
+ const T *data() const { return m_data.array; }
+ T *data() { return m_data.array; }
};
// dynamic-size matrix with fixed-size storage and fixed height
@@ -199,17 +236,27 @@ template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Si
internal::plain_array<T,Size,_Options> m_data;
DenseIndex m_cols;
public:
- inline DenseStorage() : m_cols(0) {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert)
+ DenseStorage() : m_cols(0) {}
+ DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
- inline DenseStorage(DenseIndex, DenseIndex, DenseIndex nbCols) : m_cols(nbCols) {}
- inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
- inline DenseIndex rows(void) const {return _Rows;}
- inline DenseIndex cols(void) const {return m_cols;}
- inline void conservativeResize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
- inline void resize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
- inline const T *data() const { return m_data.array; }
- inline T *data() { return m_data.array; }
+ DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_cols(other.m_cols) {}
+ DenseStorage& operator=(const DenseStorage& other)
+ {
+ if (this != &other)
+ {
+ m_data = other.m_data;
+ m_cols = other.m_cols;
+ }
+ return *this;
+ }
+ DenseStorage(DenseIndex, DenseIndex, DenseIndex nbCols) : m_cols(nbCols) {}
+ void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
+ DenseIndex rows(void) const {return _Rows;}
+ DenseIndex cols(void) const {return m_cols;}
+ void conservativeResize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
+ void resize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
+ const T *data() const { return m_data.array; }
+ T *data() { return m_data.array; }
};
// purely dynamic matrix.
@@ -219,18 +266,35 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
DenseIndex m_rows;
DenseIndex m_cols;
public:
- inline DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert)
+ DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
+ DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(0), m_rows(0), m_cols(0) {}
- inline DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
+ DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows), m_cols(nbCols)
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
- inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
- inline void swap(DenseStorage& other)
+#ifdef EIGEN_HAVE_RVALUE_REFERENCES
+ DenseStorage(DenseStorage&& other)
+ : m_data(std::move(other.m_data))
+ , m_rows(std::move(other.m_rows))
+ , m_cols(std::move(other.m_cols))
+ {
+ other.m_data = nullptr;
+ }
+ DenseStorage& operator=(DenseStorage&& other)
+ {
+ using std::swap;
+ swap(m_data, other.m_data);
+ swap(m_rows, other.m_rows);
+ swap(m_cols, other.m_cols);
+ return *this;
+ }
+#endif
+ ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
+ void swap(DenseStorage& other)
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
- inline DenseIndex rows(void) const {return m_rows;}
- inline DenseIndex cols(void) const {return m_cols;}
- inline void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
+ DenseIndex rows(void) const {return m_rows;}
+ DenseIndex cols(void) const {return m_cols;}
+ void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
{
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
m_rows = nbRows;
@@ -250,8 +314,11 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
m_rows = nbRows;
m_cols = nbCols;
}
- inline const T *data() const { return m_data; }
- inline T *data() { return m_data; }
+ const T *data() const { return m_data; }
+ T *data() { return m_data; }
+ private:
+ DenseStorage(const DenseStorage&);
+ DenseStorage& operator=(const DenseStorage&);
};
// matrix with dynamic width and fixed height (so that matrix has dynamic size).
@@ -260,15 +327,30 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
T *m_data;
DenseIndex m_cols;
public:
- inline DenseStorage() : m_data(0), m_cols(0) {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
- inline DenseStorage(DenseIndex size, DenseIndex, DenseIndex nbCols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(nbCols)
+ DenseStorage() : m_data(0), m_cols(0) {}
+ DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
+ DenseStorage(DenseIndex size, DenseIndex, DenseIndex nbCols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(nbCols)
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
- inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
- inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
- static inline DenseIndex rows(void) {return _Rows;}
- inline DenseIndex cols(void) const {return m_cols;}
- inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex nbCols)
+#ifdef EIGEN_HAVE_RVALUE_REFERENCES
+ DenseStorage(DenseStorage&& other)
+ : m_data(std::move(other.m_data))
+ , m_cols(std::move(other.m_cols))
+ {
+ other.m_data = nullptr;
+ }
+ DenseStorage& operator=(DenseStorage&& other)
+ {
+ using std::swap;
+ swap(m_data, other.m_data);
+ swap(m_cols, other.m_cols);
+ return *this;
+ }
+#endif
+ ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
+ void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
+ static DenseIndex rows(void) {return _Rows;}
+ DenseIndex cols(void) const {return m_cols;}
+ void conservativeResize(DenseIndex size, DenseIndex, DenseIndex nbCols)
{
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
m_cols = nbCols;
@@ -286,8 +368,11 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
}
m_cols = nbCols;
}
- inline const T *data() const { return m_data; }
- inline T *data() { return m_data; }
+ const T *data() const { return m_data; }
+ T *data() { return m_data; }
+ private:
+ DenseStorage(const DenseStorage&);
+ DenseStorage& operator=(const DenseStorage&);
};
// matrix with dynamic height and fixed width (so that matrix has dynamic size).
@@ -296,15 +381,30 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
T *m_data;
DenseIndex m_rows;
public:
- inline DenseStorage() : m_data(0), m_rows(0) {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
- inline DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows)
+ DenseStorage() : m_data(0), m_rows(0) {}
+ DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
+ DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows)
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
- inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
- inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
- inline DenseIndex rows(void) const {return m_rows;}
- static inline DenseIndex cols(void) {return _Cols;}
- inline void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex)
+#ifdef EIGEN_HAVE_RVALUE_REFERENCES
+ DenseStorage(DenseStorage&& other)
+ : m_data(std::move(other.m_data))
+ , m_rows(std::move(other.m_rows))
+ {
+ other.m_data = nullptr;
+ }
+ DenseStorage& operator=(DenseStorage&& other)
+ {
+ using std::swap;
+ swap(m_data, other.m_data);
+ swap(m_rows, other.m_rows);
+ return *this;
+ }
+#endif
+ ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
+ void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
+ DenseIndex rows(void) const {return m_rows;}
+ static DenseIndex cols(void) {return _Cols;}
+ void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex)
{
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
m_rows = nbRows;
@@ -322,8 +422,11 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
}
m_rows = nbRows;
}
- inline const T *data() const { return m_data; }
- inline T *data() { return m_data; }
+ const T *data() const { return m_data; }
+ T *data() { return m_data; }
+ private:
+ DenseStorage(const DenseStorage&);
+ DenseStorage& operator=(const DenseStorage&);
};
} // end namespace Eigen
diff --git a/extern/Eigen3/Eigen/src/Core/Diagonal.h b/extern/Eigen3/Eigen/src/Core/Diagonal.h
index aab8007b3fc..68cf6d4b044 100644
--- a/extern/Eigen3/Eigen/src/Core/Diagonal.h
+++ b/extern/Eigen3/Eigen/src/Core/Diagonal.h
@@ -190,18 +190,18 @@ MatrixBase<Derived>::diagonal() const
*
* \sa MatrixBase::diagonal(), class Diagonal */
template<typename Derived>
-inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<DynamicIndex>::Type
+inline typename MatrixBase<Derived>::DiagonalDynamicIndexReturnType
MatrixBase<Derived>::diagonal(Index index)
{
- return typename DiagonalIndexReturnType<DynamicIndex>::Type(derived(), index);
+ return DiagonalDynamicIndexReturnType(derived(), index);
}
/** This is the const version of diagonal(Index). */
template<typename Derived>
-inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<DynamicIndex>::Type
+inline typename MatrixBase<Derived>::ConstDiagonalDynamicIndexReturnType
MatrixBase<Derived>::diagonal(Index index) const
{
- return typename ConstDiagonalIndexReturnType<DynamicIndex>::Type(derived(), index);
+ return ConstDiagonalDynamicIndexReturnType(derived(), index);
}
/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this
diff --git a/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h b/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h
index c03a0c2e12b..cc6b536e199 100644
--- a/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h
+++ b/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h
@@ -34,8 +34,9 @@ struct traits<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
_LinearAccessMask = (RowsAtCompileTime==1 || ColsAtCompileTime==1) ? LinearAccessBit : 0,
- Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0) | AlignedBit,//(int(MatrixType::Flags)&int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit),
- CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost
+ Flags = ((HereditaryBits|_LinearAccessMask|AlignedBit) & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0),//(int(MatrixType::Flags)&int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit),
+ Cost0 = EIGEN_ADD_COST(NumTraits<Scalar>::MulCost, MatrixType::CoeffReadCost),
+ CoeffReadCost = EIGEN_ADD_COST(Cost0,DiagonalType::DiagonalVectorType::CoeffReadCost)
};
};
}
diff --git a/extern/Eigen3/Eigen/src/Core/Functors.h b/extern/Eigen3/Eigen/src/Core/Functors.h
index 04fb217323d..5f14c6587e0 100644
--- a/extern/Eigen3/Eigen/src/Core/Functors.h
+++ b/extern/Eigen3/Eigen/src/Core/Functors.h
@@ -259,6 +259,47 @@ template<> struct functor_traits<scalar_boolean_or_op> {
};
};
+/** \internal
+ * \brief Template functors for comparison of two scalars
+ * \todo Implement packet-comparisons
+ */
+template<typename Scalar, ComparisonName cmp> struct scalar_cmp_op;
+
+template<typename Scalar, ComparisonName cmp>
+struct functor_traits<scalar_cmp_op<Scalar, cmp> > {
+ enum {
+ Cost = NumTraits<Scalar>::AddCost,
+ PacketAccess = false
+ };
+};
+
+template<ComparisonName Cmp, typename Scalar>
+struct result_of<scalar_cmp_op<Scalar, Cmp>(Scalar,Scalar)> {
+ typedef bool type;
+};
+
+
+template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_EQ> {
+ EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
+ EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a==b;}
+};
+template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_LT> {
+ EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
+ EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a<b;}
+};
+template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_LE> {
+ EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
+ EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a<=b;}
+};
+template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_UNORD> {
+ EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
+ EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return !(a<=b || b<=a);}
+};
+template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_NEQ> {
+ EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
+ EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a!=b;}
+};
+
// unary functors:
/** \internal
@@ -589,7 +630,7 @@ struct linspaced_op_impl<Scalar,true>
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const
- { return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(i),m_interPacket))); }
+ { return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(Scalar(i)),m_interPacket))); }
const Scalar m_low;
const Scalar m_step;
@@ -609,7 +650,7 @@ template <typename Scalar, bool RandomAccess> struct functor_traits< linspaced_o
template <typename Scalar, bool RandomAccess> struct linspaced_op
{
typedef typename packet_traits<Scalar>::type Packet;
- linspaced_op(const Scalar& low, const Scalar& high, DenseIndex num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/(num_steps-1))) {}
+ linspaced_op(const Scalar& low, const Scalar& high, DenseIndex num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1))) {}
template<typename Index>
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
diff --git a/extern/Eigen3/Eigen/src/Core/GeneralProduct.h b/extern/Eigen3/Eigen/src/Core/GeneralProduct.h
index 2a59d94645e..0eae529909f 100644
--- a/extern/Eigen3/Eigen/src/Core/GeneralProduct.h
+++ b/extern/Eigen3/Eigen/src/Core/GeneralProduct.h
@@ -232,7 +232,7 @@ EIGEN_DONT_INLINE void outer_product_selector_run(const ProductType& prod, Dest&
// FIXME not very good if rhs is real and lhs complex while alpha is real too
const Index cols = dest.cols();
for (Index j=0; j<cols; ++j)
- func(dest.col(j), prod.rhs().coeff(j) * prod.lhs());
+ func(dest.col(j), prod.rhs().coeff(0,j) * prod.lhs());
}
// Row major
@@ -243,7 +243,7 @@ EIGEN_DONT_INLINE void outer_product_selector_run(const ProductType& prod, Dest&
// FIXME not very good if lhs is real and rhs complex while alpha is real too
const Index rows = dest.rows();
for (Index i=0; i<rows; ++i)
- func(dest.row(i), prod.lhs().coeff(i) * prod.rhs());
+ func(dest.row(i), prod.lhs().coeff(i,0) * prod.rhs());
}
template<typename Lhs, typename Rhs>
@@ -257,7 +257,7 @@ template<typename Lhs, typename Rhs>
class GeneralProduct<Lhs, Rhs, OuterProduct>
: public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
{
- template<typename T> struct IsRowMajor : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
+ template<typename T> struct is_row_major : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
public:
EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
@@ -281,22 +281,22 @@ class GeneralProduct<Lhs, Rhs, OuterProduct>
template<typename Dest>
inline void evalTo(Dest& dest) const {
- internal::outer_product_selector_run(*this, dest, set(), IsRowMajor<Dest>());
+ internal::outer_product_selector_run(*this, dest, set(), is_row_major<Dest>());
}
template<typename Dest>
inline void addTo(Dest& dest) const {
- internal::outer_product_selector_run(*this, dest, add(), IsRowMajor<Dest>());
+ internal::outer_product_selector_run(*this, dest, add(), is_row_major<Dest>());
}
template<typename Dest>
inline void subTo(Dest& dest) const {
- internal::outer_product_selector_run(*this, dest, sub(), IsRowMajor<Dest>());
+ internal::outer_product_selector_run(*this, dest, sub(), is_row_major<Dest>());
}
template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
{
- internal::outer_product_selector_run(*this, dest, adds(alpha), IsRowMajor<Dest>());
+ internal::outer_product_selector_run(*this, dest, adds(alpha), is_row_major<Dest>());
}
};
diff --git a/extern/Eigen3/Eigen/src/Core/MapBase.h b/extern/Eigen3/Eigen/src/Core/MapBase.h
index 6876de588c0..a9828f7f4b2 100644
--- a/extern/Eigen3/Eigen/src/Core/MapBase.h
+++ b/extern/Eigen3/Eigen/src/Core/MapBase.h
@@ -123,7 +123,7 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
}
- inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
+ explicit inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
{
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
checkSanity();
@@ -157,7 +157,7 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
internal::inner_stride_at_compile_time<Derived>::ret==1),
PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1);
eigen_assert(EIGEN_IMPLIES(internal::traits<Derived>::Flags&AlignedBit, (size_t(m_data) % 16) == 0)
- && "data is not aligned");
+ && "input pointer is not aligned on a 16 byte boundary");
}
PointerType m_data;
@@ -168,6 +168,7 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
template<typename Derived> class MapBase<Derived, WriteAccessors>
: public MapBase<Derived, ReadOnlyAccessors>
{
+ typedef MapBase<Derived, ReadOnlyAccessors> ReadOnlyMapBase;
public:
typedef MapBase<Derived, ReadOnlyAccessors> Base;
@@ -230,13 +231,17 @@ template<typename Derived> class MapBase<Derived, WriteAccessors>
Derived& operator=(const MapBase& other)
{
- Base::Base::operator=(other);
+ ReadOnlyMapBase::Base::operator=(other);
return derived();
}
- using Base::Base::operator=;
+ // In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base,
+ // see bugs 821 and 920.
+ using ReadOnlyMapBase::Base::operator=;
};
+#undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS
+
} // end namespace Eigen
#endif // EIGEN_MAPBASE_H
diff --git a/extern/Eigen3/Eigen/src/Core/MathFunctions.h b/extern/Eigen3/Eigen/src/Core/MathFunctions.h
index 2bfc5ebd98a..adf2f9c511b 100644
--- a/extern/Eigen3/Eigen/src/Core/MathFunctions.h
+++ b/extern/Eigen3/Eigen/src/Core/MathFunctions.h
@@ -294,7 +294,7 @@ struct hypot_impl
RealScalar _x = abs(x);
RealScalar _y = abs(y);
RealScalar p = (max)(_x, _y);
- if(p==RealScalar(0)) return 0;
+ if(p==RealScalar(0)) return RealScalar(0);
RealScalar q = (min)(_x, _y);
RealScalar qp = q/p;
return p * sqrt(RealScalar(1) + qp*qp);
diff --git a/extern/Eigen3/Eigen/src/Core/Matrix.h b/extern/Eigen3/Eigen/src/Core/Matrix.h
index d7d0b5b9a4f..02be142d8cc 100644
--- a/extern/Eigen3/Eigen/src/Core/Matrix.h
+++ b/extern/Eigen3/Eigen/src/Core/Matrix.h
@@ -211,6 +211,21 @@ class Matrix
: Base(internal::constructor_without_unaligned_array_assert())
{ Base::_check_template_params(); EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED }
+#ifdef EIGEN_HAVE_RVALUE_REFERENCES
+ Matrix(Matrix&& other)
+ : Base(std::move(other))
+ {
+ Base::_check_template_params();
+ if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic)
+ Base::_set_noalias(other);
+ }
+ Matrix& operator=(Matrix&& other)
+ {
+ other.swap(*this);
+ return *this;
+ }
+#endif
+
/** \brief Constructs a vector or row-vector with given dimension. \only_for_vectors
*
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors,
diff --git a/extern/Eigen3/Eigen/src/Core/MatrixBase.h b/extern/Eigen3/Eigen/src/Core/MatrixBase.h
index 344b38f2fc7..e83ef4dc056 100644
--- a/extern/Eigen3/Eigen/src/Core/MatrixBase.h
+++ b/extern/Eigen3/Eigen/src/Core/MatrixBase.h
@@ -159,13 +159,11 @@ template<typename Derived> class MatrixBase
template<typename OtherDerived>
Derived& operator=(const ReturnByValue<OtherDerived>& other);
-#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename ProductDerived, typename Lhs, typename Rhs>
Derived& lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other);
template<typename MatrixPower, typename Lhs, typename Rhs>
Derived& lazyAssign(const MatrixPowerProduct<MatrixPower, Lhs,Rhs>& other);
-#endif // not EIGEN_PARSED_BY_DOXYGEN
template<typename OtherDerived>
Derived& operator+=(const MatrixBase<OtherDerived>& other);
@@ -215,7 +213,7 @@ template<typename Derived> class MatrixBase
typedef Diagonal<Derived> DiagonalReturnType;
DiagonalReturnType diagonal();
- typedef typename internal::add_const<Diagonal<const Derived> >::type ConstDiagonalReturnType;
+ typedef typename internal::add_const<Diagonal<const Derived> >::type ConstDiagonalReturnType;
ConstDiagonalReturnType diagonal() const;
template<int Index> struct DiagonalIndexReturnType { typedef Diagonal<Derived,Index> Type; };
@@ -223,16 +221,12 @@ template<typename Derived> class MatrixBase
template<int Index> typename DiagonalIndexReturnType<Index>::Type diagonal();
template<int Index> typename ConstDiagonalIndexReturnType<Index>::Type diagonal() const;
+
+ typedef Diagonal<Derived,DynamicIndex> DiagonalDynamicIndexReturnType;
+ typedef typename internal::add_const<Diagonal<const Derived,DynamicIndex> >::type ConstDiagonalDynamicIndexReturnType;
- // Note: The "MatrixBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations.
- // On the other hand they confuse MSVC8...
- #if (defined _MSC_VER) && (_MSC_VER >= 1500) // 2008 or later
- typename MatrixBase::template DiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index);
- typename MatrixBase::template ConstDiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index) const;
- #else
- typename DiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index);
- typename ConstDiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index) const;
- #endif
+ DiagonalDynamicIndexReturnType diagonal(Index index);
+ ConstDiagonalDynamicIndexReturnType diagonal(Index index) const;
#ifdef EIGEN2_SUPPORT
template<unsigned int Mode> typename internal::eigen2_part_return_type<Derived, Mode>::type part();
@@ -446,6 +440,15 @@ template<typename Derived> class MatrixBase
template<typename OtherScalar>
void applyOnTheRight(Index p, Index q, const JacobiRotation<OtherScalar>& j);
+///////// SparseCore module /////////
+
+ template<typename OtherDerived>
+ EIGEN_STRONG_INLINE const typename SparseMatrixBase<OtherDerived>::template CwiseProductDenseReturnType<Derived>::Type
+ cwiseProduct(const SparseMatrixBase<OtherDerived> &other) const
+ {
+ return other.cwiseProduct(derived());
+ }
+
///////// MatrixFunctions module /////////
typedef typename internal::stem_function<Scalar>::type StemFunction;
diff --git a/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h b/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h
index 1297b8413fb..85ffae2653b 100644
--- a/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h
+++ b/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h
@@ -250,6 +250,35 @@ class PermutationBase : public EigenBase<Derived>
template<typename Other> friend
inline PlainPermutationType operator*(const Transpose<PermutationBase<Other> >& other, const PermutationBase& perm)
{ return PlainPermutationType(internal::PermPermProduct, other.eval(), perm); }
+
+ /** \returns the determinant of the permutation matrix, which is either 1 or -1 depending on the parity of the permutation.
+ *
+ * This function is O(\c n) procedure allocating a buffer of \c n booleans.
+ */
+ Index determinant() const
+ {
+ Index res = 1;
+ Index n = size();
+ Matrix<bool,RowsAtCompileTime,1,0,MaxRowsAtCompileTime> mask(n);
+ mask.fill(false);
+ Index r = 0;
+ while(r < n)
+ {
+ // search for the next seed
+ while(r<n && mask[r]) r++;
+ if(r>=n)
+ break;
+ // we got one, let's follow it until we are back to the seed
+ Index k0 = r++;
+ mask.coeffRef(k0) = true;
+ for(Index k=indices().coeff(k0); k!=k0; k=indices().coeff(k))
+ {
+ mask.coeffRef(k) = true;
+ res = -res;
+ }
+ }
+ return res;
+ }
protected:
@@ -555,7 +584,10 @@ struct permut_matrix_product_retval
const Index n = Side==OnTheLeft ? rows() : cols();
// FIXME we need an is_same for expression that is not sensitive to constness. For instance
// is_same_xpr<Block<const Matrix>, Block<Matrix> >::value should be true.
- if(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix))
+ if( is_same<MatrixTypeNestedCleaned,Dest>::value
+ && blas_traits<MatrixTypeNestedCleaned>::HasUsableDirectAccess
+ && blas_traits<Dest>::HasUsableDirectAccess
+ && extract_data(dst) == extract_data(m_matrix))
{
// apply the permutation inplace
Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size());
diff --git a/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h b/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h
index dd34b59e541..a4e4af4a7b2 100644
--- a/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h
+++ b/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h
@@ -437,6 +437,36 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
}
#endif
+#ifdef EIGEN_HAVE_RVALUE_REFERENCES
+ PlainObjectBase(PlainObjectBase&& other)
+ : m_storage( std::move(other.m_storage) )
+ {
+ }
+
+ PlainObjectBase& operator=(PlainObjectBase&& other)
+ {
+ using std::swap;
+ swap(m_storage, other.m_storage);
+ return *this;
+ }
+#endif
+
+ /** Copy constructor */
+ EIGEN_STRONG_INLINE PlainObjectBase(const PlainObjectBase& other)
+ : m_storage()
+ {
+ _check_template_params();
+ lazyAssign(other);
+ }
+
+ template<typename OtherDerived>
+ EIGEN_STRONG_INLINE PlainObjectBase(const DenseBase<OtherDerived> &other)
+ : m_storage()
+ {
+ _check_template_params();
+ lazyAssign(other);
+ }
+
EIGEN_STRONG_INLINE PlainObjectBase(Index a_size, Index nbRows, Index nbCols)
: m_storage(a_size, nbRows, nbCols)
{
@@ -573,6 +603,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
: (rows() == other.rows() && cols() == other.cols())))
&& "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
EIGEN_ONLY_USED_FOR_DEBUG(other);
+ if(this->size()==0)
+ resizeLike(other);
#else
resizeLike(other);
#endif
diff --git a/extern/Eigen3/Eigen/src/Core/ProductBase.h b/extern/Eigen3/Eigen/src/Core/ProductBase.h
index a494b5f8703..cf74470a9a1 100644
--- a/extern/Eigen3/Eigen/src/Core/ProductBase.h
+++ b/extern/Eigen3/Eigen/src/Core/ProductBase.h
@@ -85,7 +85,14 @@ class ProductBase : public MatrixBase<Derived>
public:
+#ifndef EIGEN_NO_MALLOC
+ typedef typename Base::PlainObject BasePlainObject;
+ typedef Matrix<Scalar,RowsAtCompileTime==1?1:Dynamic,ColsAtCompileTime==1?1:Dynamic,BasePlainObject::Options> DynPlainObject;
+ typedef typename internal::conditional<(BasePlainObject::SizeAtCompileTime==Dynamic) || (BasePlainObject::SizeAtCompileTime*int(sizeof(Scalar)) < int(EIGEN_STACK_ALLOCATION_LIMIT)),
+ BasePlainObject, DynPlainObject>::type PlainObject;
+#else
typedef typename Base::PlainObject PlainObject;
+#endif
ProductBase(const Lhs& a_lhs, const Rhs& a_rhs)
: m_lhs(a_lhs), m_rhs(a_rhs)
@@ -180,7 +187,12 @@ namespace internal {
template<typename Lhs, typename Rhs, int Mode, int N, typename PlainObject>
struct nested<GeneralProduct<Lhs,Rhs,Mode>, N, PlainObject>
{
- typedef PlainObject const& type;
+ typedef typename GeneralProduct<Lhs,Rhs,Mode>::PlainObject const& type;
+};
+template<typename Lhs, typename Rhs, int Mode, int N, typename PlainObject>
+struct nested<const GeneralProduct<Lhs,Rhs,Mode>, N, PlainObject>
+{
+ typedef typename GeneralProduct<Lhs,Rhs,Mode>::PlainObject const& type;
};
}
diff --git a/extern/Eigen3/Eigen/src/Core/Redux.h b/extern/Eigen3/Eigen/src/Core/Redux.h
index 50548fa9a0e..9b8662a6f9a 100644
--- a/extern/Eigen3/Eigen/src/Core/Redux.h
+++ b/extern/Eigen3/Eigen/src/Core/Redux.h
@@ -247,8 +247,9 @@ struct redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling>
}
};
-template<typename Func, typename Derived>
-struct redux_impl<Func, Derived, SliceVectorizedTraversal, NoUnrolling>
+// NOTE: for SliceVectorizedTraversal we simply bypass unrolling
+template<typename Func, typename Derived, int Unrolling>
+struct redux_impl<Func, Derived, SliceVectorizedTraversal, Unrolling>
{
typedef typename Derived::Scalar Scalar;
typedef typename packet_traits<Scalar>::type PacketScalar;
diff --git a/extern/Eigen3/Eigen/src/Core/Ref.h b/extern/Eigen3/Eigen/src/Core/Ref.h
index 00d9e6d2b41..7a3becaf882 100644
--- a/extern/Eigen3/Eigen/src/Core/Ref.h
+++ b/extern/Eigen3/Eigen/src/Core/Ref.h
@@ -101,14 +101,15 @@ struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
template<typename Derived> struct match {
enum {
HasDirectAccess = internal::has_direct_access<Derived>::ret,
- StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
+ StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic)
|| int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime)
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
OuterStrideMatch = Derived::IsVectorAtCompileTime
|| int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
AlignmentMatch = (_Options!=Aligned) || ((PlainObjectType::Flags&AlignedBit)==0) || ((traits<Derived>::Flags&AlignedBit)==AlignedBit),
- MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch
+ ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value,
+ MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch
};
typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
};
@@ -172,8 +173,12 @@ protected:
}
else
::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols());
- ::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(),
- StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride());
+
+ if(Expression::IsVectorAtCompileTime && (!PlainObjectType::IsVectorAtCompileTime) && ((Expression::Flags&RowMajorBit)!=(PlainObjectType::Flags&RowMajorBit)))
+ ::new (&m_stride) StrideBase(expr.innerStride(), StrideType::InnerStrideAtCompileTime==0?0:1);
+ else
+ ::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(),
+ StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride());
}
StrideBase m_stride;
@@ -183,7 +188,11 @@ protected:
template<typename PlainObjectType, int Options, typename StrideType> class Ref
: public RefBase<Ref<PlainObjectType, Options, StrideType> >
{
+ private:
typedef internal::traits<Ref> Traits;
+ template<typename Derived>
+ inline Ref(const PlainObjectBase<Derived>& expr,
+ typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0);
public:
typedef RefBase<Ref> Base;
@@ -195,17 +204,20 @@ template<typename PlainObjectType, int Options, typename StrideType> class Ref
inline Ref(PlainObjectBase<Derived>& expr,
typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
{
- Base::construct(expr);
+ EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
+ Base::construct(expr.derived());
}
template<typename Derived>
inline Ref(const DenseBase<Derived>& expr,
- typename internal::enable_if<bool(internal::is_lvalue<Derived>::value&&bool(Traits::template match<Derived>::MatchAtCompileTime)),Derived>::type* = 0,
- int = Derived::ThisConstantIsPrivateInPlainObjectBase)
+ typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
#else
template<typename Derived>
inline Ref(DenseBase<Derived>& expr)
#endif
{
+ EIGEN_STATIC_ASSERT(static_cast<bool>(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
+ EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
+ enum { THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY = Derived::ThisConstantIsPrivateInPlainObjectBase};
Base::construct(expr.const_cast_derived());
}
@@ -224,13 +236,23 @@ template<typename TPlainObjectType, int Options, typename StrideType> class Ref<
EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
template<typename Derived>
- inline Ref(const DenseBase<Derived>& expr)
+ inline Ref(const DenseBase<Derived>& expr,
+ typename internal::enable_if<bool(Traits::template match<Derived>::ScalarTypeMatch),Derived>::type* = 0)
{
// std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << "," << match_helper<Derived>::InnerStrideMatch << "\n";
// std::cout << int(StrideType::OuterStrideAtCompileTime) << " - " << int(Derived::OuterStrideAtCompileTime) << "\n";
// std::cout << int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n";
construct(expr.derived(), typename Traits::template match<Derived>::type());
}
+
+ inline Ref(const Ref& other) : Base(other) {
+ // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
+ }
+
+ template<typename OtherRef>
+ inline Ref(const RefBase<OtherRef>& other) {
+ construct(other.derived(), typename Traits::template match<OtherRef>::type());
+ }
protected:
diff --git a/extern/Eigen3/Eigen/src/Core/Replicate.h b/extern/Eigen3/Eigen/src/Core/Replicate.h
index dde86a8349b..ac4537c1422 100644
--- a/extern/Eigen3/Eigen/src/Core/Replicate.h
+++ b/extern/Eigen3/Eigen/src/Core/Replicate.h
@@ -135,7 +135,7 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
*/
template<typename Derived>
template<int RowFactor, int ColFactor>
-inline const Replicate<Derived,RowFactor,ColFactor>
+const Replicate<Derived,RowFactor,ColFactor>
DenseBase<Derived>::replicate() const
{
return Replicate<Derived,RowFactor,ColFactor>(derived());
@@ -150,7 +150,7 @@ DenseBase<Derived>::replicate() const
* \sa VectorwiseOp::replicate(), DenseBase::replicate<int,int>(), class Replicate
*/
template<typename Derived>
-inline const Replicate<Derived,Dynamic,Dynamic>
+const typename DenseBase<Derived>::ReplicateReturnType
DenseBase<Derived>::replicate(Index rowFactor,Index colFactor) const
{
return Replicate<Derived,Dynamic,Dynamic>(derived(),rowFactor,colFactor);
diff --git a/extern/Eigen3/Eigen/src/Core/ReturnByValue.h b/extern/Eigen3/Eigen/src/Core/ReturnByValue.h
index d66c24ba0f8..f635598dccf 100644
--- a/extern/Eigen3/Eigen/src/Core/ReturnByValue.h
+++ b/extern/Eigen3/Eigen/src/Core/ReturnByValue.h
@@ -72,6 +72,8 @@ template<typename Derived> class ReturnByValue
const Unusable& coeff(Index,Index) const { return *reinterpret_cast<const Unusable*>(this); }
Unusable& coeffRef(Index) { return *reinterpret_cast<Unusable*>(this); }
Unusable& coeffRef(Index,Index) { return *reinterpret_cast<Unusable*>(this); }
+ template<int LoadMode> Unusable& packet(Index) const;
+ template<int LoadMode> Unusable& packet(Index, Index) const;
#endif
};
@@ -83,6 +85,15 @@ Derived& DenseBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
return derived();
}
+template<typename Derived>
+template<typename OtherDerived>
+Derived& DenseBase<Derived>::lazyAssign(const ReturnByValue<OtherDerived>& other)
+{
+ other.evalTo(derived());
+ return derived();
+}
+
+
} // end namespace Eigen
#endif // EIGEN_RETURNBYVALUE_H
diff --git a/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h b/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h
index 22f3047b43f..0956475af51 100644
--- a/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h
+++ b/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h
@@ -180,15 +180,9 @@ inline Derived& DenseBase<Derived>::operator*=(const Scalar& other)
template<typename Derived>
inline Derived& DenseBase<Derived>::operator/=(const Scalar& other)
{
- typedef typename internal::conditional<NumTraits<Scalar>::IsInteger,
- internal::scalar_quotient_op<Scalar>,
- internal::scalar_product_op<Scalar> >::type BinOp;
typedef typename Derived::PlainObject PlainObject;
- SelfCwiseBinaryOp<BinOp, Derived, typename PlainObject::ConstantReturnType> tmp(derived());
- Scalar actual_other;
- if(NumTraits<Scalar>::IsInteger) actual_other = other;
- else actual_other = Scalar(1)/other;
- tmp = PlainObject::Constant(rows(),cols(), actual_other);
+ SelfCwiseBinaryOp<internal::scalar_quotient_op<Scalar>, Derived, typename PlainObject::ConstantReturnType> tmp(derived());
+ tmp = PlainObject::Constant(rows(),cols(), other);
return derived();
}
diff --git a/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h b/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h
index fba07365f6f..4d65392c685 100644
--- a/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h
+++ b/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h
@@ -278,21 +278,21 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
/** Efficient triangular matrix times vector/matrix product */
template<typename OtherDerived>
- TriangularProduct<Mode,true,MatrixType,false,OtherDerived, OtherDerived::IsVectorAtCompileTime>
+ TriangularProduct<Mode, true, MatrixType, false, OtherDerived, OtherDerived::ColsAtCompileTime==1>
operator*(const MatrixBase<OtherDerived>& rhs) const
{
return TriangularProduct
- <Mode,true,MatrixType,false,OtherDerived,OtherDerived::IsVectorAtCompileTime>
+ <Mode, true, MatrixType, false, OtherDerived, OtherDerived::ColsAtCompileTime==1>
(m_matrix, rhs.derived());
}
/** Efficient vector/matrix times triangular matrix product */
template<typename OtherDerived> friend
- TriangularProduct<Mode,false,OtherDerived,OtherDerived::IsVectorAtCompileTime,MatrixType,false>
+ TriangularProduct<Mode, false, OtherDerived, OtherDerived::RowsAtCompileTime==1, MatrixType, false>
operator*(const MatrixBase<OtherDerived>& lhs, const TriangularView& rhs)
{
return TriangularProduct
- <Mode,false,OtherDerived,OtherDerived::IsVectorAtCompileTime,MatrixType,false>
+ <Mode, false, OtherDerived, OtherDerived::RowsAtCompileTime==1, MatrixType, false>
(lhs.derived(),rhs.m_matrix);
}
@@ -380,19 +380,19 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
EIGEN_STRONG_INLINE TriangularView& operator=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
{
setZero();
- return assignProduct(other,1);
+ return assignProduct(other.derived(),1);
}
template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_STRONG_INLINE TriangularView& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
{
- return assignProduct(other,1);
+ return assignProduct(other.derived(),1);
}
template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_STRONG_INLINE TriangularView& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
{
- return assignProduct(other,-1);
+ return assignProduct(other.derived(),-1);
}
@@ -400,25 +400,34 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
EIGEN_STRONG_INLINE TriangularView& operator=(const ScaledProduct<ProductDerived>& other)
{
setZero();
- return assignProduct(other,other.alpha());
+ return assignProduct(other.derived(),other.alpha());
}
template<typename ProductDerived>
EIGEN_STRONG_INLINE TriangularView& operator+=(const ScaledProduct<ProductDerived>& other)
{
- return assignProduct(other,other.alpha());
+ return assignProduct(other.derived(),other.alpha());
}
template<typename ProductDerived>
EIGEN_STRONG_INLINE TriangularView& operator-=(const ScaledProduct<ProductDerived>& other)
{
- return assignProduct(other,-other.alpha());
+ return assignProduct(other.derived(),-other.alpha());
}
protected:
template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_STRONG_INLINE TriangularView& assignProduct(const ProductBase<ProductDerived, Lhs,Rhs>& prod, const Scalar& alpha);
+
+ template<int Mode, bool LhsIsTriangular,
+ typename Lhs, bool LhsIsVector,
+ typename Rhs, bool RhsIsVector>
+ EIGEN_STRONG_INLINE TriangularView& assignProduct(const TriangularProduct<Mode, LhsIsTriangular, Lhs, LhsIsVector, Rhs, RhsIsVector>& prod, const Scalar& alpha)
+ {
+ lazyAssign(alpha*prod.eval());
+ return *this;
+ }
MatrixTypeNested m_matrix;
};
diff --git a/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h b/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h
index f183d31de2a..8d9255eef6a 100644
--- a/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h
+++ b/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h
@@ -110,7 +110,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<
template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((float*)to, from.v); }
template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((float*)to, from.v); }
-template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr) { __pld((float *)addr); }
+template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr) { EIGEN_ARM_PREFETCH((float *)addr); }
template<> EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a)
{
diff --git a/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h b/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h
index 163bac215e6..d49670e0410 100644
--- a/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h
+++ b/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h
@@ -48,9 +48,18 @@ typedef uint32x4_t Packet4ui;
#define EIGEN_INIT_NEON_PACKET2(X, Y) {X, Y}
#define EIGEN_INIT_NEON_PACKET4(X, Y, Z, W) {X, Y, Z, W}
#endif
-
-#ifndef __pld
-#define __pld(x) asm volatile ( " pld [%[addr]]\n" :: [addr] "r" (x) : "cc" );
+
+// arm64 does have the pld instruction. If available, let's trust the __builtin_prefetch built-in function
+// which available on LLVM and GCC (at least)
+#if EIGEN_HAS_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
+ #define EIGEN_ARM_PREFETCH(ADDR) __builtin_prefetch(ADDR);
+#elif defined __pld
+ #define EIGEN_ARM_PREFETCH(ADDR) __pld(ADDR)
+#elif !defined(__aarch64__)
+ #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ( " pld [%[addr]]\n" :: [addr] "r" (ADDR) : "cc" );
+#else
+ // by default no explicit prefetching
+ #define EIGEN_ARM_PREFETCH(ADDR)
#endif
template<> struct packet_traits<float> : default_packet_traits
@@ -209,8 +218,8 @@ template<> EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet4i& f
template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_f32(to, from); }
template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_s32(to, from); }
-template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { __pld(addr); }
-template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { __pld(addr); }
+template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { EIGEN_ARM_PREFETCH(addr); }
+template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { EIGEN_ARM_PREFETCH(addr); }
// FIXME only store the 2 first elements ?
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vst1q_f32(x, a); return x[0]; }
@@ -375,6 +384,7 @@ template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
a_lo = vget_low_s32(a);
a_hi = vget_high_s32(a);
max = vpmax_s32(a_lo, a_hi);
+ max = vpmax_s32(max, max);
return vget_lane_s32(max, 0);
}
diff --git a/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h b/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h
index 99cbd0d95be..2b07168ae4f 100644
--- a/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h
+++ b/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h
@@ -52,7 +52,7 @@ Packet4f plog<Packet4f>(const Packet4f& _x)
Packet4i emm0;
- Packet4f invalid_mask = _mm_cmplt_ps(x, _mm_setzero_ps());
+ Packet4f invalid_mask = _mm_cmpnge_ps(x, _mm_setzero_ps()); // not greater equal is true if x is NaN
Packet4f iszero_mask = _mm_cmpeq_ps(x, _mm_setzero_ps());
x = pmax(x, p4f_min_norm_pos); /* cut off denormalized stuff */
@@ -126,7 +126,7 @@ Packet4f pexp<Packet4f>(const Packet4f& _x)
_EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p4, 1.6666665459E-1f);
_EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p5, 5.0000001201E-1f);
- Packet4f tmp = _mm_setzero_ps(), fx;
+ Packet4f tmp, fx;
Packet4i emm0;
// clamp x
@@ -166,7 +166,7 @@ Packet4f pexp<Packet4f>(const Packet4f& _x)
emm0 = _mm_cvttps_epi32(fx);
emm0 = _mm_add_epi32(emm0, p4i_0x7f);
emm0 = _mm_slli_epi32(emm0, 23);
- return pmul(y, _mm_castsi128_ps(emm0));
+ return pmax(pmul(y, Packet4f(_mm_castsi128_ps(emm0))), _x);
}
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
Packet2d pexp<Packet2d>(const Packet2d& _x)
@@ -195,7 +195,7 @@ Packet2d pexp<Packet2d>(const Packet2d& _x)
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_C2, 1.42860682030941723212e-6);
static const __m128i p4i_1023_0 = _mm_setr_epi32(1023, 1023, 0, 0);
- Packet2d tmp = _mm_setzero_pd(), fx;
+ Packet2d tmp, fx;
Packet4i emm0;
// clamp x
@@ -239,7 +239,7 @@ Packet2d pexp<Packet2d>(const Packet2d& _x)
emm0 = _mm_add_epi32(emm0, p4i_1023_0);
emm0 = _mm_slli_epi32(emm0, 20);
emm0 = _mm_shuffle_epi32(emm0, _MM_SHUFFLE(1,2,0,3));
- return pmul(x, _mm_castsi128_pd(emm0));
+ return pmax(pmul(x, Packet2d(_mm_castsi128_pd(emm0))), _x);
}
/* evaluation of 4 sines at onces, using SSE2 intrinsics.
@@ -279,7 +279,7 @@ Packet4f psin<Packet4f>(const Packet4f& _x)
_EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f);
_EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI
- Packet4f xmm1, xmm2 = _mm_setzero_ps(), xmm3, sign_bit, y;
+ Packet4f xmm1, xmm2, xmm3, sign_bit, y;
Packet4i emm0, emm2;
sign_bit = x;
@@ -378,7 +378,7 @@ Packet4f pcos<Packet4f>(const Packet4f& _x)
_EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f);
_EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI
- Packet4f xmm1, xmm2 = _mm_setzero_ps(), xmm3, y;
+ Packet4f xmm1, xmm2, xmm3, y;
Packet4i emm0, emm2;
x = pabs(x);
diff --git a/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h b/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h
index c06a0df1c21..2a9d65b9473 100644
--- a/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h
+++ b/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h
@@ -90,6 +90,7 @@ struct traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> >
| (SameType && (CanVectorizeLhs || CanVectorizeRhs) ? PacketAccessBit : 0),
CoeffReadCost = InnerSize == Dynamic ? Dynamic
+ : InnerSize == 0 ? 0
: InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
+ (InnerSize - 1) * NumTraits<Scalar>::AddCost,
@@ -133,7 +134,7 @@ class CoeffBasedProduct
};
typedef internal::product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal,
- Unroll ? InnerSize-1 : Dynamic,
+ Unroll ? InnerSize : Dynamic,
_LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
typedef CoeffBasedProduct<LhsNested,RhsNested,NestByRefBit> LazyCoeffBasedProductType;
@@ -184,7 +185,7 @@ class CoeffBasedProduct
{
PacketScalar res;
internal::product_packet_impl<Flags&RowMajorBit ? RowMajor : ColMajor,
- Unroll ? InnerSize-1 : Dynamic,
+ Unroll ? InnerSize : Dynamic,
_LhsNested, _RhsNested, PacketScalar, LoadMode>
::run(row, col, m_lhs, m_rhs, res);
return res;
@@ -242,12 +243,12 @@ struct product_coeff_impl<DefaultTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
{
product_coeff_impl<DefaultTraversal, UnrollingIndex-1, Lhs, Rhs, RetScalar>::run(row, col, lhs, rhs, res);
- res += lhs.coeff(row, UnrollingIndex) * rhs.coeff(UnrollingIndex, col);
+ res += lhs.coeff(row, UnrollingIndex-1) * rhs.coeff(UnrollingIndex-1, col);
}
};
template<typename Lhs, typename Rhs, typename RetScalar>
-struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar>
+struct product_coeff_impl<DefaultTraversal, 1, Lhs, Rhs, RetScalar>
{
typedef typename Lhs::Index Index;
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
@@ -257,15 +258,22 @@ struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar>
};
template<typename Lhs, typename Rhs, typename RetScalar>
+struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar>
+{
+ typedef typename Lhs::Index Index;
+ static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, RetScalar &res)
+ {
+ res = RetScalar(0);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename RetScalar>
struct product_coeff_impl<DefaultTraversal, Dynamic, Lhs, Rhs, RetScalar>
{
typedef typename Lhs::Index Index;
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar& res)
{
- eigen_assert(lhs.cols()>0 && "you are using a non initialized matrix");
- res = lhs.coeff(row, 0) * rhs.coeff(0, col);
- for(Index i = 1; i < lhs.cols(); ++i)
- res += lhs.coeff(row, i) * rhs.coeff(i, col);
+ res = (lhs.row(row).transpose().cwiseProduct( rhs.col(col) )).sum();
}
};
@@ -295,6 +303,16 @@ struct product_coeff_vectorized_unroller<0, Lhs, Rhs, Packet>
}
};
+template<typename Lhs, typename Rhs, typename RetScalar>
+struct product_coeff_impl<InnerVectorizedTraversal, 0, Lhs, Rhs, RetScalar>
+{
+ typedef typename Lhs::Index Index;
+ static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, RetScalar &res)
+ {
+ res = 0;
+ }
+};
+
template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
struct product_coeff_impl<InnerVectorizedTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
{
@@ -304,8 +322,7 @@ struct product_coeff_impl<InnerVectorizedTraversal, UnrollingIndex, Lhs, Rhs, Re
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
{
Packet pres;
- product_coeff_vectorized_unroller<UnrollingIndex+1-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, pres);
- product_coeff_impl<DefaultTraversal,UnrollingIndex,Lhs,Rhs,RetScalar>::run(row, col, lhs, rhs, res);
+ product_coeff_vectorized_unroller<UnrollingIndex-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, pres);
res = predux(pres);
}
};
@@ -373,7 +390,7 @@ struct product_packet_impl<RowMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
{
product_packet_impl<RowMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res);
- res = pmadd(pset1<Packet>(lhs.coeff(row, UnrollingIndex)), rhs.template packet<LoadMode>(UnrollingIndex, col), res);
+ res = pmadd(pset1<Packet>(lhs.coeff(row, UnrollingIndex-1)), rhs.template packet<LoadMode>(UnrollingIndex-1, col), res);
}
};
@@ -384,12 +401,12 @@ struct product_packet_impl<ColMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
{
product_packet_impl<ColMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res);
- res = pmadd(lhs.template packet<LoadMode>(row, UnrollingIndex), pset1<Packet>(rhs.coeff(UnrollingIndex, col)), res);
+ res = pmadd(lhs.template packet<LoadMode>(row, UnrollingIndex-1), pset1<Packet>(rhs.coeff(UnrollingIndex-1, col)), res);
}
};
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
-struct product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
+struct product_packet_impl<RowMajor, 1, Lhs, Rhs, Packet, LoadMode>
{
typedef typename Lhs::Index Index;
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
@@ -399,7 +416,7 @@ struct product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
};
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
-struct product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
+struct product_packet_impl<ColMajor, 1, Lhs, Rhs, Packet, LoadMode>
{
typedef typename Lhs::Index Index;
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
@@ -409,15 +426,34 @@ struct product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
};
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
+struct product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
+{
+ typedef typename Lhs::Index Index;
+ static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Packet &res)
+ {
+ res = pset1<Packet>(0);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
+struct product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
+{
+ typedef typename Lhs::Index Index;
+ static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Packet &res)
+ {
+ res = pset1<Packet>(0);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
struct product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
{
typedef typename Lhs::Index Index;
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res)
{
- eigen_assert(lhs.cols()>0 && "you are using a non initialized matrix");
- res = pmul(pset1<Packet>(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
- for(Index i = 1; i < lhs.cols(); ++i)
- res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode>(i, col), res);
+ res = pset1<Packet>(0);
+ for(Index i = 0; i < lhs.cols(); ++i)
+ res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode>(i, col), res);
}
};
@@ -427,10 +463,9 @@ struct product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
typedef typename Lhs::Index Index;
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res)
{
- eigen_assert(lhs.cols()>0 && "you are using a non initialized matrix");
- res = pmul(lhs.template packet<LoadMode>(row, 0), pset1<Packet>(rhs.coeff(0, col)));
- for(Index i = 1; i < lhs.cols(); ++i)
- res = pmadd(lhs.template packet<LoadMode>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
+ res = pset1<Packet>(0);
+ for(Index i = 0; i < lhs.cols(); ++i)
+ res = pmadd(lhs.template packet<LoadMode>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
}
};
diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h
index 3f5ffcf51c7..a36c7c7a61c 100644
--- a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h
+++ b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h
@@ -140,8 +140,14 @@ static void run(Index rows, Index cols, Index depth,
// Release all the sub blocks B'_j of B' for the current thread,
// i.e., we simply decrement the number of users by 1
for(Index j=0; j<threads; ++j)
+ {
#pragma omp atomic
+#if defined(_MSC_VER) && _MSC_VER >= 1900
+ (info[j].users) -= 1;
+#else
--(info[j].users);
+#endif
+ }
}
}
else
diff --git a/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h b/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h
index 5c3e9b7ac15..6937ee33284 100644
--- a/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h
+++ b/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h
@@ -125,19 +125,22 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpos
if(transpose)
std::swap(rows,cols);
- Index blockCols = (cols / threads) & ~Index(0x3);
- Index blockRows = (rows / threads) & ~Index(0x7);
-
GemmParallelInfo<Index>* info = new GemmParallelInfo<Index>[threads];
- #pragma omp parallel for schedule(static,1) num_threads(threads)
- for(Index i=0; i<threads; ++i)
+ #pragma omp parallel num_threads(threads)
{
+ Index i = omp_get_thread_num();
+ // Note that the actual number of threads might be lower than the number of request ones.
+ Index actual_threads = omp_get_num_threads();
+
+ Index blockCols = (cols / actual_threads) & ~Index(0x3);
+ Index blockRows = (rows / actual_threads) & ~Index(0x7);
+
Index r0 = i*blockRows;
- Index actualBlockRows = (i+1==threads) ? rows-r0 : blockRows;
+ Index actualBlockRows = (i+1==actual_threads) ? rows-r0 : blockRows;
Index c0 = i*blockCols;
- Index actualBlockCols = (i+1==threads) ? cols-c0 : blockCols;
+ Index actualBlockCols = (i+1==actual_threads) ? cols-c0 : blockCols;
info[i].rhs_start = c0;
info[i].rhs_length = actualBlockCols;
diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h
index ba41a1c99f6..4cc56a42fd5 100644
--- a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h
+++ b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h
@@ -109,7 +109,7 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,true, \
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
if (rows != depth) { \
\
- int nthr = mkl_domain_get_max_threads(MKL_BLAS); \
+ int nthr = mkl_domain_get_max_threads(EIGEN_MKL_DOMAIN_BLAS); \
\
if (((nthr==1) && (((std::max)(rows,depth)-diagSize)/(double)diagSize < 0.5))) { \
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
@@ -223,7 +223,7 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,false, \
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
if (cols != depth) { \
\
- int nthr = mkl_domain_get_max_threads(MKL_BLAS); \
+ int nthr = mkl_domain_get_max_threads(EIGEN_MKL_DOMAIN_BLAS); \
\
if ((nthr==1) && (((std::max)(cols,depth)-diagSize)/(double)diagSize < 0.5)) { \
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h b/extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h
index f103eae72c0..04240ab5032 100644
--- a/extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h
+++ b/extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h
@@ -302,9 +302,12 @@ EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conj
for (Index i=0; i<actual_mc; ++i)
r[i] -= a[i] * b;
}
- Scalar b = (Mode & UnitDiag) ? Scalar(1) : Scalar(1)/conj(rhs(j,j));
- for (Index i=0; i<actual_mc; ++i)
- r[i] *= b;
+ if((Mode & UnitDiag)==0)
+ {
+ Scalar b = conj(rhs(j,j));
+ for (Index i=0; i<actual_mc; ++i)
+ r[i] /= b;
+ }
}
// pack the just computed part of lhs to A
diff --git a/extern/Eigen3/Eigen/src/Core/util/Constants.h b/extern/Eigen3/Eigen/src/Core/util/Constants.h
index 14b9624e1d9..1e6277c4f96 100644
--- a/extern/Eigen3/Eigen/src/Core/util/Constants.h
+++ b/extern/Eigen3/Eigen/src/Core/util/Constants.h
@@ -433,6 +433,19 @@ struct MatrixXpr {};
/** The type used to identify an array expression */
struct ArrayXpr {};
+namespace internal {
+ /** \internal
+ * Constants for comparison functors
+ */
+ enum ComparisonName {
+ cmp_EQ = 0,
+ cmp_LT = 1,
+ cmp_LE = 2,
+ cmp_UNORD = 3,
+ cmp_NEQ = 4
+ };
+}
+
} // end namespace Eigen
#endif // EIGEN_CONSTANTS_H
diff --git a/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h b/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h
index d6a814586d3..f277720077b 100644
--- a/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h
+++ b/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h
@@ -235,6 +235,9 @@ template<typename Scalar> class Rotation2D;
template<typename Scalar> class AngleAxis;
template<typename Scalar,int Dim> class Translation;
+// Sparse module:
+template<typename Derived> class SparseMatrixBase;
+
#ifdef EIGEN2_SUPPORT
template<typename Derived, int _Dim> class eigen2_RotationBase;
template<typename Lhs, typename Rhs> class eigen2_Cross;
diff --git a/extern/Eigen3/Eigen/src/Core/util/MKL_support.h b/extern/Eigen3/Eigen/src/Core/util/MKL_support.h
index 1e6e355d626..1ef3b61db14 100644
--- a/extern/Eigen3/Eigen/src/Core/util/MKL_support.h
+++ b/extern/Eigen3/Eigen/src/Core/util/MKL_support.h
@@ -54,11 +54,60 @@
#endif
#if defined EIGEN_USE_MKL
+# include <mkl.h>
+/*Check IMKL version for compatibility: < 10.3 is not usable with Eigen*/
+# ifndef INTEL_MKL_VERSION
+# undef EIGEN_USE_MKL /* INTEL_MKL_VERSION is not even defined on older versions */
+# elif INTEL_MKL_VERSION < 100305 /* the intel-mkl-103-release-notes say this was when the lapacke.h interface was added*/
+# undef EIGEN_USE_MKL
+# endif
+# ifndef EIGEN_USE_MKL
+ /*If the MKL version is too old, undef everything*/
+# undef EIGEN_USE_MKL_ALL
+# undef EIGEN_USE_BLAS
+# undef EIGEN_USE_LAPACKE
+# undef EIGEN_USE_MKL_VML
+# undef EIGEN_USE_LAPACKE_STRICT
+# undef EIGEN_USE_LAPACKE
+# endif
+#endif
-#include <mkl.h>
+#if defined EIGEN_USE_MKL
#include <mkl_lapacke.h>
#define EIGEN_MKL_VML_THRESHOLD 128
+/* MKL_DOMAIN_BLAS, etc are defined only in 10.3 update 7 */
+/* MKL_BLAS, etc are not defined in 11.2 */
+#ifdef MKL_DOMAIN_ALL
+#define EIGEN_MKL_DOMAIN_ALL MKL_DOMAIN_ALL
+#else
+#define EIGEN_MKL_DOMAIN_ALL MKL_ALL
+#endif
+
+#ifdef MKL_DOMAIN_BLAS
+#define EIGEN_MKL_DOMAIN_BLAS MKL_DOMAIN_BLAS
+#else
+#define EIGEN_MKL_DOMAIN_BLAS MKL_BLAS
+#endif
+
+#ifdef MKL_DOMAIN_FFT
+#define EIGEN_MKL_DOMAIN_FFT MKL_DOMAIN_FFT
+#else
+#define EIGEN_MKL_DOMAIN_FFT MKL_FFT
+#endif
+
+#ifdef MKL_DOMAIN_VML
+#define EIGEN_MKL_DOMAIN_VML MKL_DOMAIN_VML
+#else
+#define EIGEN_MKL_DOMAIN_VML MKL_VML
+#endif
+
+#ifdef MKL_DOMAIN_PARDISO
+#define EIGEN_MKL_DOMAIN_PARDISO MKL_DOMAIN_PARDISO
+#else
+#define EIGEN_MKL_DOMAIN_PARDISO MKL_PARDISO
+#endif
+
namespace Eigen {
typedef std::complex<double> dcomplex;
diff --git a/extern/Eigen3/Eigen/src/Core/util/Macros.h b/extern/Eigen3/Eigen/src/Core/util/Macros.h
index 0088621acf7..53fb5fae420 100644
--- a/extern/Eigen3/Eigen/src/Core/util/Macros.h
+++ b/extern/Eigen3/Eigen/src/Core/util/Macros.h
@@ -13,7 +13,7 @@
#define EIGEN_WORLD_VERSION 3
#define EIGEN_MAJOR_VERSION 2
-#define EIGEN_MINOR_VERSION 1
+#define EIGEN_MINOR_VERSION 7
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
@@ -96,6 +96,27 @@
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE std::ptrdiff_t
#endif
+// A Clang feature extension to determine compiler features.
+// We use it to determine 'cxx_rvalue_references'
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+// Do we support r-value references?
+#if (__has_feature(cxx_rvalue_references) || \
+ defined(__GXX_EXPERIMENTAL_CXX0X__) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1600))
+ #define EIGEN_HAVE_RVALUE_REFERENCES
+#endif
+
+
+// Cross compiler wrapper around LLVM's __has_builtin
+#ifdef __has_builtin
+# define EIGEN_HAS_BUILTIN(x) __has_builtin(x)
+#else
+# define EIGEN_HAS_BUILTIN(x) 0
+#endif
+
/** Allows to disable some optimizations which might affect the accuracy of the result.
* Such optimization are enabled by default, and set EIGEN_FAST_MATH to 0 to disable them.
* They currently include:
@@ -247,7 +268,7 @@ namespace Eigen {
#if !defined(EIGEN_ASM_COMMENT)
#if (defined __GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
- #define EIGEN_ASM_COMMENT(X) asm("#" X)
+ #define EIGEN_ASM_COMMENT(X) __asm__("#" X)
#else
#define EIGEN_ASM_COMMENT(X)
#endif
@@ -271,6 +292,7 @@ namespace Eigen {
#error Please tell me what is the equivalent of __attribute__((aligned(n))) for your compiler
#endif
+#define EIGEN_ALIGN8 EIGEN_ALIGN_TO_BOUNDARY(8)
#define EIGEN_ALIGN16 EIGEN_ALIGN_TO_BOUNDARY(16)
#if EIGEN_ALIGN_STATICALLY
@@ -289,7 +311,8 @@ namespace Eigen {
#endif
#ifndef EIGEN_STACK_ALLOCATION_LIMIT
-#define EIGEN_STACK_ALLOCATION_LIMIT 20000
+// 131072 == 128 KB
+#define EIGEN_STACK_ALLOCATION_LIMIT 131072
#endif
#ifndef EIGEN_DEFAULT_IO_FORMAT
@@ -305,7 +328,7 @@ namespace Eigen {
// just an empty macro !
#define EIGEN_EMPTY
-#if defined(_MSC_VER) && (!defined(__INTEL_COMPILER))
+#if defined(_MSC_VER) && (_MSC_VER < 1900) && (!defined(__INTEL_COMPILER))
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
using Base::operator =;
#elif defined(__clang__) // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
@@ -324,8 +347,11 @@ namespace Eigen {
}
#endif
-#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) \
- EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived)
+/** \internal
+ * \brief Macro to manually inherit assignment operators.
+ * This is necessary, because the implicitly defined assignment operator gets deleted when a custom operator= is defined.
+ */
+#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived)
/**
* Just a side note. Commenting within defines works only by documenting
@@ -397,6 +423,8 @@ namespace Eigen {
#define EIGEN_SIZE_MAX(a,b) (((int)a == Dynamic || (int)b == Dynamic) ? Dynamic \
: ((int)a >= (int)b) ? (int)a : (int)b)
+#define EIGEN_ADD_COST(a,b) int(a)==Dynamic || int(b)==Dynamic ? Dynamic : int(a)+int(b)
+
#define EIGEN_LOGICAL_XOR(a,b) (((a) || (b)) && !((a) && (b)))
#define EIGEN_IMPLIES(a,b) (!(a) || (b))
diff --git a/extern/Eigen3/Eigen/src/Core/util/Memory.h b/extern/Eigen3/Eigen/src/Core/util/Memory.h
index cacbd02fd12..b9af5cf8c7b 100644
--- a/extern/Eigen3/Eigen/src/Core/util/Memory.h
+++ b/extern/Eigen3/Eigen/src/Core/util/Memory.h
@@ -63,7 +63,7 @@
// Currently, let's include it only on unix systems:
#if defined(__unix__) || defined(__unix)
#include <unistd.h>
- #if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
+ #if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || (defined __PGI) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
#define EIGEN_HAS_POSIX_MEMALIGN 1
#endif
#endif
@@ -272,12 +272,12 @@ inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
// The defined(_mm_free) is just here to verify that this MSVC version
// implements _mm_malloc/_mm_free based on the corresponding _aligned_
// functions. This may not always be the case and we just try to be safe.
- #if defined(_MSC_VER) && defined(_mm_free)
+ #if defined(_MSC_VER) && (!defined(_WIN32_WCE)) && defined(_mm_free)
result = _aligned_realloc(ptr,new_size,16);
#else
result = generic_aligned_realloc(ptr,new_size,old_size);
#endif
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) && (!defined(_WIN32_WCE))
result = _aligned_realloc(ptr,new_size,16);
#else
result = handmade_aligned_realloc(ptr,new_size,old_size);
@@ -417,6 +417,8 @@ template<typename T, bool Align> inline T* conditional_aligned_realloc_new(T* pt
template<typename T, bool Align> inline T* conditional_aligned_new_auto(size_t size)
{
+ if(size==0)
+ return 0; // short-cut. Also fixes Bug 884
check_size_for_overflow<T>(size);
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
if(NumTraits<T>::RequireInitialization)
@@ -464,9 +466,8 @@ template<typename T, bool Align> inline void conditional_aligned_delete_auto(T *
template<typename Scalar, typename Index>
static inline Index first_aligned(const Scalar* array, Index size)
{
- enum { PacketSize = packet_traits<Scalar>::size,
- PacketAlignedMask = PacketSize-1
- };
+ static const Index PacketSize = packet_traits<Scalar>::size;
+ static const Index PacketAlignedMask = PacketSize-1;
if(PacketSize==1)
{
@@ -522,7 +523,7 @@ template<typename T> struct smart_copy_helper<T,false> {
// you can overwrite Eigen's default behavior regarding alloca by defining EIGEN_ALLOCA
// to the appropriate stack allocation function
#ifndef EIGEN_ALLOCA
- #if (defined __linux__)
+ #if (defined __linux__) || (defined __APPLE__) || (defined alloca)
#define EIGEN_ALLOCA alloca
#elif defined(_MSC_VER)
#define EIGEN_ALLOCA _alloca
@@ -612,7 +613,6 @@ template<typename T> class aligned_stack_memory_handler
void* operator new(size_t size, const std::nothrow_t&) throw() { \
try { return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); } \
catch (...) { return 0; } \
- return 0; \
}
#else
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
@@ -777,9 +777,9 @@ namespace internal {
#ifdef EIGEN_CPUID
-inline bool cpuid_is_vendor(int abcd[4], const char* vendor)
+inline bool cpuid_is_vendor(int abcd[4], const int vendor[3])
{
- return abcd[1]==(reinterpret_cast<const int*>(vendor))[0] && abcd[3]==(reinterpret_cast<const int*>(vendor))[1] && abcd[2]==(reinterpret_cast<const int*>(vendor))[2];
+ return abcd[1]==vendor[0] && abcd[3]==vendor[1] && abcd[2]==vendor[2];
}
inline void queryCacheSizes_intel_direct(int& l1, int& l2, int& l3)
@@ -921,13 +921,16 @@ inline void queryCacheSizes(int& l1, int& l2, int& l3)
{
#ifdef EIGEN_CPUID
int abcd[4];
+ const int GenuineIntel[] = {0x756e6547, 0x49656e69, 0x6c65746e};
+ const int AuthenticAMD[] = {0x68747541, 0x69746e65, 0x444d4163};
+ const int AMDisbetter_[] = {0x69444d41, 0x74656273, 0x21726574}; // "AMDisbetter!"
// identify the CPU vendor
EIGEN_CPUID(abcd,0x0,0);
int max_std_funcs = abcd[1];
- if(cpuid_is_vendor(abcd,"GenuineIntel"))
+ if(cpuid_is_vendor(abcd,GenuineIntel))
queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
- else if(cpuid_is_vendor(abcd,"AuthenticAMD") || cpuid_is_vendor(abcd,"AMDisbetter!"))
+ else if(cpuid_is_vendor(abcd,AuthenticAMD) || cpuid_is_vendor(abcd,AMDisbetter_))
queryCacheSizes_amd(l1,l2,l3);
else
// by default let's use Intel's API
diff --git a/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h b/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h
index 8872c5b648e..bac5d9fe92b 100644
--- a/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h
+++ b/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h
@@ -90,7 +90,9 @@
YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED,
THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE,
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH,
- OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG
+ OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG,
+ IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY,
+ STORAGE_LAYOUT_DOES_NOT_MATCH
};
};
diff --git a/extern/Eigen3/Eigen/src/Core/util/XprHelper.h b/extern/Eigen3/Eigen/src/Core/util/XprHelper.h
index 3c4773054b4..d05f8e5f6f4 100644
--- a/extern/Eigen3/Eigen/src/Core/util/XprHelper.h
+++ b/extern/Eigen3/Eigen/src/Core/util/XprHelper.h
@@ -341,7 +341,7 @@ template<typename T, int n=1, typename PlainObject = typename eval<T>::type> str
};
template<typename T>
-T* const_cast_ptr(const T* ptr)
+inline T* const_cast_ptr(const T* ptr)
{
return const_cast<T*>(ptr);
}
@@ -366,17 +366,17 @@ struct dense_xpr_base<Derived, ArrayXpr>
/** \internal Helper base class to add a scalar multiple operator
* overloads for complex types */
-template<typename Derived,typename Scalar,typename OtherScalar,
+template<typename Derived, typename Scalar, typename OtherScalar, typename BaseType,
bool EnableIt = !is_same<Scalar,OtherScalar>::value >
-struct special_scalar_op_base : public DenseCoeffsBase<Derived>
+struct special_scalar_op_base : public BaseType
{
// dummy operator* so that the
// "using special_scalar_op_base::operator*" compiles
void operator*() const;
};
-template<typename Derived,typename Scalar,typename OtherScalar>
-struct special_scalar_op_base<Derived,Scalar,OtherScalar,true> : public DenseCoeffsBase<Derived>
+template<typename Derived,typename Scalar,typename OtherScalar, typename BaseType>
+struct special_scalar_op_base<Derived,Scalar,OtherScalar,BaseType,true> : public BaseType
{
const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
operator*(const OtherScalar& scalar) const
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h b/extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h
index 0e6fdb4889d..7992d494425 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h
+++ b/extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h
@@ -147,7 +147,6 @@ void fitHyperplane(int numPoints,
// compute the covariance matrix
CovMatrixType covMat = CovMatrixType::Zero(size, size);
- VectorType remean = VectorType::Zero(size);
for(int i = 0; i < numPoints; ++i)
{
VectorType diff = (*(points[i]) - mean).conjugate();
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h
index af434bc9bd6..417c72944e1 100644
--- a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h
+++ b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h
@@ -234,6 +234,12 @@ template<typename _MatrixType> class ComplexEigenSolver
}
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
+
EigenvectorType m_eivec;
EigenvalueType m_eivalues;
ComplexSchur<MatrixType> m_schur;
@@ -251,6 +257,8 @@ template<typename MatrixType>
ComplexEigenSolver<MatrixType>&
ComplexEigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
{
+ check_template_parameters();
+
// this code is inspired from Jampack
eigen_assert(matrix.cols() == matrix.rows());
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h
index 6e7150685a2..20c59a7a2e6 100644
--- a/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h
+++ b/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h
@@ -298,6 +298,13 @@ template<typename _MatrixType> class EigenSolver
void doComputeEigenvectors();
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
+ }
+
MatrixType m_eivec;
EigenvalueType m_eivalues;
bool m_isInitialized;
@@ -364,6 +371,8 @@ template<typename MatrixType>
EigenSolver<MatrixType>&
EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
{
+ check_template_parameters();
+
using std::sqrt;
using std::abs;
eigen_assert(matrix.cols() == matrix.rows());
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h
index dc240e13e13..956e80d9edc 100644
--- a/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h
+++ b/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h
@@ -263,6 +263,13 @@ template<typename _MatrixType> class GeneralizedEigenSolver
}
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
+ }
+
MatrixType m_eivec;
ComplexVectorType m_alphas;
VectorType m_betas;
@@ -290,6 +297,8 @@ template<typename MatrixType>
GeneralizedEigenSolver<MatrixType>&
GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors)
{
+ check_template_parameters();
+
using std::sqrt;
using std::abs;
eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/RealQZ.h b/extern/Eigen3/Eigen/src/Eigenvalues/RealQZ.h
index 5706eeebe91..aa3833ebad1 100644
--- a/extern/Eigen3/Eigen/src/Eigenvalues/RealQZ.h
+++ b/extern/Eigen3/Eigen/src/Eigenvalues/RealQZ.h
@@ -240,10 +240,10 @@ namespace Eigen {
m_S.coeffRef(i,j) = Scalar(0.0);
m_S.rightCols(dim-j-1).applyOnTheLeft(i-1,i,G.adjoint());
m_T.rightCols(dim-i+1).applyOnTheLeft(i-1,i,G.adjoint());
+ // update Q
+ if (m_computeQZ)
+ m_Q.applyOnTheRight(i-1,i,G);
}
- // update Q
- if (m_computeQZ)
- m_Q.applyOnTheRight(i-1,i,G);
// kill T(i,i-1)
if(m_T.coeff(i,i-1)!=Scalar(0))
{
@@ -251,10 +251,10 @@ namespace Eigen {
m_T.coeffRef(i,i-1) = Scalar(0.0);
m_S.applyOnTheRight(i,i-1,G);
m_T.topRows(i).applyOnTheRight(i,i-1,G);
+ // update Z
+ if (m_computeQZ)
+ m_Z.applyOnTheLeft(i,i-1,G.adjoint());
}
- // update Z
- if (m_computeQZ)
- m_Z.applyOnTheLeft(i,i-1,G.adjoint());
}
}
}
@@ -313,7 +313,7 @@ namespace Eigen {
using std::abs;
using std::sqrt;
const Index dim=m_S.cols();
- if (abs(m_S.coeff(i+1,i)==Scalar(0)))
+ if (abs(m_S.coeff(i+1,i))==Scalar(0))
return;
Index z = findSmallDiagEntry(i,i+1);
if (z==i-1)
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h b/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h
index 64d13634141..16d3875372e 100644
--- a/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h
+++ b/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h
@@ -234,7 +234,7 @@ template<typename _MatrixType> class RealSchur
typedef Matrix<Scalar,3,1> Vector3s;
Scalar computeNormOfT();
- Index findSmallSubdiagEntry(Index iu, const Scalar& norm);
+ Index findSmallSubdiagEntry(Index iu);
void splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift);
void computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo);
void initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector);
@@ -286,7 +286,7 @@ RealSchur<MatrixType>& RealSchur<MatrixType>::computeFromHessenberg(const HessMa
{
while (iu >= 0)
{
- Index il = findSmallSubdiagEntry(iu, norm);
+ Index il = findSmallSubdiagEntry(iu);
// Check for convergence
if (il == iu) // One root found
@@ -343,16 +343,14 @@ inline typename MatrixType::Scalar RealSchur<MatrixType>::computeNormOfT()
/** \internal Look for single small sub-diagonal element and returns its index */
template<typename MatrixType>
-inline typename MatrixType::Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu, const Scalar& norm)
+inline typename MatrixType::Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu)
{
using std::abs;
Index res = iu;
while (res > 0)
{
Scalar s = abs(m_matT.coeff(res-1,res-1)) + abs(m_matT.coeff(res,res));
- if (s == 0.0)
- s = norm;
- if (abs(m_matT.coeff(res,res-1)) < NumTraits<Scalar>::epsilon() * s)
+ if (abs(m_matT.coeff(res,res-1)) <= NumTraits<Scalar>::epsilon() * s)
break;
res--;
}
@@ -457,9 +455,7 @@ inline void RealSchur<MatrixType>::initFrancisQRStep(Index il, Index iu, const V
const Scalar lhs = m_matT.coeff(im,im-1) * (abs(v.coeff(1)) + abs(v.coeff(2)));
const Scalar rhs = v.coeff(0) * (abs(m_matT.coeff(im-1,im-1)) + abs(Tmm) + abs(m_matT.coeff(im+1,im+1)));
if (abs(lhs) < NumTraits<Scalar>::epsilon() * rhs)
- {
break;
- }
}
}
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
index 3993046a88e..1131c8af8ad 100644
--- a/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
+++ b/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
@@ -80,6 +80,8 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
/** \brief Scalar type for matrices of type \p _MatrixType. */
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
+
+ typedef Matrix<Scalar,Size,Size,ColMajor,MaxColsAtCompileTime,MaxColsAtCompileTime> EigenvectorsType;
/** \brief Real scalar type for \p _MatrixType.
*
@@ -225,7 +227,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
*
* \sa eigenvalues()
*/
- const MatrixType& eigenvectors() const
+ const EigenvectorsType& eigenvectors() const
{
eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
@@ -351,7 +353,12 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
#endif // EIGEN2_SUPPORT
protected:
- MatrixType m_eivec;
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
+
+ EigenvectorsType m_eivec;
RealVectorType m_eivalues;
typename TridiagonalizationType::SubDiagonalType m_subdiag;
ComputationInfo m_info;
@@ -376,7 +383,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
* "implicit symmetric QR step with Wilkinson shift"
*/
namespace internal {
-template<int StorageOrder,typename RealScalar, typename Scalar, typename Index>
+template<typename RealScalar, typename Scalar, typename Index>
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n);
}
@@ -384,6 +391,8 @@ template<typename MatrixType>
SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
::compute(const MatrixType& matrix, int options)
{
+ check_template_parameters();
+
using std::abs;
eigen_assert(matrix.cols() == matrix.rows());
eigen_assert((options&~(EigVecMask|GenEigMask))==0
@@ -406,7 +415,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
// declare some aliases
RealVectorType& diag = m_eivalues;
- MatrixType& mat = m_eivec;
+ EigenvectorsType& mat = m_eivec;
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
mat = matrix.template triangularView<Lower>();
@@ -442,7 +451,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
while (start>0 && m_subdiag[start-1]!=0)
start--;
- internal::tridiagonal_qr_step<MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor>(diag.data(), m_subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (Scalar*)0, n);
+ internal::tridiagonal_qr_step(diag.data(), m_subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (Scalar*)0, n);
}
if (iter <= m_maxIterations * n)
@@ -490,7 +499,13 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
typedef typename SolverType::MatrixType MatrixType;
typedef typename SolverType::RealVectorType VectorType;
typedef typename SolverType::Scalar Scalar;
+ typedef typename MatrixType::Index Index;
+ typedef typename SolverType::EigenvectorsType EigenvectorsType;
+ /** \internal
+ * Computes the roots of the characteristic polynomial of \a m.
+ * For numerical stability m.trace() should be near zero and to avoid over- or underflow m should be normalized.
+ */
static inline void computeRoots(const MatrixType& m, VectorType& roots)
{
using std::sqrt;
@@ -510,148 +525,123 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
// Construct the parameters used in classifying the roots of the equation
// and in solving the equation for the roots in closed form.
Scalar c2_over_3 = c2*s_inv3;
- Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3;
- if (a_over_3 > Scalar(0))
+ Scalar a_over_3 = (c2*c2_over_3 - c1)*s_inv3;
+ if(a_over_3<Scalar(0))
a_over_3 = Scalar(0);
Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));
- Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3;
- if (q > Scalar(0))
+ Scalar q = a_over_3*a_over_3*a_over_3 - half_b*half_b;
+ if(q<Scalar(0))
q = Scalar(0);
// Compute the eigenvalues by solving for the roots of the polynomial.
- Scalar rho = sqrt(-a_over_3);
- Scalar theta = atan2(sqrt(-q),half_b)*s_inv3;
+ Scalar rho = sqrt(a_over_3);
+ Scalar theta = atan2(sqrt(q),half_b)*s_inv3; // since sqrt(q) > 0, atan2 is in [0, pi] and theta is in [0, pi/3]
Scalar cos_theta = cos(theta);
Scalar sin_theta = sin(theta);
- roots(0) = c2_over_3 + Scalar(2)*rho*cos_theta;
- roots(1) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta);
- roots(2) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta);
-
- // Sort in increasing order.
- if (roots(0) >= roots(1))
- std::swap(roots(0),roots(1));
- if (roots(1) >= roots(2))
- {
- std::swap(roots(1),roots(2));
- if (roots(0) >= roots(1))
- std::swap(roots(0),roots(1));
- }
+ // roots are already sorted, since cos is monotonically decreasing on [0, pi]
+ roots(0) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta); // == 2*rho*cos(theta+2pi/3)
+ roots(1) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta); // == 2*rho*cos(theta+ pi/3)
+ roots(2) = c2_over_3 + Scalar(2)*rho*cos_theta;
}
-
+
+ static inline bool extract_kernel(MatrixType& mat, Ref<VectorType> res, Ref<VectorType> representative)
+ {
+ using std::abs;
+ Index i0;
+ // Find non-zero column i0 (by construction, there must exist a non zero coefficient on the diagonal):
+ mat.diagonal().cwiseAbs().maxCoeff(&i0);
+ // mat.col(i0) is a good candidate for an orthogonal vector to the current eigenvector,
+ // so let's save it:
+ representative = mat.col(i0);
+ Scalar n0, n1;
+ VectorType c0, c1;
+ n0 = (c0 = representative.cross(mat.col((i0+1)%3))).squaredNorm();
+ n1 = (c1 = representative.cross(mat.col((i0+2)%3))).squaredNorm();
+ if(n0>n1) res = c0/std::sqrt(n0);
+ else res = c1/std::sqrt(n1);
+
+ return true;
+ }
+
static inline void run(SolverType& solver, const MatrixType& mat, int options)
{
- using std::sqrt;
eigen_assert(mat.cols() == 3 && mat.cols() == mat.rows());
eigen_assert((options&~(EigVecMask|GenEigMask))==0
&& (options&EigVecMask)!=EigVecMask
&& "invalid option parameter");
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
- MatrixType& eivecs = solver.m_eivec;
+ EigenvectorsType& eivecs = solver.m_eivec;
VectorType& eivals = solver.m_eivalues;
- // map the matrix coefficients to [-1:1] to avoid over- and underflow.
- Scalar scale = mat.cwiseAbs().maxCoeff();
- MatrixType scaledMat = mat / scale;
+ // Shift the matrix to the mean eigenvalue and map the matrix coefficients to [-1:1] to avoid over- and underflow.
+ Scalar shift = mat.trace() / Scalar(3);
+ // TODO Avoid this copy. Currently it is necessary to suppress bogus values when determining maxCoeff and for computing the eigenvectors later
+ MatrixType scaledMat = mat.template selfadjointView<Lower>();
+ scaledMat.diagonal().array() -= shift;
+ Scalar scale = scaledMat.cwiseAbs().maxCoeff();
+ if(scale > 0) scaledMat /= scale; // TODO for scale==0 we could save the remaining operations
// compute the eigenvalues
computeRoots(scaledMat,eivals);
- // compute the eigen vectors
+ // compute the eigenvectors
if(computeEigenvectors)
{
- Scalar safeNorm2 = Eigen::NumTraits<Scalar>::epsilon();
- safeNorm2 *= safeNorm2;
if((eivals(2)-eivals(0))<=Eigen::NumTraits<Scalar>::epsilon())
{
+ // All three eigenvalues are numerically the same
eivecs.setIdentity();
}
else
{
- scaledMat = scaledMat.template selfadjointView<Lower>();
MatrixType tmp;
tmp = scaledMat;
+ // Compute the eigenvector of the most distinct eigenvalue
Scalar d0 = eivals(2) - eivals(1);
Scalar d1 = eivals(1) - eivals(0);
- int k = d0 > d1 ? 2 : 0;
- d0 = d0 > d1 ? d1 : d0;
-
- tmp.diagonal().array () -= eivals(k);
- VectorType cross;
- Scalar n;
- n = (cross = tmp.row(0).cross(tmp.row(1))).squaredNorm();
-
- if(n>safeNorm2)
- eivecs.col(k) = cross / sqrt(n);
- else
+ Index k(0), l(2);
+ if(d0 > d1)
{
- n = (cross = tmp.row(0).cross(tmp.row(2))).squaredNorm();
-
- if(n>safeNorm2)
- eivecs.col(k) = cross / sqrt(n);
- else
- {
- n = (cross = tmp.row(1).cross(tmp.row(2))).squaredNorm();
-
- if(n>safeNorm2)
- eivecs.col(k) = cross / sqrt(n);
- else
- {
- // the input matrix and/or the eigenvaues probably contains some inf/NaN,
- // => exit
- // scale back to the original size.
- eivals *= scale;
-
- solver.m_info = NumericalIssue;
- solver.m_isInitialized = true;
- solver.m_eigenvectorsOk = computeEigenvectors;
- return;
- }
- }
+ std::swap(k,l);
+ d0 = d1;
}
- tmp = scaledMat;
- tmp.diagonal().array() -= eivals(1);
+ // Compute the eigenvector of index k
+ {
+ tmp.diagonal().array () -= eivals(k);
+ // By construction, 'tmp' is of rank 2, and its kernel corresponds to the respective eigenvector.
+ extract_kernel(tmp, eivecs.col(k), eivecs.col(l));
+ }
- if(d0<=Eigen::NumTraits<Scalar>::epsilon())
- eivecs.col(1) = eivecs.col(k).unitOrthogonal();
+ // Compute eigenvector of index l
+ if(d0<=2*Eigen::NumTraits<Scalar>::epsilon()*d1)
+ {
+ // If d0 is too small, then the two other eigenvalues are numerically the same,
+ // and thus we only have to ortho-normalize the near orthogonal vector we saved above.
+ eivecs.col(l) -= eivecs.col(k).dot(eivecs.col(l))*eivecs.col(l);
+ eivecs.col(l).normalize();
+ }
else
{
- n = (cross = eivecs.col(k).cross(tmp.row(0).normalized())).squaredNorm();
- if(n>safeNorm2)
- eivecs.col(1) = cross / sqrt(n);
- else
- {
- n = (cross = eivecs.col(k).cross(tmp.row(1))).squaredNorm();
- if(n>safeNorm2)
- eivecs.col(1) = cross / sqrt(n);
- else
- {
- n = (cross = eivecs.col(k).cross(tmp.row(2))).squaredNorm();
- if(n>safeNorm2)
- eivecs.col(1) = cross / sqrt(n);
- else
- {
- // we should never reach this point,
- // if so the last two eigenvalues are likely to ve very closed to each other
- eivecs.col(1) = eivecs.col(k).unitOrthogonal();
- }
- }
- }
-
- // make sure that eivecs[1] is orthogonal to eivecs[2]
- Scalar d = eivecs.col(1).dot(eivecs.col(k));
- eivecs.col(1) = (eivecs.col(1) - d * eivecs.col(k)).normalized();
+ tmp = scaledMat;
+ tmp.diagonal().array () -= eivals(l);
+
+ VectorType dummy;
+ extract_kernel(tmp, eivecs.col(l), dummy);
}
- eivecs.col(k==2 ? 0 : 2) = eivecs.col(k).cross(eivecs.col(1)).normalized();
+ // Compute last eigenvector from the other two
+ eivecs.col(1) = eivecs.col(2).cross(eivecs.col(0)).normalized();
}
}
+
// Rescale back to the original size.
eivals *= scale;
+ eivals.array() += shift;
solver.m_info = Success;
solver.m_isInitialized = true;
@@ -665,11 +655,12 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
typedef typename SolverType::MatrixType MatrixType;
typedef typename SolverType::RealVectorType VectorType;
typedef typename SolverType::Scalar Scalar;
+ typedef typename SolverType::EigenvectorsType EigenvectorsType;
static inline void computeRoots(const MatrixType& m, VectorType& roots)
{
using std::sqrt;
- const Scalar t0 = Scalar(0.5) * sqrt( numext::abs2(m(0,0)-m(1,1)) + Scalar(4)*m(1,0)*m(1,0));
+ const Scalar t0 = Scalar(0.5) * sqrt( numext::abs2(m(0,0)-m(1,1)) + Scalar(4)*numext::abs2(m(1,0)));
const Scalar t1 = Scalar(0.5) * (m(0,0) + m(1,1));
roots(0) = t1 - t0;
roots(1) = t1 + t0;
@@ -678,13 +669,15 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
static inline void run(SolverType& solver, const MatrixType& mat, int options)
{
using std::sqrt;
+ using std::abs;
+
eigen_assert(mat.cols() == 2 && mat.cols() == mat.rows());
eigen_assert((options&~(EigVecMask|GenEigMask))==0
&& (options&EigVecMask)!=EigVecMask
&& "invalid option parameter");
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
- MatrixType& eivecs = solver.m_eivec;
+ EigenvectorsType& eivecs = solver.m_eivec;
VectorType& eivals = solver.m_eivalues;
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
@@ -698,22 +691,29 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
// compute the eigen vectors
if(computeEigenvectors)
{
- scaledMat.diagonal().array () -= eivals(1);
- Scalar a2 = numext::abs2(scaledMat(0,0));
- Scalar c2 = numext::abs2(scaledMat(1,1));
- Scalar b2 = numext::abs2(scaledMat(1,0));
- if(a2>c2)
+ if((eivals(1)-eivals(0))<=abs(eivals(1))*Eigen::NumTraits<Scalar>::epsilon())
{
- eivecs.col(1) << -scaledMat(1,0), scaledMat(0,0);
- eivecs.col(1) /= sqrt(a2+b2);
+ eivecs.setIdentity();
}
else
{
- eivecs.col(1) << -scaledMat(1,1), scaledMat(1,0);
- eivecs.col(1) /= sqrt(c2+b2);
- }
+ scaledMat.diagonal().array () -= eivals(1);
+ Scalar a2 = numext::abs2(scaledMat(0,0));
+ Scalar c2 = numext::abs2(scaledMat(1,1));
+ Scalar b2 = numext::abs2(scaledMat(1,0));
+ if(a2>c2)
+ {
+ eivecs.col(1) << -scaledMat(1,0), scaledMat(0,0);
+ eivecs.col(1) /= sqrt(a2+b2);
+ }
+ else
+ {
+ eivecs.col(1) << -scaledMat(1,1), scaledMat(1,0);
+ eivecs.col(1) /= sqrt(c2+b2);
+ }
- eivecs.col(0) << eivecs.col(1).unitOrthogonal();
+ eivecs.col(0) << eivecs.col(1).unitOrthogonal();
+ }
}
// Rescale back to the original size.
@@ -736,7 +736,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
}
namespace internal {
-template<int StorageOrder,typename RealScalar, typename Scalar, typename Index>
+template<typename RealScalar, typename Scalar, typename Index>
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n)
{
using std::abs;
@@ -788,8 +788,7 @@ static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index sta
// apply the givens rotation to the unit matrix Q = Q * G
if (matrixQ)
{
- // FIXME if StorageOrder == RowMajor this operation is not very efficient
- Map<Matrix<Scalar,Dynamic,Dynamic,StorageOrder> > q(matrixQ,n,n);
+ Map<Matrix<Scalar,Dynamic,Dynamic,ColMajor> > q(matrixQ,n,n);
q.applyOnTheRight(k,k+1,rot);
}
}
diff --git a/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h b/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h
index 8e186d57a34..7e1cd9eb79c 100644
--- a/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h
+++ b/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h
@@ -19,10 +19,12 @@ namespace Eigen {
*
* \brief An axis aligned box
*
- * \param _Scalar the type of the scalar coefficients
- * \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
+ * \tparam _Scalar the type of the scalar coefficients
+ * \tparam _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
*
* This class represents an axis aligned box as a pair of the minimal and maximal corners.
+ * \warning The result of most methods is undefined when applied to an empty box. You can check for empty boxes using isEmpty().
+ * \sa alignedboxtypedefs
*/
template <typename _Scalar, int _AmbientDim>
class AlignedBox
@@ -40,18 +42,21 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
/** Define constants to name the corners of a 1D, 2D or 3D axis aligned bounding box */
enum CornerType
{
- /** 1D names */
+ /** 1D names @{ */
Min=0, Max=1,
+ /** @} */
- /** Added names for 2D */
+ /** Identifier for 2D corner @{ */
BottomLeft=0, BottomRight=1,
TopLeft=2, TopRight=3,
+ /** @} */
- /** Added names for 3D */
+ /** Identifier for 3D corner @{ */
BottomLeftFloor=0, BottomRightFloor=1,
TopLeftFloor=2, TopRightFloor=3,
BottomLeftCeil=4, BottomRightCeil=5,
TopLeftCeil=6, TopRightCeil=7
+ /** @} */
};
@@ -63,34 +68,33 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
inline explicit AlignedBox(Index _dim) : m_min(_dim), m_max(_dim)
{ setEmpty(); }
- /** Constructs a box with extremities \a _min and \a _max. */
+ /** Constructs a box with extremities \a _min and \a _max.
+ * \warning If either component of \a _min is larger than the same component of \a _max, the constructed box is empty. */
template<typename OtherVectorType1, typename OtherVectorType2>
inline AlignedBox(const OtherVectorType1& _min, const OtherVectorType2& _max) : m_min(_min), m_max(_max) {}
/** Constructs a box containing a single point \a p. */
template<typename Derived>
- inline explicit AlignedBox(const MatrixBase<Derived>& a_p)
- {
- typename internal::nested<Derived,2>::type p(a_p.derived());
- m_min = p;
- m_max = p;
- }
+ inline explicit AlignedBox(const MatrixBase<Derived>& p) : m_min(p), m_max(m_min)
+ { }
~AlignedBox() {}
/** \returns the dimension in which the box holds */
inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size() : Index(AmbientDimAtCompileTime); }
- /** \deprecated use isEmpty */
+ /** \deprecated use isEmpty() */
inline bool isNull() const { return isEmpty(); }
- /** \deprecated use setEmpty */
+ /** \deprecated use setEmpty() */
inline void setNull() { setEmpty(); }
- /** \returns true if the box is empty. */
+ /** \returns true if the box is empty.
+ * \sa setEmpty */
inline bool isEmpty() const { return (m_min.array() > m_max.array()).any(); }
- /** Makes \c *this an empty box. */
+ /** Makes \c *this an empty box.
+ * \sa isEmpty */
inline void setEmpty()
{
m_min.setConstant( ScalarTraits::highest() );
@@ -159,7 +163,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
* a uniform distribution */
inline VectorType sample() const
{
- VectorType r;
+ VectorType r(dim());
for(Index d=0; d<dim(); ++d)
{
if(!ScalarTraits::IsInteger)
@@ -175,27 +179,34 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
/** \returns true if the point \a p is inside the box \c *this. */
template<typename Derived>
- inline bool contains(const MatrixBase<Derived>& a_p) const
+ inline bool contains(const MatrixBase<Derived>& p) const
{
- typename internal::nested<Derived,2>::type p(a_p.derived());
- return (m_min.array()<=p.array()).all() && (p.array()<=m_max.array()).all();
+ typename internal::nested<Derived,2>::type p_n(p.derived());
+ return (m_min.array()<=p_n.array()).all() && (p_n.array()<=m_max.array()).all();
}
/** \returns true if the box \a b is entirely inside the box \c *this. */
inline bool contains(const AlignedBox& b) const
{ return (m_min.array()<=(b.min)().array()).all() && ((b.max)().array()<=m_max.array()).all(); }
- /** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
+ /** \returns true if the box \a b is intersecting the box \c *this.
+ * \sa intersection, clamp */
+ inline bool intersects(const AlignedBox& b) const
+ { return (m_min.array()<=(b.max)().array()).all() && ((b.min)().array()<=m_max.array()).all(); }
+
+ /** Extends \c *this such that it contains the point \a p and returns a reference to \c *this.
+ * \sa extend(const AlignedBox&) */
template<typename Derived>
- inline AlignedBox& extend(const MatrixBase<Derived>& a_p)
+ inline AlignedBox& extend(const MatrixBase<Derived>& p)
{
- typename internal::nested<Derived,2>::type p(a_p.derived());
- m_min = m_min.cwiseMin(p);
- m_max = m_max.cwiseMax(p);
+ typename internal::nested<Derived,2>::type p_n(p.derived());
+ m_min = m_min.cwiseMin(p_n);
+ m_max = m_max.cwiseMax(p_n);
return *this;
}
- /** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
+ /** Extends \c *this such that it contains the box \a b and returns a reference to \c *this.
+ * \sa merged, extend(const MatrixBase&) */
inline AlignedBox& extend(const AlignedBox& b)
{
m_min = m_min.cwiseMin(b.m_min);
@@ -203,7 +214,9 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
return *this;
}
- /** Clamps \c *this by the box \a b and returns a reference to \c *this. */
+ /** Clamps \c *this by the box \a b and returns a reference to \c *this.
+ * \note If the boxes don't intersect, the resulting box is empty.
+ * \sa intersection(), intersects() */
inline AlignedBox& clamp(const AlignedBox& b)
{
m_min = m_min.cwiseMax(b.m_min);
@@ -211,11 +224,15 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
return *this;
}
- /** Returns an AlignedBox that is the intersection of \a b and \c *this */
+ /** Returns an AlignedBox that is the intersection of \a b and \c *this
+ * \note If the boxes don't intersect, the resulting box is empty.
+ * \sa intersects(), clamp, contains() */
inline AlignedBox intersection(const AlignedBox& b) const
{return AlignedBox(m_min.cwiseMax(b.m_min), m_max.cwiseMin(b.m_max)); }
- /** Returns an AlignedBox that is the union of \a b and \c *this */
+ /** Returns an AlignedBox that is the union of \a b and \c *this.
+ * \note Merging with an empty box may result in a box bigger than \c *this.
+ * \sa extend(const AlignedBox&) */
inline AlignedBox merged(const AlignedBox& b) const
{ return AlignedBox(m_min.cwiseMin(b.m_min), m_max.cwiseMax(b.m_max)); }
@@ -231,20 +248,20 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
/** \returns the squared distance between the point \a p and the box \c *this,
* and zero if \a p is inside the box.
- * \sa exteriorDistance()
+ * \sa exteriorDistance(const MatrixBase&), squaredExteriorDistance(const AlignedBox&)
*/
template<typename Derived>
- inline Scalar squaredExteriorDistance(const MatrixBase<Derived>& a_p) const;
+ inline Scalar squaredExteriorDistance(const MatrixBase<Derived>& p) const;
/** \returns the squared distance between the boxes \a b and \c *this,
* and zero if the boxes intersect.
- * \sa exteriorDistance()
+ * \sa exteriorDistance(const AlignedBox&), squaredExteriorDistance(const MatrixBase&)
*/
inline Scalar squaredExteriorDistance(const AlignedBox& b) const;
/** \returns the distance between the point \a p and the box \c *this,
* and zero if \a p is inside the box.
- * \sa squaredExteriorDistance()
+ * \sa squaredExteriorDistance(const MatrixBase&), exteriorDistance(const AlignedBox&)
*/
template<typename Derived>
inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
@@ -252,7 +269,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
/** \returns the distance between the boxes \a b and \c *this,
* and zero if the boxes intersect.
- * \sa squaredExteriorDistance()
+ * \sa squaredExteriorDistance(const AlignedBox&), exteriorDistance(const MatrixBase&)
*/
inline NonInteger exteriorDistance(const AlignedBox& b) const
{ using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(b))); }
diff --git a/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h b/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h
index 553d38c7449..bbf6a7ed8ed 100644
--- a/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h
+++ b/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h
@@ -131,7 +131,7 @@ public:
m_angle = Scalar(other.angle());
}
- static inline const AngleAxis Identity() { return AngleAxis(0, Vector3::UnitX()); }
+ static inline const AngleAxis Identity() { return AngleAxis(Scalar(0), Vector3::UnitX()); }
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
* determined by \a prec.
@@ -165,8 +165,8 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived
Scalar n2 = q.vec().squaredNorm();
if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision())
{
- m_angle = 0;
- m_axis << 1, 0, 0;
+ m_angle = Scalar(0);
+ m_axis << Scalar(1), Scalar(0), Scalar(0);
}
else
{
diff --git a/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h b/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h
index 00e71d190c3..372e422b92c 100644
--- a/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h
+++ b/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h
@@ -79,7 +79,7 @@ template<typename MatrixType,int _Direction> class Homogeneous
{
if( (int(Direction)==Vertical && row==m_matrix.rows())
|| (int(Direction)==Horizontal && col==m_matrix.cols()))
- return 1;
+ return Scalar(1);
return m_matrix.coeff(row, col);
}
diff --git a/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h b/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h
index aeff43fefa6..00b7c4300fd 100644
--- a/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h
+++ b/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h
@@ -100,7 +100,17 @@ public:
{
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3)
Hyperplane result(p0.size());
- result.normal() = (p2 - p0).cross(p1 - p0).normalized();
+ VectorType v0(p2 - p0), v1(p1 - p0);
+ result.normal() = v0.cross(v1);
+ RealScalar norm = result.normal().norm();
+ if(norm <= v0.norm() * v1.norm() * NumTraits<RealScalar>::epsilon())
+ {
+ Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
+ JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
+ result.normal() = svd.matrixV().col(2);
+ }
+ else
+ result.normal() /= norm;
result.offset() = -p0.dot(result.normal());
return result;
}
diff --git a/extern/Eigen3/Eigen/src/Geometry/Quaternion.h b/extern/Eigen3/Eigen/src/Geometry/Quaternion.h
index 9fee0c91980..25ed17bb690 100644
--- a/extern/Eigen3/Eigen/src/Geometry/Quaternion.h
+++ b/extern/Eigen3/Eigen/src/Geometry/Quaternion.h
@@ -102,11 +102,11 @@ public:
/** \returns a quaternion representing an identity rotation
* \sa MatrixBase::Identity()
*/
- static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(1, 0, 0, 0); }
+ static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(Scalar(1), Scalar(0), Scalar(0), Scalar(0)); }
/** \sa QuaternionBase::Identity(), MatrixBase::setIdentity()
*/
- inline QuaternionBase& setIdentity() { coeffs() << 0, 0, 0, 1; return *this; }
+ inline QuaternionBase& setIdentity() { coeffs() << Scalar(0), Scalar(0), Scalar(0), Scalar(1); return *this; }
/** \returns the squared norm of the quaternion's coefficients
* \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
@@ -161,7 +161,7 @@ public:
{ return coeffs().isApprox(other.coeffs(), prec); }
/** return the result vector of \a v through the rotation*/
- EIGEN_STRONG_INLINE Vector3 _transformVector(Vector3 v) const;
+ EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const;
/** \returns \c *this with scalar type casted to \a NewScalarType
*
@@ -203,6 +203,8 @@ public:
* \li \c Quaternionf for \c float
* \li \c Quaterniond for \c double
*
+ * \warning Operations interpreting the quaternion as rotation have undefined behavior if the quaternion is not normalized.
+ *
* \sa class AngleAxis, class Transform
*/
@@ -229,7 +231,7 @@ class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> >
public:
typedef _Scalar Scalar;
- EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Quaternion)
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Quaternion)
using Base::operator*=;
typedef typename internal::traits<Quaternion>::Coefficients Coefficients;
@@ -339,12 +341,12 @@ class Map<const Quaternion<_Scalar>, _Options >
public:
typedef _Scalar Scalar;
typedef typename internal::traits<Map>::Coefficients Coefficients;
- EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
using Base::operator*=;
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
*
- * The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order:
+ * The pointer \a coeffs must reference the four coefficients of Quaternion in the following order:
* \code *coeffs == {x, y, z, w} \endcode
*
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
@@ -376,7 +378,7 @@ class Map<Quaternion<_Scalar>, _Options >
public:
typedef _Scalar Scalar;
typedef typename internal::traits<Map>::Coefficients Coefficients;
- EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
using Base::operator*=;
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
@@ -459,12 +461,12 @@ EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const Quaterni
*/
template <class Derived>
EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
-QuaternionBase<Derived>::_transformVector(Vector3 v) const
+QuaternionBase<Derived>::_transformVector(const Vector3& v) const
{
// Note that this algorithm comes from the optimization by hand
// of the conversion to a Matrix followed by a Matrix/Vector product.
// It appears to be much faster than the common algorithm found
- // in the litterature (30 versus 39 flops). It also requires two
+ // in the literature (30 versus 39 flops). It also requires two
// Vector3 as temporaries.
Vector3 uv = this->vec().cross(v);
uv += uv;
@@ -584,7 +586,7 @@ inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Deri
// which yields a singular value problem
if (c < Scalar(-1)+NumTraits<Scalar>::dummy_precision())
{
- c = max<Scalar>(c,-1);
+ c = (max)(c,Scalar(-1));
Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
Vector3 axis = svd.matrixV().col(2);
@@ -635,7 +637,7 @@ inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Der
{
// FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
Scalar n2 = this->squaredNorm();
- if (n2 > 0)
+ if (n2 > Scalar(0))
return Quaternion<Scalar>(conjugate().coeffs() / n2);
else
{
@@ -665,12 +667,10 @@ template <class OtherDerived>
inline typename internal::traits<Derived>::Scalar
QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
{
- using std::acos;
+ using std::atan2;
using std::abs;
- double d = abs(this->dot(other));
- if (d>=1.0)
- return Scalar(0);
- return static_cast<Scalar>(2 * acos(d));
+ Quaternion<Scalar> d = (*this) * other.conjugate();
+ return Scalar(2) * atan2( d.vec().norm(), abs(d.w()) );
}
@@ -710,7 +710,7 @@ QuaternionBase<Derived>::slerp(const Scalar& t, const QuaternionBase<OtherDerive
scale0 = sin( ( Scalar(1) - t ) * theta) / sinTheta;
scale1 = sin( ( t * theta) ) / sinTheta;
}
- if(d<0) scale1 = -scale1;
+ if(d<Scalar(0)) scale1 = -scale1;
return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
}
diff --git a/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h b/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h
index 1cac343a5ee..a2d59fce10f 100644
--- a/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h
+++ b/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h
@@ -60,6 +60,9 @@ public:
/** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
inline Rotation2D(const Scalar& a) : m_angle(a) {}
+
+ /** Default constructor wihtout initialization. The represented rotation is undefined. */
+ Rotation2D() {}
/** \returns the rotation angle */
inline Scalar angle() const { return m_angle; }
@@ -81,10 +84,10 @@ public:
/** Applies the rotation to a 2D vector */
Vector2 operator* (const Vector2& vec) const
{ return toRotationMatrix() * vec; }
-
+
template<typename Derived>
Rotation2D& fromRotationMatrix(const MatrixBase<Derived>& m);
- Matrix2 toRotationMatrix(void) const;
+ Matrix2 toRotationMatrix() const;
/** \returns the spherical interpolation between \c *this and \a other using
* parameter \a t. It is in fact equivalent to a linear interpolation.
diff --git a/extern/Eigen3/Eigen/src/Geometry/Transform.h b/extern/Eigen3/Eigen/src/Geometry/Transform.h
index 498fea41a90..e786e535695 100644
--- a/extern/Eigen3/Eigen/src/Geometry/Transform.h
+++ b/extern/Eigen3/Eigen/src/Geometry/Transform.h
@@ -62,6 +62,8 @@ struct transform_construct_from_matrix;
template<typename TransformType> struct transform_take_affine_part;
+template<int Mode> struct transform_make_affine;
+
} // end namespace internal
/** \geometry_module \ingroup Geometry_Module
@@ -194,9 +196,9 @@ public:
/** type of the matrix used to represent the linear part of the transformation */
typedef Matrix<Scalar,Dim,Dim,Options> LinearMatrixType;
/** type of read/write reference to the linear part of the transformation */
- typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact)> LinearPart;
+ typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> LinearPart;
/** type of read reference to the linear part of the transformation */
- typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact)> ConstLinearPart;
+ typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> ConstLinearPart;
/** type of read/write reference to the affine part of the transformation */
typedef typename internal::conditional<int(Mode)==int(AffineCompact),
MatrixType&,
@@ -230,8 +232,7 @@ public:
inline Transform()
{
check_template_params();
- if (int(Mode)==Affine)
- makeAffine();
+ internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix);
}
inline Transform(const Transform& other)
@@ -591,11 +592,7 @@ public:
*/
void makeAffine()
{
- if(int(Mode)!=int(AffineCompact))
- {
- matrix().template block<1,Dim>(Dim,0).setZero();
- matrix().coeffRef(Dim,Dim) = Scalar(1);
- }
+ internal::transform_make_affine<int(Mode)>::run(m_matrix);
}
/** \internal
@@ -1079,6 +1076,24 @@ Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBas
namespace internal {
+template<int Mode>
+struct transform_make_affine
+{
+ template<typename MatrixType>
+ static void run(MatrixType &mat)
+ {
+ static const int Dim = MatrixType::ColsAtCompileTime-1;
+ mat.template block<1,Dim>(Dim,0).setZero();
+ mat.coeffRef(Dim,Dim) = typename MatrixType::Scalar(1);
+ }
+};
+
+template<>
+struct transform_make_affine<AffineCompact>
+{
+ template<typename MatrixType> static void run(MatrixType &) { }
+};
+
// selector needed to avoid taking the inverse of a 3x4 matrix
template<typename TransformType, int Mode=TransformType::Mode>
struct projective_transform_inverse
diff --git a/extern/Eigen3/Eigen/src/Geometry/Umeyama.h b/extern/Eigen3/Eigen/src/Geometry/Umeyama.h
index 345b47e0c37..5e20662f803 100644
--- a/extern/Eigen3/Eigen/src/Geometry/Umeyama.h
+++ b/extern/Eigen3/Eigen/src/Geometry/Umeyama.h
@@ -113,7 +113,7 @@ umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, boo
const Index n = src.cols(); // number of measurements
// required for demeaning ...
- const RealScalar one_over_n = 1 / static_cast<RealScalar>(n);
+ const RealScalar one_over_n = RealScalar(1) / static_cast<RealScalar>(n);
// computation of mean
const VectorType src_mean = src.rowwise().sum() * one_over_n;
@@ -136,16 +136,16 @@ umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, boo
// Eq. (39)
VectorType S = VectorType::Ones(m);
- if (sigma.determinant()<0) S(m-1) = -1;
+ if (sigma.determinant()<Scalar(0)) S(m-1) = Scalar(-1);
// Eq. (40) and (43)
const VectorType& d = svd.singularValues();
Index rank = 0; for (Index i=0; i<m; ++i) if (!internal::isMuchSmallerThan(d.coeff(i),d.coeff(0))) ++rank;
if (rank == m-1) {
- if ( svd.matrixU().determinant() * svd.matrixV().determinant() > 0 ) {
+ if ( svd.matrixU().determinant() * svd.matrixV().determinant() > Scalar(0) ) {
Rt.block(0,0,m,m).noalias() = svd.matrixU()*svd.matrixV().transpose();
} else {
- const Scalar s = S(m-1); S(m-1) = -1;
+ const Scalar s = S(m-1); S(m-1) = Scalar(-1);
Rt.block(0,0,m,m).noalias() = svd.matrixU() * S.asDiagonal() * svd.matrixV().transpose();
S(m-1) = s;
}
@@ -156,7 +156,7 @@ umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, boo
if (with_scaling)
{
// Eq. (42)
- const Scalar c = 1/src_var * svd.singularValues().dot(S);
+ const Scalar c = Scalar(1)/src_var * svd.singularValues().dot(S);
// Eq. (41)
Rt.col(m).head(m) = dst_mean;
diff --git a/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h b/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h
index 1991c652738..60dbea5f56a 100644
--- a/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h
+++ b/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h
@@ -48,7 +48,7 @@ void apply_block_householder_on_the_left(MatrixType& mat, const VectorsType& vec
typedef typename MatrixType::Index Index;
enum { TFactorSize = MatrixType::ColsAtCompileTime };
Index nbVecs = vectors.cols();
- Matrix<typename MatrixType::Scalar, TFactorSize, TFactorSize> T(nbVecs,nbVecs);
+ Matrix<typename MatrixType::Scalar, TFactorSize, TFactorSize, ColMajor> T(nbVecs,nbVecs);
make_block_householder_triangular_factor(T, vectors, hCoeffs);
const TriangularView<const VectorsType, UnitLower>& V(vectors);
diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h
index 73ca9bfde6a..1f3c060d028 100644
--- a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h
+++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h
@@ -65,10 +65,10 @@ class DiagonalPreconditioner
{
typename MatType::InnerIterator it(mat,j);
while(it && it.index()!=j) ++it;
- if(it && it.index()==j)
+ if(it && it.index()==j && it.value()!=Scalar(0))
m_invdiag(j) = Scalar(1)/it.value();
else
- m_invdiag(j) = 0;
+ m_invdiag(j) = Scalar(1);
}
m_isInitialized = true;
return *this;
diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h
index 6fc6ab85225..5512219076b 100644
--- a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h
+++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h
@@ -39,7 +39,6 @@ bool bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x,
int maxIters = iters;
int n = mat.cols();
- x = precond.solve(x);
VectorType r = rhs - mat * x;
VectorType r0 = r;
@@ -61,6 +60,7 @@ bool bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x,
VectorType s(n), t(n);
RealScalar tol2 = tol*tol;
+ RealScalar eps2 = NumTraits<Scalar>::epsilon()*NumTraits<Scalar>::epsilon();
int i = 0;
int restarts = 0;
@@ -69,7 +69,7 @@ bool bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x,
Scalar rho_old = rho;
rho = r0.dot(r);
- if (internal::isMuchSmallerThan(rho,r0_sqnorm))
+ if (abs(rho) < eps2*r0_sqnorm)
{
// The new residual vector became too orthogonal to the arbitrarily choosen direction r0
// Let's restart with a new r0:
@@ -142,7 +142,7 @@ struct traits<BiCGSTAB<_MatrixType,_Preconditioner> >
* SparseMatrix<double> A(n,n);
* // fill A and b
* BiCGSTAB<SparseMatrix<double> > solver;
- * solver(A);
+ * solver.compute(A);
* x = solver.solve(b);
* std::cout << "#iterations: " << solver.iterations() << std::endl;
* std::cout << "estimated error: " << solver.error() << std::endl;
@@ -151,20 +151,7 @@ struct traits<BiCGSTAB<_MatrixType,_Preconditioner> >
* \endcode
*
* By default the iterations start with x=0 as an initial guess of the solution.
- * One can control the start using the solveWithGuess() method. Here is a step by
- * step execution example starting with a random guess and printing the evolution
- * of the estimated error:
- * * \code
- * x = VectorXd::Random(n);
- * solver.setMaxIterations(1);
- * int i = 0;
- * do {
- * x = solver.solveWithGuess(b,x);
- * std::cout << i << " : " << solver.error() << std::endl;
- * ++i;
- * } while (solver.info()!=Success && i<100);
- * \endcode
- * Note that such a step by step excution is slightly slower.
+ * One can control the start using the solveWithGuess() method.
*
* \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
*/
@@ -199,7 +186,8 @@ public:
* this class becomes invalid. Call compute() to update it with the new
* matrix A, or modify a copy of A.
*/
- BiCGSTAB(const MatrixType& A) : Base(A) {}
+ template<typename MatrixDerived>
+ explicit BiCGSTAB(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {}
~BiCGSTAB() {}
diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h
index a74a8155e68..1a7e569c806 100644
--- a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h
+++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h
@@ -112,9 +112,9 @@ struct traits<ConjugateGradient<_MatrixType,_UpLo,_Preconditioner> >
* This class allows to solve for A.x = b sparse linear problems using a conjugate gradient algorithm.
* The sparse matrix A must be selfadjoint. The vectors x and b can be either dense or sparse.
*
- * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix.
- * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
- * or Upper. Default is Lower.
+ * \tparam _MatrixType the type of the matrix A, can be a dense or a sparse matrix.
+ * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower,
+ * Upper, or Lower|Upper in which the full matrix entries will be considered. Default is Lower.
* \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner
*
* The maximal number of iterations and tolerance value can be controlled via the setMaxIterations()
@@ -137,20 +137,7 @@ struct traits<ConjugateGradient<_MatrixType,_UpLo,_Preconditioner> >
* \endcode
*
* By default the iterations start with x=0 as an initial guess of the solution.
- * One can control the start using the solveWithGuess() method. Here is a step by
- * step execution example starting with a random guess and printing the evolution
- * of the estimated error:
- * * \code
- * x = VectorXd::Random(n);
- * cg.setMaxIterations(1);
- * int i = 0;
- * do {
- * x = cg.solveWithGuess(b,x);
- * std::cout << i << " : " << cg.error() << std::endl;
- * ++i;
- * } while (cg.info()!=Success && i<100);
- * \endcode
- * Note that such a step by step excution is slightly slower.
+ * One can control the start using the solveWithGuess() method.
*
* \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
*/
@@ -189,7 +176,8 @@ public:
* this class becomes invalid. Call compute() to update it with the new
* matrix A, or modify a copy of A.
*/
- ConjugateGradient(const MatrixType& A) : Base(A) {}
+ template<typename MatrixDerived>
+ explicit ConjugateGradient(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {}
~ConjugateGradient() {}
@@ -213,6 +201,10 @@ public:
template<typename Rhs,typename Dest>
void _solveWithGuess(const Rhs& b, Dest& x) const
{
+ typedef typename internal::conditional<UpLo==(Lower|Upper),
+ const MatrixType&,
+ SparseSelfAdjointView<const MatrixType, UpLo>
+ >::type MatrixWrapperType;
m_iterations = Base::maxIterations();
m_error = Base::m_tolerance;
@@ -222,8 +214,7 @@ public:
m_error = Base::m_tolerance;
typename Dest::ColXpr xj(x,j);
- internal::conjugate_gradient(mp_matrix->template selfadjointView<UpLo>(), b.col(j), xj,
- Base::m_preconditioner, m_iterations, m_error);
+ internal::conjugate_gradient(MatrixWrapperType(*mp_matrix), b.col(j), xj, Base::m_preconditioner, m_iterations, m_error);
}
m_isInitialized = true;
@@ -234,7 +225,7 @@ public:
template<typename Rhs,typename Dest>
void _solve(const Rhs& b, Dest& x) const
{
- x.setOnes();
+ x.setZero();
_solveWithGuess(b,x);
}
diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h
index b55afc13636..d3f37fea2a1 100644
--- a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h
+++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h
@@ -150,7 +150,6 @@ class IncompleteLUT : internal::noncopyable
{
analyzePattern(amat);
factorize(amat);
- m_isInitialized = m_factorizationIsOk;
return *this;
}
@@ -160,7 +159,7 @@ class IncompleteLUT : internal::noncopyable
template<typename Rhs, typename Dest>
void _solve(const Rhs& b, Dest& x) const
{
- x = m_Pinv * b;
+ x = m_Pinv * b;
x = m_lu.template triangularView<UnitLower>().solve(x);
x = m_lu.template triangularView<Upper>().solve(x);
x = m_P * x;
@@ -223,18 +222,29 @@ template<typename _MatrixType>
void IncompleteLUT<Scalar>::analyzePattern(const _MatrixType& amat)
{
// Compute the Fill-reducing permutation
+ // Since ILUT does not perform any numerical pivoting,
+ // it is highly preferable to keep the diagonal through symmetric permutations.
+#ifndef EIGEN_MPL2_ONLY
+ // To this end, let's symmetrize the pattern and perform AMD on it.
SparseMatrix<Scalar,ColMajor, Index> mat1 = amat;
SparseMatrix<Scalar,ColMajor, Index> mat2 = amat.transpose();
- // Symmetrize the pattern
// FIXME for a matrix with nearly symmetric pattern, mat2+mat1 is the appropriate choice.
// on the other hand for a really non-symmetric pattern, mat2*mat1 should be prefered...
SparseMatrix<Scalar,ColMajor, Index> AtA = mat2 + mat1;
- AtA.prune(keep_diag());
- internal::minimum_degree_ordering<Scalar, Index>(AtA, m_P); // Then compute the AMD ordering...
-
- m_Pinv = m_P.inverse(); // ... and the inverse permutation
+ AMDOrdering<Index> ordering;
+ ordering(AtA,m_P);
+ m_Pinv = m_P.inverse(); // cache the inverse permutation
+#else
+ // If AMD is not available, (MPL2-only), then let's use the slower COLAMD routine.
+ SparseMatrix<Scalar,ColMajor, Index> mat1 = amat;
+ COLAMDOrdering<Index> ordering;
+ ordering(mat1,m_Pinv);
+ m_P = m_Pinv.inverse();
+#endif
m_analysisIsOk = true;
+ m_factorizationIsOk = false;
+ m_isInitialized = false;
}
template <typename Scalar>
@@ -442,6 +452,7 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
m_lu.makeCompressed();
m_factorizationIsOk = true;
+ m_isInitialized = m_factorizationIsOk;
m_info = Success;
}
diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h
index 2036922d69c..501ef2f8d87 100644
--- a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h
+++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h
@@ -49,10 +49,11 @@ public:
* this class becomes invalid. Call compute() to update it with the new
* matrix A, or modify a copy of A.
*/
- IterativeSolverBase(const MatrixType& A)
+ template<typename InputDerived>
+ IterativeSolverBase(const EigenBase<InputDerived>& A)
{
init();
- compute(A);
+ compute(A.derived());
}
~IterativeSolverBase() {}
@@ -62,9 +63,11 @@ public:
* Currently, this function mostly call analyzePattern on the preconditioner. In the future
* we might, for instance, implement column reodering for faster matrix vector products.
*/
- Derived& analyzePattern(const MatrixType& A)
+ template<typename InputDerived>
+ Derived& analyzePattern(const EigenBase<InputDerived>& A)
{
- m_preconditioner.analyzePattern(A);
+ grabInput(A.derived());
+ m_preconditioner.analyzePattern(*mp_matrix);
m_isInitialized = true;
m_analysisIsOk = true;
m_info = Success;
@@ -80,11 +83,12 @@ public:
* this class becomes invalid. Call compute() to update it with the new
* matrix A, or modify a copy of A.
*/
- Derived& factorize(const MatrixType& A)
+ template<typename InputDerived>
+ Derived& factorize(const EigenBase<InputDerived>& A)
{
+ grabInput(A.derived());
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
- mp_matrix = &A;
- m_preconditioner.factorize(A);
+ m_preconditioner.factorize(*mp_matrix);
m_factorizationIsOk = true;
m_info = Success;
return derived();
@@ -100,10 +104,11 @@ public:
* this class becomes invalid. Call compute() to update it with the new
* matrix A, or modify a copy of A.
*/
- Derived& compute(const MatrixType& A)
+ template<typename InputDerived>
+ Derived& compute(const EigenBase<InputDerived>& A)
{
- mp_matrix = &A;
- m_preconditioner.compute(A);
+ grabInput(A.derived());
+ m_preconditioner.compute(*mp_matrix);
m_isInitialized = true;
m_analysisIsOk = true;
m_factorizationIsOk = true;
@@ -212,6 +217,28 @@ public:
}
protected:
+
+ template<typename InputDerived>
+ void grabInput(const EigenBase<InputDerived>& A)
+ {
+ // we const cast to prevent the creation of a MatrixType temporary by the compiler.
+ grabInput_impl(A.const_cast_derived());
+ }
+
+ template<typename InputDerived>
+ void grabInput_impl(const EigenBase<InputDerived>& A)
+ {
+ m_copyMatrix = A;
+ mp_matrix = &m_copyMatrix;
+ }
+
+ void grabInput_impl(MatrixType& A)
+ {
+ if(MatrixType::RowsAtCompileTime==Dynamic && MatrixType::ColsAtCompileTime==Dynamic)
+ m_copyMatrix.resize(0,0);
+ mp_matrix = &A;
+ }
+
void init()
{
m_isInitialized = false;
@@ -220,6 +247,7 @@ protected:
m_maxIterations = -1;
m_tolerance = NumTraits<Scalar>::epsilon();
}
+ MatrixType m_copyMatrix;
const MatrixType* mp_matrix;
Preconditioner m_preconditioner;
diff --git a/extern/Eigen3/Eigen/src/LU/FullPivLU.h b/extern/Eigen3/Eigen/src/LU/FullPivLU.h
index dfe25f424d7..26bc714475c 100644
--- a/extern/Eigen3/Eigen/src/LU/FullPivLU.h
+++ b/extern/Eigen3/Eigen/src/LU/FullPivLU.h
@@ -20,10 +20,11 @@ namespace Eigen {
*
* \param MatrixType the type of the matrix of which we are computing the LU decomposition
*
- * This class represents a LU decomposition of any matrix, with complete pivoting: the matrix A
- * is decomposed as A = PLUQ where L is unit-lower-triangular, U is upper-triangular, and P and Q
- * are permutation matrices. This is a rank-revealing LU decomposition. The eigenvalues (diagonal
- * coefficients) of U are sorted in such a way that any zeros are at the end.
+ * This class represents a LU decomposition of any matrix, with complete pivoting: the matrix A is
+ * decomposed as \f$ A = P^{-1} L U Q^{-1} \f$ where L is unit-lower-triangular, U is
+ * upper-triangular, and P and Q are permutation matrices. This is a rank-revealing LU
+ * decomposition. The eigenvalues (diagonal coefficients) of U are sorted in such a way that any
+ * zeros are at the end.
*
* This decomposition provides the generic approach to solving systems of linear equations, computing
* the rank, invertibility, inverse, kernel, and determinant.
@@ -373,6 +374,12 @@ template<typename _MatrixType> class FullPivLU
inline Index cols() const { return m_lu.cols(); }
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
+
MatrixType m_lu;
PermutationPType m_p;
PermutationQType m_q;
@@ -417,6 +424,8 @@ FullPivLU<MatrixType>::FullPivLU(const MatrixType& matrix)
template<typename MatrixType>
FullPivLU<MatrixType>& FullPivLU<MatrixType>::compute(const MatrixType& matrix)
{
+ check_template_parameters();
+
// the permutations are stored as int indices, so just to be sure:
eigen_assert(matrix.rows()<=NumTraits<int>::highest() && matrix.cols()<=NumTraits<int>::highest());
@@ -511,8 +520,8 @@ typename internal::traits<MatrixType>::Scalar FullPivLU<MatrixType>::determinant
}
/** \returns the matrix represented by the decomposition,
- * i.e., it returns the product: P^{-1} L U Q^{-1}.
- * This function is provided for debug purpose. */
+ * i.e., it returns the product: \f$ P^{-1} L U Q^{-1} \f$.
+ * This function is provided for debug purposes. */
template<typename MatrixType>
MatrixType FullPivLU<MatrixType>::reconstructedMatrix() const
{
diff --git a/extern/Eigen3/Eigen/src/LU/PartialPivLU.h b/extern/Eigen3/Eigen/src/LU/PartialPivLU.h
index 740ee694c45..7d1db948c0a 100644
--- a/extern/Eigen3/Eigen/src/LU/PartialPivLU.h
+++ b/extern/Eigen3/Eigen/src/LU/PartialPivLU.h
@@ -171,6 +171,12 @@ template<typename _MatrixType> class PartialPivLU
inline Index cols() const { return m_lu.cols(); }
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
+
MatrixType m_lu;
PermutationType m_p;
TranspositionType m_rowsTranspositions;
@@ -386,6 +392,8 @@ void partial_lu_inplace(MatrixType& lu, TranspositionType& row_transpositions, t
template<typename MatrixType>
PartialPivLU<MatrixType>& PartialPivLU<MatrixType>::compute(const MatrixType& matrix)
{
+ check_template_parameters();
+
// the row permutation is stored as int indices, so just to be sure:
eigen_assert(matrix.rows()<NumTraits<int>::highest());
diff --git a/extern/Eigen3/Eigen/src/OrderingMethods/Amd.h b/extern/Eigen3/Eigen/src/OrderingMethods/Amd.h
index 41b4fd7e392..70550b8a90a 100644
--- a/extern/Eigen3/Eigen/src/OrderingMethods/Amd.h
+++ b/extern/Eigen3/Eigen/src/OrderingMethods/Amd.h
@@ -137,22 +137,27 @@ void minimum_degree_ordering(SparseMatrix<Scalar,ColMajor,Index>& C, Permutation
degree[i] = len[i]; // degree of node i
}
mark = internal::cs_wclear<Index>(0, 0, w, n); /* clear w */
- elen[n] = -2; /* n is a dead element */
- Cp[n] = -1; /* n is a root of assembly tree */
- w[n] = 0; /* n is a dead element */
/* --- Initialize degree lists ------------------------------------------ */
for(i = 0; i < n; i++)
{
+ bool has_diag = false;
+ for(p = Cp[i]; p<Cp[i+1]; ++p)
+ if(Ci[p]==i)
+ {
+ has_diag = true;
+ break;
+ }
+
d = degree[i];
- if(d == 0) /* node i is empty */
+ if(d == 1 && has_diag) /* node i is empty */
{
elen[i] = -2; /* element i is dead */
nel++;
Cp[i] = -1; /* i is a root of assembly tree */
w[i] = 0;
}
- else if(d > dense) /* node i is dense */
+ else if(d > dense || !has_diag) /* node i is dense or has no structural diagonal element */
{
nv[i] = 0; /* absorb i into element n */
elen[i] = -1; /* node i is dead */
@@ -168,6 +173,10 @@ void minimum_degree_ordering(SparseMatrix<Scalar,ColMajor,Index>& C, Permutation
}
}
+ elen[n] = -2; /* n is a dead element */
+ Cp[n] = -1; /* n is a root of assembly tree */
+ w[n] = 0; /* n is a dead element */
+
while (nel < n) /* while (selecting pivots) do */
{
/* --- Select node of minimum approximate degree -------------------- */
diff --git a/extern/Eigen3/Eigen/src/OrderingMethods/Ordering.h b/extern/Eigen3/Eigen/src/OrderingMethods/Ordering.h
index b4da6531a1d..f3c31f9cbfc 100644
--- a/extern/Eigen3/Eigen/src/OrderingMethods/Ordering.h
+++ b/extern/Eigen3/Eigen/src/OrderingMethods/Ordering.h
@@ -109,7 +109,7 @@ class NaturalOrdering
* \class COLAMDOrdering
*
* Functor computing the \em column \em approximate \em minimum \em degree ordering
- * The matrix should be in column-major format
+ * The matrix should be in column-major and \b compressed format (see SparseMatrix::makeCompressed()).
*/
template<typename Index>
class COLAMDOrdering
@@ -118,10 +118,14 @@ class COLAMDOrdering
typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
typedef Matrix<Index, Dynamic, 1> IndexVector;
- /** Compute the permutation vector form a sparse matrix */
+ /** Compute the permutation vector \a perm form the sparse matrix \a mat
+ * \warning The input sparse matrix \a mat must be in compressed mode (see SparseMatrix::makeCompressed()).
+ */
template <typename MatrixType>
void operator() (const MatrixType& mat, PermutationType& perm)
{
+ eigen_assert(mat.isCompressed() && "COLAMDOrdering requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to COLAMDOrdering");
+
Index m = mat.rows();
Index n = mat.cols();
Index nnz = mat.nonZeros();
@@ -132,12 +136,12 @@ class COLAMDOrdering
Index stats [COLAMD_STATS];
internal::colamd_set_defaults(knobs);
- Index info;
IndexVector p(n+1), A(Alen);
for(Index i=0; i <= n; i++) p(i) = mat.outerIndexPtr()[i];
for(Index i=0; i < nnz; i++) A(i) = mat.innerIndexPtr()[i];
// Call Colamd routine to compute the ordering
- info = internal::colamd(m, n, Alen, A.data(), p.data(), knobs, stats);
+ Index info = internal::colamd(m, n, Alen, A.data(), p.data(), knobs, stats);
+ EIGEN_UNUSED_VARIABLE(info);
eigen_assert( info && "COLAMD failed " );
perm.resize(n);
diff --git a/extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h b/extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h
index 1c48f0df7b5..18cd7d88aea 100644
--- a/extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h
+++ b/extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h
@@ -219,7 +219,7 @@ class PardisoImpl
void pardisoInit(int type)
{
m_type = type;
- bool symmetric = abs(m_type) < 10;
+ bool symmetric = std::abs(m_type) < 10;
m_iparm[0] = 1; // No solver default
m_iparm[1] = 3; // use Metis for the ordering
m_iparm[2] = 1; // Numbers of processors, value of OMP_NUM_THREADS
diff --git a/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h b/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h
index bec85810ccc..567eab7cda5 100644
--- a/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h
+++ b/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h
@@ -76,7 +76,8 @@ template<typename _MatrixType> class ColPivHouseholderQR
m_colsTranspositions(),
m_temp(),
m_colSqNorms(),
- m_isInitialized(false) {}
+ m_isInitialized(false),
+ m_usePrescribedThreshold(false) {}
/** \brief Default Constructor with memory preallocation
*
@@ -383,6 +384,12 @@ template<typename _MatrixType> class ColPivHouseholderQR
}
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
+
MatrixType m_qr;
HCoeffsType m_hCoeffs;
PermutationType m_colsPermutation;
@@ -421,6 +428,8 @@ typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::logAbsDetermina
template<typename MatrixType>
ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
{
+ check_template_parameters();
+
using std::abs;
Index rows = matrix.rows();
Index cols = matrix.cols();
@@ -462,20 +471,10 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
// we store that back into our table: it can't hurt to correct our table.
m_colSqNorms.coeffRef(biggest_col_index) = biggest_col_sq_norm;
- // if the current biggest column is smaller than epsilon times the initial biggest column,
- // terminate to avoid generating nan/inf values.
- // Note that here, if we test instead for "biggest == 0", we get a failure every 1000 (or so)
- // repetitions of the unit test, with the result of solve() filled with large values of the order
- // of 1/(size*epsilon).
- if(biggest_col_sq_norm < threshold_helper * RealScalar(rows-k))
- {
+ // Track the number of meaningful pivots but do not stop the decomposition to make
+ // sure that the initial matrix is properly reproduced. See bug 941.
+ if(m_nonzero_pivots==size && biggest_col_sq_norm < threshold_helper * RealScalar(rows-k))
m_nonzero_pivots = k;
- m_hCoeffs.tail(size-k).setZero();
- m_qr.bottomRightCorner(rows-k,cols-k)
- .template triangularView<StrictlyLower>()
- .setZero();
- break;
- }
// apply the transposition to the columns
m_colsTranspositions.coeffRef(k) = biggest_col_index;
@@ -504,7 +503,7 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
}
m_colsPermutation.setIdentity(PermIndexType(cols));
- for(PermIndexType k = 0; k < m_nonzero_pivots; ++k)
+ for(PermIndexType k = 0; k < size/*m_nonzero_pivots*/; ++k)
m_colsPermutation.applyTranspositionOnTheRight(k, PermIndexType(m_colsTranspositions.coeff(k)));
m_det_pq = (number_of_transpositions%2) ? -1 : 1;
@@ -554,13 +553,15 @@ struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
} // end namespace internal
-/** \returns the matrix Q as a sequence of householder transformations */
+/** \returns the matrix Q as a sequence of householder transformations.
+ * You can extract the meaningful part only by using:
+ * \code qr.householderQ().setLength(qr.nonzeroPivots()) \endcode*/
template<typename MatrixType>
typename ColPivHouseholderQR<MatrixType>::HouseholderSequenceType ColPivHouseholderQR<MatrixType>
::householderQ() const
{
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate()).setLength(m_nonzero_pivots);
+ return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
}
/** \return the column-pivoting Householder QR decomposition of \c *this.
diff --git a/extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h b/extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h
index 6168e7abfb4..0b39966e145 100644
--- a/extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h
+++ b/extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h
@@ -368,6 +368,12 @@ template<typename _MatrixType> class FullPivHouseholderQR
RealScalar maxPivot() const { return m_maxpivot; }
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
+
MatrixType m_qr;
HCoeffsType m_hCoeffs;
IntDiagSizeVectorType m_rows_transpositions;
@@ -407,6 +413,8 @@ typename MatrixType::RealScalar FullPivHouseholderQR<MatrixType>::logAbsDetermin
template<typename MatrixType>
FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
{
+ check_template_parameters();
+
using std::abs;
Index rows = matrix.rows();
Index cols = matrix.cols();
diff --git a/extern/Eigen3/Eigen/src/QR/HouseholderQR.h b/extern/Eigen3/Eigen/src/QR/HouseholderQR.h
index abc61bcbbe1..343a6649934 100644
--- a/extern/Eigen3/Eigen/src/QR/HouseholderQR.h
+++ b/extern/Eigen3/Eigen/src/QR/HouseholderQR.h
@@ -189,6 +189,12 @@ template<typename _MatrixType> class HouseholderQR
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
protected:
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
+
MatrixType m_qr;
HCoeffsType m_hCoeffs;
RowVectorType m_temp;
@@ -251,56 +257,62 @@ void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename
}
/** \internal */
-template<typename MatrixQR, typename HCoeffs>
-void householder_qr_inplace_blocked(MatrixQR& mat, HCoeffs& hCoeffs,
- typename MatrixQR::Index maxBlockSize=32,
- typename MatrixQR::Scalar* tempData = 0)
+template<typename MatrixQR, typename HCoeffs,
+ typename MatrixQRScalar = typename MatrixQR::Scalar,
+ bool InnerStrideIsOne = (MatrixQR::InnerStrideAtCompileTime == 1 && HCoeffs::InnerStrideAtCompileTime == 1)>
+struct householder_qr_inplace_blocked
{
- typedef typename MatrixQR::Index Index;
- typedef typename MatrixQR::Scalar Scalar;
- typedef Block<MatrixQR,Dynamic,Dynamic> BlockType;
-
- Index rows = mat.rows();
- Index cols = mat.cols();
- Index size = (std::min)(rows, cols);
-
- typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
- TempType tempVector;
- if(tempData==0)
+ // This is specialized for MKL-supported Scalar types in HouseholderQR_MKL.h
+ static void run(MatrixQR& mat, HCoeffs& hCoeffs,
+ typename MatrixQR::Index maxBlockSize=32,
+ typename MatrixQR::Scalar* tempData = 0)
{
- tempVector.resize(cols);
- tempData = tempVector.data();
- }
-
- Index blockSize = (std::min)(maxBlockSize,size);
+ typedef typename MatrixQR::Index Index;
+ typedef typename MatrixQR::Scalar Scalar;
+ typedef Block<MatrixQR,Dynamic,Dynamic> BlockType;
- Index k = 0;
- for (k = 0; k < size; k += blockSize)
- {
- Index bs = (std::min)(size-k,blockSize); // actual size of the block
- Index tcols = cols - k - bs; // trailing columns
- Index brows = rows-k; // rows of the block
+ Index rows = mat.rows();
+ Index cols = mat.cols();
+ Index size = (std::min)(rows, cols);
- // partition the matrix:
- // A00 | A01 | A02
- // mat = A10 | A11 | A12
- // A20 | A21 | A22
- // and performs the qr dec of [A11^T A12^T]^T
- // and update [A21^T A22^T]^T using level 3 operations.
- // Finally, the algorithm continue on A22
-
- BlockType A11_21 = mat.block(k,k,brows,bs);
- Block<HCoeffs,Dynamic,1> hCoeffsSegment = hCoeffs.segment(k,bs);
+ typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
+ TempType tempVector;
+ if(tempData==0)
+ {
+ tempVector.resize(cols);
+ tempData = tempVector.data();
+ }
- householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
+ Index blockSize = (std::min)(maxBlockSize,size);
- if(tcols)
+ Index k = 0;
+ for (k = 0; k < size; k += blockSize)
{
- BlockType A21_22 = mat.block(k,k+bs,brows,tcols);
- apply_block_householder_on_the_left(A21_22,A11_21,hCoeffsSegment.adjoint());
+ Index bs = (std::min)(size-k,blockSize); // actual size of the block
+ Index tcols = cols - k - bs; // trailing columns
+ Index brows = rows-k; // rows of the block
+
+ // partition the matrix:
+ // A00 | A01 | A02
+ // mat = A10 | A11 | A12
+ // A20 | A21 | A22
+ // and performs the qr dec of [A11^T A12^T]^T
+ // and update [A21^T A22^T]^T using level 3 operations.
+ // Finally, the algorithm continue on A22
+
+ BlockType A11_21 = mat.block(k,k,brows,bs);
+ Block<HCoeffs,Dynamic,1> hCoeffsSegment = hCoeffs.segment(k,bs);
+
+ householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
+
+ if(tcols)
+ {
+ BlockType A21_22 = mat.block(k,k+bs,brows,tcols);
+ apply_block_householder_on_the_left(A21_22,A11_21,hCoeffsSegment.adjoint());
+ }
}
}
-}
+};
template<typename _MatrixType, typename Rhs>
struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
@@ -343,6 +355,8 @@ struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
template<typename MatrixType>
HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType& matrix)
{
+ check_template_parameters();
+
Index rows = matrix.rows();
Index cols = matrix.cols();
Index size = (std::min)(rows,cols);
@@ -352,7 +366,7 @@ HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType&
m_temp.resize(cols);
- internal::householder_qr_inplace_blocked(m_qr, m_hCoeffs, 48, m_temp.data());
+ internal::householder_qr_inplace_blocked<MatrixType, HCoeffsType>::run(m_qr, m_hCoeffs, 48, m_temp.data());
m_isInitialized = true;
return *this;
diff --git a/extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h b/extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h
index 5313de604d2..b80f1b48dac 100644
--- a/extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h
+++ b/extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h
@@ -34,28 +34,30 @@
#ifndef EIGEN_QR_MKL_H
#define EIGEN_QR_MKL_H
-#include "Eigen/src/Core/util/MKL_support.h"
+#include "../Core/util/MKL_support.h"
namespace Eigen {
-namespace internal {
+ namespace internal {
-/** \internal Specialization for the data types supported by MKL */
+ /** \internal Specialization for the data types supported by MKL */
#define EIGEN_MKL_QR_NOPIV(EIGTYPE, MKLTYPE, MKLPREFIX) \
template<typename MatrixQR, typename HCoeffs> \
-void householder_qr_inplace_blocked(MatrixQR& mat, HCoeffs& hCoeffs, \
- typename MatrixQR::Index maxBlockSize=32, \
- EIGTYPE* tempData = 0) \
+struct householder_qr_inplace_blocked<MatrixQR, HCoeffs, EIGTYPE, true> \
{ \
- lapack_int m = mat.rows(); \
- lapack_int n = mat.cols(); \
- lapack_int lda = mat.outerStride(); \
- lapack_int matrix_order = (MatrixQR::IsRowMajor) ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR; \
- LAPACKE_##MKLPREFIX##geqrf( matrix_order, m, n, (MKLTYPE*)mat.data(), lda, (MKLTYPE*)hCoeffs.data()); \
- hCoeffs.adjointInPlace(); \
-\
-}
+ static void run(MatrixQR& mat, HCoeffs& hCoeffs, \
+ typename MatrixQR::Index = 32, \
+ typename MatrixQR::Scalar* = 0) \
+ { \
+ lapack_int m = (lapack_int) mat.rows(); \
+ lapack_int n = (lapack_int) mat.cols(); \
+ lapack_int lda = (lapack_int) mat.outerStride(); \
+ lapack_int matrix_order = (MatrixQR::IsRowMajor) ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR; \
+ LAPACKE_##MKLPREFIX##geqrf( matrix_order, m, n, (MKLTYPE*)mat.data(), lda, (MKLTYPE*)hCoeffs.data()); \
+ hCoeffs.adjointInPlace(); \
+ } \
+};
EIGEN_MKL_QR_NOPIV(double, double, d)
EIGEN_MKL_QR_NOPIV(float, float, s)
diff --git a/extern/Eigen3/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h b/extern/Eigen3/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h
index a2cc2a9e261..36138101d74 100644
--- a/extern/Eigen3/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h
+++ b/extern/Eigen3/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h
@@ -47,7 +47,7 @@ namespace Eigen {
* You can then apply it to a vector.
*
* R is the sparse triangular factor. Use matrixQR() to get it as SparseMatrix.
- * NOTE : The Index type of R is always UF_long. You can get it with SPQR::Index
+ * NOTE : The Index type of R is always SuiteSparse_long. You can get it with SPQR::Index
*
* \tparam _MatrixType The type of the sparse matrix A, must be a column-major SparseMatrix<>
* NOTE
@@ -59,24 +59,18 @@ class SPQR
public:
typedef typename _MatrixType::Scalar Scalar;
typedef typename _MatrixType::RealScalar RealScalar;
- typedef UF_long Index ;
+ typedef SuiteSparse_long Index ;
typedef SparseMatrix<Scalar, ColMajor, Index> MatrixType;
typedef PermutationMatrix<Dynamic, Dynamic> PermutationType;
public:
SPQR()
- : m_isInitialized(false),
- m_ordering(SPQR_ORDERING_DEFAULT),
- m_allow_tol(SPQR_DEFAULT_TOL),
- m_tolerance (NumTraits<Scalar>::epsilon())
+ : m_isInitialized(false), m_ordering(SPQR_ORDERING_DEFAULT), m_allow_tol(SPQR_DEFAULT_TOL), m_tolerance (NumTraits<Scalar>::epsilon()), m_useDefaultThreshold(true)
{
cholmod_l_start(&m_cc);
}
- SPQR(const _MatrixType& matrix)
- : m_isInitialized(false),
- m_ordering(SPQR_ORDERING_DEFAULT),
- m_allow_tol(SPQR_DEFAULT_TOL),
- m_tolerance (NumTraits<Scalar>::epsilon())
+ SPQR(const _MatrixType& matrix)
+ : m_isInitialized(false), m_ordering(SPQR_ORDERING_DEFAULT), m_allow_tol(SPQR_DEFAULT_TOL), m_tolerance (NumTraits<Scalar>::epsilon()), m_useDefaultThreshold(true)
{
cholmod_l_start(&m_cc);
compute(matrix);
@@ -101,10 +95,26 @@ class SPQR
if(m_isInitialized) SPQR_free();
MatrixType mat(matrix);
+
+ /* Compute the default threshold as in MatLab, see:
+ * Tim Davis, "Algorithm 915, SuiteSparseQR: Multifrontal Multithreaded Rank-Revealing
+ * Sparse QR Factorization, ACM Trans. on Math. Soft. 38(1), 2011, Page 8:3
+ */
+ RealScalar pivotThreshold = m_tolerance;
+ if(m_useDefaultThreshold)
+ {
+ using std::max;
+ RealScalar max2Norm = 0.0;
+ for (int j = 0; j < mat.cols(); j++) max2Norm = (max)(max2Norm, mat.col(j).norm());
+ if(max2Norm==RealScalar(0))
+ max2Norm = RealScalar(1);
+ pivotThreshold = 20 * (mat.rows() + mat.cols()) * max2Norm * NumTraits<RealScalar>::epsilon();
+ }
+
cholmod_sparse A;
A = viewAsCholmod(mat);
Index col = matrix.cols();
- m_rank = SuiteSparseQR<Scalar>(m_ordering, m_tolerance, col, &A,
+ m_rank = SuiteSparseQR<Scalar>(m_ordering, pivotThreshold, col, &A,
&m_cR, &m_E, &m_H, &m_HPinv, &m_HTau, &m_cc);
if (!m_cR)
@@ -120,7 +130,7 @@ class SPQR
/**
* Get the number of rows of the input matrix and the Q matrix
*/
- inline Index rows() const {return m_H->nrow; }
+ inline Index rows() const {return m_cR->nrow; }
/**
* Get the number of columns of the input matrix.
@@ -145,16 +155,25 @@ class SPQR
{
eigen_assert(m_isInitialized && " The QR factorization should be computed first, call compute()");
eigen_assert(b.cols()==1 && "This method is for vectors only");
-
+
//Compute Q^T * b
- typename Dest::PlainObject y;
+ typename Dest::PlainObject y, y2;
y = matrixQ().transpose() * b;
- // Solves with the triangular matrix R
+
+ // Solves with the triangular matrix R
Index rk = this->rank();
- y.topRows(rk) = this->matrixR().topLeftCorner(rk, rk).template triangularView<Upper>().solve(y.topRows(rk));
- y.bottomRows(cols()-rk).setZero();
+ y2 = y;
+ y.resize((std::max)(cols(),Index(y.rows())),y.cols());
+ y.topRows(rk) = this->matrixR().topLeftCorner(rk, rk).template triangularView<Upper>().solve(y2.topRows(rk));
+
// Apply the column permutation
- dest.topRows(cols()) = colsPermutation() * y.topRows(cols());
+ // colsPermutation() performs a copy of the permutation,
+ // so let's apply it manually:
+ for(Index i = 0; i < rk; ++i) dest.row(m_E[i]) = y.row(i);
+ for(Index i = rk; i < cols(); ++i) dest.row(m_E[i]).setZero();
+
+// y.bottomRows(y.rows()-rk).setZero();
+// dest = colsPermutation() * y.topRows(cols());
m_info = Success;
}
@@ -197,7 +216,11 @@ class SPQR
/// Set the fill-reducing ordering method to be used
void setSPQROrdering(int ord) { m_ordering = ord;}
/// Set the tolerance tol to treat columns with 2-norm < =tol as zero
- void setPivotThreshold(const RealScalar& tol) { m_tolerance = tol; }
+ void setPivotThreshold(const RealScalar& tol)
+ {
+ m_useDefaultThreshold = false;
+ m_tolerance = tol;
+ }
/** \returns a pointer to the SPQR workspace */
cholmod_common *cholmodCommon() const { return &m_cc; }
@@ -230,6 +253,7 @@ class SPQR
mutable cholmod_dense *m_HTau; // The Householder coefficients
mutable Index m_rank; // The rank of the matrix
mutable cholmod_common m_cc; // Workspace and parameters
+ bool m_useDefaultThreshold; // Use default threshold
template<typename ,typename > friend struct SPQR_QProduct;
};
diff --git a/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h b/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h
index f44995cd39c..1b29774190a 100644
--- a/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h
+++ b/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h
@@ -375,17 +375,19 @@ struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
Scalar z;
JacobiRotation<Scalar> rot;
RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
+
if(n==0)
{
z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
work_matrix.row(p) *= z;
if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
if(work_matrix.coeff(q,q)!=Scalar(0))
+ {
z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
- else
- z = Scalar(0);
- work_matrix.row(q) *= z;
- if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
+ work_matrix.row(q) *= z;
+ if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
+ }
+ // otherwise the second row is already zero, so we have nothing to do.
}
else
{
@@ -415,6 +417,7 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
JacobiRotation<RealScalar> *j_right)
{
using std::sqrt;
+ using std::abs;
Matrix<RealScalar,2,2> m;
m << numext::real(matrix.coeff(p,p)), numext::real(matrix.coeff(p,q)),
numext::real(matrix.coeff(q,p)), numext::real(matrix.coeff(q,q));
@@ -428,9 +431,11 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
}
else
{
- RealScalar u = d / t;
- rot1.c() = RealScalar(1) / sqrt(RealScalar(1) + numext::abs2(u));
- rot1.s() = rot1.c() * u;
+ RealScalar t2d2 = numext::hypot(t,d);
+ rot1.c() = abs(t)/t2d2;
+ rot1.s() = d/t2d2;
+ if(t<RealScalar(0))
+ rot1.s() = -rot1.s();
}
m.applyOnTheLeft(0,1,rot1);
j_right->makeJacobi(m,0,1);
@@ -531,8 +536,9 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
JacobiSVD()
: m_isInitialized(false),
m_isAllocated(false),
+ m_usePrescribedThreshold(false),
m_computationOptions(0),
- m_rows(-1), m_cols(-1)
+ m_rows(-1), m_cols(-1), m_diagSize(0)
{}
@@ -545,6 +551,7 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
JacobiSVD(Index rows, Index cols, unsigned int computationOptions = 0)
: m_isInitialized(false),
m_isAllocated(false),
+ m_usePrescribedThreshold(false),
m_computationOptions(0),
m_rows(-1), m_cols(-1)
{
@@ -564,6 +571,7 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
JacobiSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
: m_isInitialized(false),
m_isAllocated(false),
+ m_usePrescribedThreshold(false),
m_computationOptions(0),
m_rows(-1), m_cols(-1)
{
@@ -665,23 +673,92 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
return m_nonzeroSingularValues;
}
+
+ /** \returns the rank of the matrix of which \c *this is the SVD.
+ *
+ * \note This method has to determine which singular values should be considered nonzero.
+ * For that, it uses the threshold value that you can control by calling
+ * setThreshold(const RealScalar&).
+ */
+ inline Index rank() const
+ {
+ using std::abs;
+ eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
+ if(m_singularValues.size()==0) return 0;
+ RealScalar premultiplied_threshold = m_singularValues.coeff(0) * threshold();
+ Index i = m_nonzeroSingularValues-1;
+ while(i>=0 && m_singularValues.coeff(i) < premultiplied_threshold) --i;
+ return i+1;
+ }
+
+ /** Allows to prescribe a threshold to be used by certain methods, such as rank() and solve(),
+ * which need to determine when singular values are to be considered nonzero.
+ * This is not used for the SVD decomposition itself.
+ *
+ * When it needs to get the threshold value, Eigen calls threshold().
+ * The default is \c NumTraits<Scalar>::epsilon()
+ *
+ * \param threshold The new value to use as the threshold.
+ *
+ * A singular value will be considered nonzero if its value is strictly greater than
+ * \f$ \vert singular value \vert \leqslant threshold \times \vert max singular value \vert \f$.
+ *
+ * If you want to come back to the default behavior, call setThreshold(Default_t)
+ */
+ JacobiSVD& setThreshold(const RealScalar& threshold)
+ {
+ m_usePrescribedThreshold = true;
+ m_prescribedThreshold = threshold;
+ return *this;
+ }
+
+ /** Allows to come back to the default behavior, letting Eigen use its default formula for
+ * determining the threshold.
+ *
+ * You should pass the special object Eigen::Default as parameter here.
+ * \code svd.setThreshold(Eigen::Default); \endcode
+ *
+ * See the documentation of setThreshold(const RealScalar&).
+ */
+ JacobiSVD& setThreshold(Default_t)
+ {
+ m_usePrescribedThreshold = false;
+ return *this;
+ }
+
+ /** Returns the threshold that will be used by certain methods such as rank().
+ *
+ * See the documentation of setThreshold(const RealScalar&).
+ */
+ RealScalar threshold() const
+ {
+ eigen_assert(m_isInitialized || m_usePrescribedThreshold);
+ return m_usePrescribedThreshold ? m_prescribedThreshold
+ : (std::max<Index>)(1,m_diagSize)*NumTraits<Scalar>::epsilon();
+ }
inline Index rows() const { return m_rows; }
inline Index cols() const { return m_cols; }
private:
void allocate(Index rows, Index cols, unsigned int computationOptions);
+
+ static void check_template_parameters()
+ {
+ EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
+ }
protected:
MatrixUType m_matrixU;
MatrixVType m_matrixV;
SingularValuesType m_singularValues;
WorkMatrixType m_workMatrix;
- bool m_isInitialized, m_isAllocated;
+ bool m_isInitialized, m_isAllocated, m_usePrescribedThreshold;
bool m_computeFullU, m_computeThinU;
bool m_computeFullV, m_computeThinV;
unsigned int m_computationOptions;
Index m_nonzeroSingularValues, m_rows, m_cols, m_diagSize;
+ RealScalar m_prescribedThreshold;
template<typename __MatrixType, int _QRPreconditioner, bool _IsComplex>
friend struct internal::svd_precondition_2x2_block_to_be_real;
@@ -690,6 +767,7 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreColsThanRows> m_qr_precond_morecols;
internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols> m_qr_precond_morerows;
+ MatrixType m_scaledMatrix;
};
template<typename MatrixType, int QRPreconditioner>
@@ -736,14 +814,17 @@ void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols, u
: 0);
m_workMatrix.resize(m_diagSize, m_diagSize);
- if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this);
- if(m_rows>m_cols) m_qr_precond_morerows.allocate(*this);
+ if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this);
+ if(m_rows>m_cols) m_qr_precond_morerows.allocate(*this);
+ if(m_cols!=m_cols) m_scaledMatrix.resize(rows,cols);
}
template<typename MatrixType, int QRPreconditioner>
JacobiSVD<MatrixType, QRPreconditioner>&
JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsigned int computationOptions)
{
+ check_template_parameters();
+
using std::abs;
allocate(matrix.rows(), matrix.cols(), computationOptions);
@@ -754,11 +835,21 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
// limit for very small denormal numbers to be considered zero in order to avoid infinite loops (see bug 286)
const RealScalar considerAsZero = RealScalar(2) * std::numeric_limits<RealScalar>::denorm_min();
+ // Scaling factor to reduce over/under-flows
+ RealScalar scale = matrix.cwiseAbs().maxCoeff();
+ if(scale==RealScalar(0)) scale = RealScalar(1);
+
/*** step 1. The R-SVD step: we use a QR decomposition to reduce to the case of a square matrix */
- if(!m_qr_precond_morecols.run(*this, matrix) && !m_qr_precond_morerows.run(*this, matrix))
+ if(m_rows!=m_cols)
{
- m_workMatrix = matrix.block(0,0,m_diagSize,m_diagSize);
+ m_scaledMatrix = matrix / scale;
+ m_qr_precond_morecols.run(*this, m_scaledMatrix);
+ m_qr_precond_morerows.run(*this, m_scaledMatrix);
+ }
+ else
+ {
+ m_workMatrix = matrix.block(0,0,m_diagSize,m_diagSize) / scale;
if(m_computeFullU) m_matrixU.setIdentity(m_rows,m_rows);
if(m_computeThinU) m_matrixU.setIdentity(m_rows,m_diagSize);
if(m_computeFullV) m_matrixV.setIdentity(m_cols,m_cols);
@@ -784,7 +875,8 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
using std::max;
RealScalar threshold = (max)(considerAsZero, precision * (max)(abs(m_workMatrix.coeff(p,p)),
abs(m_workMatrix.coeff(q,q))));
- if((max)(abs(m_workMatrix.coeff(p,q)),abs(m_workMatrix.coeff(q,p))) > threshold)
+ // We compare both values to threshold instead of calling max to be robust to NaN (See bug 791)
+ if(abs(m_workMatrix.coeff(p,q))>threshold || abs(m_workMatrix.coeff(q,p)) > threshold)
{
finished = false;
@@ -833,6 +925,8 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
if(computeV()) m_matrixV.col(pos).swap(m_matrixV.col(i));
}
}
+
+ m_singularValues *= scale;
m_isInitialized = true;
return *this;
@@ -854,11 +948,11 @@ struct solve_retval<JacobiSVD<_MatrixType, QRPreconditioner>, Rhs>
// So A^{-1} = V S^{-1} U^*
Matrix<Scalar, Dynamic, Rhs::ColsAtCompileTime, 0, _MatrixType::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime> tmp;
- Index nonzeroSingVals = dec().nonzeroSingularValues();
+ Index rank = dec().rank();
- tmp.noalias() = dec().matrixU().leftCols(nonzeroSingVals).adjoint() * rhs();
- tmp = dec().singularValues().head(nonzeroSingVals).asDiagonal().inverse() * tmp;
- dst = dec().matrixV().leftCols(nonzeroSingVals) * tmp;
+ tmp.noalias() = dec().matrixU().leftCols(rank).adjoint() * rhs();
+ tmp = dec().singularValues().head(rank).asDiagonal().inverse() * tmp;
+ dst = dec().matrixV().leftCols(rank) * tmp;
}
};
} // end namespace internal
diff --git a/extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h b/extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h
index f41d7e010f7..e1f96ba5a14 100644
--- a/extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h
+++ b/extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h
@@ -37,6 +37,7 @@ class SimplicialCholeskyBase : internal::noncopyable
{
public:
typedef typename internal::traits<Derived>::MatrixType MatrixType;
+ typedef typename internal::traits<Derived>::OrderingType OrderingType;
enum { UpLo = internal::traits<Derived>::UpLo };
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
@@ -240,15 +241,16 @@ class SimplicialCholeskyBase : internal::noncopyable
RealScalar m_shiftScale;
};
-template<typename _MatrixType, int _UpLo = Lower> class SimplicialLLT;
-template<typename _MatrixType, int _UpLo = Lower> class SimplicialLDLT;
-template<typename _MatrixType, int _UpLo = Lower> class SimplicialCholesky;
+template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::Index> > class SimplicialLLT;
+template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::Index> > class SimplicialLDLT;
+template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::Index> > class SimplicialCholesky;
namespace internal {
-template<typename _MatrixType, int _UpLo> struct traits<SimplicialLLT<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
{
typedef _MatrixType MatrixType;
+ typedef _Ordering OrderingType;
enum { UpLo = _UpLo };
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
@@ -259,9 +261,10 @@ template<typename _MatrixType, int _UpLo> struct traits<SimplicialLLT<_MatrixTyp
static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); }
};
-template<typename _MatrixType,int _UpLo> struct traits<SimplicialLDLT<_MatrixType,_UpLo> >
+template<typename _MatrixType,int _UpLo, typename _Ordering> struct traits<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
{
typedef _MatrixType MatrixType;
+ typedef _Ordering OrderingType;
enum { UpLo = _UpLo };
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
@@ -272,9 +275,10 @@ template<typename _MatrixType,int _UpLo> struct traits<SimplicialLDLT<_MatrixTyp
static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); }
};
-template<typename _MatrixType, int _UpLo> struct traits<SimplicialCholesky<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
{
typedef _MatrixType MatrixType;
+ typedef _Ordering OrderingType;
enum { UpLo = _UpLo };
};
@@ -294,11 +298,12 @@ template<typename _MatrixType, int _UpLo> struct traits<SimplicialCholesky<_Matr
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
* or Upper. Default is Lower.
+ * \tparam _Ordering The ordering method to use, either AMDOrdering<> or NaturalOrdering<>. Default is AMDOrdering<>
*
- * \sa class SimplicialLDLT
+ * \sa class SimplicialLDLT, class AMDOrdering, class NaturalOrdering
*/
-template<typename _MatrixType, int _UpLo>
- class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering>
+ class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
{
public:
typedef _MatrixType MatrixType;
@@ -382,11 +387,12 @@ public:
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
* or Upper. Default is Lower.
+ * \tparam _Ordering The ordering method to use, either AMDOrdering<> or NaturalOrdering<>. Default is AMDOrdering<>
*
- * \sa class SimplicialLLT
+ * \sa class SimplicialLLT, class AMDOrdering, class NaturalOrdering
*/
-template<typename _MatrixType, int _UpLo>
- class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering>
+ class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
{
public:
typedef _MatrixType MatrixType;
@@ -467,8 +473,8 @@ public:
*
* \sa class SimplicialLDLT, class SimplicialLLT
*/
-template<typename _MatrixType, int _UpLo>
- class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<_MatrixType,_UpLo> >
+template<typename _MatrixType, int _UpLo, typename _Ordering>
+ class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
{
public:
typedef _MatrixType MatrixType;
@@ -612,15 +618,13 @@ void SimplicialCholeskyBase<Derived>::ordering(const MatrixType& a, CholMatrixTy
{
eigen_assert(a.rows()==a.cols());
const Index size = a.rows();
- // TODO allows to configure the permutation
// Note that amd compute the inverse permutation
{
CholMatrixType C;
C = a.template selfadjointView<UpLo>();
- // remove diagonal entries:
- // seems not to be needed
- // C.prune(keep_diag());
- internal::minimum_degree_ordering(C, m_Pinv);
+
+ OrderingType ordering;
+ ordering(C,m_Pinv);
}
if(m_Pinv.size()>0)
diff --git a/extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h b/extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h
index 17fff96a78b..220c6451cb9 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h
@@ -69,7 +69,7 @@ class AmbiVector
delete[] m_buffer;
if (size<1000)
{
- Index allocSize = (size * sizeof(ListEl))/sizeof(Scalar);
+ Index allocSize = (size * sizeof(ListEl) + sizeof(Scalar) - 1)/sizeof(Scalar);
m_allocatedElements = (allocSize*sizeof(Scalar))/sizeof(ListEl);
m_buffer = new Scalar[allocSize];
}
@@ -88,7 +88,7 @@ class AmbiVector
Index copyElements = m_allocatedElements;
m_allocatedElements = (std::min)(Index(m_allocatedElements*1.5),m_size);
Index allocSize = m_allocatedElements * sizeof(ListEl);
- allocSize = allocSize/sizeof(Scalar) + (allocSize%sizeof(Scalar)>0?1:0);
+ allocSize = (allocSize + sizeof(Scalar) - 1)/sizeof(Scalar);
Scalar* newBuffer = new Scalar[allocSize];
memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl));
delete[] m_buffer;
diff --git a/extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h b/extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h
index 3321fab4a8a..a667cb56ebe 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h
@@ -51,8 +51,8 @@ class CompressedStorage
CompressedStorage& operator=(const CompressedStorage& other)
{
resize(other.size());
- memcpy(m_values, other.m_values, m_size * sizeof(Scalar));
- memcpy(m_indices, other.m_indices, m_size * sizeof(Index));
+ internal::smart_copy(other.m_values, other.m_values + m_size, m_values);
+ internal::smart_copy(other.m_indices, other.m_indices + m_size, m_indices);
return *this;
}
@@ -83,10 +83,10 @@ class CompressedStorage
reallocate(m_size);
}
- void resize(size_t size, float reserveSizeFactor = 0)
+ void resize(size_t size, double reserveSizeFactor = 0)
{
if (m_allocatedSize<size)
- reallocate(size + size_t(reserveSizeFactor*size));
+ reallocate(size + size_t(reserveSizeFactor*double(size)));
m_size = size;
}
diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h b/extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h
index 16a20a5744e..0c90bafbeab 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h
@@ -57,6 +57,16 @@ public:
inline BlockImpl(const XprType& xpr, int startRow, int startCol, int blockRows, int blockCols)
: m_matrix(xpr), m_outerStart(IsRowMajor ? startRow : startCol), m_outerSize(IsRowMajor ? blockRows : blockCols)
{}
+
+ inline const Scalar coeff(int row, int col) const
+ {
+ return m_matrix.coeff(row + IsRowMajor ? m_outerStart : 0, col +IsRowMajor ? 0 : m_outerStart);
+ }
+
+ inline const Scalar coeff(int index) const
+ {
+ return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
+ }
EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
@@ -68,6 +78,8 @@ public:
const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
+ private:
+ Index nonZeros() const;
};
@@ -82,6 +94,7 @@ class BlockImpl<SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true
typedef SparseMatrix<_Scalar, _Options, _Index> SparseMatrixType;
typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _MatrixTypeNested;
typedef Block<SparseMatrixType, BlockRows, BlockCols, true> BlockType;
+ typedef Block<const SparseMatrixType, BlockRows, BlockCols, true> ConstBlockType;
public:
enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
@@ -223,6 +236,118 @@ public:
else
return Map<const Matrix<Index,OuterSize,1> >(m_matrix.innerNonZeroPtr()+m_outerStart, m_outerSize.value()).sum();
}
+
+ inline Scalar& coeffRef(int row, int col)
+ {
+ return m_matrix.const_cast_derived().coeffRef(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
+ }
+
+ inline const Scalar coeff(int row, int col) const
+ {
+ return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
+ }
+
+ inline const Scalar coeff(int index) const
+ {
+ return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
+ }
+
+ const Scalar& lastCoeff() const
+ {
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(BlockImpl);
+ eigen_assert(nonZeros()>0);
+ if(m_matrix.isCompressed())
+ return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart+1]-1];
+ else
+ return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart]+m_matrix.innerNonZeroPtr()[m_outerStart]-1];
+ }
+
+ EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
+ EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
+
+ protected:
+
+ typename SparseMatrixType::Nested m_matrix;
+ Index m_outerStart;
+ const internal::variable_if_dynamic<Index, OuterSize> m_outerSize;
+
+};
+
+
+template<typename _Scalar, int _Options, typename _Index, int BlockRows, int BlockCols>
+class BlockImpl<const SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true,Sparse>
+ : public SparseMatrixBase<Block<const SparseMatrix<_Scalar, _Options, _Index>,BlockRows,BlockCols,true> >
+{
+ typedef SparseMatrix<_Scalar, _Options, _Index> SparseMatrixType;
+ typedef typename internal::remove_all<typename SparseMatrixType::Nested>::type _MatrixTypeNested;
+ typedef Block<const SparseMatrixType, BlockRows, BlockCols, true> BlockType;
+public:
+ enum { IsRowMajor = internal::traits<BlockType>::IsRowMajor };
+ EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType)
+protected:
+ enum { OuterSize = IsRowMajor ? BlockRows : BlockCols };
+public:
+
+ class InnerIterator: public SparseMatrixType::InnerIterator
+ {
+ public:
+ inline InnerIterator(const BlockType& xpr, Index outer)
+ : SparseMatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
+ {}
+ inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
+ inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
+ protected:
+ Index m_outer;
+ };
+ class ReverseInnerIterator: public SparseMatrixType::ReverseInnerIterator
+ {
+ public:
+ inline ReverseInnerIterator(const BlockType& xpr, Index outer)
+ : SparseMatrixType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
+ {}
+ inline Index row() const { return IsRowMajor ? m_outer : this->index(); }
+ inline Index col() const { return IsRowMajor ? this->index() : m_outer; }
+ protected:
+ Index m_outer;
+ };
+
+ inline BlockImpl(const SparseMatrixType& xpr, int i)
+ : m_matrix(xpr), m_outerStart(i), m_outerSize(OuterSize)
+ {}
+
+ inline BlockImpl(const SparseMatrixType& xpr, int startRow, int startCol, int blockRows, int blockCols)
+ : m_matrix(xpr), m_outerStart(IsRowMajor ? startRow : startCol), m_outerSize(IsRowMajor ? blockRows : blockCols)
+ {}
+
+ inline const Scalar* valuePtr() const
+ { return m_matrix.valuePtr() + m_matrix.outerIndexPtr()[m_outerStart]; }
+
+ inline const Index* innerIndexPtr() const
+ { return m_matrix.innerIndexPtr() + m_matrix.outerIndexPtr()[m_outerStart]; }
+
+ inline const Index* outerIndexPtr() const
+ { return m_matrix.outerIndexPtr() + m_outerStart; }
+
+ Index nonZeros() const
+ {
+ if(m_matrix.isCompressed())
+ return std::size_t(m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()])
+ - std::size_t(m_matrix.outerIndexPtr()[m_outerStart]);
+ else if(m_outerSize.value()==0)
+ return 0;
+ else
+ return Map<const Matrix<Index,OuterSize,1> >(m_matrix.innerNonZeroPtr()+m_outerStart, m_outerSize.value()).sum();
+ }
+
+ inline const Scalar coeff(int row, int col) const
+ {
+ return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart));
+ }
+
+ inline const Scalar coeff(int index) const
+ {
+ return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart);
+ }
const Scalar& lastCoeff() const
{
@@ -265,7 +390,8 @@ const typename SparseMatrixBase<Derived>::ConstInnerVectorReturnType SparseMatri
* is col-major (resp. row-major).
*/
template<typename Derived>
-Block<Derived,Dynamic,Dynamic,true> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize)
+typename SparseMatrixBase<Derived>::InnerVectorsReturnType
+SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize)
{
return Block<Derived,Dynamic,Dynamic,true>(derived(),
IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart,
@@ -277,7 +403,8 @@ Block<Derived,Dynamic,Dynamic,true> SparseMatrixBase<Derived>::innerVectors(Inde
* is col-major (resp. row-major). Read-only.
*/
template<typename Derived>
-const Block<const Derived,Dynamic,Dynamic,true> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize) const
+const typename SparseMatrixBase<Derived>::ConstInnerVectorsReturnType
+SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize) const
{
return Block<const Derived,Dynamic,Dynamic,true>(derived(),
IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart,
@@ -304,8 +431,8 @@ public:
: m_matrix(xpr),
m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
- m_blockRows(xpr.rows()),
- m_blockCols(xpr.cols())
+ m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
+ m_blockCols(BlockCols==1 ? 1 : xpr.cols())
{}
/** Dynamic-size constructor
@@ -407,3 +534,4 @@ public:
} // end namespace Eigen
#endif // EIGEN_SPARSE_BLOCK_H
+
diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
index ec86ca933c2..4ca9128337f 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h
@@ -73,7 +73,8 @@ class CwiseBinaryOpImpl<BinaryOp,Lhs,Rhs,Sparse>::InnerIterator
typedef internal::sparse_cwise_binary_op_inner_iterator_selector<
BinaryOp,Lhs,Rhs, InnerIterator> Base;
- EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOpImpl& binOp, Index outer)
+ // NOTE: we have to prefix Index by "typename Lhs::" to avoid an ICE with VC11
+ EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOpImpl& binOp, typename Lhs::Index outer)
: Base(binOp.derived(),outer)
{}
};
@@ -313,10 +314,10 @@ SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& othe
template<typename Derived>
template<typename OtherDerived>
-EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
+EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::template CwiseProductDenseReturnType<OtherDerived>::Type
SparseMatrixBase<Derived>::cwiseProduct(const MatrixBase<OtherDerived> &other) const
{
- return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(derived(), other.derived());
+ return typename CwiseProductDenseReturnType<OtherDerived>::Type(derived(), other.derived());
}
} // end namespace Eigen
diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h b/extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h
index 54fd633a10c..ccb6ae7b788 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h
@@ -19,7 +19,10 @@ template<typename Lhs, typename Rhs, int InnerSize> struct SparseDenseProductRet
template<typename Lhs, typename Rhs> struct SparseDenseProductReturnType<Lhs,Rhs,1>
{
- typedef SparseDenseOuterProduct<Lhs,Rhs,false> Type;
+ typedef typename internal::conditional<
+ Lhs::IsRowMajor,
+ SparseDenseOuterProduct<Rhs,Lhs,true>,
+ SparseDenseOuterProduct<Lhs,Rhs,false> >::type Type;
};
template<typename Lhs, typename Rhs, int InnerSize> struct DenseSparseProductReturnType
@@ -29,7 +32,10 @@ template<typename Lhs, typename Rhs, int InnerSize> struct DenseSparseProductRet
template<typename Lhs, typename Rhs> struct DenseSparseProductReturnType<Lhs,Rhs,1>
{
- typedef SparseDenseOuterProduct<Rhs,Lhs,true> Type;
+ typedef typename internal::conditional<
+ Rhs::IsRowMajor,
+ SparseDenseOuterProduct<Rhs,Lhs,true>,
+ SparseDenseOuterProduct<Lhs,Rhs,false> >::type Type;
};
namespace internal {
@@ -114,17 +120,30 @@ class SparseDenseOuterProduct<Lhs,Rhs,Transpose>::InnerIterator : public _LhsNes
typedef typename SparseDenseOuterProduct::Index Index;
public:
EIGEN_STRONG_INLINE InnerIterator(const SparseDenseOuterProduct& prod, Index outer)
- : Base(prod.lhs(), 0), m_outer(outer), m_factor(prod.rhs().coeff(outer))
- {
- }
+ : Base(prod.lhs(), 0), m_outer(outer), m_factor(get(prod.rhs(), outer, typename internal::traits<Rhs>::StorageKind() ))
+ { }
inline Index outer() const { return m_outer; }
- inline Index row() const { return Transpose ? Base::row() : m_outer; }
- inline Index col() const { return Transpose ? m_outer : Base::row(); }
+ inline Index row() const { return Transpose ? m_outer : Base::index(); }
+ inline Index col() const { return Transpose ? Base::index() : m_outer; }
inline Scalar value() const { return Base::value() * m_factor; }
protected:
+ static Scalar get(const _RhsNested &rhs, Index outer, Dense = Dense())
+ {
+ return rhs.coeff(outer);
+ }
+
+ static Scalar get(const _RhsNested &rhs, Index outer, Sparse = Sparse())
+ {
+ typename Traits::_RhsNested::InnerIterator it(rhs, outer);
+ if (it && it.index()==0)
+ return it.value();
+
+ return Scalar(0);
+ }
+
Index m_outer;
Scalar m_factor;
};
@@ -161,7 +180,7 @@ struct sparse_time_dense_product_impl<SparseLhsType,DenseRhsType,DenseResType, R
typename Res::Scalar tmp(0);
for(LhsInnerIterator it(lhs,j); it ;++it)
tmp += it.value() * rhs.coeff(it.index(),c);
- res.coeffRef(j,c) = alpha * tmp;
+ res.coeffRef(j,c) += alpha * tmp;
}
}
}
@@ -287,15 +306,6 @@ class DenseTimeSparseProduct
DenseTimeSparseProduct& operator=(const DenseTimeSparseProduct&);
};
-// sparse * dense
-template<typename Derived>
-template<typename OtherDerived>
-inline const typename SparseDenseProductReturnType<Derived,OtherDerived>::Type
-SparseMatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
-{
- return typename SparseDenseProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
-}
-
} // end namespace Eigen
#endif // EIGEN_SPARSEDENSEPRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h b/extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h
index 01ce0dcfee3..2ff2015512f 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h
@@ -691,7 +691,8 @@ class SparseMatrix
m_data.swap(other.m_data);
}
- /** Sets *this to the identity matrix */
+ /** Sets *this to the identity matrix.
+ * This function also turns the matrix into compressed mode, and drop any reserved memory. */
inline void setIdentity()
{
eigen_assert(rows() == cols() && "ONLY FOR SQUARED MATRICES");
@@ -699,6 +700,8 @@ class SparseMatrix
Eigen::Map<Matrix<Index, Dynamic, 1> >(&this->m_data.index(0), rows()).setLinSpaced(0, rows()-1);
Eigen::Map<Matrix<Scalar, Dynamic, 1> >(&this->m_data.value(0), rows()).setOnes();
Eigen::Map<Matrix<Index, Dynamic, 1> >(this->m_outerIndex, rows()+1).setLinSpaced(0, rows());
+ std::free(m_innerNonZeros);
+ m_innerNonZeros = 0;
}
inline SparseMatrix& operator=(const SparseMatrix& other)
{
@@ -940,7 +943,7 @@ void set_from_triplets(const InputIterator& begin, const InputIterator& end, Spa
enum { IsRowMajor = SparseMatrixType::IsRowMajor };
typedef typename SparseMatrixType::Scalar Scalar;
typedef typename SparseMatrixType::Index Index;
- SparseMatrix<Scalar,IsRowMajor?ColMajor:RowMajor> trMat(mat.rows(),mat.cols());
+ SparseMatrix<Scalar,IsRowMajor?ColMajor:RowMajor,Index> trMat(mat.rows(),mat.cols());
if(begin!=end)
{
@@ -1178,7 +1181,7 @@ EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_Index>::Scalar& Sparse
size_t p = m_outerIndex[outer+1];
++m_outerIndex[outer+1];
- float reallocRatio = 1;
+ double reallocRatio = 1;
if (m_data.allocatedSize()<=m_data.size())
{
// if there is no preallocated memory, let's reserve a minimum of 32 elements
@@ -1190,13 +1193,13 @@ EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_Index>::Scalar& Sparse
{
// we need to reallocate the data, to reduce multiple reallocations
// we use a smart resize algorithm based on the current filling ratio
- // in addition, we use float to avoid integers overflows
- float nnzEstimate = float(m_outerIndex[outer])*float(m_outerSize)/float(outer+1);
- reallocRatio = (nnzEstimate-float(m_data.size()))/float(m_data.size());
+ // in addition, we use double to avoid integers overflows
+ double nnzEstimate = double(m_outerIndex[outer])*double(m_outerSize)/double(outer+1);
+ reallocRatio = (nnzEstimate-double(m_data.size()))/double(m_data.size());
// furthermore we bound the realloc ratio to:
// 1) reduce multiple minor realloc when the matrix is almost filled
// 2) avoid to allocate too much memory when the matrix is almost empty
- reallocRatio = (std::min)((std::max)(reallocRatio,1.5f),8.f);
+ reallocRatio = (std::min)((std::max)(reallocRatio,1.5),8.);
}
}
m_data.resize(m_data.size()+1,reallocRatio);
diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h b/extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h
index bbcf7fb1c62..9341d9ad2c0 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h
@@ -23,7 +23,14 @@ namespace Eigen {
* This class can be extended with the help of the plugin mechanism described on the page
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_SPARSEMATRIXBASE_PLUGIN.
*/
-template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
+template<typename Derived> class SparseMatrixBase
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+ : public internal::special_scalar_op_base<Derived,typename internal::traits<Derived>::Scalar,
+ typename NumTraits<typename internal::traits<Derived>::Scalar>::Real,
+ EigenBase<Derived> >
+#else
+ : public EigenBase<Derived>
+#endif // not EIGEN_PARSED_BY_DOXYGEN
{
public:
@@ -36,7 +43,6 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
>::type PacketReturnType;
typedef SparseMatrixBase StorageBaseType;
- typedef EigenBase<Derived> Base;
template<typename OtherDerived>
Derived& operator=(const EigenBase<OtherDerived> &other)
@@ -132,6 +138,9 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
inline Derived& derived() { return *static_cast<Derived*>(this); }
inline Derived& const_cast_derived() const
{ return *static_cast<Derived*>(const_cast<SparseMatrixBase*>(this)); }
+
+ typedef internal::special_scalar_op_base<Derived, Scalar, RealScalar, EigenBase<Derived> > Base;
+ using Base::operator*;
#endif // not EIGEN_PARSED_BY_DOXYGEN
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::SparseMatrixBase
@@ -317,20 +326,18 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
Derived& operator*=(const Scalar& other);
Derived& operator/=(const Scalar& other);
- #define EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE \
- CwiseBinaryOp< \
- internal::scalar_product_op< \
- typename internal::scalar_product_traits< \
- typename internal::traits<Derived>::Scalar, \
- typename internal::traits<OtherDerived>::Scalar \
- >::ReturnType \
- >, \
- const Derived, \
- const OtherDerived \
- >
+ template<typename OtherDerived> struct CwiseProductDenseReturnType {
+ typedef CwiseBinaryOp<internal::scalar_product_op<typename internal::scalar_product_traits<
+ typename internal::traits<Derived>::Scalar,
+ typename internal::traits<OtherDerived>::Scalar
+ >::ReturnType>,
+ const Derived,
+ const OtherDerived
+ > Type;
+ };
template<typename OtherDerived>
- EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
+ EIGEN_STRONG_INLINE const typename CwiseProductDenseReturnType<OtherDerived>::Type
cwiseProduct(const MatrixBase<OtherDerived> &other) const;
// sparse * sparse
@@ -358,7 +365,8 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
/** sparse * dense (returns a dense object unless it is an outer product) */
template<typename OtherDerived>
const typename SparseDenseProductReturnType<Derived,OtherDerived>::Type
- operator*(const MatrixBase<OtherDerived> &other) const;
+ operator*(const MatrixBase<OtherDerived> &other) const
+ { return typename SparseDenseProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived()); }
/** \returns an expression of P H P^-1 where H is the matrix represented by \c *this */
SparseSymmetricPermutationProduct<Derived,Upper|Lower> twistedBy(const PermutationMatrix<Dynamic,Dynamic,Index>& perm) const
@@ -403,8 +411,10 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
const ConstInnerVectorReturnType innerVector(Index outer) const;
// set of inner-vectors
- Block<Derived,Dynamic,Dynamic,true> innerVectors(Index outerStart, Index outerSize);
- const Block<const Derived,Dynamic,Dynamic,true> innerVectors(Index outerStart, Index outerSize) const;
+ typedef Block<Derived,Dynamic,Dynamic,true> InnerVectorsReturnType;
+ typedef Block<const Derived,Dynamic,Dynamic,true> ConstInnerVectorsReturnType;
+ InnerVectorsReturnType innerVectors(Index outerStart, Index outerSize);
+ const ConstInnerVectorsReturnType innerVectors(Index outerStart, Index outerSize) const;
/** \internal use operator= */
template<typename DenseDerived>
diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h b/extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h
index b85be93f6f9..75e21000959 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h
@@ -61,7 +61,7 @@ struct permut_sparsematrix_product_retval
for(Index j=0; j<m_matrix.outerSize(); ++j)
{
Index jp = m_permutation.indices().coeff(j);
- sizes[((Side==OnTheLeft) ^ Transposed) ? jp : j] = m_matrix.innerVector(((Side==OnTheRight) ^ Transposed) ? jp : j).size();
+ sizes[((Side==OnTheLeft) ^ Transposed) ? jp : j] = m_matrix.innerVector(((Side==OnTheRight) ^ Transposed) ? jp : j).nonZeros();
}
tmp.reserve(sizes);
for(Index j=0; j<m_matrix.outerSize(); ++j)
diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h b/extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h
index 7c300ee8dbc..76d031d52c8 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h
@@ -26,7 +26,7 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>
inline Index nonZeros() const { return derived().nestedExpression().nonZeros(); }
};
-// NOTE: VC10 trigger an ICE if don't put typename TransposeImpl<MatrixType,Sparse>:: in front of Index,
+// NOTE: VC10 and VC11 trigger an ICE if don't put typename TransposeImpl<MatrixType,Sparse>:: in front of Index,
// a typedef typename TransposeImpl<MatrixType,Sparse>::Index Index;
// does not fix the issue.
// An alternative is to define the nested class in the parent class itself.
@@ -40,8 +40,8 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>::InnerItera
EIGEN_STRONG_INLINE InnerIterator(const TransposeImpl& trans, typename TransposeImpl<MatrixType,Sparse>::Index outer)
: Base(trans.derived().nestedExpression(), outer)
{}
- Index row() const { return Base::col(); }
- Index col() const { return Base::row(); }
+ typename TransposeImpl<MatrixType,Sparse>::Index row() const { return Base::col(); }
+ typename TransposeImpl<MatrixType,Sparse>::Index col() const { return Base::row(); }
};
template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>::ReverseInnerIterator
@@ -54,8 +54,8 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>::ReverseInn
EIGEN_STRONG_INLINE ReverseInnerIterator(const TransposeImpl& xpr, typename TransposeImpl<MatrixType,Sparse>::Index outer)
: Base(xpr.derived().nestedExpression(), outer)
{}
- Index row() const { return Base::col(); }
- Index col() const { return Base::row(); }
+ typename TransposeImpl<MatrixType,Sparse>::Index row() const { return Base::col(); }
+ typename TransposeImpl<MatrixType,Sparse>::Index col() const { return Base::row(); }
};
} // end namespace Eigen
diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h b/extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h
index 05023858b16..d627546def0 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h
@@ -67,7 +67,6 @@ const int InnerRandomAccessPattern = 0x2 | CoherentAccessPattern;
const int OuterRandomAccessPattern = 0x4 | CoherentAccessPattern;
const int RandomAccessPattern = 0x8 | OuterRandomAccessPattern | InnerRandomAccessPattern;
-template<typename Derived> class SparseMatrixBase;
template<typename _Scalar, int _Flags = 0, typename _Index = int> class SparseMatrix;
template<typename _Scalar, int _Flags = 0, typename _Index = int> class DynamicSparseMatrix;
template<typename _Scalar, int _Flags = 0, typename _Index = int> class SparseVector;
@@ -84,8 +83,10 @@ template<typename Lhs, typename Rhs> class DenseTimeSparseProduct;
template<typename Lhs, typename Rhs, bool Transpose> class SparseDenseOuterProduct;
template<typename Lhs, typename Rhs> struct SparseSparseProductReturnType;
-template<typename Lhs, typename Rhs, int InnerSize = internal::traits<Lhs>::ColsAtCompileTime> struct DenseSparseProductReturnType;
-template<typename Lhs, typename Rhs, int InnerSize = internal::traits<Lhs>::ColsAtCompileTime> struct SparseDenseProductReturnType;
+template<typename Lhs, typename Rhs,
+ int InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(internal::traits<Lhs>::ColsAtCompileTime,internal::traits<Rhs>::RowsAtCompileTime)> struct DenseSparseProductReturnType;
+template<typename Lhs, typename Rhs,
+ int InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(internal::traits<Lhs>::ColsAtCompileTime,internal::traits<Rhs>::RowsAtCompileTime)> struct SparseDenseProductReturnType;
template<typename MatrixType,int UpLo> class SparseSymmetricPermutationProduct;
namespace internal {
diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseVector.h b/extern/Eigen3/Eigen/src/SparseCore/SparseVector.h
index 7e15c814b6f..49865d0e72f 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/SparseVector.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/SparseVector.h
@@ -158,6 +158,7 @@ class SparseVector
Index inner = IsColVector ? row : col;
Index outer = IsColVector ? col : row;
+ EIGEN_ONLY_USED_FOR_DEBUG(outer);
eigen_assert(outer==0);
return insert(inner);
}
diff --git a/extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h b/extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h
index cb8ad82b4f6..ccc12af7962 100644
--- a/extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h
+++ b/extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h
@@ -69,7 +69,7 @@ struct sparse_solve_triangular_selector<Lhs,Rhs,Mode,Upper,RowMajor>
for(int i=lhs.rows()-1 ; i>=0 ; --i)
{
Scalar tmp = other.coeff(i,col);
- Scalar l_ii = 0;
+ Scalar l_ii(0);
typename Lhs::InnerIterator it(lhs, i);
while(it && it.index()<i)
++it;
diff --git a/extern/Eigen3/Eigen/src/SparseLU/SparseLU.h b/extern/Eigen3/Eigen/src/SparseLU/SparseLU.h
index 1d592f2c8c7..bdc4f193ddb 100644
--- a/extern/Eigen3/Eigen/src/SparseLU/SparseLU.h
+++ b/extern/Eigen3/Eigen/src/SparseLU/SparseLU.h
@@ -260,16 +260,16 @@ class SparseLU : public internal::SparseLUImpl<typename _MatrixType::Scalar, typ
eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
// Initialize with the determinant of the row matrix
Scalar det = Scalar(1.);
- //Note that the diagonal blocks of U are stored in supernodes,
+ // Note that the diagonal blocks of U are stored in supernodes,
// which are available in the L part :)
for (Index j = 0; j < this->cols(); ++j)
{
for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it)
{
- if(it.row() < j) continue;
- if(it.row() == j)
+ if(it.index() == j)
{
- det *= (std::abs)(it.value());
+ using std::abs;
+ det *= abs(it.value());
break;
}
}
@@ -296,7 +296,8 @@ class SparseLU : public internal::SparseLUImpl<typename _MatrixType::Scalar, typ
if(it.row() < j) continue;
if(it.row() == j)
{
- det += (std::log)((std::abs)(it.value()));
+ using std::log; using std::abs;
+ det += log(abs(it.value()));
break;
}
}
@@ -304,21 +305,64 @@ class SparseLU : public internal::SparseLUImpl<typename _MatrixType::Scalar, typ
return det;
}
- /** \returns A number representing the sign of the determinant
- *
- * \sa absDeterminant(), logAbsDeterminant()
- */
- Scalar signDeterminant()
- {
- eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
- return Scalar(m_detPermR);
- }
+ /** \returns A number representing the sign of the determinant
+ *
+ * \sa absDeterminant(), logAbsDeterminant()
+ */
+ Scalar signDeterminant()
+ {
+ eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
+ // Initialize with the determinant of the row matrix
+ Index det = 1;
+ // Note that the diagonal blocks of U are stored in supernodes,
+ // which are available in the L part :)
+ for (Index j = 0; j < this->cols(); ++j)
+ {
+ for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it)
+ {
+ if(it.index() == j)
+ {
+ if(it.value()<0)
+ det = -det;
+ else if(it.value()==0)
+ return 0;
+ break;
+ }
+ }
+ }
+ return det * m_detPermR * m_detPermC;
+ }
+
+ /** \returns The determinant of the matrix.
+ *
+ * \sa absDeterminant(), logAbsDeterminant()
+ */
+ Scalar determinant()
+ {
+ eigen_assert(m_factorizationIsOk && "The matrix should be factorized first.");
+ // Initialize with the determinant of the row matrix
+ Scalar det = Scalar(1.);
+ // Note that the diagonal blocks of U are stored in supernodes,
+ // which are available in the L part :)
+ for (Index j = 0; j < this->cols(); ++j)
+ {
+ for (typename SCMatrix::InnerIterator it(m_Lstore, j); it; ++it)
+ {
+ if(it.index() == j)
+ {
+ det *= it.value();
+ break;
+ }
+ }
+ }
+ return det * Scalar(m_detPermR * m_detPermC);
+ }
protected:
// Functions
void initperfvalues()
{
- m_perfv.panel_size = 1;
+ m_perfv.panel_size = 16;
m_perfv.relax = 1;
m_perfv.maxsuper = 128;
m_perfv.rowblk = 16;
@@ -346,8 +390,8 @@ class SparseLU : public internal::SparseLUImpl<typename _MatrixType::Scalar, typ
// values for performance
internal::perfvalues<Index> m_perfv;
RealScalar m_diagpivotthresh; // Specifies the threshold used for a diagonal entry to be an acceptable pivot
- Index m_nnzL, m_nnzU; // Nonzeros in L and U factors
- Index m_detPermR; // Determinant of the coefficient matrix
+ Index m_nnzL, m_nnzU; // Nonzeros in L and U factors
+ Index m_detPermR, m_detPermC; // Determinants of the permutation matrices
private:
// Disable copy constructor
SparseLU (const SparseLU& );
@@ -623,7 +667,8 @@ void SparseLU<MatrixType, OrderingType>::factorize(const MatrixType& matrix)
}
// Update the determinant of the row permutation matrix
- if (pivrow != jj) m_detPermR *= -1;
+ // FIXME: the following test is not correct, we should probably take iperm_c into account and pivrow is not directly the row pivot.
+ if (pivrow != jj) m_detPermR = -m_detPermR;
// Prune columns (0:jj-1) using column jj
Base::pruneL(jj, m_perm_r.indices(), pivrow, nseg, segrep, repfnz_k, xprune, m_glu);
@@ -638,10 +683,13 @@ void SparseLU<MatrixType, OrderingType>::factorize(const MatrixType& matrix)
jcol += panel_size; // Move to the next panel
} // end for -- end elimination
+ m_detPermR = m_perm_r.determinant();
+ m_detPermC = m_perm_c.determinant();
+
// Count the number of nonzeros in factors
Base::countnz(n, m_nnzL, m_nnzU, m_glu);
// Apply permutation to the L subscripts
- Base::fixupL(n, m_perm_r.indices(), m_glu);
+ Base::fixupL(n, m_perm_r.indices(), m_glu);
// Create supernode matrix L
m_Lstore.setInfos(m, n, m_glu.lusup, m_glu.xlusup, m_glu.lsub, m_glu.xlsub, m_glu.supno, m_glu.xsup);
@@ -701,8 +749,8 @@ struct SparseLUMatrixUReturnType : internal::no_assignment_operator
}
else
{
- Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(m_mapL.valuePtr()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
- Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
+ Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(m_mapL.valuePtr()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
+ Map< Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
U = A.template triangularView<Upper>().solve(U);
}
diff --git a/extern/Eigen3/Eigen/src/SparseLU/SparseLUImpl.h b/extern/Eigen3/Eigen/src/SparseLU/SparseLUImpl.h
index 14d70897df7..99d651e40d3 100644
--- a/extern/Eigen3/Eigen/src/SparseLU/SparseLUImpl.h
+++ b/extern/Eigen3/Eigen/src/SparseLU/SparseLUImpl.h
@@ -21,6 +21,8 @@ class SparseLUImpl
{
public:
typedef Matrix<Scalar,Dynamic,1> ScalarVector;
+ typedef Matrix<Scalar,Dynamic,Dynamic,ColMajor> ScalarMatrix;
+ typedef Map<ScalarMatrix, 0, OuterStride<> > MappedMatrixBlock;
typedef Matrix<Index,Dynamic,1> IndexVector;
typedef typename ScalarVector::RealScalar RealScalar;
typedef Ref<Matrix<Scalar,Dynamic,1> > BlockScalarVector;
diff --git a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_Memory.h b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_Memory.h
index 1ffa7d54e96..45f96d16a8e 100644
--- a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_Memory.h
+++ b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_Memory.h
@@ -153,8 +153,8 @@ Index SparseLUImpl<Scalar,Index>::memInit(Index m, Index n, Index annz, Index lw
{
Index& num_expansions = glu.num_expansions; //No memory expansions so far
num_expansions = 0;
- glu.nzumax = glu.nzlumax = (std::min)(fillratio * annz / n, m) * n; // estimated number of nonzeros in U
- glu.nzlmax = (std::max)(Index(4), fillratio) * annz / 4; // estimated nnz in L factor
+ glu.nzumax = glu.nzlumax = (std::min)(fillratio * (annz+1) / n, m) * n; // estimated number of nonzeros in U
+ glu.nzlmax = (std::max)(Index(4), fillratio) * (annz+1) / 4; // estimated nnz in L factor
// Return the estimated size to the user if necessary
Index tempSpace;
tempSpace = (2*panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
diff --git a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h
index ad6f2183fed..54a56940861 100644
--- a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h
+++ b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h
@@ -189,8 +189,8 @@ class MappedSuperNodalMatrix<Scalar,Index>::InnerIterator
m_idval(mat.colIndexPtr()[outer]),
m_startidval(m_idval),
m_endidval(mat.colIndexPtr()[outer+1]),
- m_idrow(mat.rowIndexPtr()[outer]),
- m_endidrow(mat.rowIndexPtr()[outer+1])
+ m_idrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]]]),
+ m_endidrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]]+1])
{}
inline InnerIterator& operator++()
{
@@ -236,7 +236,7 @@ void MappedSuperNodalMatrix<Scalar,Index>::solveInPlace( MatrixBase<Dest>&X) con
Index n = X.rows();
Index nrhs = X.cols();
const Scalar * Lval = valuePtr(); // Nonzero values
- Matrix<Scalar,Dynamic,Dynamic> work(n, nrhs); // working vector
+ Matrix<Scalar,Dynamic,Dynamic, ColMajor> work(n, nrhs); // working vector
work.setZero();
for (Index k = 0; k <= nsuper(); k ++)
{
@@ -267,12 +267,12 @@ void MappedSuperNodalMatrix<Scalar,Index>::solveInPlace( MatrixBase<Dest>&X) con
Index lda = colIndexPtr()[fsupc+1] - luptr;
// Triangular solve
- Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
- Map< Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
+ Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
+ Map< Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > U (&(X(fsupc,0)), nsupc, nrhs, OuterStride<>(n) );
U = A.template triangularView<UnitLower>().solve(U);
// Matrix-vector product
- new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > ( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
+ new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > ( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
work.block(0, 0, nrow, nrhs) = A * U;
//Begin Scatter
diff --git a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_column_bmod.h b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_column_bmod.h
index f24bd87d3e9..cacc7e98712 100644
--- a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_column_bmod.h
+++ b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_column_bmod.h
@@ -162,11 +162,11 @@ Index SparseLUImpl<Scalar,Index>::column_bmod(const Index jcol, const Index nseg
// points to the beginning of jcol in snode L\U(jsupno)
ufirst = glu.xlusup(jcol) + d_fsupc;
Index lda = glu.xlusup(jcol+1) - glu.xlusup(jcol);
- Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A( &(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
+ MappedMatrixBlock A( &(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
VectorBlock<ScalarVector> u(glu.lusup, ufirst, nsupc);
u = A.template triangularView<UnitLower>().solve(u);
- new (&A) Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > ( &(glu.lusup.data()[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
+ new (&A) MappedMatrixBlock ( &(glu.lusup.data()[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
VectorBlock<ScalarVector> l(glu.lusup, ufirst+nsupc, nrow);
l.noalias() -= A * u;
diff --git a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_kernel_bmod.h b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_kernel_bmod.h
index 0d0283b132b..6af02675429 100644
--- a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_kernel_bmod.h
+++ b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_kernel_bmod.h
@@ -56,7 +56,7 @@ EIGEN_DONT_INLINE void LU_kernel_bmod<SegSizeAtCompileTime>::run(const int segsi
// Dense triangular solve -- start effective triangle
luptr += lda * no_zeros + no_zeros;
// Form Eigen matrix and vector
- Map<Matrix<Scalar,SegSizeAtCompileTime,SegSizeAtCompileTime>, 0, OuterStride<> > A( &(lusup.data()[luptr]), segsize, segsize, OuterStride<>(lda) );
+ Map<Matrix<Scalar,SegSizeAtCompileTime,SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > A( &(lusup.data()[luptr]), segsize, segsize, OuterStride<>(lda) );
Map<Matrix<Scalar,SegSizeAtCompileTime,1> > u(tempv.data(), segsize);
u = A.template triangularView<UnitLower>().solve(u);
@@ -65,7 +65,7 @@ EIGEN_DONT_INLINE void LU_kernel_bmod<SegSizeAtCompileTime>::run(const int segsi
luptr += segsize;
const Index PacketSize = internal::packet_traits<Scalar>::size;
Index ldl = internal::first_multiple(nrow, PacketSize);
- Map<Matrix<Scalar,Dynamic,SegSizeAtCompileTime>, 0, OuterStride<> > B( &(lusup.data()[luptr]), nrow, segsize, OuterStride<>(lda) );
+ Map<Matrix<Scalar,Dynamic,SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > B( &(lusup.data()[luptr]), nrow, segsize, OuterStride<>(lda) );
Index aligned_offset = internal::first_aligned(tempv.data()+segsize, PacketSize);
Index aligned_with_B_offset = (PacketSize-internal::first_aligned(B.data(), PacketSize))%PacketSize;
Map<Matrix<Scalar,Dynamic,1>, 0, OuterStride<> > l(tempv.data()+segsize+aligned_offset+aligned_with_B_offset, nrow, OuterStride<>(ldl) );
diff --git a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_panel_bmod.h b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_panel_bmod.h
index da0e0fc3c60..9d2ff290635 100644
--- a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_panel_bmod.h
+++ b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_panel_bmod.h
@@ -102,7 +102,7 @@ void SparseLUImpl<Scalar,Index>::panel_bmod(const Index m, const Index w, const
if(nsupc >= 2)
{
Index ldu = internal::first_multiple<Index>(u_rows, PacketSize);
- Map<Matrix<Scalar,Dynamic,Dynamic>, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
+ Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
// gather U
Index u_col = 0;
@@ -136,17 +136,17 @@ void SparseLUImpl<Scalar,Index>::panel_bmod(const Index m, const Index w, const
Index lda = glu.xlusup(fsupc+1) - glu.xlusup(fsupc);
no_zeros = (krep - u_rows + 1) - fsupc;
luptr += lda * no_zeros + no_zeros;
- Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > A(glu.lusup.data()+luptr, u_rows, u_rows, OuterStride<>(lda) );
+ MappedMatrixBlock A(glu.lusup.data()+luptr, u_rows, u_rows, OuterStride<>(lda) );
U = A.template triangularView<UnitLower>().solve(U);
// update
luptr += u_rows;
- Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > B(glu.lusup.data()+luptr, nrow, u_rows, OuterStride<>(lda) );
+ MappedMatrixBlock B(glu.lusup.data()+luptr, nrow, u_rows, OuterStride<>(lda) );
eigen_assert(tempv.size()>w*ldu + nrow*w + 1);
Index ldl = internal::first_multiple<Index>(nrow, PacketSize);
Index offset = (PacketSize-internal::first_aligned(B.data(), PacketSize)) % PacketSize;
- Map<Matrix<Scalar,Dynamic,Dynamic>, 0, OuterStride<> > L(tempv.data()+w*ldu+offset, nrow, u_cols, OuterStride<>(ldl));
+ MappedMatrixBlock L(tempv.data()+w*ldu+offset, nrow, u_cols, OuterStride<>(ldl));
L.setZero();
internal::sparselu_gemm<Scalar>(L.rows(), L.cols(), B.cols(), B.data(), B.outerStride(), U.data(), U.outerStride(), L.data(), L.outerStride());
diff --git a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_pivotL.h b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_pivotL.h
index ddcd4ec98f8..2e49ef667f4 100644
--- a/extern/Eigen3/Eigen/src/SparseLU/SparseLU_pivotL.h
+++ b/extern/Eigen3/Eigen/src/SparseLU/SparseLU_pivotL.h
@@ -71,13 +71,14 @@ Index SparseLUImpl<Scalar,Index>::pivotL(const Index jcol, const RealScalar& dia
// Determine the largest abs numerical value for partial pivoting
Index diagind = iperm_c(jcol); // diagonal index
- RealScalar pivmax = 0.0;
+ RealScalar pivmax(-1.0);
Index pivptr = nsupc;
Index diag = emptyIdxLU;
RealScalar rtemp;
Index isub, icol, itemp, k;
for (isub = nsupc; isub < nsupr; ++isub) {
- rtemp = std::abs(lu_col_ptr[isub]);
+ using std::abs;
+ rtemp = abs(lu_col_ptr[isub]);
if (rtemp > pivmax) {
pivmax = rtemp;
pivptr = isub;
@@ -86,8 +87,9 @@ Index SparseLUImpl<Scalar,Index>::pivotL(const Index jcol, const RealScalar& dia
}
// Test for singularity
- if ( pivmax == 0.0 ) {
- pivrow = lsub_ptr[pivptr];
+ if ( pivmax <= RealScalar(0.0) ) {
+ // if pivmax == -1, the column is structurally empty, otherwise it is only numerically zero
+ pivrow = pivmax < RealScalar(0.0) ? diagind : lsub_ptr[pivptr];
perm_r(pivrow) = jcol;
return (jcol+1);
}
@@ -101,7 +103,8 @@ Index SparseLUImpl<Scalar,Index>::pivotL(const Index jcol, const RealScalar& dia
if (diag >= 0 )
{
// Diagonal element exists
- rtemp = std::abs(lu_col_ptr[diag]);
+ using std::abs;
+ rtemp = abs(lu_col_ptr[diag]);
if (rtemp != 0.0 && rtemp >= thresh) pivptr = diag;
}
pivrow = lsub_ptr[pivptr];
diff --git a/extern/Eigen3/Eigen/src/SparseQR/SparseQR.h b/extern/Eigen3/Eigen/src/SparseQR/SparseQR.h
index afda43bfc67..a00bd5db124 100644
--- a/extern/Eigen3/Eigen/src/SparseQR/SparseQR.h
+++ b/extern/Eigen3/Eigen/src/SparseQR/SparseQR.h
@@ -2,7 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2012-2013 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
-// Copyright (C) 2012-2013 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2012-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
@@ -58,6 +58,7 @@ namespace internal {
* \tparam _OrderingType The fill-reducing ordering method. See the \link OrderingMethods_Module
* OrderingMethods \endlink module for the list of built-in and external ordering methods.
*
+ * \warning The input sparse matrix A must be in compressed mode (see SparseMatrix::makeCompressed()).
*
*/
template<typename _MatrixType, typename _OrderingType>
@@ -74,13 +75,26 @@ class SparseQR
typedef Matrix<Scalar, Dynamic, 1> ScalarVector;
typedef PermutationMatrix<Dynamic, Dynamic, Index> PermutationType;
public:
- SparseQR () : m_isInitialized(false), m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true),m_isQSorted(false)
+ SparseQR () : m_isInitialized(false), m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true),m_isQSorted(false),m_isEtreeOk(false)
{ }
- SparseQR(const MatrixType& mat) : m_isInitialized(false), m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true),m_isQSorted(false)
+ /** Construct a QR factorization of the matrix \a mat.
+ *
+ * \warning The matrix \a mat must be in compressed mode (see SparseMatrix::makeCompressed()).
+ *
+ * \sa compute()
+ */
+ SparseQR(const MatrixType& mat) : m_isInitialized(false), m_analysisIsok(false), m_lastError(""), m_useDefaultThreshold(true),m_isQSorted(false),m_isEtreeOk(false)
{
compute(mat);
}
+
+ /** Computes the QR factorization of the sparse matrix \a mat.
+ *
+ * \warning The matrix \a mat must be in compressed mode (see SparseMatrix::makeCompressed()).
+ *
+ * \sa analyzePattern(), factorize()
+ */
void compute(const MatrixType& mat)
{
analyzePattern(mat);
@@ -166,7 +180,7 @@ class SparseQR
y.bottomRows(y.rows()-rank).setZero();
// Apply the column permutation
- if (m_perm_c.size()) dest.topRows(cols()) = colsPermutation() * y.topRows(cols());
+ if (m_perm_c.size()) dest = colsPermutation() * y.topRows(cols());
else dest = y.topRows(cols());
m_info = Success;
@@ -206,7 +220,7 @@ class SparseQR
/** \brief Reports whether previous computation was successful.
*
- * \returns \c Success if computation was succesful,
+ * \returns \c Success if computation was successful,
* \c NumericalIssue if the QR factorization reports a numerical problem
* \c InvalidInput if the input matrix is invalid
*
@@ -248,6 +262,7 @@ class SparseQR
IndexVector m_etree; // Column elimination tree
IndexVector m_firstRowElt; // First element in each row
bool m_isQSorted; // whether Q is sorted or not
+ bool m_isEtreeOk; // whether the elimination tree match the initial input matrix
template <typename, typename > friend struct SparseQR_QProduct;
template <typename > friend struct SparseQRMatrixQReturnType;
@@ -256,19 +271,25 @@ class SparseQR
/** \brief Preprocessing step of a QR factorization
*
+ * \warning The matrix \a mat must be in compressed mode (see SparseMatrix::makeCompressed()).
+ *
* In this step, the fill-reducing permutation is computed and applied to the columns of A
- * and the column elimination tree is computed as well. Only the sparcity pattern of \a mat is exploited.
+ * and the column elimination tree is computed as well. Only the sparsity pattern of \a mat is exploited.
*
* \note In this step it is assumed that there is no empty row in the matrix \a mat.
*/
template <typename MatrixType, typename OrderingType>
void SparseQR<MatrixType,OrderingType>::analyzePattern(const MatrixType& mat)
{
+ eigen_assert(mat.isCompressed() && "SparseQR requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to SparseQR");
+ // Copy to a column major matrix if the input is rowmajor
+ typename internal::conditional<MatrixType::IsRowMajor,QRMatrixType,const MatrixType&>::type matCpy(mat);
// Compute the column fill reducing ordering
OrderingType ord;
- ord(mat, m_perm_c);
+ ord(matCpy, m_perm_c);
Index n = mat.cols();
Index m = mat.rows();
+ Index diagSize = (std::min)(m,n);
if (!m_perm_c.size())
{
@@ -278,22 +299,23 @@ void SparseQR<MatrixType,OrderingType>::analyzePattern(const MatrixType& mat)
// Compute the column elimination tree of the permuted matrix
m_outputPerm_c = m_perm_c.inverse();
- internal::coletree(mat, m_etree, m_firstRowElt, m_outputPerm_c.indices().data());
+ internal::coletree(matCpy, m_etree, m_firstRowElt, m_outputPerm_c.indices().data());
+ m_isEtreeOk = true;
- m_R.resize(n, n);
- m_Q.resize(m, n);
+ m_R.resize(m, n);
+ m_Q.resize(m, diagSize);
// Allocate space for nonzero elements : rough estimation
m_R.reserve(2*mat.nonZeros()); //FIXME Get a more accurate estimation through symbolic factorization with the etree
m_Q.reserve(2*mat.nonZeros());
- m_hcoeffs.resize(n);
+ m_hcoeffs.resize(diagSize);
m_analysisIsok = true;
}
/** \brief Performs the numerical QR factorization of the input matrix
*
* The function SparseQR::analyzePattern(const MatrixType&) must have been called beforehand with
- * a matrix having the same sparcity pattern than \a mat.
+ * a matrix having the same sparsity pattern than \a mat.
*
* \param mat The sparse column-major matrix
*/
@@ -306,23 +328,47 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
eigen_assert(m_analysisIsok && "analyzePattern() should be called before this step");
Index m = mat.rows();
Index n = mat.cols();
- IndexVector mark(m); mark.setConstant(-1); // Record the visited nodes
- IndexVector Ridx(n), Qidx(m); // Store temporarily the row indexes for the current column of R and Q
- Index nzcolR, nzcolQ; // Number of nonzero for the current column of R and Q
- ScalarVector tval(m); // The dense vector used to compute the current column
- bool found_diag;
-
+ Index diagSize = (std::min)(m,n);
+ IndexVector mark((std::max)(m,n)); mark.setConstant(-1); // Record the visited nodes
+ IndexVector Ridx(n), Qidx(m); // Store temporarily the row indexes for the current column of R and Q
+ Index nzcolR, nzcolQ; // Number of nonzero for the current column of R and Q
+ ScalarVector tval(m); // The dense vector used to compute the current column
+ RealScalar pivotThreshold = m_threshold;
+
+ m_R.setZero();
+ m_Q.setZero();
m_pmat = mat;
+ if(!m_isEtreeOk)
+ {
+ m_outputPerm_c = m_perm_c.inverse();
+ internal::coletree(m_pmat, m_etree, m_firstRowElt, m_outputPerm_c.indices().data());
+ m_isEtreeOk = true;
+ }
+
m_pmat.uncompress(); // To have the innerNonZeroPtr allocated
+
// Apply the fill-in reducing permutation lazily:
- for (int i = 0; i < n; i++)
{
- Index p = m_perm_c.size() ? m_perm_c.indices()(i) : i;
- m_pmat.outerIndexPtr()[p] = mat.outerIndexPtr()[i];
- m_pmat.innerNonZeroPtr()[p] = mat.outerIndexPtr()[i+1] - mat.outerIndexPtr()[i];
+ // If the input is row major, copy the original column indices,
+ // otherwise directly use the input matrix
+ //
+ IndexVector originalOuterIndicesCpy;
+ const Index *originalOuterIndices = mat.outerIndexPtr();
+ if(MatrixType::IsRowMajor)
+ {
+ originalOuterIndicesCpy = IndexVector::Map(m_pmat.outerIndexPtr(),n+1);
+ originalOuterIndices = originalOuterIndicesCpy.data();
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ Index p = m_perm_c.size() ? m_perm_c.indices()(i) : i;
+ m_pmat.outerIndexPtr()[p] = originalOuterIndices[i];
+ m_pmat.innerNonZeroPtr()[p] = originalOuterIndices[i+1] - originalOuterIndices[i];
+ }
}
- /* Compute the default threshold, see :
+ /* Compute the default threshold as in MatLab, see:
* Tim Davis, "Algorithm 915, SuiteSparseQR: Multifrontal Multithreaded Rank-Revealing
* Sparse QR Factorization, ACM Trans. on Math. Soft. 38(1), 2011, Page 8:3
*/
@@ -330,33 +376,35 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
{
RealScalar max2Norm = 0.0;
for (int j = 0; j < n; j++) max2Norm = (max)(max2Norm, m_pmat.col(j).norm());
- m_threshold = 20 * (m + n) * max2Norm * NumTraits<RealScalar>::epsilon();
+ if(max2Norm==RealScalar(0))
+ max2Norm = RealScalar(1);
+ pivotThreshold = 20 * (m + n) * max2Norm * NumTraits<RealScalar>::epsilon();
}
// Initialize the numerical permutation
m_pivotperm.setIdentity(n);
Index nonzeroCol = 0; // Record the number of valid pivots
-
+ m_Q.startVec(0);
+
// Left looking rank-revealing QR factorization: compute a column of R and Q at a time
- for (Index col = 0; col < (std::min)(n,m); ++col)
+ for (Index col = 0; col < n; ++col)
{
mark.setConstant(-1);
m_R.startVec(col);
- m_Q.startVec(col);
mark(nonzeroCol) = col;
Qidx(0) = nonzeroCol;
nzcolR = 0; nzcolQ = 1;
- found_diag = col>=m;
+ bool found_diag = nonzeroCol>=m;
tval.setZero();
// Symbolic factorization: find the nonzero locations of the column k of the factors R and Q, i.e.,
// all the nodes (with indexes lower than rank) reachable through the column elimination tree (etree) rooted at node k.
// Note: if the diagonal entry does not exist, then its contribution must be explicitly added,
// thus the trick with found_diag that permits to do one more iteration on the diagonal element if this one has not been found.
- for (typename MatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp)
+ for (typename QRMatrixType::InnerIterator itp(m_pmat, col); itp || !found_diag; ++itp)
{
- Index curIdx = nonzeroCol ;
+ Index curIdx = nonzeroCol;
if(itp) curIdx = itp.row();
if(curIdx == nonzeroCol) found_diag = true;
@@ -398,7 +446,7 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
// Browse all the indexes of R(:,col) in reverse order
for (Index i = nzcolR-1; i >= 0; i--)
{
- Index curIdx = m_pivotperm.indices()(Ridx(i));
+ Index curIdx = Ridx(i);
// Apply the curIdx-th householder vector to the current column (temporarily stored into tval)
Scalar tdot(0);
@@ -427,33 +475,36 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
}
}
} // End update current column
-
- // Compute the Householder reflection that eliminate the current column
- // FIXME this step should call the Householder module.
- Scalar tau;
- RealScalar beta;
- Scalar c0 = nzcolQ ? tval(Qidx(0)) : Scalar(0);
- // First, the squared norm of Q((col+1):m, col)
- RealScalar sqrNorm = 0.;
- for (Index itq = 1; itq < nzcolQ; ++itq) sqrNorm += numext::abs2(tval(Qidx(itq)));
+ Scalar tau = 0;
+ RealScalar beta = 0;
- if(sqrNorm == RealScalar(0) && numext::imag(c0) == RealScalar(0))
- {
- tau = RealScalar(0);
- beta = numext::real(c0);
- tval(Qidx(0)) = 1;
- }
- else
+ if(nonzeroCol < diagSize)
{
- beta = std::sqrt(numext::abs2(c0) + sqrNorm);
- if(numext::real(c0) >= RealScalar(0))
- beta = -beta;
- tval(Qidx(0)) = 1;
- for (Index itq = 1; itq < nzcolQ; ++itq)
- tval(Qidx(itq)) /= (c0 - beta);
- tau = numext::conj((beta-c0) / beta);
-
+ // Compute the Householder reflection that eliminate the current column
+ // FIXME this step should call the Householder module.
+ Scalar c0 = nzcolQ ? tval(Qidx(0)) : Scalar(0);
+
+ // First, the squared norm of Q((col+1):m, col)
+ RealScalar sqrNorm = 0.;
+ for (Index itq = 1; itq < nzcolQ; ++itq) sqrNorm += numext::abs2(tval(Qidx(itq)));
+ if(sqrNorm == RealScalar(0) && numext::imag(c0) == RealScalar(0))
+ {
+ beta = numext::real(c0);
+ tval(Qidx(0)) = 1;
+ }
+ else
+ {
+ using std::sqrt;
+ beta = sqrt(numext::abs2(c0) + sqrNorm);
+ if(numext::real(c0) >= RealScalar(0))
+ beta = -beta;
+ tval(Qidx(0)) = 1;
+ for (Index itq = 1; itq < nzcolQ; ++itq)
+ tval(Qidx(itq)) /= (c0 - beta);
+ tau = numext::conj((beta-c0) / beta);
+
+ }
}
// Insert values in R
@@ -467,45 +518,49 @@ void SparseQR<MatrixType,OrderingType>::factorize(const MatrixType& mat)
}
}
- if(abs(beta) >= m_threshold)
+ if(nonzeroCol < diagSize && abs(beta) >= pivotThreshold)
{
m_R.insertBackByOuterInner(col, nonzeroCol) = beta;
- nonzeroCol++;
// The householder coefficient
- m_hcoeffs(col) = tau;
+ m_hcoeffs(nonzeroCol) = tau;
// Record the householder reflections
for (Index itq = 0; itq < nzcolQ; ++itq)
{
Index iQ = Qidx(itq);
- m_Q.insertBackByOuterInnerUnordered(col,iQ) = tval(iQ);
+ m_Q.insertBackByOuterInnerUnordered(nonzeroCol,iQ) = tval(iQ);
tval(iQ) = Scalar(0.);
- }
+ }
+ nonzeroCol++;
+ if(nonzeroCol<diagSize)
+ m_Q.startVec(nonzeroCol);
}
else
{
// Zero pivot found: move implicitly this column to the end
- m_hcoeffs(col) = Scalar(0);
for (Index j = nonzeroCol; j < n-1; j++)
std::swap(m_pivotperm.indices()(j), m_pivotperm.indices()[j+1]);
// Recompute the column elimination tree
internal::coletree(m_pmat, m_etree, m_firstRowElt, m_pivotperm.indices().data());
+ m_isEtreeOk = false;
}
}
+ m_hcoeffs.tail(diagSize-nonzeroCol).setZero();
+
// Finalize the column pointers of the sparse matrices R and Q
m_Q.finalize();
m_Q.makeCompressed();
m_R.finalize();
m_R.makeCompressed();
m_isQSorted = false;
-
+
m_nonzeropivots = nonzeroCol;
if(nonzeroCol<n)
{
// Permute the triangular factor to put the 'dead' columns to the end
- MatrixType tempR(m_R);
+ QRMatrixType tempR(m_R);
m_R = tempR * m_pivotperm;
// Update the column permutation
@@ -561,14 +616,16 @@ struct SparseQR_QProduct : ReturnByValue<SparseQR_QProduct<SparseQRType, Derived
template<typename DesType>
void evalTo(DesType& res) const
{
+ Index m = m_qr.rows();
Index n = m_qr.cols();
+ Index diagSize = (std::min)(m,n);
res = m_other;
if (m_transpose)
{
eigen_assert(m_qr.m_Q.rows() == m_other.rows() && "Non conforming object sizes");
//Compute res = Q' * other column by column
for(Index j = 0; j < res.cols(); j++){
- for (Index k = 0; k < n; k++)
+ for (Index k = 0; k < diagSize; k++)
{
Scalar tau = Scalar(0);
tau = m_qr.m_Q.col(k).dot(res.col(j));
@@ -581,10 +638,10 @@ struct SparseQR_QProduct : ReturnByValue<SparseQR_QProduct<SparseQRType, Derived
else
{
eigen_assert(m_qr.m_Q.rows() == m_other.rows() && "Non conforming object sizes");
- // Compute res = Q' * other column by column
+ // Compute res = Q * other column by column
for(Index j = 0; j < res.cols(); j++)
{
- for (Index k = n-1; k >=0; k--)
+ for (Index k = diagSize-1; k >=0; k--)
{
Scalar tau = Scalar(0);
tau = m_qr.m_Q.col(k).dot(res.col(j));
@@ -618,7 +675,7 @@ struct SparseQRMatrixQReturnType : public EigenBase<SparseQRMatrixQReturnType<Sp
return SparseQRMatrixQTransposeReturnType<SparseQRType>(m_qr);
}
inline Index rows() const { return m_qr.rows(); }
- inline Index cols() const { return m_qr.cols(); }
+ inline Index cols() const { return (std::min)(m_qr.rows(),m_qr.cols()); }
// To use for operations with the transpose of Q
SparseQRMatrixQTransposeReturnType<SparseQRType> transpose() const
{
diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h b/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h
index 4ee8e5c10a5..aaf66330b17 100644
--- a/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h
+++ b/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h
@@ -11,7 +11,7 @@
#ifndef EIGEN_STDDEQUE_H
#define EIGEN_STDDEQUE_H
-#include "Eigen/src/StlSupport/details.h"
+#include "details.h"
// Define the explicit instantiation (e.g. necessary for the Intel compiler)
#if defined(__INTEL_COMPILER) || defined(__GNUC__)
diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdList.h b/extern/Eigen3/Eigen/src/StlSupport/StdList.h
index 627381ecec0..3c742430c12 100644
--- a/extern/Eigen3/Eigen/src/StlSupport/StdList.h
+++ b/extern/Eigen3/Eigen/src/StlSupport/StdList.h
@@ -10,7 +10,7 @@
#ifndef EIGEN_STDLIST_H
#define EIGEN_STDLIST_H
-#include "Eigen/src/StlSupport/details.h"
+#include "details.h"
// Define the explicit instantiation (e.g. necessary for the Intel compiler)
#if defined(__INTEL_COMPILER) || defined(__GNUC__)
diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdVector.h b/extern/Eigen3/Eigen/src/StlSupport/StdVector.h
index 40a9abefa82..611664a2e8a 100644
--- a/extern/Eigen3/Eigen/src/StlSupport/StdVector.h
+++ b/extern/Eigen3/Eigen/src/StlSupport/StdVector.h
@@ -11,7 +11,7 @@
#ifndef EIGEN_STDVECTOR_H
#define EIGEN_STDVECTOR_H
-#include "Eigen/src/StlSupport/details.h"
+#include "details.h"
/**
* This section contains a convenience MACRO which allows an easy specialization of
diff --git a/extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h b/extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h
index 3a48cecf769..29c60c37875 100644
--- a/extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h
+++ b/extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h
@@ -107,6 +107,16 @@ inline int umfpack_get_determinant(std::complex<double> *Mx, double *Ex, void *N
return umfpack_zi_get_determinant(&mx_real,0,Ex,NumericHandle,User_Info);
}
+namespace internal {
+ template<typename T> struct umfpack_helper_is_sparse_plain : false_type {};
+ template<typename Scalar, int Options, typename StorageIndex>
+ struct umfpack_helper_is_sparse_plain<SparseMatrix<Scalar,Options,StorageIndex> >
+ : true_type {};
+ template<typename Scalar, int Options, typename StorageIndex>
+ struct umfpack_helper_is_sparse_plain<MappedSparseMatrix<Scalar,Options,StorageIndex> >
+ : true_type {};
+}
+
/** \ingroup UmfPackSupport_Module
* \brief A sparse LU factorization and solver based on UmfPack
*
@@ -192,10 +202,14 @@ class UmfPackLU : internal::noncopyable
* Note that the matrix should be column-major, and in compressed format for best performance.
* \sa SparseMatrix::makeCompressed().
*/
- void compute(const MatrixType& matrix)
+ template<typename InputMatrixType>
+ void compute(const InputMatrixType& matrix)
{
- analyzePattern(matrix);
- factorize(matrix);
+ if(m_symbolic) umfpack_free_symbolic(&m_symbolic,Scalar());
+ if(m_numeric) umfpack_free_numeric(&m_numeric,Scalar());
+ grapInput(matrix.derived());
+ analyzePattern_impl();
+ factorize_impl();
}
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
@@ -230,23 +244,15 @@ class UmfPackLU : internal::noncopyable
*
* \sa factorize(), compute()
*/
- void analyzePattern(const MatrixType& matrix)
+ template<typename InputMatrixType>
+ void analyzePattern(const InputMatrixType& matrix)
{
- if(m_symbolic)
- umfpack_free_symbolic(&m_symbolic,Scalar());
- if(m_numeric)
- umfpack_free_numeric(&m_numeric,Scalar());
+ if(m_symbolic) umfpack_free_symbolic(&m_symbolic,Scalar());
+ if(m_numeric) umfpack_free_numeric(&m_numeric,Scalar());
- grapInput(matrix);
-
- int errorCode = 0;
- errorCode = umfpack_symbolic(matrix.rows(), matrix.cols(), m_outerIndexPtr, m_innerIndexPtr, m_valuePtr,
- &m_symbolic, 0, 0);
+ grapInput(matrix.derived());
- m_isInitialized = true;
- m_info = errorCode ? InvalidInput : Success;
- m_analysisIsOk = true;
- m_factorizationIsOk = false;
+ analyzePattern_impl();
}
/** Performs a numeric decomposition of \a matrix
@@ -255,20 +261,16 @@ class UmfPackLU : internal::noncopyable
*
* \sa analyzePattern(), compute()
*/
- void factorize(const MatrixType& matrix)
+ template<typename InputMatrixType>
+ void factorize(const InputMatrixType& matrix)
{
eigen_assert(m_analysisIsOk && "UmfPackLU: you must first call analyzePattern()");
if(m_numeric)
umfpack_free_numeric(&m_numeric,Scalar());
- grapInput(matrix);
-
- int errorCode;
- errorCode = umfpack_numeric(m_outerIndexPtr, m_innerIndexPtr, m_valuePtr,
- m_symbolic, &m_numeric, 0, 0);
-
- m_info = errorCode ? NumericalIssue : Success;
- m_factorizationIsOk = true;
+ grapInput(matrix.derived());
+
+ factorize_impl();
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -283,19 +285,20 @@ class UmfPackLU : internal::noncopyable
protected:
-
void init()
{
- m_info = InvalidInput;
- m_isInitialized = false;
- m_numeric = 0;
- m_symbolic = 0;
- m_outerIndexPtr = 0;
- m_innerIndexPtr = 0;
- m_valuePtr = 0;
+ m_info = InvalidInput;
+ m_isInitialized = false;
+ m_numeric = 0;
+ m_symbolic = 0;
+ m_outerIndexPtr = 0;
+ m_innerIndexPtr = 0;
+ m_valuePtr = 0;
+ m_extractedDataAreDirty = true;
}
- void grapInput(const MatrixType& mat)
+ template<typename InputMatrixType>
+ void grapInput_impl(const InputMatrixType& mat, internal::true_type)
{
m_copyMatrix.resize(mat.rows(), mat.cols());
if( ((MatrixType::Flags&RowMajorBit)==RowMajorBit) || sizeof(typename MatrixType::Index)!=sizeof(int) || !mat.isCompressed() )
@@ -313,6 +316,45 @@ class UmfPackLU : internal::noncopyable
m_valuePtr = mat.valuePtr();
}
}
+
+ template<typename InputMatrixType>
+ void grapInput_impl(const InputMatrixType& mat, internal::false_type)
+ {
+ m_copyMatrix = mat;
+ m_outerIndexPtr = m_copyMatrix.outerIndexPtr();
+ m_innerIndexPtr = m_copyMatrix.innerIndexPtr();
+ m_valuePtr = m_copyMatrix.valuePtr();
+ }
+
+ template<typename InputMatrixType>
+ void grapInput(const InputMatrixType& mat)
+ {
+ grapInput_impl(mat, internal::umfpack_helper_is_sparse_plain<InputMatrixType>());
+ }
+
+ void analyzePattern_impl()
+ {
+ int errorCode = 0;
+ errorCode = umfpack_symbolic(m_copyMatrix.rows(), m_copyMatrix.cols(), m_outerIndexPtr, m_innerIndexPtr, m_valuePtr,
+ &m_symbolic, 0, 0);
+
+ m_isInitialized = true;
+ m_info = errorCode ? InvalidInput : Success;
+ m_analysisIsOk = true;
+ m_factorizationIsOk = false;
+ m_extractedDataAreDirty = true;
+ }
+
+ void factorize_impl()
+ {
+ int errorCode;
+ errorCode = umfpack_numeric(m_outerIndexPtr, m_innerIndexPtr, m_valuePtr,
+ m_symbolic, &m_numeric, 0, 0);
+
+ m_info = errorCode ? NumericalIssue : Success;
+ m_factorizationIsOk = true;
+ m_extractedDataAreDirty = true;
+ }
// cached data to reduce reallocation, etc.
mutable LUMatrixType m_l;
diff --git a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h b/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h
index 5c8c476eecf..1951286f3ae 100644
--- a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h
+++ b/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h
@@ -70,6 +70,43 @@ max
return (max)(Derived::PlainObject::Constant(rows(), cols(), other));
}
+
+#define EIGEN_MAKE_CWISE_COMP_OP(OP, COMPARATOR) \
+template<typename OtherDerived> \
+EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_cmp_op<Scalar, internal::cmp_ ## COMPARATOR>, const Derived, const OtherDerived> \
+OP(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const \
+{ \
+ return CwiseBinaryOp<internal::scalar_cmp_op<Scalar, internal::cmp_ ## COMPARATOR>, const Derived, const OtherDerived>(derived(), other.derived()); \
+}\
+typedef CwiseBinaryOp<internal::scalar_cmp_op<Scalar, internal::cmp_ ## COMPARATOR>, const Derived, const CwiseNullaryOp<internal::scalar_constant_op<Scalar>, PlainObject> > Cmp ## COMPARATOR ## ReturnType; \
+typedef CwiseBinaryOp<internal::scalar_cmp_op<Scalar, internal::cmp_ ## COMPARATOR>, const CwiseNullaryOp<internal::scalar_constant_op<Scalar>, PlainObject>, const Derived > RCmp ## COMPARATOR ## ReturnType; \
+EIGEN_STRONG_INLINE const Cmp ## COMPARATOR ## ReturnType \
+OP(const Scalar& s) const { \
+ return this->OP(Derived::PlainObject::Constant(rows(), cols(), s)); \
+} \
+friend EIGEN_STRONG_INLINE const RCmp ## COMPARATOR ## ReturnType \
+OP(const Scalar& s, const Derived& d) { \
+ return Derived::PlainObject::Constant(d.rows(), d.cols(), s).OP(d); \
+}
+
+#define EIGEN_MAKE_CWISE_COMP_R_OP(OP, R_OP, RCOMPARATOR) \
+template<typename OtherDerived> \
+EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_cmp_op<Scalar, internal::cmp_##RCOMPARATOR>, const OtherDerived, const Derived> \
+OP(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const \
+{ \
+ return CwiseBinaryOp<internal::scalar_cmp_op<Scalar, internal::cmp_##RCOMPARATOR>, const OtherDerived, const Derived>(other.derived(), derived()); \
+} \
+\
+inline const RCmp ## RCOMPARATOR ## ReturnType \
+OP(const Scalar& s) const { \
+ return Derived::PlainObject::Constant(rows(), cols(), s).R_OP(*this); \
+} \
+friend inline const Cmp ## RCOMPARATOR ## ReturnType \
+OP(const Scalar& s, const Derived& d) { \
+ return d.R_OP(Derived::PlainObject::Constant(d.rows(), d.cols(), s)); \
+}
+
+
/** \returns an expression of the coefficient-wise \< operator of *this and \a other
*
* Example: \include Cwise_less.cpp
@@ -77,7 +114,7 @@ max
*
* \sa all(), any(), operator>(), operator<=()
*/
-EIGEN_MAKE_CWISE_BINARY_OP(operator<,std::less)
+EIGEN_MAKE_CWISE_COMP_OP(operator<, LT)
/** \returns an expression of the coefficient-wise \<= operator of *this and \a other
*
@@ -86,7 +123,7 @@ EIGEN_MAKE_CWISE_BINARY_OP(operator<,std::less)
*
* \sa all(), any(), operator>=(), operator<()
*/
-EIGEN_MAKE_CWISE_BINARY_OP(operator<=,std::less_equal)
+EIGEN_MAKE_CWISE_COMP_OP(operator<=, LE)
/** \returns an expression of the coefficient-wise \> operator of *this and \a other
*
@@ -95,7 +132,7 @@ EIGEN_MAKE_CWISE_BINARY_OP(operator<=,std::less_equal)
*
* \sa all(), any(), operator>=(), operator<()
*/
-EIGEN_MAKE_CWISE_BINARY_OP(operator>,std::greater)
+EIGEN_MAKE_CWISE_COMP_R_OP(operator>, operator<, LT)
/** \returns an expression of the coefficient-wise \>= operator of *this and \a other
*
@@ -104,7 +141,7 @@ EIGEN_MAKE_CWISE_BINARY_OP(operator>,std::greater)
*
* \sa all(), any(), operator>(), operator<=()
*/
-EIGEN_MAKE_CWISE_BINARY_OP(operator>=,std::greater_equal)
+EIGEN_MAKE_CWISE_COMP_R_OP(operator>=, operator<=, LE)
/** \returns an expression of the coefficient-wise == operator of *this and \a other
*
@@ -118,7 +155,7 @@ EIGEN_MAKE_CWISE_BINARY_OP(operator>=,std::greater_equal)
*
* \sa all(), any(), isApprox(), isMuchSmallerThan()
*/
-EIGEN_MAKE_CWISE_BINARY_OP(operator==,std::equal_to)
+EIGEN_MAKE_CWISE_COMP_OP(operator==, EQ)
/** \returns an expression of the coefficient-wise != operator of *this and \a other
*
@@ -132,7 +169,10 @@ EIGEN_MAKE_CWISE_BINARY_OP(operator==,std::equal_to)
*
* \sa all(), any(), isApprox(), isMuchSmallerThan()
*/
-EIGEN_MAKE_CWISE_BINARY_OP(operator!=,std::not_equal_to)
+EIGEN_MAKE_CWISE_COMP_OP(operator!=, NEQ)
+
+#undef EIGEN_MAKE_CWISE_COMP_OP
+#undef EIGEN_MAKE_CWISE_COMP_R_OP
// scalar addition
@@ -209,3 +249,5 @@ operator||(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL);
return CwiseBinaryOp<internal::scalar_boolean_or_op, const Derived, const OtherDerived>(derived(),other.derived());
}
+
+
diff --git a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h b/extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h
index a596367906f..1c3ed3fcd70 100644
--- a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h
+++ b/extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h
@@ -185,19 +185,3 @@ cube() const
{
return derived();
}
-
-#define EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(METHOD_NAME,FUNCTOR) \
- inline const CwiseUnaryOp<std::binder2nd<FUNCTOR<Scalar> >, const Derived> \
- METHOD_NAME(const Scalar& s) const { \
- return CwiseUnaryOp<std::binder2nd<FUNCTOR<Scalar> >, const Derived> \
- (derived(), std::bind2nd(FUNCTOR<Scalar>(), s)); \
- }
-
-EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator==, std::equal_to)
-EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator!=, std::not_equal_to)
-EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator<, std::less)
-EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator<=, std::less_equal)
-EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator>, std::greater)
-EIGEN_MAKE_SCALAR_CWISE_UNARY_OP(operator>=, std::greater_equal)
-
-
diff --git a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h
index 7f62149e04b..c4a042b7027 100644
--- a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h
+++ b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h
@@ -124,3 +124,20 @@ cwiseQuotient(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
{
return CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const Derived, const OtherDerived>(derived(), other.derived());
}
+
+typedef CwiseBinaryOp<internal::scalar_cmp_op<Scalar,internal::cmp_EQ>, const Derived, const ConstantReturnType> CwiseScalarEqualReturnType;
+
+/** \returns an expression of the coefficient-wise == operator of \c *this and a scalar \a s
+ *
+ * \warning this performs an exact comparison, which is generally a bad idea with floating-point types.
+ * In order to check for equality between two vectors or matrices with floating-point coefficients, it is
+ * generally a far better idea to use a fuzzy comparison as provided by isApprox() and
+ * isMuchSmallerThan().
+ *
+ * \sa cwiseEqual(const MatrixBase<OtherDerived> &) const
+ */
+inline const CwiseScalarEqualReturnType
+cwiseEqual(const Scalar& s) const
+{
+ return CwiseScalarEqualReturnType(derived(), Derived::Constant(rows(), cols(), s), internal::scalar_cmp_op<Scalar,internal::cmp_EQ>());
+}
diff --git a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h
index 0cf0640bae6..8de10935d55 100644
--- a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h
+++ b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h
@@ -50,18 +50,3 @@ cwiseSqrt() const { return derived(); }
inline const CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const Derived>
cwiseInverse() const { return derived(); }
-/** \returns an expression of the coefficient-wise == operator of \c *this and a scalar \a s
- *
- * \warning this performs an exact comparison, which is generally a bad idea with floating-point types.
- * In order to check for equality between two vectors or matrices with floating-point coefficients, it is
- * generally a far better idea to use a fuzzy comparison as provided by isApprox() and
- * isMuchSmallerThan().
- *
- * \sa cwiseEqual(const MatrixBase<OtherDerived> &) const
- */
-inline const CwiseUnaryOp<std::binder1st<std::equal_to<Scalar> >, const Derived>
-cwiseEqual(const Scalar& s) const
-{
- return CwiseUnaryOp<std::binder1st<std::equal_to<Scalar> >,const Derived>
- (derived(), std::bind1st(std::equal_to<Scalar>(), s));
-}
diff --git a/extern/Eigen3/eigen-update.sh b/extern/Eigen3/eigen-update.sh
index 1cf0337adf6..9d22098c4fd 100755
--- a/extern/Eigen3/eigen-update.sh
+++ b/extern/Eigen3/eigen-update.sh
@@ -17,7 +17,7 @@ if [ -d eigen ]
then
cd eigen
# put here the version you want to use
- hg up 3.2.1
+ hg up 3.2.7
rm -f `find Eigen/ -type f -name "CMakeLists.txt"`
cp -r Eigen ..
cd ..
diff --git a/extern/SConscript b/extern/SConscript
index 484c0e959c2..a5d8c1f078e 100644
--- a/extern/SConscript
+++ b/extern/SConscript
@@ -7,11 +7,9 @@ if env['WITH_BF_GLEW_ES']:
else:
SConscript(['glew/SConscript'])
-SConscript(['colamd/SConscript'])
SConscript(['rangetree/SConscript'])
SConscript(['wcwidth/SConscript'])
SConscript(['libmv/SConscript'])
-SConscript(['Eigen3/SConscript'])
if env['WITH_BF_GAMEENGINE']:
SConscript(['recastnavigation/SConscript'])
diff --git a/extern/colamd/CMakeLists.txt b/extern/colamd/CMakeLists.txt
deleted file mode 100644
index 3019ee5904e..00000000000
--- a/extern/colamd/CMakeLists.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# The Original Code is Copyright (C) 2011, Blender Foundation
-# All rights reserved.
-#
-# Contributor(s): Blender Foundation,
-# Sergey Sharybin
-#
-# ***** END GPL LICENSE BLOCK *****
-
-set(INC
- Include
-)
-
-set(INC_SYS
-
-)
-
-set(SRC
- Source/colamd.c
- Source/colamd_global.c
-
- Include/colamd.h
- Include/UFconfig.h
-)
-
-blender_add_lib(extern_colamd "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/colamd/Doc/ChangeLog b/extern/colamd/Doc/ChangeLog
deleted file mode 100644
index 29308e9ad01..00000000000
--- a/extern/colamd/Doc/ChangeLog
+++ /dev/null
@@ -1,129 +0,0 @@
-May 31, 2007: version 2.7.0
-
- * ported to 64-bit MATLAB
-
- * subdirectories added (Source/, Include/, Lib/, Doc/, MATLAB/, Demo/)
-
-Dec 12, 2006, version 2.5.2
-
- * minor MATLAB cleanup. MATLAB functions renamed colamd2 and symamd2,
- so that they do not conflict with the built-in versions. Note that
- the MATLAB built-in functions colamd and symamd are identical to
- the colamd and symamd functions here.
-
-Aug 31, 2006: Version 2.5.1
-
- * minor change to colamd.m and symamd.m, to use etree instead
- of sparsfun.
-
-Apr. 30, 2006: Version 2.5
-
- * colamd_recommended modified, to do more careful integer overflow
- checking. It now returns size_t, not int. colamd_l_recommended
- also returns size_t. A zero is returned if an error occurs. A
- postive return value denotes success. In v2.4 and earlier,
- -1 was returned on error (an int or long).
-
- * long replaced with UF_long integer, which is long except on WIN64.
-
-Nov 15, 2005:
-
- * minor editting of comments; version number (2.4) unchanged.
-
-Changes from Version 2.3 to 2.4 (Aug 30, 2005)
-
- * Makefile now relies on ../UFconfig/UFconfig.mk
-
- * changed the dense row/col detection. The meaning of the knobs
- has thus changed.
-
- * added an option to turn off aggressive absorption. It was
- always on in versions 2.3 and earlier.
-
- * added a #define'd version number
-
- * added a function pointer (colamd_printf) for COLAMD's printing.
-
- * added a -DNPRINT option, to turn off printing at compile-time.
-
- * added a check for integer overflow in colamd_recommended
-
- * minor changes to allow for more simpler 100% test coverage
-
- * bug fix. If symamd v2.3 fails to allocate its copy of the input
- matrix, then it erroneously frees a calloc'd workspace twice.
- This bug has no effect on the MATLAB symamd mexFunction, since
- mxCalloc terminates the mexFunction if it fails to allocate
- memory. Similarly, UMFPACK is not affected because it does not
- use symamd. The bug has no effect on the colamd ordering
- routine in v2.3.
-
-Changes from Version 2.2 to 2.3 (Sept. 8, 2003)
-
- * removed the call to the MATLAB spparms ('spumoni') function.
- This can take a lot of time if you are ordering many small
- matrices. Only affects the MATLAB interface (colamdmex.c,
- symamdmex.c, colamdtestmex.c, and symamdtestmex.c). The
- usage of the optional 2nd argument to the colamd and symamd
- mexFunctions was changed accordingly.
-
-Changes from Version 2.1 to 2.2 (Sept. 23, 2002)
-
- * extensive testing routines added (colamd_test.m, colamdtestmex.c,
- and symamdtestmex.c), and the Makefile modified accordingly.
-
- * a few typos in the comments corrected
-
- * use of the MATLAB "flops" command removed from colamd_demo, and an
- m-file routine luflops.m added.
-
- * an explicit typecast from unsigned to int added, for COLAMD_C and
- COLAMD_R in colamd.h.
-
- * #include <stdio.h> added to colamd_example.c
-
-
-Changes from Version 2.0 to 2.1 (May 4, 2001)
-
- * TRUE and FALSE are predefined on some systems, so they are defined
- here only if not already defined.
-
- * web site changed
-
- * UNIX Makefile modified, to handle the case if "." is not in your path.
-
-
-Changes from Version 1.0 to 2.0 (January 31, 2000)
-
- No bugs were found in version 1.1. These changes merely add new
- functionality.
-
- * added the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro.
-
- * moved the output statistics, from A, to a separate output argument.
- The arguments changed for the C-callable routines.
-
- * added colamd_report and symamd_report.
-
- * added a C-callable symamd routine. Formerly, symamd was only
- available as a mexFunction from MATLAB.
-
- * added error-checking to symamd. Formerly, it assumed its input
- was error-free.
-
- * added the optional stats and knobs arguments to the symamd mexFunction
-
- * deleted colamd_help. A help message is still available from
- "help colamd" and "help symamd" in MATLAB.
-
- * deleted colamdtree.m and symamdtree.m. Now, colamd.m and symamd.m
- also do the elimination tree post-ordering. The Version 1.1
- colamd and symamd mexFunctions, which do not do the post-
- ordering, are now visible as colamdmex and symamdmex from
- MATLAB. Essentialy, the post-ordering is now the default
- behavior of colamd.m and symamd.m, to match the behavior of
- colmmd and symmmd. The post-ordering is only available in the
- MATLAB interface, not the C-callable interface.
-
- * made a slight change to the dense row/column detection in symamd,
- to match the stated specifications.
diff --git a/extern/colamd/Doc/lesser.txt b/extern/colamd/Doc/lesser.txt
deleted file mode 100644
index 8add30ad590..00000000000
--- a/extern/colamd/Doc/lesser.txt
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/extern/colamd/Include/UFconfig.h b/extern/colamd/Include/UFconfig.h
deleted file mode 100644
index 7b5e79e544f..00000000000
--- a/extern/colamd/Include/UFconfig.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* ========================================================================== */
-/* === UFconfig.h =========================================================== */
-/* ========================================================================== */
-
-/* Configuration file for SuiteSparse: a Suite of Sparse matrix packages
- * (AMD, COLAMD, CCOLAMD, CAMD, CHOLMOD, UMFPACK, CXSparse, and others).
- *
- * UFconfig.h provides the definition of the long integer. On most systems,
- * a C program can be compiled in LP64 mode, in which long's and pointers are
- * both 64-bits, and int's are 32-bits. Windows 64, however, uses the LLP64
- * model, in which int's and long's are 32-bits, and long long's and pointers
- * are 64-bits.
- *
- * SuiteSparse packages that include long integer versions are
- * intended for the LP64 mode. However, as a workaround for Windows 64
- * (and perhaps other systems), the long integer can be redefined.
- *
- * If _WIN64 is defined, then the __int64 type is used instead of long.
- *
- * The long integer can also be defined at compile time. For example, this
- * could be added to UFconfig.mk:
- *
- * CFLAGS = -O -D'UF_long=long long' -D'UF_long_max=9223372036854775801' \
- * -D'UF_long_id="%lld"'
- *
- * This file defines UF_long as either long (on all but _WIN64) or
- * __int64 on Windows 64. The intent is that a UF_long is always a 64-bit
- * integer in a 64-bit code. ptrdiff_t might be a better choice than long;
- * it is always the same size as a pointer.
- *
- * This file also defines the SUITESPARSE_VERSION and related definitions.
- *
- * Copyright (c) 2007, University of Florida. No licensing restrictions
- * apply to this file or to the UFconfig directory. Author: Timothy A. Davis.
- */
-
-#ifndef _UFCONFIG_H
-#define _UFCONFIG_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <limits.h>
-
-/* ========================================================================== */
-/* === UF_long ============================================================== */
-/* ========================================================================== */
-
-#ifndef UF_long
-
-#ifdef _WIN64
-
-#define UF_long __int64
-#define UF_long_max _I64_MAX
-#define UF_long_id "%I64d"
-
-#else
-
-#define UF_long long
-#define UF_long_max LONG_MAX
-#define UF_long_id "%ld"
-
-#endif
-#endif
-
-/* ========================================================================== */
-/* === SuiteSparse version ================================================== */
-/* ========================================================================== */
-
-/* SuiteSparse is not a package itself, but a collection of packages, some of
- * which must be used together (UMFPACK requires AMD, CHOLMOD requires AMD,
- * COLAMD, CAMD, and CCOLAMD, etc). A version number is provided here for the
- * collection itself. The versions of packages within each version of
- * SuiteSparse are meant to work together. Combining one packge from one
- * version of SuiteSparse, with another package from another version of
- * SuiteSparse, may or may not work.
- *
- * SuiteSparse Version 3.4.0 contains the following packages:
- *
- * AMD version 2.2.0
- * CAMD version 2.2.0
- * COLAMD version 2.7.1
- * CCOLAMD version 2.7.1
- * CHOLMOD version 1.7.1
- * CSparse version 2.2.3
- * CXSparse version 2.2.3
- * KLU version 1.1.0
- * BTF version 1.1.0
- * LDL version 2.0.1
- * UFconfig version number is the same as SuiteSparse
- * UMFPACK version 5.4.0
- * RBio version 1.1.2
- * UFcollection version 1.2.0
- * LINFACTOR version 1.1.0
- * MESHND version 1.1.1
- * SSMULT version 2.0.0
- * MATLAB_Tools no specific version number
- * SuiteSparseQR version 1.1.2
- *
- * Other package dependencies:
- * BLAS required by CHOLMOD and UMFPACK
- * LAPACK required by CHOLMOD
- * METIS 4.0.1 required by CHOLMOD (optional) and KLU (optional)
- */
-
-#define SUITESPARSE_DATE "May 20, 2009"
-#define SUITESPARSE_VER_CODE(main,sub) ((main) * 1000 + (sub))
-#define SUITESPARSE_MAIN_VERSION 3
-#define SUITESPARSE_SUB_VERSION 4
-#define SUITESPARSE_SUBSUB_VERSION 0
-#define SUITESPARSE_VERSION \
- SUITESPARSE_VER_CODE(SUITESPARSE_MAIN_VERSION,SUITESPARSE_SUB_VERSION)
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/extern/colamd/Include/colamd.h b/extern/colamd/Include/colamd.h
deleted file mode 100644
index 26372d8fa96..00000000000
--- a/extern/colamd/Include/colamd.h
+++ /dev/null
@@ -1,255 +0,0 @@
-/* ========================================================================== */
-/* === colamd/symamd prototypes and definitions ============================= */
-/* ========================================================================== */
-
-/* COLAMD / SYMAMD include file
-
- You must include this file (colamd.h) in any routine that uses colamd,
- symamd, or the related macros and definitions.
-
- Authors:
-
- The authors of the code itself are Stefan I. Larimore and Timothy A.
- Davis (davis at cise.ufl.edu), University of Florida. The algorithm was
- developed in collaboration with John Gilbert, Xerox PARC, and Esmond
- Ng, Oak Ridge National Laboratory.
-
- Acknowledgements:
-
- This work was supported by the National Science Foundation, under
- grants DMS-9504974 and DMS-9803599.
-
- Notice:
-
- Copyright (c) 1998-2007, Timothy A. Davis, All Rights Reserved.
-
- THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
- EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
-
- Permission is hereby granted to use, copy, modify, and/or distribute
- this program, provided that the Copyright, this License, and the
- Availability of the original version is retained on all copies and made
- accessible to the end-user of any code or package that includes COLAMD
- or any modified version of COLAMD.
-
- Availability:
-
- The colamd/symamd library is available at
-
- http://www.cise.ufl.edu/research/sparse/colamd/
-
- This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.h
- file. It is required by the colamd.c, colamdmex.c, and symamdmex.c
- files, and by any C code that calls the routines whose prototypes are
- listed below, or that uses the colamd/symamd definitions listed below.
-
-*/
-
-#ifndef COLAMD_H
-#define COLAMD_H
-
-/* make it easy for C++ programs to include COLAMD */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* ========================================================================== */
-/* === Include files ======================================================== */
-/* ========================================================================== */
-
-#include <stdlib.h>
-
-/* ========================================================================== */
-/* === COLAMD version ======================================================= */
-/* ========================================================================== */
-
-/* COLAMD Version 2.4 and later will include the following definitions.
- * As an example, to test if the version you are using is 2.4 or later:
- *
- * #ifdef COLAMD_VERSION
- * if (COLAMD_VERSION >= COLAMD_VERSION_CODE (2,4)) ...
- * #endif
- *
- * This also works during compile-time:
- *
- * #if defined(COLAMD_VERSION) && (COLAMD_VERSION >= COLAMD_VERSION_CODE (2,4))
- * printf ("This is version 2.4 or later\n") ;
- * #else
- * printf ("This is an early version\n") ;
- * #endif
- *
- * Versions 2.3 and earlier of COLAMD do not include a #define'd version number.
- */
-
-#define COLAMD_DATE "Nov 1, 2007"
-#define COLAMD_VERSION_CODE(main,sub) ((main) * 1000 + (sub))
-#define COLAMD_MAIN_VERSION 2
-#define COLAMD_SUB_VERSION 7
-#define COLAMD_SUBSUB_VERSION 1
-#define COLAMD_VERSION \
- COLAMD_VERSION_CODE(COLAMD_MAIN_VERSION,COLAMD_SUB_VERSION)
-
-/* ========================================================================== */
-/* === Knob and statistics definitions ====================================== */
-/* ========================================================================== */
-
-/* size of the knobs [ ] array. Only knobs [0..1] are currently used. */
-#define COLAMD_KNOBS 20
-
-/* number of output statistics. Only stats [0..6] are currently used. */
-#define COLAMD_STATS 20
-
-/* knobs [0] and stats [0]: dense row knob and output statistic. */
-#define COLAMD_DENSE_ROW 0
-
-/* knobs [1] and stats [1]: dense column knob and output statistic. */
-#define COLAMD_DENSE_COL 1
-
-/* knobs [2]: aggressive absorption */
-#define COLAMD_AGGRESSIVE 2
-
-/* stats [2]: memory defragmentation count output statistic */
-#define COLAMD_DEFRAG_COUNT 2
-
-/* stats [3]: colamd status: zero OK, > 0 warning or notice, < 0 error */
-#define COLAMD_STATUS 3
-
-/* stats [4..6]: error info, or info on jumbled columns */
-#define COLAMD_INFO1 4
-#define COLAMD_INFO2 5
-#define COLAMD_INFO3 6
-
-/* error codes returned in stats [3]: */
-#define COLAMD_OK (0)
-#define COLAMD_OK_BUT_JUMBLED (1)
-#define COLAMD_ERROR_A_not_present (-1)
-#define COLAMD_ERROR_p_not_present (-2)
-#define COLAMD_ERROR_nrow_negative (-3)
-#define COLAMD_ERROR_ncol_negative (-4)
-#define COLAMD_ERROR_nnz_negative (-5)
-#define COLAMD_ERROR_p0_nonzero (-6)
-#define COLAMD_ERROR_A_too_small (-7)
-#define COLAMD_ERROR_col_length_negative (-8)
-#define COLAMD_ERROR_row_index_out_of_bounds (-9)
-#define COLAMD_ERROR_out_of_memory (-10)
-#define COLAMD_ERROR_internal_error (-999)
-
-
-/* ========================================================================== */
-/* === Prototypes of user-callable routines ================================= */
-/* ========================================================================== */
-
-/* define UF_long */
-#include "UFconfig.h"
-
-size_t colamd_recommended /* returns recommended value of Alen, */
- /* or 0 if input arguments are erroneous */
-(
- int nnz, /* nonzeros in A */
- int n_row, /* number of rows in A */
- int n_col /* number of columns in A */
-) ;
-
-size_t colamd_l_recommended /* returns recommended value of Alen, */
- /* or 0 if input arguments are erroneous */
-(
- UF_long nnz, /* nonzeros in A */
- UF_long n_row, /* number of rows in A */
- UF_long n_col /* number of columns in A */
-) ;
-
-void colamd_set_defaults /* sets default parameters */
-( /* knobs argument is modified on output */
- double knobs [COLAMD_KNOBS] /* parameter settings for colamd */
-) ;
-
-void colamd_l_set_defaults /* sets default parameters */
-( /* knobs argument is modified on output */
- double knobs [COLAMD_KNOBS] /* parameter settings for colamd */
-) ;
-
-int colamd /* returns (1) if successful, (0) otherwise*/
-( /* A and p arguments are modified on output */
- int n_row, /* number of rows in A */
- int n_col, /* number of columns in A */
- int Alen, /* size of the array A */
- int A [], /* row indices of A, of size Alen */
- int p [], /* column pointers of A, of size n_col+1 */
- double knobs [COLAMD_KNOBS],/* parameter settings for colamd */
- int stats [COLAMD_STATS] /* colamd output statistics and error codes */
-) ;
-
-UF_long colamd_l /* returns (1) if successful, (0) otherwise*/
-( /* A and p arguments are modified on output */
- UF_long n_row, /* number of rows in A */
- UF_long n_col, /* number of columns in A */
- UF_long Alen, /* size of the array A */
- UF_long A [], /* row indices of A, of size Alen */
- UF_long p [], /* column pointers of A, of size n_col+1 */
- double knobs [COLAMD_KNOBS],/* parameter settings for colamd */
- UF_long stats [COLAMD_STATS]/* colamd output statistics and error codes */
-) ;
-
-int symamd /* return (1) if OK, (0) otherwise */
-(
- int n, /* number of rows and columns of A */
- int A [], /* row indices of A */
- int p [], /* column pointers of A */
- int perm [], /* output permutation, size n_col+1 */
- double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */
- int stats [COLAMD_STATS], /* output statistics and error codes */
- void * (*allocate) (size_t, size_t),
- /* pointer to calloc (ANSI C) or */
- /* mxCalloc (for MATLAB mexFunction) */
- void (*release) (void *)
- /* pointer to free (ANSI C) or */
- /* mxFree (for MATLAB mexFunction) */
-) ;
-
-UF_long symamd_l /* return (1) if OK, (0) otherwise */
-(
- UF_long n, /* number of rows and columns of A */
- UF_long A [], /* row indices of A */
- UF_long p [], /* column pointers of A */
- UF_long perm [], /* output permutation, size n_col+1 */
- double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */
- UF_long stats [COLAMD_STATS], /* output statistics and error codes */
- void * (*allocate) (size_t, size_t),
- /* pointer to calloc (ANSI C) or */
- /* mxCalloc (for MATLAB mexFunction) */
- void (*release) (void *)
- /* pointer to free (ANSI C) or */
- /* mxFree (for MATLAB mexFunction) */
-) ;
-
-void colamd_report
-(
- int stats [COLAMD_STATS]
-) ;
-
-void colamd_l_report
-(
- UF_long stats [COLAMD_STATS]
-) ;
-
-void symamd_report
-(
- int stats [COLAMD_STATS]
-) ;
-
-void symamd_l_report
-(
- UF_long stats [COLAMD_STATS]
-) ;
-
-#ifndef EXTERN
-#define EXTERN extern
-#endif
-
-EXTERN int (*colamd_printf) (const char *, ...) ;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* COLAMD_H */
diff --git a/extern/colamd/README.txt b/extern/colamd/README.txt
deleted file mode 100644
index 5ed81c71d02..00000000000
--- a/extern/colamd/README.txt
+++ /dev/null
@@ -1,127 +0,0 @@
-The COLAMD ordering method - Version 2.7
--------------------------------------------------------------------------------
-
-The COLAMD column approximate minimum degree ordering algorithm computes
-a permutation vector P such that the LU factorization of A (:,P)
-tends to be sparser than that of A. The Cholesky factorization of
-(A (:,P))'*(A (:,P)) will also tend to be sparser than that of A'*A.
-SYMAMD is a symmetric minimum degree ordering method based on COLAMD,
-available as a MATLAB-callable function. It constructs a matrix M such
-that M'*M has the same pattern as A, and then uses COLAMD to compute a column
-ordering of M. Colamd and symamd tend to be faster and generate better
-orderings than their MATLAB counterparts, colmmd and symmmd.
-
-To compile and test the colamd m-files and mexFunctions, just unpack the
-COLAMD/ directory from the COLAMD.tar.gz file, and run MATLAB from
-within that directory. Next, type colamd_test to compile and test colamd
-and symamd. This will work on any computer with MATLAB (Unix, PC, or Mac).
-Alternatively, type "make" (in Unix) to compile and run a simple example C
-code, without using MATLAB.
-
-To compile and install the colamd m-files and mexFunctions, just cd to
-COLAMD/MATLAB and type colamd_install in the MATLAB command window.
-A short demo will run. Optionally, type colamd_test to run an extensive tests.
-Type "make" in Unix in the COLAMD directory to compile the C-callable
-library and to run a short demo.
-
-If you have MATLAB 7.2 or earlier, you must first edit UFconfig/UFconfig.h to
-remove the "-largeArrayDims" option from the MEX command (or just use
-colamd_make.m inside MATLAB).
-
-Colamd is a built-in routine in MATLAB, available from The
-Mathworks, Inc. Under most cases, the compiled COLAMD from Versions 2.0 to the
-current version do not differ. Colamd Versions 2.2 and 2.3 differ only in their
-mexFunction interaces to MATLAB. v2.4 fixes a bug in the symamd routine in
-v2.3. The bug (in v2.3 and earlier) has no effect on the MATLAB symamd
-mexFunction. v2.5 adds additional checks for integer overflow, so that
-the "int" version can be safely used with 64-bit pointers. Refer to the
-ChangeLog for more details.
-
-To use colamd and symamd within an application written in C, all you need are
-colamd.c, colamd_global.c, and colamd.h, which are the C-callable
-colamd/symamd codes. See colamd.c for more information on how to call
-colamd from a C program.
-
-Requires UFconfig, in the ../UFconfig directory relative to this directory.
-
- Copyright (c) 1998-2007, Timothy A. Davis, All Rights Reserved.
-
- See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c
- file) for the License.
-
-
-Related papers:
-
- T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column
- minimum degree ordering algorithm, ACM Transactions on Mathematical
- Software, vol. 30, no. 3., pp. 353-376, 2004.
-
- T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD,
- an approximate column minimum degree ordering algorithm, ACM
- Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380,
- 2004.
-
- "An approximate minimum degree column ordering algorithm",
- S. I. Larimore, MS Thesis, Dept. of Computer and Information
- Science and Engineering, University of Florida, Gainesville, FL,
- 1998. CISE Tech Report TR-98-016. Available at
- ftp://ftp.cise.ufl.edu/cis/tech-reports/tr98/tr98-016.ps
- via anonymous ftp.
-
- Approximate Deficiency for Ordering the Columns of a Matrix,
- J. L. Kern, Senior Thesis, Dept. of Computer and Information
- Science and Engineering, University of Florida, Gainesville, FL,
- 1999. Available at http://www.cise.ufl.edu/~davis/Kern/kern.ps
-
-
-Authors: Stefan I. Larimore and Timothy A. Davis, University of Florida,
-in collaboration with John Gilbert, Xerox PARC (now at UC Santa Barbara),
-and Esmong Ng, Lawrence Berkeley National Laboratory (much of this work
-he did while at Oak Ridge National Laboratory).
-
-COLAMD files:
-
- Demo simple demo
- Doc additional documentation (see colamd.c for more)
- Include include file
- Lib compiled C-callable library
- Makefile primary Unix Makefile
- MATLAB MATLAB functions
- README.txt this file
- Source C source code
-
- ./Demo:
- colamd_example.c simple example
- colamd_example.out output of colamd_example.c
- colamd_l_example.c simple example, long integers
- colamd_l_example.out output of colamd_l_example.c
- Makefile Makefile for C demos
-
- ./Doc:
- ChangeLog change log
- lesser.txt license
-
- ./Include:
- colamd.h include file
-
- ./Lib:
- Makefile Makefile for C-callable library
-
- ./MATLAB:
- colamd2.m MATLAB interface for colamd2
- colamd_demo.m simple demo
- colamd_install.m compile and install colamd2 and symamd2
- colamd_make.m compile colamd2 and symamd2
- colamdmex.ca MATLAB mexFunction for colamd2
- colamd_test.m extensive test
- colamdtestmex.c test function for colamd
- Contents.m contents of the MATLAB directory
- luflops.m test code
- Makefile Makefile for MATLAB functions
- symamd2.m MATLAB interface for symamd2
- symamdmex.c MATLAB mexFunction for symamd2
- symamdtestmex.c test function for symamd
-
- ./Source:
- colamd.c primary source code
- colamd_global.c globally defined function pointers (malloc, free, ...)
diff --git a/extern/colamd/SConscript b/extern/colamd/SConscript
deleted file mode 100644
index 7930e3ace2d..00000000000
--- a/extern/colamd/SConscript
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/python
-import sys
-import os
-
-Import('env')
-
-defs = ''
-cflags = []
-
-src = env.Glob('Source/*.c')
-
-incs = './Include'
-
-env.BlenderLib ( libname = 'extern_colamd', sources=src, includes=Split(incs), defines=Split(defs), libtype=['extern', 'player'], priority=[20,137], compileflags=cflags )
diff --git a/extern/colamd/Source/colamd.c b/extern/colamd/Source/colamd.c
deleted file mode 100644
index 5fe20d62822..00000000000
--- a/extern/colamd/Source/colamd.c
+++ /dev/null
@@ -1,3611 +0,0 @@
-/* ========================================================================== */
-/* === colamd/symamd - a sparse matrix column ordering algorithm ============ */
-/* ========================================================================== */
-
-/* COLAMD / SYMAMD
-
- colamd: an approximate minimum degree column ordering algorithm,
- for LU factorization of symmetric or unsymmetric matrices,
- QR factorization, least squares, interior point methods for
- linear programming problems, and other related problems.
-
- symamd: an approximate minimum degree ordering algorithm for Cholesky
- factorization of symmetric matrices.
-
- Purpose:
-
- Colamd computes a permutation Q such that the Cholesky factorization of
- (AQ)'(AQ) has less fill-in and requires fewer floating point operations
- than A'A. This also provides a good ordering for sparse partial
- pivoting methods, P(AQ) = LU, where Q is computed prior to numerical
- factorization, and P is computed during numerical factorization via
- conventional partial pivoting with row interchanges. Colamd is the
- column ordering method used in SuperLU, part of the ScaLAPACK library.
- It is also available as built-in function in MATLAB Version 6,
- available from MathWorks, Inc. (http://www.mathworks.com). This
- routine can be used in place of colmmd in MATLAB.
-
- Symamd computes a permutation P of a symmetric matrix A such that the
- Cholesky factorization of PAP' has less fill-in and requires fewer
- floating point operations than A. Symamd constructs a matrix M such
- that M'M has the same nonzero pattern of A, and then orders the columns
- of M using colmmd. The column ordering of M is then returned as the
- row and column ordering P of A.
-
- Authors:
-
- The authors of the code itself are Stefan I. Larimore and Timothy A.
- Davis (davis at cise.ufl.edu), University of Florida. The algorithm was
- developed in collaboration with John Gilbert, Xerox PARC, and Esmond
- Ng, Oak Ridge National Laboratory.
-
- Acknowledgements:
-
- This work was supported by the National Science Foundation, under
- grants DMS-9504974 and DMS-9803599.
-
- Copyright and License:
-
- Copyright (c) 1998-2007, Timothy A. Davis, All Rights Reserved.
- COLAMD is also available under alternate licenses, contact T. Davis
- for details.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
- USA
-
- Permission is hereby granted to use or copy this program under the
- terms of the GNU LGPL, provided that the Copyright, this License,
- and the Availability of the original version is retained on all copies.
- User documentation of any code that uses this code or any modified
- version of this code must cite the Copyright, this License, the
- Availability note, and "Used by permission." Permission to modify
- the code and to distribute modified code is granted, provided the
- Copyright, this License, and the Availability note are retained,
- and a notice that the code was modified is included.
-
- Availability:
-
- The colamd/symamd library is available at
-
- http://www.cise.ufl.edu/research/sparse/colamd/
-
- This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.c
- file. It requires the colamd.h file. It is required by the colamdmex.c
- and symamdmex.c files, for the MATLAB interface to colamd and symamd.
- Appears as ACM Algorithm 836.
-
- See the ChangeLog file for changes since Version 1.0.
-
- References:
-
- T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column
- minimum degree ordering algorithm, ACM Transactions on Mathematical
- Software, vol. 30, no. 3., pp. 353-376, 2004.
-
- T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD,
- an approximate column minimum degree ordering algorithm, ACM
- Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380,
- 2004.
-
-*/
-
-/* ========================================================================== */
-/* === Description of user-callable routines ================================ */
-/* ========================================================================== */
-
-/* COLAMD includes both int and UF_long versions of all its routines. The
- * description below is for the int version. For UF_long, all int arguments
- * become UF_long. UF_long is normally defined as long, except for WIN64.
-
- ----------------------------------------------------------------------------
- colamd_recommended:
- ----------------------------------------------------------------------------
-
- C syntax:
-
- #include "colamd.h"
- size_t colamd_recommended (int nnz, int n_row, int n_col) ;
- size_t colamd_l_recommended (UF_long nnz, UF_long n_row,
- UF_long n_col) ;
-
- Purpose:
-
- Returns recommended value of Alen for use by colamd. Returns 0
- if any input argument is negative. The use of this routine
- is optional. Not needed for symamd, which dynamically allocates
- its own memory.
-
- Note that in v2.4 and earlier, these routines returned int or long.
- They now return a value of type size_t.
-
- Arguments (all input arguments):
-
- int nnz ; Number of nonzeros in the matrix A. This must
- be the same value as p [n_col] in the call to
- colamd - otherwise you will get a wrong value
- of the recommended memory to use.
-
- int n_row ; Number of rows in the matrix A.
-
- int n_col ; Number of columns in the matrix A.
-
- ----------------------------------------------------------------------------
- colamd_set_defaults:
- ----------------------------------------------------------------------------
-
- C syntax:
-
- #include "colamd.h"
- colamd_set_defaults (double knobs [COLAMD_KNOBS]) ;
- colamd_l_set_defaults (double knobs [COLAMD_KNOBS]) ;
-
- Purpose:
-
- Sets the default parameters. The use of this routine is optional.
-
- Arguments:
-
- double knobs [COLAMD_KNOBS] ; Output only.
-
- NOTE: the meaning of the dense row/col knobs has changed in v2.4
-
- knobs [0] and knobs [1] control dense row and col detection:
-
- Colamd: rows with more than
- max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n_col))
- entries are removed prior to ordering. Columns with more than
- max (16, knobs [COLAMD_DENSE_COL] * sqrt (MIN (n_row,n_col)))
- entries are removed prior to
- ordering, and placed last in the output column ordering.
-
- Symamd: uses only knobs [COLAMD_DENSE_ROW], which is knobs [0].
- Rows and columns with more than
- max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n))
- entries are removed prior to ordering, and placed last in the
- output ordering.
-
- COLAMD_DENSE_ROW and COLAMD_DENSE_COL are defined as 0 and 1,
- respectively, in colamd.h. Default values of these two knobs
- are both 10. Currently, only knobs [0] and knobs [1] are
- used, but future versions may use more knobs. If so, they will
- be properly set to their defaults by the future version of
- colamd_set_defaults, so that the code that calls colamd will
- not need to change, assuming that you either use
- colamd_set_defaults, or pass a (double *) NULL pointer as the
- knobs array to colamd or symamd.
-
- knobs [2]: aggressive absorption
-
- knobs [COLAMD_AGGRESSIVE] controls whether or not to do
- aggressive absorption during the ordering. Default is TRUE.
-
-
- ----------------------------------------------------------------------------
- colamd:
- ----------------------------------------------------------------------------
-
- C syntax:
-
- #include "colamd.h"
- int colamd (int n_row, int n_col, int Alen, int *A, int *p,
- double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS]) ;
- UF_long colamd_l (UF_long n_row, UF_long n_col, UF_long Alen,
- UF_long *A, UF_long *p, double knobs [COLAMD_KNOBS],
- UF_long stats [COLAMD_STATS]) ;
-
- Purpose:
-
- Computes a column ordering (Q) of A such that P(AQ)=LU or
- (AQ)'AQ=LL' have less fill-in and require fewer floating point
- operations than factorizing the unpermuted matrix A or A'A,
- respectively.
-
- Returns:
-
- TRUE (1) if successful, FALSE (0) otherwise.
-
- Arguments:
-
- int n_row ; Input argument.
-
- Number of rows in the matrix A.
- Restriction: n_row >= 0.
- Colamd returns FALSE if n_row is negative.
-
- int n_col ; Input argument.
-
- Number of columns in the matrix A.
- Restriction: n_col >= 0.
- Colamd returns FALSE if n_col is negative.
-
- int Alen ; Input argument.
-
- Restriction (see note):
- Alen >= 2*nnz + 6*(n_col+1) + 4*(n_row+1) + n_col
- Colamd returns FALSE if these conditions are not met.
-
- Note: this restriction makes an modest assumption regarding
- the size of the two typedef's structures in colamd.h.
- We do, however, guarantee that
-
- Alen >= colamd_recommended (nnz, n_row, n_col)
-
- will be sufficient. Note: the macro version does not check
- for integer overflow, and thus is not recommended. Use
- the colamd_recommended routine instead.
-
- int A [Alen] ; Input argument, undefined on output.
-
- A is an integer array of size Alen. Alen must be at least as
- large as the bare minimum value given above, but this is very
- low, and can result in excessive run time. For best
- performance, we recommend that Alen be greater than or equal to
- colamd_recommended (nnz, n_row, n_col), which adds
- nnz/5 to the bare minimum value given above.
-
- On input, the row indices of the entries in column c of the
- matrix are held in A [(p [c]) ... (p [c+1]-1)]. The row indices
- in a given column c need not be in ascending order, and
- duplicate row indices may be be present. However, colamd will
- work a little faster if both of these conditions are met
- (Colamd puts the matrix into this format, if it finds that the
- the conditions are not met).
-
- The matrix is 0-based. That is, rows are in the range 0 to
- n_row-1, and columns are in the range 0 to n_col-1. Colamd
- returns FALSE if any row index is out of range.
-
- The contents of A are modified during ordering, and are
- undefined on output.
-
- int p [n_col+1] ; Both input and output argument.
-
- p is an integer array of size n_col+1. On input, it holds the
- "pointers" for the column form of the matrix A. Column c of
- the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first
- entry, p [0], must be zero, and p [c] <= p [c+1] must hold
- for all c in the range 0 to n_col-1. The value p [n_col] is
- thus the total number of entries in the pattern of the matrix A.
- Colamd returns FALSE if these conditions are not met.
-
- On output, if colamd returns TRUE, the array p holds the column
- permutation (Q, for P(AQ)=LU or (AQ)'(AQ)=LL'), where p [0] is
- the first column index in the new ordering, and p [n_col-1] is
- the last. That is, p [k] = j means that column j of A is the
- kth pivot column, in AQ, where k is in the range 0 to n_col-1
- (p [0] = j means that column j of A is the first column in AQ).
-
- If colamd returns FALSE, then no permutation is returned, and
- p is undefined on output.
-
- double knobs [COLAMD_KNOBS] ; Input argument.
-
- See colamd_set_defaults for a description.
-
- int stats [COLAMD_STATS] ; Output argument.
-
- Statistics on the ordering, and error status.
- See colamd.h for related definitions.
- Colamd returns FALSE if stats is not present.
-
- stats [0]: number of dense or empty rows ignored.
-
- stats [1]: number of dense or empty columns ignored (and
- ordered last in the output permutation p)
- Note that a row can become "empty" if it
- contains only "dense" and/or "empty" columns,
- and similarly a column can become "empty" if it
- only contains "dense" and/or "empty" rows.
-
- stats [2]: number of garbage collections performed.
- This can be excessively high if Alen is close
- to the minimum required value.
-
- stats [3]: status code. < 0 is an error code.
- > 1 is a warning or notice.
-
- 0 OK. Each column of the input matrix contained
- row indices in increasing order, with no
- duplicates.
-
- 1 OK, but columns of input matrix were jumbled
- (unsorted columns or duplicate entries). Colamd
- had to do some extra work to sort the matrix
- first and remove duplicate entries, but it
- still was able to return a valid permutation
- (return value of colamd was TRUE).
-
- stats [4]: highest numbered column that
- is unsorted or has duplicate
- entries.
- stats [5]: last seen duplicate or
- unsorted row index.
- stats [6]: number of duplicate or
- unsorted row indices.
-
- -1 A is a null pointer
-
- -2 p is a null pointer
-
- -3 n_row is negative
-
- stats [4]: n_row
-
- -4 n_col is negative
-
- stats [4]: n_col
-
- -5 number of nonzeros in matrix is negative
-
- stats [4]: number of nonzeros, p [n_col]
-
- -6 p [0] is nonzero
-
- stats [4]: p [0]
-
- -7 A is too small
-
- stats [4]: required size
- stats [5]: actual size (Alen)
-
- -8 a column has a negative number of entries
-
- stats [4]: column with < 0 entries
- stats [5]: number of entries in col
-
- -9 a row index is out of bounds
-
- stats [4]: column with bad row index
- stats [5]: bad row index
- stats [6]: n_row, # of rows of matrx
-
- -10 (unused; see symamd.c)
-
- -999 (unused; see symamd.c)
-
- Future versions may return more statistics in the stats array.
-
- Example:
-
- See http://www.cise.ufl.edu/research/sparse/colamd/example.c
- for a complete example.
-
- To order the columns of a 5-by-4 matrix with 11 nonzero entries in
- the following nonzero pattern
-
- x 0 x 0
- x 0 x x
- 0 x x 0
- 0 0 x x
- x x 0 0
-
- with default knobs and no output statistics, do the following:
-
- #include "colamd.h"
- #define ALEN 100
- int A [ALEN] = {0, 1, 4, 2, 4, 0, 1, 2, 3, 1, 3} ;
- int p [ ] = {0, 3, 5, 9, 11} ;
- int stats [COLAMD_STATS] ;
- colamd (5, 4, ALEN, A, p, (double *) NULL, stats) ;
-
- The permutation is returned in the array p, and A is destroyed.
-
- ----------------------------------------------------------------------------
- symamd:
- ----------------------------------------------------------------------------
-
- C syntax:
-
- #include "colamd.h"
- int symamd (int n, int *A, int *p, int *perm,
- double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS],
- void (*allocate) (size_t, size_t), void (*release) (void *)) ;
- UF_long symamd_l (UF_long n, UF_long *A, UF_long *p, UF_long *perm,
- double knobs [COLAMD_KNOBS], UF_long stats [COLAMD_STATS],
- void (*allocate) (size_t, size_t), void (*release) (void *)) ;
-
- Purpose:
-
- The symamd routine computes an ordering P of a symmetric sparse
- matrix A such that the Cholesky factorization PAP' = LL' remains
- sparse. It is based on a column ordering of a matrix M constructed
- so that the nonzero pattern of M'M is the same as A. The matrix A
- is assumed to be symmetric; only the strictly lower triangular part
- is accessed. You must pass your selected memory allocator (usually
- calloc/free or mxCalloc/mxFree) to symamd, for it to allocate
- memory for the temporary matrix M.
-
- Returns:
-
- TRUE (1) if successful, FALSE (0) otherwise.
-
- Arguments:
-
- int n ; Input argument.
-
- Number of rows and columns in the symmetrix matrix A.
- Restriction: n >= 0.
- Symamd returns FALSE if n is negative.
-
- int A [nnz] ; Input argument.
-
- A is an integer array of size nnz, where nnz = p [n].
-
- The row indices of the entries in column c of the matrix are
- held in A [(p [c]) ... (p [c+1]-1)]. The row indices in a
- given column c need not be in ascending order, and duplicate
- row indices may be present. However, symamd will run faster
- if the columns are in sorted order with no duplicate entries.
-
- The matrix is 0-based. That is, rows are in the range 0 to
- n-1, and columns are in the range 0 to n-1. Symamd
- returns FALSE if any row index is out of range.
-
- The contents of A are not modified.
-
- int p [n+1] ; Input argument.
-
- p is an integer array of size n+1. On input, it holds the
- "pointers" for the column form of the matrix A. Column c of
- the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first
- entry, p [0], must be zero, and p [c] <= p [c+1] must hold
- for all c in the range 0 to n-1. The value p [n] is
- thus the total number of entries in the pattern of the matrix A.
- Symamd returns FALSE if these conditions are not met.
-
- The contents of p are not modified.
-
- int perm [n+1] ; Output argument.
-
- On output, if symamd returns TRUE, the array perm holds the
- permutation P, where perm [0] is the first index in the new
- ordering, and perm [n-1] is the last. That is, perm [k] = j
- means that row and column j of A is the kth column in PAP',
- where k is in the range 0 to n-1 (perm [0] = j means
- that row and column j of A are the first row and column in
- PAP'). The array is used as a workspace during the ordering,
- which is why it must be of length n+1, not just n.
-
- double knobs [COLAMD_KNOBS] ; Input argument.
-
- See colamd_set_defaults for a description.
-
- int stats [COLAMD_STATS] ; Output argument.
-
- Statistics on the ordering, and error status.
- See colamd.h for related definitions.
- Symamd returns FALSE if stats is not present.
-
- stats [0]: number of dense or empty row and columns ignored
- (and ordered last in the output permutation
- perm). Note that a row/column can become
- "empty" if it contains only "dense" and/or
- "empty" columns/rows.
-
- stats [1]: (same as stats [0])
-
- stats [2]: number of garbage collections performed.
-
- stats [3]: status code. < 0 is an error code.
- > 1 is a warning or notice.
-
- 0 OK. Each column of the input matrix contained
- row indices in increasing order, with no
- duplicates.
-
- 1 OK, but columns of input matrix were jumbled
- (unsorted columns or duplicate entries). Symamd
- had to do some extra work to sort the matrix
- first and remove duplicate entries, but it
- still was able to return a valid permutation
- (return value of symamd was TRUE).
-
- stats [4]: highest numbered column that
- is unsorted or has duplicate
- entries.
- stats [5]: last seen duplicate or
- unsorted row index.
- stats [6]: number of duplicate or
- unsorted row indices.
-
- -1 A is a null pointer
-
- -2 p is a null pointer
-
- -3 (unused, see colamd.c)
-
- -4 n is negative
-
- stats [4]: n
-
- -5 number of nonzeros in matrix is negative
-
- stats [4]: # of nonzeros (p [n]).
-
- -6 p [0] is nonzero
-
- stats [4]: p [0]
-
- -7 (unused)
-
- -8 a column has a negative number of entries
-
- stats [4]: column with < 0 entries
- stats [5]: number of entries in col
-
- -9 a row index is out of bounds
-
- stats [4]: column with bad row index
- stats [5]: bad row index
- stats [6]: n_row, # of rows of matrx
-
- -10 out of memory (unable to allocate temporary
- workspace for M or count arrays using the
- "allocate" routine passed into symamd).
-
- Future versions may return more statistics in the stats array.
-
- void * (*allocate) (size_t, size_t)
-
- A pointer to a function providing memory allocation. The
- allocated memory must be returned initialized to zero. For a
- C application, this argument should normally be a pointer to
- calloc. For a MATLAB mexFunction, the routine mxCalloc is
- passed instead.
-
- void (*release) (size_t, size_t)
-
- A pointer to a function that frees memory allocated by the
- memory allocation routine above. For a C application, this
- argument should normally be a pointer to free. For a MATLAB
- mexFunction, the routine mxFree is passed instead.
-
-
- ----------------------------------------------------------------------------
- colamd_report:
- ----------------------------------------------------------------------------
-
- C syntax:
-
- #include "colamd.h"
- colamd_report (int stats [COLAMD_STATS]) ;
- colamd_l_report (UF_long stats [COLAMD_STATS]) ;
-
- Purpose:
-
- Prints the error status and statistics recorded in the stats
- array on the standard error output (for a standard C routine)
- or on the MATLAB output (for a mexFunction).
-
- Arguments:
-
- int stats [COLAMD_STATS] ; Input only. Statistics from colamd.
-
-
- ----------------------------------------------------------------------------
- symamd_report:
- ----------------------------------------------------------------------------
-
- C syntax:
-
- #include "colamd.h"
- symamd_report (int stats [COLAMD_STATS]) ;
- symamd_l_report (UF_long stats [COLAMD_STATS]) ;
-
- Purpose:
-
- Prints the error status and statistics recorded in the stats
- array on the standard error output (for a standard C routine)
- or on the MATLAB output (for a mexFunction).
-
- Arguments:
-
- int stats [COLAMD_STATS] ; Input only. Statistics from symamd.
-
-
-*/
-
-/* ========================================================================== */
-/* === Scaffolding code definitions ======================================== */
-/* ========================================================================== */
-
-/* Ensure that debugging is turned off: */
-#ifndef NDEBUG
-#define NDEBUG
-#endif
-
-/* turn on debugging by uncommenting the following line
- #undef NDEBUG
-*/
-
-/*
- Our "scaffolding code" philosophy: In our opinion, well-written library
- code should keep its "debugging" code, and just normally have it turned off
- by the compiler so as not to interfere with performance. This serves
- several purposes:
-
- (1) assertions act as comments to the reader, telling you what the code
- expects at that point. All assertions will always be true (unless
- there really is a bug, of course).
-
- (2) leaving in the scaffolding code assists anyone who would like to modify
- the code, or understand the algorithm (by reading the debugging output,
- one can get a glimpse into what the code is doing).
-
- (3) (gasp!) for actually finding bugs. This code has been heavily tested
- and "should" be fully functional and bug-free ... but you never know...
-
- The code will become outrageously slow when debugging is
- enabled. To control the level of debugging output, set an environment
- variable D to 0 (little), 1 (some), 2, 3, or 4 (lots). When debugging,
- you should see the following message on the standard output:
-
- colamd: debug version, D = 1 (THIS WILL BE SLOW!)
-
- or a similar message for symamd. If you don't, then debugging has not
- been enabled.
-
-*/
-
-/* ========================================================================== */
-/* === Include files ======================================================== */
-/* ========================================================================== */
-
-#include "colamd.h"
-#include <limits.h>
-#include <math.h>
-
-#ifdef MATLAB_MEX_FILE
-#include "mex.h"
-#include "matrix.h"
-#endif /* MATLAB_MEX_FILE */
-
-#if !defined (NPRINT) || !defined (NDEBUG)
-#include <stdio.h>
-#endif
-
-#ifndef NULL
-#define NULL ((void *) 0)
-#endif
-
-/* ========================================================================== */
-/* === int or UF_long ======================================================= */
-/* ========================================================================== */
-
-/* define UF_long */
-#include "UFconfig.h"
-
-#ifdef DLONG
-
-#define Int UF_long
-#define ID UF_long_id
-#define Int_MAX UF_long_max
-
-#define COLAMD_recommended colamd_l_recommended
-#define COLAMD_set_defaults colamd_l_set_defaults
-#define COLAMD_MAIN colamd_l
-#define SYMAMD_MAIN symamd_l
-#define COLAMD_report colamd_l_report
-#define SYMAMD_report symamd_l_report
-
-#else
-
-#define Int int
-#define ID "%d"
-#define Int_MAX INT_MAX
-
-#define COLAMD_recommended colamd_recommended
-#define COLAMD_set_defaults colamd_set_defaults
-#define COLAMD_MAIN colamd
-#define SYMAMD_MAIN symamd
-#define COLAMD_report colamd_report
-#define SYMAMD_report symamd_report
-
-#endif
-
-/* ========================================================================== */
-/* === Row and Column structures ============================================ */
-/* ========================================================================== */
-
-/* User code that makes use of the colamd/symamd routines need not directly */
-/* reference these structures. They are used only for colamd_recommended. */
-
-typedef struct Colamd_Col_struct
-{
- Int start ; /* index for A of first row in this column, or DEAD */
- /* if column is dead */
- Int length ; /* number of rows in this column */
- union
- {
- Int thickness ; /* number of original columns represented by this */
- /* col, if the column is alive */
- Int parent ; /* parent in parent tree super-column structure, if */
- /* the column is dead */
- } shared1 ;
- union
- {
- Int score ; /* the score used to maintain heap, if col is alive */
- Int order ; /* pivot ordering of this column, if col is dead */
- } shared2 ;
- union
- {
- Int headhash ; /* head of a hash bucket, if col is at the head of */
- /* a degree list */
- Int hash ; /* hash value, if col is not in a degree list */
- Int prev ; /* previous column in degree list, if col is in a */
- /* degree list (but not at the head of a degree list) */
- } shared3 ;
- union
- {
- Int degree_next ; /* next column, if col is in a degree list */
- Int hash_next ; /* next column, if col is in a hash list */
- } shared4 ;
-
-} Colamd_Col ;
-
-typedef struct Colamd_Row_struct
-{
- Int start ; /* index for A of first col in this row */
- Int length ; /* number of principal columns in this row */
- union
- {
- Int degree ; /* number of principal & non-principal columns in row */
- Int p ; /* used as a row pointer in init_rows_cols () */
- } shared1 ;
- union
- {
- Int mark ; /* for computing set differences and marking dead rows*/
- Int first_column ;/* first column in row (used in garbage collection) */
- } shared2 ;
-
-} Colamd_Row ;
-
-/* ========================================================================== */
-/* === Definitions ========================================================== */
-/* ========================================================================== */
-
-/* Routines are either PUBLIC (user-callable) or PRIVATE (not user-callable) */
-#define PUBLIC
-#define PRIVATE static
-
-#define DENSE_DEGREE(alpha,n) \
- ((Int) MAX (16.0, (alpha) * sqrt ((double) (n))))
-
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-
-#define ONES_COMPLEMENT(r) (-(r)-1)
-
-/* -------------------------------------------------------------------------- */
-/* Change for version 2.1: define TRUE and FALSE only if not yet defined */
-/* -------------------------------------------------------------------------- */
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-/* -------------------------------------------------------------------------- */
-
-#define EMPTY (-1)
-
-/* Row and column status */
-#define ALIVE (0)
-#define DEAD (-1)
-
-/* Column status */
-#define DEAD_PRINCIPAL (-1)
-#define DEAD_NON_PRINCIPAL (-2)
-
-/* Macros for row and column status update and checking. */
-#define ROW_IS_DEAD(r) ROW_IS_MARKED_DEAD (Row[r].shared2.mark)
-#define ROW_IS_MARKED_DEAD(row_mark) (row_mark < ALIVE)
-#define ROW_IS_ALIVE(r) (Row [r].shared2.mark >= ALIVE)
-#define COL_IS_DEAD(c) (Col [c].start < ALIVE)
-#define COL_IS_ALIVE(c) (Col [c].start >= ALIVE)
-#define COL_IS_DEAD_PRINCIPAL(c) (Col [c].start == DEAD_PRINCIPAL)
-#define KILL_ROW(r) { Row [r].shared2.mark = DEAD ; }
-#define KILL_PRINCIPAL_COL(c) { Col [c].start = DEAD_PRINCIPAL ; }
-#define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; }
-
-/* ========================================================================== */
-/* === Colamd reporting mechanism =========================================== */
-/* ========================================================================== */
-
-#if defined (MATLAB_MEX_FILE) || defined (MATHWORKS)
-/* In MATLAB, matrices are 1-based to the user, but 0-based internally */
-#define INDEX(i) ((i)+1)
-#else
-/* In C, matrices are 0-based and indices are reported as such in *_report */
-#define INDEX(i) (i)
-#endif
-
-/* All output goes through the PRINTF macro. */
-#define PRINTF(params) { if (colamd_printf != NULL) (void) colamd_printf params ; }
-
-/* ========================================================================== */
-/* === Prototypes of PRIVATE routines ======================================= */
-/* ========================================================================== */
-
-PRIVATE Int init_rows_cols
-(
- Int n_row,
- Int n_col,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int A [],
- Int p [],
- Int stats [COLAMD_STATS]
-) ;
-
-PRIVATE void init_scoring
-(
- Int n_row,
- Int n_col,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int A [],
- Int head [],
- double knobs [COLAMD_KNOBS],
- Int *p_n_row2,
- Int *p_n_col2,
- Int *p_max_deg
-) ;
-
-PRIVATE Int find_ordering
-(
- Int n_row,
- Int n_col,
- Int Alen,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int A [],
- Int head [],
- Int n_col2,
- Int max_deg,
- Int pfree,
- Int aggressive
-) ;
-
-PRIVATE void order_children
-(
- Int n_col,
- Colamd_Col Col [],
- Int p []
-) ;
-
-PRIVATE void detect_super_cols
-(
-
-#ifndef NDEBUG
- Int n_col,
- Colamd_Row Row [],
-#endif /* NDEBUG */
-
- Colamd_Col Col [],
- Int A [],
- Int head [],
- Int row_start,
- Int row_length
-) ;
-
-PRIVATE Int garbage_collection
-(
- Int n_row,
- Int n_col,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int A [],
- Int *pfree
-) ;
-
-PRIVATE Int clear_mark
-(
- Int tag_mark,
- Int max_mark,
- Int n_row,
- Colamd_Row Row []
-) ;
-
-PRIVATE void print_report
-(
- char *method,
- Int stats [COLAMD_STATS]
-) ;
-
-/* ========================================================================== */
-/* === Debugging prototypes and definitions ================================= */
-/* ========================================================================== */
-
-#ifndef NDEBUG
-
-#include <assert.h>
-
-/* colamd_debug is the *ONLY* global variable, and is only */
-/* present when debugging */
-
-PRIVATE Int colamd_debug = 0 ; /* debug print level */
-
-#define DEBUG0(params) { PRINTF (params) ; }
-#define DEBUG1(params) { if (colamd_debug >= 1) PRINTF (params) ; }
-#define DEBUG2(params) { if (colamd_debug >= 2) PRINTF (params) ; }
-#define DEBUG3(params) { if (colamd_debug >= 3) PRINTF (params) ; }
-#define DEBUG4(params) { if (colamd_debug >= 4) PRINTF (params) ; }
-
-#ifdef MATLAB_MEX_FILE
-#define ASSERT(expression) (mxAssert ((expression), ""))
-#else
-#define ASSERT(expression) (assert (expression))
-#endif /* MATLAB_MEX_FILE */
-
-PRIVATE void colamd_get_debug /* gets the debug print level from getenv */
-(
- char *method
-) ;
-
-PRIVATE void debug_deg_lists
-(
- Int n_row,
- Int n_col,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int head [],
- Int min_score,
- Int should,
- Int max_deg
-) ;
-
-PRIVATE void debug_mark
-(
- Int n_row,
- Colamd_Row Row [],
- Int tag_mark,
- Int max_mark
-) ;
-
-PRIVATE void debug_matrix
-(
- Int n_row,
- Int n_col,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int A []
-) ;
-
-PRIVATE void debug_structures
-(
- Int n_row,
- Int n_col,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int A [],
- Int n_col2
-) ;
-
-#else /* NDEBUG */
-
-/* === No debugging ========================================================= */
-
-#define DEBUG0(params) ;
-#define DEBUG1(params) ;
-#define DEBUG2(params) ;
-#define DEBUG3(params) ;
-#define DEBUG4(params) ;
-
-#define ASSERT(expression)
-
-#endif /* NDEBUG */
-
-/* ========================================================================== */
-/* === USER-CALLABLE ROUTINES: ============================================== */
-/* ========================================================================== */
-
-/* ========================================================================== */
-/* === colamd_recommended =================================================== */
-/* ========================================================================== */
-
-/*
- The colamd_recommended routine returns the suggested size for Alen. This
- value has been determined to provide good balance between the number of
- garbage collections and the memory requirements for colamd. If any
- argument is negative, or if integer overflow occurs, a 0 is returned as an
- error condition. 2*nnz space is required for the row and column
- indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is
- required for the Col and Row arrays, respectively, which are internal to
- colamd (roughly 6*n_col + 4*n_row). An additional n_col space is the
- minimal amount of "elbow room", and nnz/5 more space is recommended for
- run time efficiency.
-
- Alen is approximately 2.2*nnz + 7*n_col + 4*n_row + 10.
-
- This function is not needed when using symamd.
-*/
-
-/* add two values of type size_t, and check for integer overflow */
-static size_t t_add (size_t a, size_t b, int *ok)
-{
- (*ok) = (*ok) && ((a + b) >= MAX (a,b)) ;
- return ((*ok) ? (a + b) : 0) ;
-}
-
-/* compute a*k where k is a small integer, and check for integer overflow */
-static size_t t_mult (size_t a, size_t k, int *ok)
-{
- size_t i, s = 0 ;
- for (i = 0 ; i < k ; i++)
- {
- s = t_add (s, a, ok) ;
- }
- return (s) ;
-}
-
-/* size of the Col and Row structures */
-#define COLAMD_C(n_col,ok) \
- ((t_mult (t_add (n_col, 1, ok), sizeof (Colamd_Col), ok) / sizeof (Int)))
-
-#define COLAMD_R(n_row,ok) \
- ((t_mult (t_add (n_row, 1, ok), sizeof (Colamd_Row), ok) / sizeof (Int)))
-
-
-PUBLIC size_t COLAMD_recommended /* returns recommended value of Alen. */
-(
- /* === Parameters ======================================================= */
-
- Int nnz, /* number of nonzeros in A */
- Int n_row, /* number of rows in A */
- Int n_col /* number of columns in A */
-)
-{
- size_t s, c, r ;
- int ok = TRUE ;
- if (nnz < 0 || n_row < 0 || n_col < 0)
- {
- return (0) ;
- }
- s = t_mult (nnz, 2, &ok) ; /* 2*nnz */
- c = COLAMD_C (n_col, &ok) ; /* size of column structures */
- r = COLAMD_R (n_row, &ok) ; /* size of row structures */
- s = t_add (s, c, &ok) ;
- s = t_add (s, r, &ok) ;
- s = t_add (s, n_col, &ok) ; /* elbow room */
- s = t_add (s, nnz/5, &ok) ; /* elbow room */
- ok = ok && (s < Int_MAX) ;
- return (ok ? s : 0) ;
-}
-
-
-/* ========================================================================== */
-/* === colamd_set_defaults ================================================== */
-/* ========================================================================== */
-
-/*
- The colamd_set_defaults routine sets the default values of the user-
- controllable parameters for colamd and symamd:
-
- Colamd: rows with more than max (16, knobs [0] * sqrt (n_col))
- entries are removed prior to ordering. Columns with more than
- max (16, knobs [1] * sqrt (MIN (n_row,n_col))) entries are removed
- prior to ordering, and placed last in the output column ordering.
-
- Symamd: Rows and columns with more than max (16, knobs [0] * sqrt (n))
- entries are removed prior to ordering, and placed last in the
- output ordering.
-
- knobs [0] dense row control
-
- knobs [1] dense column control
-
- knobs [2] if nonzero, do aggresive absorption
-
- knobs [3..19] unused, but future versions might use this
-
-*/
-
-PUBLIC void COLAMD_set_defaults
-(
- /* === Parameters ======================================================= */
-
- double knobs [COLAMD_KNOBS] /* knob array */
-)
-{
- /* === Local variables ================================================== */
-
- Int i ;
-
- if (!knobs)
- {
- return ; /* no knobs to initialize */
- }
- for (i = 0 ; i < COLAMD_KNOBS ; i++)
- {
- knobs [i] = 0 ;
- }
- knobs [COLAMD_DENSE_ROW] = 10 ;
- knobs [COLAMD_DENSE_COL] = 10 ;
- knobs [COLAMD_AGGRESSIVE] = TRUE ; /* default: do aggressive absorption*/
-}
-
-
-/* ========================================================================== */
-/* === symamd =============================================================== */
-/* ========================================================================== */
-
-PUBLIC Int SYMAMD_MAIN /* return TRUE if OK, FALSE otherwise */
-(
- /* === Parameters ======================================================= */
-
- Int n, /* number of rows and columns of A */
- Int A [], /* row indices of A */
- Int p [], /* column pointers of A */
- Int perm [], /* output permutation, size n+1 */
- double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */
- Int stats [COLAMD_STATS], /* output statistics and error codes */
- void * (*allocate) (size_t, size_t),
- /* pointer to calloc (ANSI C) or */
- /* mxCalloc (for MATLAB mexFunction) */
- void (*release) (void *)
- /* pointer to free (ANSI C) or */
- /* mxFree (for MATLAB mexFunction) */
-)
-{
- /* === Local variables ================================================== */
-
- Int *count ; /* length of each column of M, and col pointer*/
- Int *mark ; /* mark array for finding duplicate entries */
- Int *M ; /* row indices of matrix M */
- size_t Mlen ; /* length of M */
- Int n_row ; /* number of rows in M */
- Int nnz ; /* number of entries in A */
- Int i ; /* row index of A */
- Int j ; /* column index of A */
- Int k ; /* row index of M */
- Int mnz ; /* number of nonzeros in M */
- Int pp ; /* index into a column of A */
- Int last_row ; /* last row seen in the current column */
- Int length ; /* number of nonzeros in a column */
-
- double cknobs [COLAMD_KNOBS] ; /* knobs for colamd */
- double default_knobs [COLAMD_KNOBS] ; /* default knobs for colamd */
-
-#ifndef NDEBUG
- colamd_get_debug ("symamd") ;
-#endif /* NDEBUG */
-
- /* === Check the input arguments ======================================== */
-
- if (!stats)
- {
- DEBUG0 (("symamd: stats not present\n")) ;
- return (FALSE) ;
- }
- for (i = 0 ; i < COLAMD_STATS ; i++)
- {
- stats [i] = 0 ;
- }
- stats [COLAMD_STATUS] = COLAMD_OK ;
- stats [COLAMD_INFO1] = -1 ;
- stats [COLAMD_INFO2] = -1 ;
-
- if (!A)
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ;
- DEBUG0 (("symamd: A not present\n")) ;
- return (FALSE) ;
- }
-
- if (!p) /* p is not present */
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ;
- DEBUG0 (("symamd: p not present\n")) ;
- return (FALSE) ;
- }
-
- if (n < 0) /* n must be >= 0 */
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ;
- stats [COLAMD_INFO1] = n ;
- DEBUG0 (("symamd: n negative %d\n", n)) ;
- return (FALSE) ;
- }
-
- nnz = p [n] ;
- if (nnz < 0) /* nnz must be >= 0 */
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ;
- stats [COLAMD_INFO1] = nnz ;
- DEBUG0 (("symamd: number of entries negative %d\n", nnz)) ;
- return (FALSE) ;
- }
-
- if (p [0] != 0)
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ;
- stats [COLAMD_INFO1] = p [0] ;
- DEBUG0 (("symamd: p[0] not zero %d\n", p [0])) ;
- return (FALSE) ;
- }
-
- /* === If no knobs, set default knobs =================================== */
-
- if (!knobs)
- {
- COLAMD_set_defaults (default_knobs) ;
- knobs = default_knobs ;
- }
-
- /* === Allocate count and mark ========================================== */
-
- count = (Int *) ((*allocate) (n+1, sizeof (Int))) ;
- if (!count)
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ;
- DEBUG0 (("symamd: allocate count (size %d) failed\n", n+1)) ;
- return (FALSE) ;
- }
-
- mark = (Int *) ((*allocate) (n+1, sizeof (Int))) ;
- if (!mark)
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ;
- (*release) ((void *) count) ;
- DEBUG0 (("symamd: allocate mark (size %d) failed\n", n+1)) ;
- return (FALSE) ;
- }
-
- /* === Compute column counts of M, check if A is valid ================== */
-
- stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/
-
- for (i = 0 ; i < n ; i++)
- {
- mark [i] = -1 ;
- }
-
- for (j = 0 ; j < n ; j++)
- {
- last_row = -1 ;
-
- length = p [j+1] - p [j] ;
- if (length < 0)
- {
- /* column pointers must be non-decreasing */
- stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;
- stats [COLAMD_INFO1] = j ;
- stats [COLAMD_INFO2] = length ;
- (*release) ((void *) count) ;
- (*release) ((void *) mark) ;
- DEBUG0 (("symamd: col %d negative length %d\n", j, length)) ;
- return (FALSE) ;
- }
-
- for (pp = p [j] ; pp < p [j+1] ; pp++)
- {
- i = A [pp] ;
- if (i < 0 || i >= n)
- {
- /* row index i, in column j, is out of bounds */
- stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ;
- stats [COLAMD_INFO1] = j ;
- stats [COLAMD_INFO2] = i ;
- stats [COLAMD_INFO3] = n ;
- (*release) ((void *) count) ;
- (*release) ((void *) mark) ;
- DEBUG0 (("symamd: row %d col %d out of bounds\n", i, j)) ;
- return (FALSE) ;
- }
-
- if (i <= last_row || mark [i] == j)
- {
- /* row index is unsorted or repeated (or both), thus col */
- /* is jumbled. This is a notice, not an error condition. */
- stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ;
- stats [COLAMD_INFO1] = j ;
- stats [COLAMD_INFO2] = i ;
- (stats [COLAMD_INFO3]) ++ ;
- DEBUG1 (("symamd: row %d col %d unsorted/duplicate\n", i, j)) ;
- }
-
- if (i > j && mark [i] != j)
- {
- /* row k of M will contain column indices i and j */
- count [i]++ ;
- count [j]++ ;
- }
-
- /* mark the row as having been seen in this column */
- mark [i] = j ;
-
- last_row = i ;
- }
- }
-
- /* v2.4: removed free(mark) */
-
- /* === Compute column pointers of M ===================================== */
-
- /* use output permutation, perm, for column pointers of M */
- perm [0] = 0 ;
- for (j = 1 ; j <= n ; j++)
- {
- perm [j] = perm [j-1] + count [j-1] ;
- }
- for (j = 0 ; j < n ; j++)
- {
- count [j] = perm [j] ;
- }
-
- /* === Construct M ====================================================== */
-
- mnz = perm [n] ;
- n_row = mnz / 2 ;
- Mlen = COLAMD_recommended (mnz, n_row, n) ;
- M = (Int *) ((*allocate) (Mlen, sizeof (Int))) ;
- DEBUG0 (("symamd: M is %d-by-%d with %d entries, Mlen = %g\n",
- n_row, n, mnz, (double) Mlen)) ;
-
- if (!M)
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ;
- (*release) ((void *) count) ;
- (*release) ((void *) mark) ;
- DEBUG0 (("symamd: allocate M (size %g) failed\n", (double) Mlen)) ;
- return (FALSE) ;
- }
-
- k = 0 ;
-
- if (stats [COLAMD_STATUS] == COLAMD_OK)
- {
- /* Matrix is OK */
- for (j = 0 ; j < n ; j++)
- {
- ASSERT (p [j+1] - p [j] >= 0) ;
- for (pp = p [j] ; pp < p [j+1] ; pp++)
- {
- i = A [pp] ;
- ASSERT (i >= 0 && i < n) ;
- if (i > j)
- {
- /* row k of M contains column indices i and j */
- M [count [i]++] = k ;
- M [count [j]++] = k ;
- k++ ;
- }
- }
- }
- }
- else
- {
- /* Matrix is jumbled. Do not add duplicates to M. Unsorted cols OK. */
- DEBUG0 (("symamd: Duplicates in A.\n")) ;
- for (i = 0 ; i < n ; i++)
- {
- mark [i] = -1 ;
- }
- for (j = 0 ; j < n ; j++)
- {
- ASSERT (p [j+1] - p [j] >= 0) ;
- for (pp = p [j] ; pp < p [j+1] ; pp++)
- {
- i = A [pp] ;
- ASSERT (i >= 0 && i < n) ;
- if (i > j && mark [i] != j)
- {
- /* row k of M contains column indices i and j */
- M [count [i]++] = k ;
- M [count [j]++] = k ;
- k++ ;
- mark [i] = j ;
- }
- }
- }
- /* v2.4: free(mark) moved below */
- }
-
- /* count and mark no longer needed */
- (*release) ((void *) count) ;
- (*release) ((void *) mark) ; /* v2.4: free (mark) moved here */
- ASSERT (k == n_row) ;
-
- /* === Adjust the knobs for M =========================================== */
-
- for (i = 0 ; i < COLAMD_KNOBS ; i++)
- {
- cknobs [i] = knobs [i] ;
- }
-
- /* there are no dense rows in M */
- cknobs [COLAMD_DENSE_ROW] = -1 ;
- cknobs [COLAMD_DENSE_COL] = knobs [COLAMD_DENSE_ROW] ;
-
- /* === Order the columns of M =========================================== */
-
- /* v2.4: colamd cannot fail here, so the error check is removed */
- (void) COLAMD_MAIN (n_row, n, (Int) Mlen, M, perm, cknobs, stats) ;
-
- /* Note that the output permutation is now in perm */
-
- /* === get the statistics for symamd from colamd ======================== */
-
- /* a dense column in colamd means a dense row and col in symamd */
- stats [COLAMD_DENSE_ROW] = stats [COLAMD_DENSE_COL] ;
-
- /* === Free M =========================================================== */
-
- (*release) ((void *) M) ;
- DEBUG0 (("symamd: done.\n")) ;
- return (TRUE) ;
-
-}
-
-/* ========================================================================== */
-/* === colamd =============================================================== */
-/* ========================================================================== */
-
-/*
- The colamd routine computes a column ordering Q of a sparse matrix
- A such that the LU factorization P(AQ) = LU remains sparse, where P is
- selected via partial pivoting. The routine can also be viewed as
- providing a permutation Q such that the Cholesky factorization
- (AQ)'(AQ) = LL' remains sparse.
-*/
-
-PUBLIC Int COLAMD_MAIN /* returns TRUE if successful, FALSE otherwise*/
-(
- /* === Parameters ======================================================= */
-
- Int n_row, /* number of rows in A */
- Int n_col, /* number of columns in A */
- Int Alen, /* length of A */
- Int A [], /* row indices of A */
- Int p [], /* pointers to columns in A */
- double knobs [COLAMD_KNOBS],/* parameters (uses defaults if NULL) */
- Int stats [COLAMD_STATS] /* output statistics and error codes */
-)
-{
- /* === Local variables ================================================== */
-
- Int i ; /* loop index */
- Int nnz ; /* nonzeros in A */
- size_t Row_size ; /* size of Row [], in integers */
- size_t Col_size ; /* size of Col [], in integers */
- size_t need ; /* minimum required length of A */
- Colamd_Row *Row ; /* pointer into A of Row [0..n_row] array */
- Colamd_Col *Col ; /* pointer into A of Col [0..n_col] array */
- Int n_col2 ; /* number of non-dense, non-empty columns */
- Int n_row2 ; /* number of non-dense, non-empty rows */
- Int ngarbage ; /* number of garbage collections performed */
- Int max_deg ; /* maximum row degree */
- double default_knobs [COLAMD_KNOBS] ; /* default knobs array */
- Int aggressive ; /* do aggressive absorption */
- int ok ;
-
-#ifndef NDEBUG
- colamd_get_debug ("colamd") ;
-#endif /* NDEBUG */
-
- /* === Check the input arguments ======================================== */
-
- if (!stats)
- {
- DEBUG0 (("colamd: stats not present\n")) ;
- return (FALSE) ;
- }
- for (i = 0 ; i < COLAMD_STATS ; i++)
- {
- stats [i] = 0 ;
- }
- stats [COLAMD_STATUS] = COLAMD_OK ;
- stats [COLAMD_INFO1] = -1 ;
- stats [COLAMD_INFO2] = -1 ;
-
- if (!A) /* A is not present */
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ;
- DEBUG0 (("colamd: A not present\n")) ;
- return (FALSE) ;
- }
-
- if (!p) /* p is not present */
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ;
- DEBUG0 (("colamd: p not present\n")) ;
- return (FALSE) ;
- }
-
- if (n_row < 0) /* n_row must be >= 0 */
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_nrow_negative ;
- stats [COLAMD_INFO1] = n_row ;
- DEBUG0 (("colamd: nrow negative %d\n", n_row)) ;
- return (FALSE) ;
- }
-
- if (n_col < 0) /* n_col must be >= 0 */
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ;
- stats [COLAMD_INFO1] = n_col ;
- DEBUG0 (("colamd: ncol negative %d\n", n_col)) ;
- return (FALSE) ;
- }
-
- nnz = p [n_col] ;
- if (nnz < 0) /* nnz must be >= 0 */
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ;
- stats [COLAMD_INFO1] = nnz ;
- DEBUG0 (("colamd: number of entries negative %d\n", nnz)) ;
- return (FALSE) ;
- }
-
- if (p [0] != 0)
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ;
- stats [COLAMD_INFO1] = p [0] ;
- DEBUG0 (("colamd: p[0] not zero %d\n", p [0])) ;
- return (FALSE) ;
- }
-
- /* === If no knobs, set default knobs =================================== */
-
- if (!knobs)
- {
- COLAMD_set_defaults (default_knobs) ;
- knobs = default_knobs ;
- }
-
- aggressive = (knobs [COLAMD_AGGRESSIVE] != FALSE) ;
-
- /* === Allocate the Row and Col arrays from array A ===================== */
-
- ok = TRUE ;
- Col_size = COLAMD_C (n_col, &ok) ; /* size of Col array of structs */
- Row_size = COLAMD_R (n_row, &ok) ; /* size of Row array of structs */
-
- /* need = 2*nnz + n_col + Col_size + Row_size ; */
- need = t_mult (nnz, 2, &ok) ;
- need = t_add (need, n_col, &ok) ;
- need = t_add (need, Col_size, &ok) ;
- need = t_add (need, Row_size, &ok) ;
-
- if (!ok || need > (size_t) Alen || need > Int_MAX)
- {
- /* not enough space in array A to perform the ordering */
- stats [COLAMD_STATUS] = COLAMD_ERROR_A_too_small ;
- stats [COLAMD_INFO1] = need ;
- stats [COLAMD_INFO2] = Alen ;
- DEBUG0 (("colamd: Need Alen >= %d, given only Alen = %d\n", need,Alen));
- return (FALSE) ;
- }
-
- Alen -= Col_size + Row_size ;
- Col = (Colamd_Col *) &A [Alen] ;
- Row = (Colamd_Row *) &A [Alen + Col_size] ;
-
- /* === Construct the row and column data structures ===================== */
-
- if (!init_rows_cols (n_row, n_col, Row, Col, A, p, stats))
- {
- /* input matrix is invalid */
- DEBUG0 (("colamd: Matrix invalid\n")) ;
- return (FALSE) ;
- }
-
- /* === Initialize scores, kill dense rows/columns ======================= */
-
- init_scoring (n_row, n_col, Row, Col, A, p, knobs,
- &n_row2, &n_col2, &max_deg) ;
-
- /* === Order the supercolumns =========================================== */
-
- ngarbage = find_ordering (n_row, n_col, Alen, Row, Col, A, p,
- n_col2, max_deg, 2*nnz, aggressive) ;
-
- /* === Order the non-principal columns ================================== */
-
- order_children (n_col, Col, p) ;
-
- /* === Return statistics in stats ======================================= */
-
- stats [COLAMD_DENSE_ROW] = n_row - n_row2 ;
- stats [COLAMD_DENSE_COL] = n_col - n_col2 ;
- stats [COLAMD_DEFRAG_COUNT] = ngarbage ;
- DEBUG0 (("colamd: done.\n")) ;
- return (TRUE) ;
-}
-
-
-/* ========================================================================== */
-/* === colamd_report ======================================================== */
-/* ========================================================================== */
-
-PUBLIC void COLAMD_report
-(
- Int stats [COLAMD_STATS]
-)
-{
- print_report ("colamd", stats) ;
-}
-
-
-/* ========================================================================== */
-/* === symamd_report ======================================================== */
-/* ========================================================================== */
-
-PUBLIC void SYMAMD_report
-(
- Int stats [COLAMD_STATS]
-)
-{
- print_report ("symamd", stats) ;
-}
-
-
-
-/* ========================================================================== */
-/* === NON-USER-CALLABLE ROUTINES: ========================================== */
-/* ========================================================================== */
-
-/* There are no user-callable routines beyond this point in the file */
-
-
-/* ========================================================================== */
-/* === init_rows_cols ======================================================= */
-/* ========================================================================== */
-
-/*
- Takes the column form of the matrix in A and creates the row form of the
- matrix. Also, row and column attributes are stored in the Col and Row
- structs. If the columns are un-sorted or contain duplicate row indices,
- this routine will also sort and remove duplicate row indices from the
- column form of the matrix. Returns FALSE if the matrix is invalid,
- TRUE otherwise. Not user-callable.
-*/
-
-PRIVATE Int init_rows_cols /* returns TRUE if OK, or FALSE otherwise */
-(
- /* === Parameters ======================================================= */
-
- Int n_row, /* number of rows of A */
- Int n_col, /* number of columns of A */
- Colamd_Row Row [], /* of size n_row+1 */
- Colamd_Col Col [], /* of size n_col+1 */
- Int A [], /* row indices of A, of size Alen */
- Int p [], /* pointers to columns in A, of size n_col+1 */
- Int stats [COLAMD_STATS] /* colamd statistics */
-)
-{
- /* === Local variables ================================================== */
-
- Int col ; /* a column index */
- Int row ; /* a row index */
- Int *cp ; /* a column pointer */
- Int *cp_end ; /* a pointer to the end of a column */
- Int *rp ; /* a row pointer */
- Int *rp_end ; /* a pointer to the end of a row */
- Int last_row ; /* previous row */
-
- /* === Initialize columns, and check column pointers ==================== */
-
- for (col = 0 ; col < n_col ; col++)
- {
- Col [col].start = p [col] ;
- Col [col].length = p [col+1] - p [col] ;
-
- if (Col [col].length < 0)
- {
- /* column pointers must be non-decreasing */
- stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;
- stats [COLAMD_INFO1] = col ;
- stats [COLAMD_INFO2] = Col [col].length ;
- DEBUG0 (("colamd: col %d length %d < 0\n", col, Col [col].length)) ;
- return (FALSE) ;
- }
-
- Col [col].shared1.thickness = 1 ;
- Col [col].shared2.score = 0 ;
- Col [col].shared3.prev = EMPTY ;
- Col [col].shared4.degree_next = EMPTY ;
- }
-
- /* p [0..n_col] no longer needed, used as "head" in subsequent routines */
-
- /* === Scan columns, compute row degrees, and check row indices ========= */
-
- stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/
-
- for (row = 0 ; row < n_row ; row++)
- {
- Row [row].length = 0 ;
- Row [row].shared2.mark = -1 ;
- }
-
- for (col = 0 ; col < n_col ; col++)
- {
- last_row = -1 ;
-
- cp = &A [p [col]] ;
- cp_end = &A [p [col+1]] ;
-
- while (cp < cp_end)
- {
- row = *cp++ ;
-
- /* make sure row indices within range */
- if (row < 0 || row >= n_row)
- {
- stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ;
- stats [COLAMD_INFO1] = col ;
- stats [COLAMD_INFO2] = row ;
- stats [COLAMD_INFO3] = n_row ;
- DEBUG0 (("colamd: row %d col %d out of bounds\n", row, col)) ;
- return (FALSE) ;
- }
-
- if (row <= last_row || Row [row].shared2.mark == col)
- {
- /* row index are unsorted or repeated (or both), thus col */
- /* is jumbled. This is a notice, not an error condition. */
- stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ;
- stats [COLAMD_INFO1] = col ;
- stats [COLAMD_INFO2] = row ;
- (stats [COLAMD_INFO3]) ++ ;
- DEBUG1 (("colamd: row %d col %d unsorted/duplicate\n",row,col));
- }
-
- if (Row [row].shared2.mark != col)
- {
- Row [row].length++ ;
- }
- else
- {
- /* this is a repeated entry in the column, */
- /* it will be removed */
- Col [col].length-- ;
- }
-
- /* mark the row as having been seen in this column */
- Row [row].shared2.mark = col ;
-
- last_row = row ;
- }
- }
-
- /* === Compute row pointers ============================================= */
-
- /* row form of the matrix starts directly after the column */
- /* form of matrix in A */
- Row [0].start = p [n_col] ;
- Row [0].shared1.p = Row [0].start ;
- Row [0].shared2.mark = -1 ;
- for (row = 1 ; row < n_row ; row++)
- {
- Row [row].start = Row [row-1].start + Row [row-1].length ;
- Row [row].shared1.p = Row [row].start ;
- Row [row].shared2.mark = -1 ;
- }
-
- /* === Create row form ================================================== */
-
- if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED)
- {
- /* if cols jumbled, watch for repeated row indices */
- for (col = 0 ; col < n_col ; col++)
- {
- cp = &A [p [col]] ;
- cp_end = &A [p [col+1]] ;
- while (cp < cp_end)
- {
- row = *cp++ ;
- if (Row [row].shared2.mark != col)
- {
- A [(Row [row].shared1.p)++] = col ;
- Row [row].shared2.mark = col ;
- }
- }
- }
- }
- else
- {
- /* if cols not jumbled, we don't need the mark (this is faster) */
- for (col = 0 ; col < n_col ; col++)
- {
- cp = &A [p [col]] ;
- cp_end = &A [p [col+1]] ;
- while (cp < cp_end)
- {
- A [(Row [*cp++].shared1.p)++] = col ;
- }
- }
- }
-
- /* === Clear the row marks and set row degrees ========================== */
-
- for (row = 0 ; row < n_row ; row++)
- {
- Row [row].shared2.mark = 0 ;
- Row [row].shared1.degree = Row [row].length ;
- }
-
- /* === See if we need to re-create columns ============================== */
-
- if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED)
- {
- DEBUG0 (("colamd: reconstructing column form, matrix jumbled\n")) ;
-
-#ifndef NDEBUG
- /* make sure column lengths are correct */
- for (col = 0 ; col < n_col ; col++)
- {
- p [col] = Col [col].length ;
- }
- for (row = 0 ; row < n_row ; row++)
- {
- rp = &A [Row [row].start] ;
- rp_end = rp + Row [row].length ;
- while (rp < rp_end)
- {
- p [*rp++]-- ;
- }
- }
- for (col = 0 ; col < n_col ; col++)
- {
- ASSERT (p [col] == 0) ;
- }
- /* now p is all zero (different than when debugging is turned off) */
-#endif /* NDEBUG */
-
- /* === Compute col pointers ========================================= */
-
- /* col form of the matrix starts at A [0]. */
- /* Note, we may have a gap between the col form and the row */
- /* form if there were duplicate entries, if so, it will be */
- /* removed upon the first garbage collection */
- Col [0].start = 0 ;
- p [0] = Col [0].start ;
- for (col = 1 ; col < n_col ; col++)
- {
- /* note that the lengths here are for pruned columns, i.e. */
- /* no duplicate row indices will exist for these columns */
- Col [col].start = Col [col-1].start + Col [col-1].length ;
- p [col] = Col [col].start ;
- }
-
- /* === Re-create col form =========================================== */
-
- for (row = 0 ; row < n_row ; row++)
- {
- rp = &A [Row [row].start] ;
- rp_end = rp + Row [row].length ;
- while (rp < rp_end)
- {
- A [(p [*rp++])++] = row ;
- }
- }
- }
-
- /* === Done. Matrix is not (or no longer) jumbled ====================== */
-
- return (TRUE) ;
-}
-
-
-/* ========================================================================== */
-/* === init_scoring ========================================================= */
-/* ========================================================================== */
-
-/*
- Kills dense or empty columns and rows, calculates an initial score for
- each column, and places all columns in the degree lists. Not user-callable.
-*/
-
-PRIVATE void init_scoring
-(
- /* === Parameters ======================================================= */
-
- Int n_row, /* number of rows of A */
- Int n_col, /* number of columns of A */
- Colamd_Row Row [], /* of size n_row+1 */
- Colamd_Col Col [], /* of size n_col+1 */
- Int A [], /* column form and row form of A */
- Int head [], /* of size n_col+1 */
- double knobs [COLAMD_KNOBS],/* parameters */
- Int *p_n_row2, /* number of non-dense, non-empty rows */
- Int *p_n_col2, /* number of non-dense, non-empty columns */
- Int *p_max_deg /* maximum row degree */
-)
-{
- /* === Local variables ================================================== */
-
- Int c ; /* a column index */
- Int r, row ; /* a row index */
- Int *cp ; /* a column pointer */
- Int deg ; /* degree of a row or column */
- Int *cp_end ; /* a pointer to the end of a column */
- Int *new_cp ; /* new column pointer */
- Int col_length ; /* length of pruned column */
- Int score ; /* current column score */
- Int n_col2 ; /* number of non-dense, non-empty columns */
- Int n_row2 ; /* number of non-dense, non-empty rows */
- Int dense_row_count ; /* remove rows with more entries than this */
- Int dense_col_count ; /* remove cols with more entries than this */
- Int min_score ; /* smallest column score */
- Int max_deg ; /* maximum row degree */
- Int next_col ; /* Used to add to degree list.*/
-
-#ifndef NDEBUG
- Int debug_count ; /* debug only. */
-#endif /* NDEBUG */
-
- /* === Extract knobs ==================================================== */
-
- /* Note: if knobs contains a NaN, this is undefined: */
- if (knobs [COLAMD_DENSE_ROW] < 0)
- {
- /* only remove completely dense rows */
- dense_row_count = n_col-1 ;
- }
- else
- {
- dense_row_count = DENSE_DEGREE (knobs [COLAMD_DENSE_ROW], n_col) ;
- }
- if (knobs [COLAMD_DENSE_COL] < 0)
- {
- /* only remove completely dense columns */
- dense_col_count = n_row-1 ;
- }
- else
- {
- dense_col_count =
- DENSE_DEGREE (knobs [COLAMD_DENSE_COL], MIN (n_row, n_col)) ;
- }
-
- DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
- max_deg = 0 ;
- n_col2 = n_col ;
- n_row2 = n_row ;
-
- /* === Kill empty columns =============================================== */
-
- /* Put the empty columns at the end in their natural order, so that LU */
- /* factorization can proceed as far as possible. */
- for (c = n_col-1 ; c >= 0 ; c--)
- {
- deg = Col [c].length ;
- if (deg == 0)
- {
- /* this is a empty column, kill and order it last */
- Col [c].shared2.order = --n_col2 ;
- KILL_PRINCIPAL_COL (c) ;
- }
- }
- DEBUG1 (("colamd: null columns killed: %d\n", n_col - n_col2)) ;
-
- /* === Kill dense columns =============================================== */
-
- /* Put the dense columns at the end, in their natural order */
- for (c = n_col-1 ; c >= 0 ; c--)
- {
- /* skip any dead columns */
- if (COL_IS_DEAD (c))
- {
- continue ;
- }
- deg = Col [c].length ;
- if (deg > dense_col_count)
- {
- /* this is a dense column, kill and order it last */
- Col [c].shared2.order = --n_col2 ;
- /* decrement the row degrees */
- cp = &A [Col [c].start] ;
- cp_end = cp + Col [c].length ;
- while (cp < cp_end)
- {
- Row [*cp++].shared1.degree-- ;
- }
- KILL_PRINCIPAL_COL (c) ;
- }
- }
- DEBUG1 (("colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ;
-
- /* === Kill dense and empty rows ======================================== */
-
- for (r = 0 ; r < n_row ; r++)
- {
- deg = Row [r].shared1.degree ;
- ASSERT (deg >= 0 && deg <= n_col) ;
- if (deg > dense_row_count || deg == 0)
- {
- /* kill a dense or empty row */
- KILL_ROW (r) ;
- --n_row2 ;
- }
- else
- {
- /* keep track of max degree of remaining rows */
- max_deg = MAX (max_deg, deg) ;
- }
- }
- DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
-
- /* === Compute initial column scores ==================================== */
-
- /* At this point the row degrees are accurate. They reflect the number */
- /* of "live" (non-dense) columns in each row. No empty rows exist. */
- /* Some "live" columns may contain only dead rows, however. These are */
- /* pruned in the code below. */
-
- /* now find the initial matlab score for each column */
- for (c = n_col-1 ; c >= 0 ; c--)
- {
- /* skip dead column */
- if (COL_IS_DEAD (c))
- {
- continue ;
- }
- score = 0 ;
- cp = &A [Col [c].start] ;
- new_cp = cp ;
- cp_end = cp + Col [c].length ;
- while (cp < cp_end)
- {
- /* get a row */
- row = *cp++ ;
- /* skip if dead */
- if (ROW_IS_DEAD (row))
- {
- continue ;
- }
- /* compact the column */
- *new_cp++ = row ;
- /* add row's external degree */
- score += Row [row].shared1.degree - 1 ;
- /* guard against integer overflow */
- score = MIN (score, n_col) ;
- }
- /* determine pruned column length */
- col_length = (Int) (new_cp - &A [Col [c].start]) ;
- if (col_length == 0)
- {
- /* a newly-made null column (all rows in this col are "dense" */
- /* and have already been killed) */
- DEBUG2 (("Newly null killed: %d\n", c)) ;
- Col [c].shared2.order = --n_col2 ;
- KILL_PRINCIPAL_COL (c) ;
- }
- else
- {
- /* set column length and set score */
- ASSERT (score >= 0) ;
- ASSERT (score <= n_col) ;
- Col [c].length = col_length ;
- Col [c].shared2.score = score ;
- }
- }
- DEBUG1 (("colamd: Dense, null, and newly-null columns killed: %d\n",
- n_col-n_col2)) ;
-
- /* At this point, all empty rows and columns are dead. All live columns */
- /* are "clean" (containing no dead rows) and simplicial (no supercolumns */
- /* yet). Rows may contain dead columns, but all live rows contain at */
- /* least one live column. */
-
-#ifndef NDEBUG
- debug_structures (n_row, n_col, Row, Col, A, n_col2) ;
-#endif /* NDEBUG */
-
- /* === Initialize degree lists ========================================== */
-
-#ifndef NDEBUG
- debug_count = 0 ;
-#endif /* NDEBUG */
-
- /* clear the hash buckets */
- for (c = 0 ; c <= n_col ; c++)
- {
- head [c] = EMPTY ;
- }
- min_score = n_col ;
- /* place in reverse order, so low column indices are at the front */
- /* of the lists. This is to encourage natural tie-breaking */
- for (c = n_col-1 ; c >= 0 ; c--)
- {
- /* only add principal columns to degree lists */
- if (COL_IS_ALIVE (c))
- {
- DEBUG4 (("place %d score %d minscore %d ncol %d\n",
- c, Col [c].shared2.score, min_score, n_col)) ;
-
- /* === Add columns score to DList =============================== */
-
- score = Col [c].shared2.score ;
-
- ASSERT (min_score >= 0) ;
- ASSERT (min_score <= n_col) ;
- ASSERT (score >= 0) ;
- ASSERT (score <= n_col) ;
- ASSERT (head [score] >= EMPTY) ;
-
- /* now add this column to dList at proper score location */
- next_col = head [score] ;
- Col [c].shared3.prev = EMPTY ;
- Col [c].shared4.degree_next = next_col ;
-
- /* if there already was a column with the same score, set its */
- /* previous pointer to this new column */
- if (next_col != EMPTY)
- {
- Col [next_col].shared3.prev = c ;
- }
- head [score] = c ;
-
- /* see if this score is less than current min */
- min_score = MIN (min_score, score) ;
-
-#ifndef NDEBUG
- debug_count++ ;
-#endif /* NDEBUG */
-
- }
- }
-
-#ifndef NDEBUG
- DEBUG1 (("colamd: Live cols %d out of %d, non-princ: %d\n",
- debug_count, n_col, n_col-debug_count)) ;
- ASSERT (debug_count == n_col2) ;
- debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2, max_deg) ;
-#endif /* NDEBUG */
-
- /* === Return number of remaining columns, and max row degree =========== */
-
- *p_n_col2 = n_col2 ;
- *p_n_row2 = n_row2 ;
- *p_max_deg = max_deg ;
-}
-
-
-/* ========================================================================== */
-/* === find_ordering ======================================================== */
-/* ========================================================================== */
-
-/*
- Order the principal columns of the supercolumn form of the matrix
- (no supercolumns on input). Uses a minimum approximate column minimum
- degree ordering method. Not user-callable.
-*/
-
-PRIVATE Int find_ordering /* return the number of garbage collections */
-(
- /* === Parameters ======================================================= */
-
- Int n_row, /* number of rows of A */
- Int n_col, /* number of columns of A */
- Int Alen, /* size of A, 2*nnz + n_col or larger */
- Colamd_Row Row [], /* of size n_row+1 */
- Colamd_Col Col [], /* of size n_col+1 */
- Int A [], /* column form and row form of A */
- Int head [], /* of size n_col+1 */
- Int n_col2, /* Remaining columns to order */
- Int max_deg, /* Maximum row degree */
- Int pfree, /* index of first free slot (2*nnz on entry) */
- Int aggressive
-)
-{
- /* === Local variables ================================================== */
-
- Int k ; /* current pivot ordering step */
- Int pivot_col ; /* current pivot column */
- Int *cp ; /* a column pointer */
- Int *rp ; /* a row pointer */
- Int pivot_row ; /* current pivot row */
- Int *new_cp ; /* modified column pointer */
- Int *new_rp ; /* modified row pointer */
- Int pivot_row_start ; /* pointer to start of pivot row */
- Int pivot_row_degree ; /* number of columns in pivot row */
- Int pivot_row_length ; /* number of supercolumns in pivot row */
- Int pivot_col_score ; /* score of pivot column */
- Int needed_memory ; /* free space needed for pivot row */
- Int *cp_end ; /* pointer to the end of a column */
- Int *rp_end ; /* pointer to the end of a row */
- Int row ; /* a row index */
- Int col ; /* a column index */
- Int max_score ; /* maximum possible score */
- Int cur_score ; /* score of current column */
- unsigned Int hash ; /* hash value for supernode detection */
- Int head_column ; /* head of hash bucket */
- Int first_col ; /* first column in hash bucket */
- Int tag_mark ; /* marker value for mark array */
- Int row_mark ; /* Row [row].shared2.mark */
- Int set_difference ; /* set difference size of row with pivot row */
- Int min_score ; /* smallest column score */
- Int col_thickness ; /* "thickness" (no. of columns in a supercol) */
- Int max_mark ; /* maximum value of tag_mark */
- Int pivot_col_thickness ; /* number of columns represented by pivot col */
- Int prev_col ; /* Used by Dlist operations. */
- Int next_col ; /* Used by Dlist operations. */
- Int ngarbage ; /* number of garbage collections performed */
-
-#ifndef NDEBUG
- Int debug_d ; /* debug loop counter */
- Int debug_step = 0 ; /* debug loop counter */
-#endif /* NDEBUG */
-
- /* === Initialization and clear mark ==================================== */
-
- max_mark = INT_MAX - n_col ; /* INT_MAX defined in <limits.h> */
- tag_mark = clear_mark (0, max_mark, n_row, Row) ;
- min_score = 0 ;
- ngarbage = 0 ;
- DEBUG1 (("colamd: Ordering, n_col2=%d\n", n_col2)) ;
-
- /* === Order the columns ================================================ */
-
- for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */)
- {
-
-#ifndef NDEBUG
- if (debug_step % 100 == 0)
- {
- DEBUG2 (("\n... Step k: %d out of n_col2: %d\n", k, n_col2)) ;
- }
- else
- {
- DEBUG3 (("\n----------Step k: %d out of n_col2: %d\n", k, n_col2)) ;
- }
- debug_step++ ;
- debug_deg_lists (n_row, n_col, Row, Col, head,
- min_score, n_col2-k, max_deg) ;
- debug_matrix (n_row, n_col, Row, Col, A) ;
-#endif /* NDEBUG */
-
- /* === Select pivot column, and order it ============================ */
-
- /* make sure degree list isn't empty */
- ASSERT (min_score >= 0) ;
- ASSERT (min_score <= n_col) ;
- ASSERT (head [min_score] >= EMPTY) ;
-
-#ifndef NDEBUG
- for (debug_d = 0 ; debug_d < min_score ; debug_d++)
- {
- ASSERT (head [debug_d] == EMPTY) ;
- }
-#endif /* NDEBUG */
-
- /* get pivot column from head of minimum degree list */
- while (head [min_score] == EMPTY && min_score < n_col)
- {
- min_score++ ;
- }
- pivot_col = head [min_score] ;
- ASSERT (pivot_col >= 0 && pivot_col <= n_col) ;
- next_col = Col [pivot_col].shared4.degree_next ;
- head [min_score] = next_col ;
- if (next_col != EMPTY)
- {
- Col [next_col].shared3.prev = EMPTY ;
- }
-
- ASSERT (COL_IS_ALIVE (pivot_col)) ;
-
- /* remember score for defrag check */
- pivot_col_score = Col [pivot_col].shared2.score ;
-
- /* the pivot column is the kth column in the pivot order */
- Col [pivot_col].shared2.order = k ;
-
- /* increment order count by column thickness */
- pivot_col_thickness = Col [pivot_col].shared1.thickness ;
- k += pivot_col_thickness ;
- ASSERT (pivot_col_thickness > 0) ;
- DEBUG3 (("Pivot col: %d thick %d\n", pivot_col, pivot_col_thickness)) ;
-
- /* === Garbage_collection, if necessary ============================= */
-
- needed_memory = MIN (pivot_col_score, n_col - k) ;
- if (pfree + needed_memory >= Alen)
- {
- pfree = garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ;
- ngarbage++ ;
- /* after garbage collection we will have enough */
- ASSERT (pfree + needed_memory < Alen) ;
- /* garbage collection has wiped out the Row[].shared2.mark array */
- tag_mark = clear_mark (0, max_mark, n_row, Row) ;
-
-#ifndef NDEBUG
- debug_matrix (n_row, n_col, Row, Col, A) ;
-#endif /* NDEBUG */
- }
-
- /* === Compute pivot row pattern ==================================== */
-
- /* get starting location for this new merged row */
- pivot_row_start = pfree ;
-
- /* initialize new row counts to zero */
- pivot_row_degree = 0 ;
-
- /* tag pivot column as having been visited so it isn't included */
- /* in merged pivot row */
- Col [pivot_col].shared1.thickness = -pivot_col_thickness ;
-
- /* pivot row is the union of all rows in the pivot column pattern */
- cp = &A [Col [pivot_col].start] ;
- cp_end = cp + Col [pivot_col].length ;
- while (cp < cp_end)
- {
- /* get a row */
- row = *cp++ ;
- DEBUG4 (("Pivot col pattern %d %d\n", ROW_IS_ALIVE (row), row)) ;
- /* skip if row is dead */
- if (ROW_IS_ALIVE (row))
- {
- rp = &A [Row [row].start] ;
- rp_end = rp + Row [row].length ;
- while (rp < rp_end)
- {
- /* get a column */
- col = *rp++ ;
- /* add the column, if alive and untagged */
- col_thickness = Col [col].shared1.thickness ;
- if (col_thickness > 0 && COL_IS_ALIVE (col))
- {
- /* tag column in pivot row */
- Col [col].shared1.thickness = -col_thickness ;
- ASSERT (pfree < Alen) ;
- /* place column in pivot row */
- A [pfree++] = col ;
- pivot_row_degree += col_thickness ;
- }
- }
- }
- }
-
- /* clear tag on pivot column */
- Col [pivot_col].shared1.thickness = pivot_col_thickness ;
- max_deg = MAX (max_deg, pivot_row_degree) ;
-
-#ifndef NDEBUG
- DEBUG3 (("check2\n")) ;
- debug_mark (n_row, Row, tag_mark, max_mark) ;
-#endif /* NDEBUG */
-
- /* === Kill all rows used to construct pivot row ==================== */
-
- /* also kill pivot row, temporarily */
- cp = &A [Col [pivot_col].start] ;
- cp_end = cp + Col [pivot_col].length ;
- while (cp < cp_end)
- {
- /* may be killing an already dead row */
- row = *cp++ ;
- DEBUG3 (("Kill row in pivot col: %d\n", row)) ;
- KILL_ROW (row) ;
- }
-
- /* === Select a row index to use as the new pivot row =============== */
-
- pivot_row_length = pfree - pivot_row_start ;
- if (pivot_row_length > 0)
- {
- /* pick the "pivot" row arbitrarily (first row in col) */
- pivot_row = A [Col [pivot_col].start] ;
- DEBUG3 (("Pivotal row is %d\n", pivot_row)) ;
- }
- else
- {
- /* there is no pivot row, since it is of zero length */
- pivot_row = EMPTY ;
- ASSERT (pivot_row_length == 0) ;
- }
- ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ;
-
- /* === Approximate degree computation =============================== */
-
- /* Here begins the computation of the approximate degree. The column */
- /* score is the sum of the pivot row "length", plus the size of the */
- /* set differences of each row in the column minus the pattern of the */
- /* pivot row itself. The column ("thickness") itself is also */
- /* excluded from the column score (we thus use an approximate */
- /* external degree). */
-
- /* The time taken by the following code (compute set differences, and */
- /* add them up) is proportional to the size of the data structure */
- /* being scanned - that is, the sum of the sizes of each column in */
- /* the pivot row. Thus, the amortized time to compute a column score */
- /* is proportional to the size of that column (where size, in this */
- /* context, is the column "length", or the number of row indices */
- /* in that column). The number of row indices in a column is */
- /* monotonically non-decreasing, from the length of the original */
- /* column on input to colamd. */
-
- /* === Compute set differences ====================================== */
-
- DEBUG3 (("** Computing set differences phase. **\n")) ;
-
- /* pivot row is currently dead - it will be revived later. */
-
- DEBUG3 (("Pivot row: ")) ;
- /* for each column in pivot row */
- rp = &A [pivot_row_start] ;
- rp_end = rp + pivot_row_length ;
- while (rp < rp_end)
- {
- col = *rp++ ;
- ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ;
- DEBUG3 (("Col: %d\n", col)) ;
-
- /* clear tags used to construct pivot row pattern */
- col_thickness = -Col [col].shared1.thickness ;
- ASSERT (col_thickness > 0) ;
- Col [col].shared1.thickness = col_thickness ;
-
- /* === Remove column from degree list =========================== */
-
- cur_score = Col [col].shared2.score ;
- prev_col = Col [col].shared3.prev ;
- next_col = Col [col].shared4.degree_next ;
- ASSERT (cur_score >= 0) ;
- ASSERT (cur_score <= n_col) ;
- ASSERT (cur_score >= EMPTY) ;
- if (prev_col == EMPTY)
- {
- head [cur_score] = next_col ;
- }
- else
- {
- Col [prev_col].shared4.degree_next = next_col ;
- }
- if (next_col != EMPTY)
- {
- Col [next_col].shared3.prev = prev_col ;
- }
-
- /* === Scan the column ========================================== */
-
- cp = &A [Col [col].start] ;
- cp_end = cp + Col [col].length ;
- while (cp < cp_end)
- {
- /* get a row */
- row = *cp++ ;
- row_mark = Row [row].shared2.mark ;
- /* skip if dead */
- if (ROW_IS_MARKED_DEAD (row_mark))
- {
- continue ;
- }
- ASSERT (row != pivot_row) ;
- set_difference = row_mark - tag_mark ;
- /* check if the row has been seen yet */
- if (set_difference < 0)
- {
- ASSERT (Row [row].shared1.degree <= max_deg) ;
- set_difference = Row [row].shared1.degree ;
- }
- /* subtract column thickness from this row's set difference */
- set_difference -= col_thickness ;
- ASSERT (set_difference >= 0) ;
- /* absorb this row if the set difference becomes zero */
- if (set_difference == 0 && aggressive)
- {
- DEBUG3 (("aggressive absorption. Row: %d\n", row)) ;
- KILL_ROW (row) ;
- }
- else
- {
- /* save the new mark */
- Row [row].shared2.mark = set_difference + tag_mark ;
- }
- }
- }
-
-#ifndef NDEBUG
- debug_deg_lists (n_row, n_col, Row, Col, head,
- min_score, n_col2-k-pivot_row_degree, max_deg) ;
-#endif /* NDEBUG */
-
- /* === Add up set differences for each column ======================= */
-
- DEBUG3 (("** Adding set differences phase. **\n")) ;
-
- /* for each column in pivot row */
- rp = &A [pivot_row_start] ;
- rp_end = rp + pivot_row_length ;
- while (rp < rp_end)
- {
- /* get a column */
- col = *rp++ ;
- ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ;
- hash = 0 ;
- cur_score = 0 ;
- cp = &A [Col [col].start] ;
- /* compact the column */
- new_cp = cp ;
- cp_end = cp + Col [col].length ;
-
- DEBUG4 (("Adding set diffs for Col: %d.\n", col)) ;
-
- while (cp < cp_end)
- {
- /* get a row */
- row = *cp++ ;
- ASSERT(row >= 0 && row < n_row) ;
- row_mark = Row [row].shared2.mark ;
- /* skip if dead */
- if (ROW_IS_MARKED_DEAD (row_mark))
- {
- DEBUG4 ((" Row %d, dead\n", row)) ;
- continue ;
- }
- DEBUG4 ((" Row %d, set diff %d\n", row, row_mark-tag_mark));
- ASSERT (row_mark >= tag_mark) ;
- /* compact the column */
- *new_cp++ = row ;
- /* compute hash function */
- hash += row ;
- /* add set difference */
- cur_score += row_mark - tag_mark ;
- /* integer overflow... */
- cur_score = MIN (cur_score, n_col) ;
- }
-
- /* recompute the column's length */
- Col [col].length = (Int) (new_cp - &A [Col [col].start]) ;
-
- /* === Further mass elimination ================================= */
-
- if (Col [col].length == 0)
- {
- DEBUG4 (("further mass elimination. Col: %d\n", col)) ;
- /* nothing left but the pivot row in this column */
- KILL_PRINCIPAL_COL (col) ;
- pivot_row_degree -= Col [col].shared1.thickness ;
- ASSERT (pivot_row_degree >= 0) ;
- /* order it */
- Col [col].shared2.order = k ;
- /* increment order count by column thickness */
- k += Col [col].shared1.thickness ;
- }
- else
- {
- /* === Prepare for supercolumn detection ==================== */
-
- DEBUG4 (("Preparing supercol detection for Col: %d.\n", col)) ;
-
- /* save score so far */
- Col [col].shared2.score = cur_score ;
-
- /* add column to hash table, for supercolumn detection */
- hash %= n_col + 1 ;
-
- DEBUG4 ((" Hash = %d, n_col = %d.\n", hash, n_col)) ;
- ASSERT (((Int) hash) <= n_col) ;
-
- head_column = head [hash] ;
- if (head_column > EMPTY)
- {
- /* degree list "hash" is non-empty, use prev (shared3) of */
- /* first column in degree list as head of hash bucket */
- first_col = Col [head_column].shared3.headhash ;
- Col [head_column].shared3.headhash = col ;
- }
- else
- {
- /* degree list "hash" is empty, use head as hash bucket */
- first_col = - (head_column + 2) ;
- head [hash] = - (col + 2) ;
- }
- Col [col].shared4.hash_next = first_col ;
-
- /* save hash function in Col [col].shared3.hash */
- Col [col].shared3.hash = (Int) hash ;
- ASSERT (COL_IS_ALIVE (col)) ;
- }
- }
-
- /* The approximate external column degree is now computed. */
-
- /* === Supercolumn detection ======================================== */
-
- DEBUG3 (("** Supercolumn detection phase. **\n")) ;
-
- detect_super_cols (
-
-#ifndef NDEBUG
- n_col, Row,
-#endif /* NDEBUG */
-
- Col, A, head, pivot_row_start, pivot_row_length) ;
-
- /* === Kill the pivotal column ====================================== */
-
- KILL_PRINCIPAL_COL (pivot_col) ;
-
- /* === Clear mark =================================================== */
-
- tag_mark = clear_mark (tag_mark+max_deg+1, max_mark, n_row, Row) ;
-
-#ifndef NDEBUG
- DEBUG3 (("check3\n")) ;
- debug_mark (n_row, Row, tag_mark, max_mark) ;
-#endif /* NDEBUG */
-
- /* === Finalize the new pivot row, and column scores ================ */
-
- DEBUG3 (("** Finalize scores phase. **\n")) ;
-
- /* for each column in pivot row */
- rp = &A [pivot_row_start] ;
- /* compact the pivot row */
- new_rp = rp ;
- rp_end = rp + pivot_row_length ;
- while (rp < rp_end)
- {
- col = *rp++ ;
- /* skip dead columns */
- if (COL_IS_DEAD (col))
- {
- continue ;
- }
- *new_rp++ = col ;
- /* add new pivot row to column */
- A [Col [col].start + (Col [col].length++)] = pivot_row ;
-
- /* retrieve score so far and add on pivot row's degree. */
- /* (we wait until here for this in case the pivot */
- /* row's degree was reduced due to mass elimination). */
- cur_score = Col [col].shared2.score + pivot_row_degree ;
-
- /* calculate the max possible score as the number of */
- /* external columns minus the 'k' value minus the */
- /* columns thickness */
- max_score = n_col - k - Col [col].shared1.thickness ;
-
- /* make the score the external degree of the union-of-rows */
- cur_score -= Col [col].shared1.thickness ;
-
- /* make sure score is less or equal than the max score */
- cur_score = MIN (cur_score, max_score) ;
- ASSERT (cur_score >= 0) ;
-
- /* store updated score */
- Col [col].shared2.score = cur_score ;
-
- /* === Place column back in degree list ========================= */
-
- ASSERT (min_score >= 0) ;
- ASSERT (min_score <= n_col) ;
- ASSERT (cur_score >= 0) ;
- ASSERT (cur_score <= n_col) ;
- ASSERT (head [cur_score] >= EMPTY) ;
- next_col = head [cur_score] ;
- Col [col].shared4.degree_next = next_col ;
- Col [col].shared3.prev = EMPTY ;
- if (next_col != EMPTY)
- {
- Col [next_col].shared3.prev = col ;
- }
- head [cur_score] = col ;
-
- /* see if this score is less than current min */
- min_score = MIN (min_score, cur_score) ;
-
- }
-
-#ifndef NDEBUG
- debug_deg_lists (n_row, n_col, Row, Col, head,
- min_score, n_col2-k, max_deg) ;
-#endif /* NDEBUG */
-
- /* === Resurrect the new pivot row ================================== */
-
- if (pivot_row_degree > 0)
- {
- /* update pivot row length to reflect any cols that were killed */
- /* during super-col detection and mass elimination */
- Row [pivot_row].start = pivot_row_start ;
- Row [pivot_row].length = (Int) (new_rp - &A[pivot_row_start]) ;
- ASSERT (Row [pivot_row].length > 0) ;
- Row [pivot_row].shared1.degree = pivot_row_degree ;
- Row [pivot_row].shared2.mark = 0 ;
- /* pivot row is no longer dead */
-
- DEBUG1 (("Resurrect Pivot_row %d deg: %d\n",
- pivot_row, pivot_row_degree)) ;
- }
- }
-
- /* === All principal columns have now been ordered ====================== */
-
- return (ngarbage) ;
-}
-
-
-/* ========================================================================== */
-/* === order_children ======================================================= */
-/* ========================================================================== */
-
-/*
- The find_ordering routine has ordered all of the principal columns (the
- representatives of the supercolumns). The non-principal columns have not
- yet been ordered. This routine orders those columns by walking up the
- parent tree (a column is a child of the column which absorbed it). The
- final permutation vector is then placed in p [0 ... n_col-1], with p [0]
- being the first column, and p [n_col-1] being the last. It doesn't look
- like it at first glance, but be assured that this routine takes time linear
- in the number of columns. Although not immediately obvious, the time
- taken by this routine is O (n_col), that is, linear in the number of
- columns. Not user-callable.
-*/
-
-PRIVATE void order_children
-(
- /* === Parameters ======================================================= */
-
- Int n_col, /* number of columns of A */
- Colamd_Col Col [], /* of size n_col+1 */
- Int p [] /* p [0 ... n_col-1] is the column permutation*/
-)
-{
- /* === Local variables ================================================== */
-
- Int i ; /* loop counter for all columns */
- Int c ; /* column index */
- Int parent ; /* index of column's parent */
- Int order ; /* column's order */
-
- /* === Order each non-principal column ================================== */
-
- for (i = 0 ; i < n_col ; i++)
- {
- /* find an un-ordered non-principal column */
- ASSERT (COL_IS_DEAD (i)) ;
- if (!COL_IS_DEAD_PRINCIPAL (i) && Col [i].shared2.order == EMPTY)
- {
- parent = i ;
- /* once found, find its principal parent */
- do
- {
- parent = Col [parent].shared1.parent ;
- } while (!COL_IS_DEAD_PRINCIPAL (parent)) ;
-
- /* now, order all un-ordered non-principal columns along path */
- /* to this parent. collapse tree at the same time */
- c = i ;
- /* get order of parent */
- order = Col [parent].shared2.order ;
-
- do
- {
- ASSERT (Col [c].shared2.order == EMPTY) ;
-
- /* order this column */
- Col [c].shared2.order = order++ ;
- /* collaps tree */
- Col [c].shared1.parent = parent ;
-
- /* get immediate parent of this column */
- c = Col [c].shared1.parent ;
-
- /* continue until we hit an ordered column. There are */
- /* guarranteed not to be anymore unordered columns */
- /* above an ordered column */
- } while (Col [c].shared2.order == EMPTY) ;
-
- /* re-order the super_col parent to largest order for this group */
- Col [parent].shared2.order = order ;
- }
- }
-
- /* === Generate the permutation ========================================= */
-
- for (c = 0 ; c < n_col ; c++)
- {
- p [Col [c].shared2.order] = c ;
- }
-}
-
-
-/* ========================================================================== */
-/* === detect_super_cols ==================================================== */
-/* ========================================================================== */
-
-/*
- Detects supercolumns by finding matches between columns in the hash buckets.
- Check amongst columns in the set A [row_start ... row_start + row_length-1].
- The columns under consideration are currently *not* in the degree lists,
- and have already been placed in the hash buckets.
-
- The hash bucket for columns whose hash function is equal to h is stored
- as follows:
-
- if head [h] is >= 0, then head [h] contains a degree list, so:
-
- head [h] is the first column in degree bucket h.
- Col [head [h]].headhash gives the first column in hash bucket h.
-
- otherwise, the degree list is empty, and:
-
- -(head [h] + 2) is the first column in hash bucket h.
-
- For a column c in a hash bucket, Col [c].shared3.prev is NOT a "previous
- column" pointer. Col [c].shared3.hash is used instead as the hash number
- for that column. The value of Col [c].shared4.hash_next is the next column
- in the same hash bucket.
-
- Assuming no, or "few" hash collisions, the time taken by this routine is
- linear in the sum of the sizes (lengths) of each column whose score has
- just been computed in the approximate degree computation.
- Not user-callable.
-*/
-
-PRIVATE void detect_super_cols
-(
- /* === Parameters ======================================================= */
-
-#ifndef NDEBUG
- /* these two parameters are only needed when debugging is enabled: */
- Int n_col, /* number of columns of A */
- Colamd_Row Row [], /* of size n_row+1 */
-#endif /* NDEBUG */
-
- Colamd_Col Col [], /* of size n_col+1 */
- Int A [], /* row indices of A */
- Int head [], /* head of degree lists and hash buckets */
- Int row_start, /* pointer to set of columns to check */
- Int row_length /* number of columns to check */
-)
-{
- /* === Local variables ================================================== */
-
- Int hash ; /* hash value for a column */
- Int *rp ; /* pointer to a row */
- Int c ; /* a column index */
- Int super_c ; /* column index of the column to absorb into */
- Int *cp1 ; /* column pointer for column super_c */
- Int *cp2 ; /* column pointer for column c */
- Int length ; /* length of column super_c */
- Int prev_c ; /* column preceding c in hash bucket */
- Int i ; /* loop counter */
- Int *rp_end ; /* pointer to the end of the row */
- Int col ; /* a column index in the row to check */
- Int head_column ; /* first column in hash bucket or degree list */
- Int first_col ; /* first column in hash bucket */
-
- /* === Consider each column in the row ================================== */
-
- rp = &A [row_start] ;
- rp_end = rp + row_length ;
- while (rp < rp_end)
- {
- col = *rp++ ;
- if (COL_IS_DEAD (col))
- {
- continue ;
- }
-
- /* get hash number for this column */
- hash = Col [col].shared3.hash ;
- ASSERT (hash <= n_col) ;
-
- /* === Get the first column in this hash bucket ===================== */
-
- head_column = head [hash] ;
- if (head_column > EMPTY)
- {
- first_col = Col [head_column].shared3.headhash ;
- }
- else
- {
- first_col = - (head_column + 2) ;
- }
-
- /* === Consider each column in the hash bucket ====================== */
-
- for (super_c = first_col ; super_c != EMPTY ;
- super_c = Col [super_c].shared4.hash_next)
- {
- ASSERT (COL_IS_ALIVE (super_c)) ;
- ASSERT (Col [super_c].shared3.hash == hash) ;
- length = Col [super_c].length ;
-
- /* prev_c is the column preceding column c in the hash bucket */
- prev_c = super_c ;
-
- /* === Compare super_c with all columns after it ================ */
-
- for (c = Col [super_c].shared4.hash_next ;
- c != EMPTY ; c = Col [c].shared4.hash_next)
- {
- ASSERT (c != super_c) ;
- ASSERT (COL_IS_ALIVE (c)) ;
- ASSERT (Col [c].shared3.hash == hash) ;
-
- /* not identical if lengths or scores are different */
- if (Col [c].length != length ||
- Col [c].shared2.score != Col [super_c].shared2.score)
- {
- prev_c = c ;
- continue ;
- }
-
- /* compare the two columns */
- cp1 = &A [Col [super_c].start] ;
- cp2 = &A [Col [c].start] ;
-
- for (i = 0 ; i < length ; i++)
- {
- /* the columns are "clean" (no dead rows) */
- ASSERT (ROW_IS_ALIVE (*cp1)) ;
- ASSERT (ROW_IS_ALIVE (*cp2)) ;
- /* row indices will same order for both supercols, */
- /* no gather scatter nessasary */
- if (*cp1++ != *cp2++)
- {
- break ;
- }
- }
-
- /* the two columns are different if the for-loop "broke" */
- if (i != length)
- {
- prev_c = c ;
- continue ;
- }
-
- /* === Got it! two columns are identical =================== */
-
- ASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ;
-
- Col [super_c].shared1.thickness += Col [c].shared1.thickness ;
- Col [c].shared1.parent = super_c ;
- KILL_NON_PRINCIPAL_COL (c) ;
- /* order c later, in order_children() */
- Col [c].shared2.order = EMPTY ;
- /* remove c from hash bucket */
- Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ;
- }
- }
-
- /* === Empty this hash bucket ======================================= */
-
- if (head_column > EMPTY)
- {
- /* corresponding degree list "hash" is not empty */
- Col [head_column].shared3.headhash = EMPTY ;
- }
- else
- {
- /* corresponding degree list "hash" is empty */
- head [hash] = EMPTY ;
- }
- }
-}
-
-
-/* ========================================================================== */
-/* === garbage_collection =================================================== */
-/* ========================================================================== */
-
-/*
- Defragments and compacts columns and rows in the workspace A. Used when
- all avaliable memory has been used while performing row merging. Returns
- the index of the first free position in A, after garbage collection. The
- time taken by this routine is linear is the size of the array A, which is
- itself linear in the number of nonzeros in the input matrix.
- Not user-callable.
-*/
-
-PRIVATE Int garbage_collection /* returns the new value of pfree */
-(
- /* === Parameters ======================================================= */
-
- Int n_row, /* number of rows */
- Int n_col, /* number of columns */
- Colamd_Row Row [], /* row info */
- Colamd_Col Col [], /* column info */
- Int A [], /* A [0 ... Alen-1] holds the matrix */
- Int *pfree /* &A [0] ... pfree is in use */
-)
-{
- /* === Local variables ================================================== */
-
- Int *psrc ; /* source pointer */
- Int *pdest ; /* destination pointer */
- Int j ; /* counter */
- Int r ; /* a row index */
- Int c ; /* a column index */
- Int length ; /* length of a row or column */
-
-#ifndef NDEBUG
- Int debug_rows ;
- DEBUG2 (("Defrag..\n")) ;
- for (psrc = &A[0] ; psrc < pfree ; psrc++) ASSERT (*psrc >= 0) ;
- debug_rows = 0 ;
-#endif /* NDEBUG */
-
- /* === Defragment the columns =========================================== */
-
- pdest = &A[0] ;
- for (c = 0 ; c < n_col ; c++)
- {
- if (COL_IS_ALIVE (c))
- {
- psrc = &A [Col [c].start] ;
-
- /* move and compact the column */
- ASSERT (pdest <= psrc) ;
- Col [c].start = (Int) (pdest - &A [0]) ;
- length = Col [c].length ;
- for (j = 0 ; j < length ; j++)
- {
- r = *psrc++ ;
- if (ROW_IS_ALIVE (r))
- {
- *pdest++ = r ;
- }
- }
- Col [c].length = (Int) (pdest - &A [Col [c].start]) ;
- }
- }
-
- /* === Prepare to defragment the rows =================================== */
-
- for (r = 0 ; r < n_row ; r++)
- {
- if (ROW_IS_DEAD (r) || (Row [r].length == 0))
- {
- /* This row is already dead, or is of zero length. Cannot compact
- * a row of zero length, so kill it. NOTE: in the current version,
- * there are no zero-length live rows. Kill the row (for the first
- * time, or again) just to be safe. */
- KILL_ROW (r) ;
- }
- else
- {
- /* save first column index in Row [r].shared2.first_column */
- psrc = &A [Row [r].start] ;
- Row [r].shared2.first_column = *psrc ;
- ASSERT (ROW_IS_ALIVE (r)) ;
- /* flag the start of the row with the one's complement of row */
- *psrc = ONES_COMPLEMENT (r) ;
-#ifndef NDEBUG
- debug_rows++ ;
-#endif /* NDEBUG */
- }
- }
-
- /* === Defragment the rows ============================================== */
-
- psrc = pdest ;
- while (psrc < pfree)
- {
- /* find a negative number ... the start of a row */
- if (*psrc++ < 0)
- {
- psrc-- ;
- /* get the row index */
- r = ONES_COMPLEMENT (*psrc) ;
- ASSERT (r >= 0 && r < n_row) ;
- /* restore first column index */
- *psrc = Row [r].shared2.first_column ;
- ASSERT (ROW_IS_ALIVE (r)) ;
- ASSERT (Row [r].length > 0) ;
- /* move and compact the row */
- ASSERT (pdest <= psrc) ;
- Row [r].start = (Int) (pdest - &A [0]) ;
- length = Row [r].length ;
- for (j = 0 ; j < length ; j++)
- {
- c = *psrc++ ;
- if (COL_IS_ALIVE (c))
- {
- *pdest++ = c ;
- }
- }
- Row [r].length = (Int) (pdest - &A [Row [r].start]) ;
- ASSERT (Row [r].length > 0) ;
-#ifndef NDEBUG
- debug_rows-- ;
-#endif /* NDEBUG */
- }
- }
- /* ensure we found all the rows */
- ASSERT (debug_rows == 0) ;
-
- /* === Return the new value of pfree ==================================== */
-
- return ((Int) (pdest - &A [0])) ;
-}
-
-
-/* ========================================================================== */
-/* === clear_mark =========================================================== */
-/* ========================================================================== */
-
-/*
- Clears the Row [].shared2.mark array, and returns the new tag_mark.
- Return value is the new tag_mark. Not user-callable.
-*/
-
-PRIVATE Int clear_mark /* return the new value for tag_mark */
-(
- /* === Parameters ======================================================= */
-
- Int tag_mark, /* new value of tag_mark */
- Int max_mark, /* max allowed value of tag_mark */
-
- Int n_row, /* number of rows in A */
- Colamd_Row Row [] /* Row [0 ... n_row-1].shared2.mark is set to zero */
-)
-{
- /* === Local variables ================================================== */
-
- Int r ;
-
- if (tag_mark <= 0 || tag_mark >= max_mark)
- {
- for (r = 0 ; r < n_row ; r++)
- {
- if (ROW_IS_ALIVE (r))
- {
- Row [r].shared2.mark = 0 ;
- }
- }
- tag_mark = 1 ;
- }
-
- return (tag_mark) ;
-}
-
-
-/* ========================================================================== */
-/* === print_report ========================================================= */
-/* ========================================================================== */
-
-PRIVATE void print_report
-(
- char *method,
- Int stats [COLAMD_STATS]
-)
-{
-
- Int i1, i2, i3 ;
-
- PRINTF (("\n%s version %d.%d, %s: ", method,
- COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE)) ;
-
- if (!stats)
- {
- PRINTF (("No statistics available.\n")) ;
- return ;
- }
-
- i1 = stats [COLAMD_INFO1] ;
- i2 = stats [COLAMD_INFO2] ;
- i3 = stats [COLAMD_INFO3] ;
-
- if (stats [COLAMD_STATUS] >= 0)
- {
- PRINTF (("OK. ")) ;
- }
- else
- {
- PRINTF (("ERROR. ")) ;
- }
-
- switch (stats [COLAMD_STATUS])
- {
-
- case COLAMD_OK_BUT_JUMBLED:
-
- PRINTF(("Matrix has unsorted or duplicate row indices.\n")) ;
-
- PRINTF(("%s: number of duplicate or out-of-order row indices: %d\n",
- method, i3)) ;
-
- PRINTF(("%s: last seen duplicate or out-of-order row index: %d\n",
- method, INDEX (i2))) ;
-
- PRINTF(("%s: last seen in column: %d",
- method, INDEX (i1))) ;
-
- /* no break - fall through to next case instead */
-
- case COLAMD_OK:
-
- PRINTF(("\n")) ;
-
- PRINTF(("%s: number of dense or empty rows ignored: %d\n",
- method, stats [COLAMD_DENSE_ROW])) ;
-
- PRINTF(("%s: number of dense or empty columns ignored: %d\n",
- method, stats [COLAMD_DENSE_COL])) ;
-
- PRINTF(("%s: number of garbage collections performed: %d\n",
- method, stats [COLAMD_DEFRAG_COUNT])) ;
- break ;
-
- case COLAMD_ERROR_A_not_present:
-
- PRINTF(("Array A (row indices of matrix) not present.\n")) ;
- break ;
-
- case COLAMD_ERROR_p_not_present:
-
- PRINTF(("Array p (column pointers for matrix) not present.\n")) ;
- break ;
-
- case COLAMD_ERROR_nrow_negative:
-
- PRINTF(("Invalid number of rows (%d).\n", i1)) ;
- break ;
-
- case COLAMD_ERROR_ncol_negative:
-
- PRINTF(("Invalid number of columns (%d).\n", i1)) ;
- break ;
-
- case COLAMD_ERROR_nnz_negative:
-
- PRINTF(("Invalid number of nonzero entries (%d).\n", i1)) ;
- break ;
-
- case COLAMD_ERROR_p0_nonzero:
-
- PRINTF(("Invalid column pointer, p [0] = %d, must be zero.\n", i1));
- break ;
-
- case COLAMD_ERROR_A_too_small:
-
- PRINTF(("Array A too small.\n")) ;
- PRINTF((" Need Alen >= %d, but given only Alen = %d.\n",
- i1, i2)) ;
- break ;
-
- case COLAMD_ERROR_col_length_negative:
-
- PRINTF
- (("Column %d has a negative number of nonzero entries (%d).\n",
- INDEX (i1), i2)) ;
- break ;
-
- case COLAMD_ERROR_row_index_out_of_bounds:
-
- PRINTF
- (("Row index (row %d) out of bounds (%d to %d) in column %d.\n",
- INDEX (i2), INDEX (0), INDEX (i3-1), INDEX (i1))) ;
- break ;
-
- case COLAMD_ERROR_out_of_memory:
-
- PRINTF(("Out of memory.\n")) ;
- break ;
-
- /* v2.4: internal-error case deleted */
- }
-}
-
-
-
-
-/* ========================================================================== */
-/* === colamd debugging routines ============================================ */
-/* ========================================================================== */
-
-/* When debugging is disabled, the remainder of this file is ignored. */
-
-#ifndef NDEBUG
-
-
-/* ========================================================================== */
-/* === debug_structures ===================================================== */
-/* ========================================================================== */
-
-/*
- At this point, all empty rows and columns are dead. All live columns
- are "clean" (containing no dead rows) and simplicial (no supercolumns
- yet). Rows may contain dead columns, but all live rows contain at
- least one live column.
-*/
-
-PRIVATE void debug_structures
-(
- /* === Parameters ======================================================= */
-
- Int n_row,
- Int n_col,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int A [],
- Int n_col2
-)
-{
- /* === Local variables ================================================== */
-
- Int i ;
- Int c ;
- Int *cp ;
- Int *cp_end ;
- Int len ;
- Int score ;
- Int r ;
- Int *rp ;
- Int *rp_end ;
- Int deg ;
-
- /* === Check A, Row, and Col ============================================ */
-
- for (c = 0 ; c < n_col ; c++)
- {
- if (COL_IS_ALIVE (c))
- {
- len = Col [c].length ;
- score = Col [c].shared2.score ;
- DEBUG4 (("initial live col %5d %5d %5d\n", c, len, score)) ;
- ASSERT (len > 0) ;
- ASSERT (score >= 0) ;
- ASSERT (Col [c].shared1.thickness == 1) ;
- cp = &A [Col [c].start] ;
- cp_end = cp + len ;
- while (cp < cp_end)
- {
- r = *cp++ ;
- ASSERT (ROW_IS_ALIVE (r)) ;
- }
- }
- else
- {
- i = Col [c].shared2.order ;
- ASSERT (i >= n_col2 && i < n_col) ;
- }
- }
-
- for (r = 0 ; r < n_row ; r++)
- {
- if (ROW_IS_ALIVE (r))
- {
- i = 0 ;
- len = Row [r].length ;
- deg = Row [r].shared1.degree ;
- ASSERT (len > 0) ;
- ASSERT (deg > 0) ;
- rp = &A [Row [r].start] ;
- rp_end = rp + len ;
- while (rp < rp_end)
- {
- c = *rp++ ;
- if (COL_IS_ALIVE (c))
- {
- i++ ;
- }
- }
- ASSERT (i > 0) ;
- }
- }
-}
-
-
-/* ========================================================================== */
-/* === debug_deg_lists ====================================================== */
-/* ========================================================================== */
-
-/*
- Prints the contents of the degree lists. Counts the number of columns
- in the degree list and compares it to the total it should have. Also
- checks the row degrees.
-*/
-
-PRIVATE void debug_deg_lists
-(
- /* === Parameters ======================================================= */
-
- Int n_row,
- Int n_col,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int head [],
- Int min_score,
- Int should,
- Int max_deg
-)
-{
- /* === Local variables ================================================== */
-
- Int deg ;
- Int col ;
- Int have ;
- Int row ;
-
- /* === Check the degree lists =========================================== */
-
- if (n_col > 10000 && colamd_debug <= 0)
- {
- return ;
- }
- have = 0 ;
- DEBUG4 (("Degree lists: %d\n", min_score)) ;
- for (deg = 0 ; deg <= n_col ; deg++)
- {
- col = head [deg] ;
- if (col == EMPTY)
- {
- continue ;
- }
- DEBUG4 (("%d:", deg)) ;
- while (col != EMPTY)
- {
- DEBUG4 ((" %d", col)) ;
- have += Col [col].shared1.thickness ;
- ASSERT (COL_IS_ALIVE (col)) ;
- col = Col [col].shared4.degree_next ;
- }
- DEBUG4 (("\n")) ;
- }
- DEBUG4 (("should %d have %d\n", should, have)) ;
- ASSERT (should == have) ;
-
- /* === Check the row degrees ============================================ */
-
- if (n_row > 10000 && colamd_debug <= 0)
- {
- return ;
- }
- for (row = 0 ; row < n_row ; row++)
- {
- if (ROW_IS_ALIVE (row))
- {
- ASSERT (Row [row].shared1.degree <= max_deg) ;
- }
- }
-}
-
-
-/* ========================================================================== */
-/* === debug_mark =========================================================== */
-/* ========================================================================== */
-
-/*
- Ensures that the tag_mark is less that the maximum and also ensures that
- each entry in the mark array is less than the tag mark.
-*/
-
-PRIVATE void debug_mark
-(
- /* === Parameters ======================================================= */
-
- Int n_row,
- Colamd_Row Row [],
- Int tag_mark,
- Int max_mark
-)
-{
- /* === Local variables ================================================== */
-
- Int r ;
-
- /* === Check the Row marks ============================================== */
-
- ASSERT (tag_mark > 0 && tag_mark <= max_mark) ;
- if (n_row > 10000 && colamd_debug <= 0)
- {
- return ;
- }
- for (r = 0 ; r < n_row ; r++)
- {
- ASSERT (Row [r].shared2.mark < tag_mark) ;
- }
-}
-
-
-/* ========================================================================== */
-/* === debug_matrix ========================================================= */
-/* ========================================================================== */
-
-/*
- Prints out the contents of the columns and the rows.
-*/
-
-PRIVATE void debug_matrix
-(
- /* === Parameters ======================================================= */
-
- Int n_row,
- Int n_col,
- Colamd_Row Row [],
- Colamd_Col Col [],
- Int A []
-)
-{
- /* === Local variables ================================================== */
-
- Int r ;
- Int c ;
- Int *rp ;
- Int *rp_end ;
- Int *cp ;
- Int *cp_end ;
-
- /* === Dump the rows and columns of the matrix ========================== */
-
- if (colamd_debug < 3)
- {
- return ;
- }
- DEBUG3 (("DUMP MATRIX:\n")) ;
- for (r = 0 ; r < n_row ; r++)
- {
- DEBUG3 (("Row %d alive? %d\n", r, ROW_IS_ALIVE (r))) ;
- if (ROW_IS_DEAD (r))
- {
- continue ;
- }
- DEBUG3 (("start %d length %d degree %d\n",
- Row [r].start, Row [r].length, Row [r].shared1.degree)) ;
- rp = &A [Row [r].start] ;
- rp_end = rp + Row [r].length ;
- while (rp < rp_end)
- {
- c = *rp++ ;
- DEBUG4 ((" %d col %d\n", COL_IS_ALIVE (c), c)) ;
- }
- }
-
- for (c = 0 ; c < n_col ; c++)
- {
- DEBUG3 (("Col %d alive? %d\n", c, COL_IS_ALIVE (c))) ;
- if (COL_IS_DEAD (c))
- {
- continue ;
- }
- DEBUG3 (("start %d length %d shared1 %d shared2 %d\n",
- Col [c].start, Col [c].length,
- Col [c].shared1.thickness, Col [c].shared2.score)) ;
- cp = &A [Col [c].start] ;
- cp_end = cp + Col [c].length ;
- while (cp < cp_end)
- {
- r = *cp++ ;
- DEBUG4 ((" %d row %d\n", ROW_IS_ALIVE (r), r)) ;
- }
- }
-}
-
-PRIVATE void colamd_get_debug
-(
- char *method
-)
-{
- FILE *f ;
- colamd_debug = 0 ; /* no debug printing */
- f = fopen ("debug", "r") ;
- if (f == (FILE *) NULL)
- {
- colamd_debug = 0 ;
- }
- else
- {
- fscanf (f, "%d", &colamd_debug) ;
- fclose (f) ;
- }
- DEBUG0 (("%s: debug version, D = %d (THIS WILL BE SLOW!)\n",
- method, colamd_debug)) ;
-}
-
-#endif /* NDEBUG */
diff --git a/extern/colamd/Source/colamd_global.c b/extern/colamd/Source/colamd_global.c
deleted file mode 100644
index 4d1ae22300c..00000000000
--- a/extern/colamd/Source/colamd_global.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/* ========================================================================== */
-/* === colamd_global.c ====================================================== */
-/* ========================================================================== */
-
-/* ----------------------------------------------------------------------------
- * COLAMD, Copyright (C) 2007, Timothy A. Davis.
- * See License.txt for the Version 2.1 of the GNU Lesser General Public License
- * http://www.cise.ufl.edu/research/sparse
- * -------------------------------------------------------------------------- */
-
-/* Global variables for COLAMD */
-
-#ifndef NPRINT
-#ifdef MATLAB_MEX_FILE
-#include "mex.h"
-int (*colamd_printf) (const char *, ...) = mexPrintf ;
-#else
-#include <stdio.h>
-int (*colamd_printf) (const char *, ...) = printf ;
-#endif
-#else
-int (*colamd_printf) (const char *, ...) = ((void *) 0) ;
-#endif
-
diff --git a/extern/cuew/auto/cuda_extra.py b/extern/cuew/auto/cuda_extra.py
index fd4f466df83..5fd2c179339 100644
--- a/extern/cuew/auto/cuda_extra.py
+++ b/extern/cuew/auto/cuda_extra.py
@@ -101,7 +101,7 @@ int cuewCompilerVersion(void) {
while (!feof(pipe)) {
if (fgets(buf, sizeof(buf), pipe) != NULL) {
- strncat(output, buf, sizeof(output) - strlen(output));
+ strncat(output, buf, sizeof(output) - strlen(output) - 1);
}
}
diff --git a/extern/cuew/auto/cuew_gen.py b/extern/cuew/auto/cuew_gen.py
index a94525c52b1..75e5bf876f4 100644
--- a/extern/cuew/auto/cuew_gen.py
+++ b/extern/cuew/auto/cuew_gen.py
@@ -276,7 +276,11 @@ def parse_files():
if line[0].isspace() and line.lstrip().startswith("#define"):
line = line[12:-1]
token = line.split()
- if len(token) == 2 and token[1].endswith("_v2"):
+ if len(token) == 2 and (token[1].endswith("_v2") or
+ token[1].endswith("_v2)")):
+ if token[1].startswith('__CUDA_API_PTDS') or \
+ token[1].startswith('__CUDA_API_PTSZ'):
+ token[1] = token[1][16:-1]
DEFINES_V2.append(token)
v = FuncDefVisitor()
@@ -560,7 +564,8 @@ def print_implementation():
if error in CUDA_ERRORS:
str = CUDA_ERRORS[error]
else:
- str = error[11:]
+ temp = error[11:].replace('_', ' ')
+ str = temp[0] + temp[1:].lower()
print(" case %s: return \"%s\";" % (error, str))
print(" default: return \"Unknown CUDA error value\";")
diff --git a/extern/cuew/include/cuew.h b/extern/cuew/include/cuew.h
index fd03311ad41..1b12e5b4463 100644
--- a/extern/cuew/include/cuew.h
+++ b/extern/cuew/include/cuew.h
@@ -27,13 +27,16 @@ extern "C" {
#define CUEW_VERSION_MAJOR 1
#define CUEW_VERSION_MINOR 2
-#define CUDA_VERSION 6000
+#define CUDA_VERSION 7050
#define CU_IPC_HANDLE_SIZE 64
+#define CU_STREAM_LEGACY ((CUstream)0x1)
+#define CU_STREAM_PER_THREAD ((CUstream)0x2)
#define CU_MEMHOSTALLOC_PORTABLE 0x01
#define CU_MEMHOSTALLOC_DEVICEMAP 0x02
#define CU_MEMHOSTALLOC_WRITECOMBINED 0x04
#define CU_MEMHOSTREGISTER_PORTABLE 0x01
#define CU_MEMHOSTREGISTER_DEVICEMAP 0x02
+#define CU_MEMHOSTREGISTER_IOMEMORY 0x04
#define CUDA_ARRAY3D_LAYERED 0x01
#define CUDA_ARRAY3D_2DARRAY 0x01
#define CUDA_ARRAY3D_SURFACE_LDST 0x02
@@ -100,10 +103,16 @@ extern "C" {
#define cuCtxPushCurrent cuCtxPushCurrent_v2
#define cuStreamDestroy cuStreamDestroy_v2
#define cuEventDestroy cuEventDestroy_v2
+#define cuLinkCreate cuLinkCreate_v2
+#define cuLinkAddData cuLinkAddData_v2
+#define cuLinkAddFile cuLinkAddFile_v2
+#define cuMemHostRegister cuMemHostRegister_v2
+#define cuGraphicsResourceSetMapFlags cuGraphicsResourceSetMapFlags_v2
#define cuTexRefSetAddress2D cuTexRefSetAddress2D_v2
#define cuGLCtxCreate cuGLCtxCreate_v2
#define cuGLMapBufferObject cuGLMapBufferObject_v2
#define cuGLMapBufferObjectAsync cuGLMapBufferObjectAsync_v2
+#define cuGLGetDevices cuGLGetDevices_v2
/* Types. */
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
@@ -172,6 +181,11 @@ typedef enum CUevent_flags_enum {
CU_EVENT_INTERPROCESS = 0x4,
} CUevent_flags;
+typedef enum CUoccupancy_flags_enum {
+ CU_OCCUPANCY_DEFAULT = 0x0,
+ CU_OCCUPANCY_DISABLE_CACHING_OVERRIDE = 0x1,
+} CUoccupancy_flags;
+
typedef enum CUarray_format_enum {
CU_AD_FORMAT_UNSIGNED_INT8 = 0x01,
CU_AD_FORMAT_UNSIGNED_INT16 = 0x02,
@@ -381,7 +395,9 @@ typedef enum CUjit_target_enum {
CU_TARGET_COMPUTE_30 = 30,
CU_TARGET_COMPUTE_32 = 32,
CU_TARGET_COMPUTE_35 = 35,
+ CU_TARGET_COMPUTE_37 = 37,
CU_TARGET_COMPUTE_50 = 50,
+ CU_TARGET_COMPUTE_52 = 52,
} CUjit_target;
typedef enum CUjit_fallback_enum {
@@ -474,6 +490,7 @@ typedef enum cudaError_enum {
CUDA_ERROR_CONTEXT_ALREADY_IN_USE = 216,
CUDA_ERROR_PEER_ACCESS_UNSUPPORTED = 217,
CUDA_ERROR_INVALID_PTX = 218,
+ CUDA_ERROR_INVALID_GRAPHICS_CONTEXT = 219,
CUDA_ERROR_INVALID_SOURCE = 300,
CUDA_ERROR_FILE_NOT_FOUND = 301,
CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND = 302,
@@ -506,6 +523,7 @@ typedef enum cudaError_enum {
} CUresult;
typedef void* CUstreamCallback;
+typedef size_t* CUoccupancyB2DSize;
typedef struct CUDA_MEMCPY2D_st {
size_t srcXInBytes;
@@ -730,6 +748,11 @@ typedef CUresult CUDAAPI tcuDeviceTotalMem_v2(size_t* bytes, CUdevice dev);
typedef CUresult CUDAAPI tcuDeviceGetAttribute(int* pi, CUdevice_attribute attrib, CUdevice dev);
typedef CUresult CUDAAPI tcuDeviceGetProperties(CUdevprop* prop, CUdevice dev);
typedef CUresult CUDAAPI tcuDeviceComputeCapability(int* major, int* minor, CUdevice dev);
+typedef CUresult CUDAAPI tcuDevicePrimaryCtxRetain(CUcontext* pctx, CUdevice dev);
+typedef CUresult CUDAAPI tcuDevicePrimaryCtxRelease(CUdevice dev);
+typedef CUresult CUDAAPI tcuDevicePrimaryCtxSetFlags(CUdevice dev, unsigned flags);
+typedef CUresult CUDAAPI tcuDevicePrimaryCtxGetState(CUdevice dev, unsigned* flags, int* active);
+typedef CUresult CUDAAPI tcuDevicePrimaryCtxReset(CUdevice dev);
typedef CUresult CUDAAPI tcuCtxCreate_v2(CUcontext* pctx, unsigned flags, CUdevice dev);
typedef CUresult CUDAAPI tcuCtxDestroy_v2(CUcontext ctx);
typedef CUresult CUDAAPI tcuCtxPushCurrent_v2(CUcontext ctx);
@@ -737,6 +760,7 @@ typedef CUresult CUDAAPI tcuCtxPopCurrent_v2(CUcontext* pctx);
typedef CUresult CUDAAPI tcuCtxSetCurrent(CUcontext ctx);
typedef CUresult CUDAAPI tcuCtxGetCurrent(CUcontext* pctx);
typedef CUresult CUDAAPI tcuCtxGetDevice(CUdevice* device);
+typedef CUresult CUDAAPI tcuCtxGetFlags(unsigned* flags);
typedef CUresult CUDAAPI tcuCtxSynchronize(void);
typedef CUresult CUDAAPI tcuCtxSetLimit(CUlimit limit, size_t value);
typedef CUresult CUDAAPI tcuCtxGetLimit(size_t* pvalue, CUlimit limit);
@@ -757,9 +781,9 @@ typedef CUresult CUDAAPI tcuModuleGetFunction(CUfunction* hfunc, CUmodule hmod,
typedef CUresult CUDAAPI tcuModuleGetGlobal_v2(CUdeviceptr* dptr, size_t* bytes, CUmodule hmod, const char* name);
typedef CUresult CUDAAPI tcuModuleGetTexRef(CUtexref* pTexRef, CUmodule hmod, const char* name);
typedef CUresult CUDAAPI tcuModuleGetSurfRef(CUsurfref* pSurfRef, CUmodule hmod, const char* name);
-typedef CUresult CUDAAPI tcuLinkCreate(unsigned numOptions, CUjit_option* options, void* optionValues, CUlinkState* stateOut);
-typedef CUresult CUDAAPI tcuLinkAddData(CUlinkState state, CUjitInputType type, void* data, size_t size, const char* name, unsigned numOptions, CUjit_option* options, void* optionValues);
-typedef CUresult CUDAAPI tcuLinkAddFile(CUlinkState state, CUjitInputType type, const char* path, unsigned numOptions, CUjit_option* options, void* optionValues);
+typedef CUresult CUDAAPI tcuLinkCreate_v2(unsigned numOptions, CUjit_option* options, void* optionValues, CUlinkState* stateOut);
+typedef CUresult CUDAAPI tcuLinkAddData_v2(CUlinkState state, CUjitInputType type, void* data, size_t size, const char* name, unsigned numOptions, CUjit_option* options, void* optionValues);
+typedef CUresult CUDAAPI tcuLinkAddFile_v2(CUlinkState state, CUjitInputType type, const char* path, unsigned numOptions, CUjit_option* options, void* optionValues);
typedef CUresult CUDAAPI tcuLinkComplete(CUlinkState state, void* cubinOut, size_t* sizeOut);
typedef CUresult CUDAAPI tcuLinkDestroy(CUlinkState state);
typedef CUresult CUDAAPI tcuMemGetInfo_v2(size_t* free, size_t* total);
@@ -780,7 +804,7 @@ typedef CUresult CUDAAPI tcuIpcOpenEventHandle(CUevent* phEvent, CUipcEventHandl
typedef CUresult CUDAAPI tcuIpcGetMemHandle(CUipcMemHandle* pHandle, CUdeviceptr dptr);
typedef CUresult CUDAAPI tcuIpcOpenMemHandle(CUdeviceptr* pdptr, CUipcMemHandle handle, unsigned Flags);
typedef CUresult CUDAAPI tcuIpcCloseMemHandle(CUdeviceptr dptr);
-typedef CUresult CUDAAPI tcuMemHostRegister(void* p, size_t bytesize, unsigned Flags);
+typedef CUresult CUDAAPI tcuMemHostRegister_v2(void* p, size_t bytesize, unsigned Flags);
typedef CUresult CUDAAPI tcuMemHostUnregister(void* p);
typedef CUresult CUDAAPI tcuMemcpy(CUdeviceptr dst, CUdeviceptr src, size_t ByteCount);
typedef CUresult CUDAAPI tcuMemcpyPeer(CUdeviceptr dstDevice, CUcontext dstContext, CUdeviceptr srcDevice, CUcontext srcContext, size_t ByteCount);
@@ -828,6 +852,7 @@ typedef CUresult CUDAAPI tcuMipmappedArrayGetLevel(CUarray* pLevelArray, CUmipma
typedef CUresult CUDAAPI tcuMipmappedArrayDestroy(CUmipmappedArray hMipmappedArray);
typedef CUresult CUDAAPI tcuPointerGetAttribute(void* data, CUpointer_attribute attribute, CUdeviceptr ptr);
typedef CUresult CUDAAPI tcuPointerSetAttribute(const void* value, CUpointer_attribute attribute, CUdeviceptr ptr);
+typedef CUresult CUDAAPI tcuPointerGetAttributes(unsigned numAttributes, CUpointer_attribute* attributes, void* data, CUdeviceptr ptr);
typedef CUresult CUDAAPI tcuStreamCreate(CUstream* phStream, unsigned Flags);
typedef CUresult CUDAAPI tcuStreamCreateWithPriority(CUstream* phStream, unsigned flags, int priority);
typedef CUresult CUDAAPI tcuStreamGetPriority(CUstream hStream, int* priority);
@@ -858,6 +883,10 @@ typedef CUresult CUDAAPI tcuLaunch(CUfunction f);
typedef CUresult CUDAAPI tcuLaunchGrid(CUfunction f, int grid_width, int grid_height);
typedef CUresult CUDAAPI tcuLaunchGridAsync(CUfunction f, int grid_width, int grid_height, CUstream hStream);
typedef CUresult CUDAAPI tcuParamSetTexRef(CUfunction hfunc, int texunit, CUtexref hTexRef);
+typedef CUresult CUDAAPI tcuOccupancyMaxActiveBlocksPerMultiprocessor(int* numBlocks, CUfunction func, int blockSize, size_t dynamicSMemSize);
+typedef CUresult CUDAAPI tcuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags(int* numBlocks, CUfunction func, int blockSize, size_t dynamicSMemSize, unsigned flags);
+typedef CUresult CUDAAPI tcuOccupancyMaxPotentialBlockSize(int* minGridSize, int* blockSize, CUfunction func, CUoccupancyB2DSize blockSizeToDynamicSMemSize, size_t dynamicSMemSize, int blockSizeLimit);
+typedef CUresult CUDAAPI tcuOccupancyMaxPotentialBlockSizeWithFlags(int* minGridSize, int* blockSize, CUfunction func, CUoccupancyB2DSize blockSizeToDynamicSMemSize, size_t dynamicSMemSize, int blockSizeLimit, unsigned flags);
typedef CUresult CUDAAPI tcuTexRefSetArray(CUtexref hTexRef, CUarray hArray, unsigned Flags);
typedef CUresult CUDAAPI tcuTexRefSetMipmappedArray(CUtexref hTexRef, CUmipmappedArray hMipmappedArray, unsigned Flags);
typedef CUresult CUDAAPI tcuTexRefSetAddress_v2(size_t* ByteOffset, CUtexref hTexRef, CUdeviceptr dptr, size_t bytes);
@@ -900,14 +929,14 @@ typedef CUresult CUDAAPI tcuGraphicsUnregisterResource(CUgraphicsResource resour
typedef CUresult CUDAAPI tcuGraphicsSubResourceGetMappedArray(CUarray* pArray, CUgraphicsResource resource, unsigned arrayIndex, unsigned mipLevel);
typedef CUresult CUDAAPI tcuGraphicsResourceGetMappedMipmappedArray(CUmipmappedArray* pMipmappedArray, CUgraphicsResource resource);
typedef CUresult CUDAAPI tcuGraphicsResourceGetMappedPointer_v2(CUdeviceptr* pDevPtr, size_t* pSize, CUgraphicsResource resource);
-typedef CUresult CUDAAPI tcuGraphicsResourceSetMapFlags(CUgraphicsResource resource, unsigned flags);
+typedef CUresult CUDAAPI tcuGraphicsResourceSetMapFlags_v2(CUgraphicsResource resource, unsigned flags);
typedef CUresult CUDAAPI tcuGraphicsMapResources(unsigned count, CUgraphicsResource* resources, CUstream hStream);
typedef CUresult CUDAAPI tcuGraphicsUnmapResources(unsigned count, CUgraphicsResource* resources, CUstream hStream);
typedef CUresult CUDAAPI tcuGetExportTable(const void* ppExportTable, const CUuuid* pExportTableId);
typedef CUresult CUDAAPI tcuGraphicsGLRegisterBuffer(CUgraphicsResource* pCudaResource, GLuint buffer, unsigned Flags);
typedef CUresult CUDAAPI tcuGraphicsGLRegisterImage(CUgraphicsResource* pCudaResource, GLuint image, GLenum target, unsigned Flags);
-typedef CUresult CUDAAPI tcuGLGetDevices(unsigned* pCudaDeviceCount, CUdevice* pCudaDevices, unsigned cudaDeviceCount, CUGLDeviceList deviceList);
+typedef CUresult CUDAAPI tcuGLGetDevices_v2(unsigned* pCudaDeviceCount, CUdevice* pCudaDevices, unsigned cudaDeviceCount, CUGLDeviceList deviceList);
typedef CUresult CUDAAPI tcuGLCtxCreate_v2(CUcontext* pCtx, unsigned Flags, CUdevice device);
typedef CUresult CUDAAPI tcuGLInit(void);
typedef CUresult CUDAAPI tcuGLRegisterBufferObject(GLuint buffer);
@@ -931,6 +960,11 @@ extern tcuDeviceTotalMem_v2 *cuDeviceTotalMem_v2;
extern tcuDeviceGetAttribute *cuDeviceGetAttribute;
extern tcuDeviceGetProperties *cuDeviceGetProperties;
extern tcuDeviceComputeCapability *cuDeviceComputeCapability;
+extern tcuDevicePrimaryCtxRetain *cuDevicePrimaryCtxRetain;
+extern tcuDevicePrimaryCtxRelease *cuDevicePrimaryCtxRelease;
+extern tcuDevicePrimaryCtxSetFlags *cuDevicePrimaryCtxSetFlags;
+extern tcuDevicePrimaryCtxGetState *cuDevicePrimaryCtxGetState;
+extern tcuDevicePrimaryCtxReset *cuDevicePrimaryCtxReset;
extern tcuCtxCreate_v2 *cuCtxCreate_v2;
extern tcuCtxDestroy_v2 *cuCtxDestroy_v2;
extern tcuCtxPushCurrent_v2 *cuCtxPushCurrent_v2;
@@ -938,6 +972,7 @@ extern tcuCtxPopCurrent_v2 *cuCtxPopCurrent_v2;
extern tcuCtxSetCurrent *cuCtxSetCurrent;
extern tcuCtxGetCurrent *cuCtxGetCurrent;
extern tcuCtxGetDevice *cuCtxGetDevice;
+extern tcuCtxGetFlags *cuCtxGetFlags;
extern tcuCtxSynchronize *cuCtxSynchronize;
extern tcuCtxSetLimit *cuCtxSetLimit;
extern tcuCtxGetLimit *cuCtxGetLimit;
@@ -958,9 +993,9 @@ extern tcuModuleGetFunction *cuModuleGetFunction;
extern tcuModuleGetGlobal_v2 *cuModuleGetGlobal_v2;
extern tcuModuleGetTexRef *cuModuleGetTexRef;
extern tcuModuleGetSurfRef *cuModuleGetSurfRef;
-extern tcuLinkCreate *cuLinkCreate;
-extern tcuLinkAddData *cuLinkAddData;
-extern tcuLinkAddFile *cuLinkAddFile;
+extern tcuLinkCreate_v2 *cuLinkCreate_v2;
+extern tcuLinkAddData_v2 *cuLinkAddData_v2;
+extern tcuLinkAddFile_v2 *cuLinkAddFile_v2;
extern tcuLinkComplete *cuLinkComplete;
extern tcuLinkDestroy *cuLinkDestroy;
extern tcuMemGetInfo_v2 *cuMemGetInfo_v2;
@@ -981,7 +1016,7 @@ extern tcuIpcOpenEventHandle *cuIpcOpenEventHandle;
extern tcuIpcGetMemHandle *cuIpcGetMemHandle;
extern tcuIpcOpenMemHandle *cuIpcOpenMemHandle;
extern tcuIpcCloseMemHandle *cuIpcCloseMemHandle;
-extern tcuMemHostRegister *cuMemHostRegister;
+extern tcuMemHostRegister_v2 *cuMemHostRegister_v2;
extern tcuMemHostUnregister *cuMemHostUnregister;
extern tcuMemcpy *cuMemcpy;
extern tcuMemcpyPeer *cuMemcpyPeer;
@@ -1029,6 +1064,7 @@ extern tcuMipmappedArrayGetLevel *cuMipmappedArrayGetLevel;
extern tcuMipmappedArrayDestroy *cuMipmappedArrayDestroy;
extern tcuPointerGetAttribute *cuPointerGetAttribute;
extern tcuPointerSetAttribute *cuPointerSetAttribute;
+extern tcuPointerGetAttributes *cuPointerGetAttributes;
extern tcuStreamCreate *cuStreamCreate;
extern tcuStreamCreateWithPriority *cuStreamCreateWithPriority;
extern tcuStreamGetPriority *cuStreamGetPriority;
@@ -1059,6 +1095,10 @@ extern tcuLaunch *cuLaunch;
extern tcuLaunchGrid *cuLaunchGrid;
extern tcuLaunchGridAsync *cuLaunchGridAsync;
extern tcuParamSetTexRef *cuParamSetTexRef;
+extern tcuOccupancyMaxActiveBlocksPerMultiprocessor *cuOccupancyMaxActiveBlocksPerMultiprocessor;
+extern tcuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags *cuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags;
+extern tcuOccupancyMaxPotentialBlockSize *cuOccupancyMaxPotentialBlockSize;
+extern tcuOccupancyMaxPotentialBlockSizeWithFlags *cuOccupancyMaxPotentialBlockSizeWithFlags;
extern tcuTexRefSetArray *cuTexRefSetArray;
extern tcuTexRefSetMipmappedArray *cuTexRefSetMipmappedArray;
extern tcuTexRefSetAddress_v2 *cuTexRefSetAddress_v2;
@@ -1101,14 +1141,14 @@ extern tcuGraphicsUnregisterResource *cuGraphicsUnregisterResource;
extern tcuGraphicsSubResourceGetMappedArray *cuGraphicsSubResourceGetMappedArray;
extern tcuGraphicsResourceGetMappedMipmappedArray *cuGraphicsResourceGetMappedMipmappedArray;
extern tcuGraphicsResourceGetMappedPointer_v2 *cuGraphicsResourceGetMappedPointer_v2;
-extern tcuGraphicsResourceSetMapFlags *cuGraphicsResourceSetMapFlags;
+extern tcuGraphicsResourceSetMapFlags_v2 *cuGraphicsResourceSetMapFlags_v2;
extern tcuGraphicsMapResources *cuGraphicsMapResources;
extern tcuGraphicsUnmapResources *cuGraphicsUnmapResources;
extern tcuGetExportTable *cuGetExportTable;
extern tcuGraphicsGLRegisterBuffer *cuGraphicsGLRegisterBuffer;
extern tcuGraphicsGLRegisterImage *cuGraphicsGLRegisterImage;
-extern tcuGLGetDevices *cuGLGetDevices;
+extern tcuGLGetDevices_v2 *cuGLGetDevices_v2;
extern tcuGLCtxCreate_v2 *cuGLCtxCreate_v2;
extern tcuGLInit *cuGLInit;
extern tcuGLRegisterBufferObject *cuGLRegisterBufferObject;
diff --git a/extern/cuew/src/cuew.c b/extern/cuew/src/cuew.c
index da892efc0f4..3058e29d89f 100644
--- a/extern/cuew/src/cuew.c
+++ b/extern/cuew/src/cuew.c
@@ -36,7 +36,7 @@
typedef HMODULE DynamicLibrary;
-# define dynamic_library_open(path) LoadLibrary(path)
+# define dynamic_library_open(path) LoadLibraryA(path)
# define dynamic_library_close(lib) FreeLibrary(lib)
# define dynamic_library_find(lib, symbol) GetProcAddress(lib, symbol)
#else
@@ -70,6 +70,11 @@ tcuDeviceTotalMem_v2 *cuDeviceTotalMem_v2;
tcuDeviceGetAttribute *cuDeviceGetAttribute;
tcuDeviceGetProperties *cuDeviceGetProperties;
tcuDeviceComputeCapability *cuDeviceComputeCapability;
+tcuDevicePrimaryCtxRetain *cuDevicePrimaryCtxRetain;
+tcuDevicePrimaryCtxRelease *cuDevicePrimaryCtxRelease;
+tcuDevicePrimaryCtxSetFlags *cuDevicePrimaryCtxSetFlags;
+tcuDevicePrimaryCtxGetState *cuDevicePrimaryCtxGetState;
+tcuDevicePrimaryCtxReset *cuDevicePrimaryCtxReset;
tcuCtxCreate_v2 *cuCtxCreate_v2;
tcuCtxDestroy_v2 *cuCtxDestroy_v2;
tcuCtxPushCurrent_v2 *cuCtxPushCurrent_v2;
@@ -77,6 +82,7 @@ tcuCtxPopCurrent_v2 *cuCtxPopCurrent_v2;
tcuCtxSetCurrent *cuCtxSetCurrent;
tcuCtxGetCurrent *cuCtxGetCurrent;
tcuCtxGetDevice *cuCtxGetDevice;
+tcuCtxGetFlags *cuCtxGetFlags;
tcuCtxSynchronize *cuCtxSynchronize;
tcuCtxSetLimit *cuCtxSetLimit;
tcuCtxGetLimit *cuCtxGetLimit;
@@ -97,9 +103,9 @@ tcuModuleGetFunction *cuModuleGetFunction;
tcuModuleGetGlobal_v2 *cuModuleGetGlobal_v2;
tcuModuleGetTexRef *cuModuleGetTexRef;
tcuModuleGetSurfRef *cuModuleGetSurfRef;
-tcuLinkCreate *cuLinkCreate;
-tcuLinkAddData *cuLinkAddData;
-tcuLinkAddFile *cuLinkAddFile;
+tcuLinkCreate_v2 *cuLinkCreate_v2;
+tcuLinkAddData_v2 *cuLinkAddData_v2;
+tcuLinkAddFile_v2 *cuLinkAddFile_v2;
tcuLinkComplete *cuLinkComplete;
tcuLinkDestroy *cuLinkDestroy;
tcuMemGetInfo_v2 *cuMemGetInfo_v2;
@@ -120,7 +126,7 @@ tcuIpcOpenEventHandle *cuIpcOpenEventHandle;
tcuIpcGetMemHandle *cuIpcGetMemHandle;
tcuIpcOpenMemHandle *cuIpcOpenMemHandle;
tcuIpcCloseMemHandle *cuIpcCloseMemHandle;
-tcuMemHostRegister *cuMemHostRegister;
+tcuMemHostRegister_v2 *cuMemHostRegister_v2;
tcuMemHostUnregister *cuMemHostUnregister;
tcuMemcpy *cuMemcpy;
tcuMemcpyPeer *cuMemcpyPeer;
@@ -168,6 +174,7 @@ tcuMipmappedArrayGetLevel *cuMipmappedArrayGetLevel;
tcuMipmappedArrayDestroy *cuMipmappedArrayDestroy;
tcuPointerGetAttribute *cuPointerGetAttribute;
tcuPointerSetAttribute *cuPointerSetAttribute;
+tcuPointerGetAttributes *cuPointerGetAttributes;
tcuStreamCreate *cuStreamCreate;
tcuStreamCreateWithPriority *cuStreamCreateWithPriority;
tcuStreamGetPriority *cuStreamGetPriority;
@@ -198,6 +205,10 @@ tcuLaunch *cuLaunch;
tcuLaunchGrid *cuLaunchGrid;
tcuLaunchGridAsync *cuLaunchGridAsync;
tcuParamSetTexRef *cuParamSetTexRef;
+tcuOccupancyMaxActiveBlocksPerMultiprocessor *cuOccupancyMaxActiveBlocksPerMultiprocessor;
+tcuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags *cuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags;
+tcuOccupancyMaxPotentialBlockSize *cuOccupancyMaxPotentialBlockSize;
+tcuOccupancyMaxPotentialBlockSizeWithFlags *cuOccupancyMaxPotentialBlockSizeWithFlags;
tcuTexRefSetArray *cuTexRefSetArray;
tcuTexRefSetMipmappedArray *cuTexRefSetMipmappedArray;
tcuTexRefSetAddress_v2 *cuTexRefSetAddress_v2;
@@ -240,14 +251,14 @@ tcuGraphicsUnregisterResource *cuGraphicsUnregisterResource;
tcuGraphicsSubResourceGetMappedArray *cuGraphicsSubResourceGetMappedArray;
tcuGraphicsResourceGetMappedMipmappedArray *cuGraphicsResourceGetMappedMipmappedArray;
tcuGraphicsResourceGetMappedPointer_v2 *cuGraphicsResourceGetMappedPointer_v2;
-tcuGraphicsResourceSetMapFlags *cuGraphicsResourceSetMapFlags;
+tcuGraphicsResourceSetMapFlags_v2 *cuGraphicsResourceSetMapFlags_v2;
tcuGraphicsMapResources *cuGraphicsMapResources;
tcuGraphicsUnmapResources *cuGraphicsUnmapResources;
tcuGetExportTable *cuGetExportTable;
tcuGraphicsGLRegisterBuffer *cuGraphicsGLRegisterBuffer;
tcuGraphicsGLRegisterImage *cuGraphicsGLRegisterImage;
-tcuGLGetDevices *cuGLGetDevices;
+tcuGLGetDevices_v2 *cuGLGetDevices_v2;
tcuGLCtxCreate_v2 *cuGLCtxCreate_v2;
tcuGLInit *cuGLInit;
tcuGLRegisterBufferObject *cuGLRegisterBufferObject;
@@ -328,6 +339,11 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuDeviceGetAttribute);
CUDA_LIBRARY_FIND(cuDeviceGetProperties);
CUDA_LIBRARY_FIND(cuDeviceComputeCapability);
+ CUDA_LIBRARY_FIND(cuDevicePrimaryCtxRetain);
+ CUDA_LIBRARY_FIND(cuDevicePrimaryCtxRelease);
+ CUDA_LIBRARY_FIND(cuDevicePrimaryCtxSetFlags);
+ CUDA_LIBRARY_FIND(cuDevicePrimaryCtxGetState);
+ CUDA_LIBRARY_FIND(cuDevicePrimaryCtxReset);
CUDA_LIBRARY_FIND(cuCtxCreate_v2);
CUDA_LIBRARY_FIND(cuCtxDestroy_v2);
CUDA_LIBRARY_FIND(cuCtxPushCurrent_v2);
@@ -335,6 +351,7 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuCtxSetCurrent);
CUDA_LIBRARY_FIND(cuCtxGetCurrent);
CUDA_LIBRARY_FIND(cuCtxGetDevice);
+ CUDA_LIBRARY_FIND(cuCtxGetFlags);
CUDA_LIBRARY_FIND(cuCtxSynchronize);
CUDA_LIBRARY_FIND(cuCtxSetLimit);
CUDA_LIBRARY_FIND(cuCtxGetLimit);
@@ -355,9 +372,9 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuModuleGetGlobal_v2);
CUDA_LIBRARY_FIND(cuModuleGetTexRef);
CUDA_LIBRARY_FIND(cuModuleGetSurfRef);
- CUDA_LIBRARY_FIND(cuLinkCreate);
- CUDA_LIBRARY_FIND(cuLinkAddData);
- CUDA_LIBRARY_FIND(cuLinkAddFile);
+ CUDA_LIBRARY_FIND(cuLinkCreate_v2);
+ CUDA_LIBRARY_FIND(cuLinkAddData_v2);
+ CUDA_LIBRARY_FIND(cuLinkAddFile_v2);
CUDA_LIBRARY_FIND(cuLinkComplete);
CUDA_LIBRARY_FIND(cuLinkDestroy);
CUDA_LIBRARY_FIND(cuMemGetInfo_v2);
@@ -378,7 +395,7 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuIpcGetMemHandle);
CUDA_LIBRARY_FIND(cuIpcOpenMemHandle);
CUDA_LIBRARY_FIND(cuIpcCloseMemHandle);
- CUDA_LIBRARY_FIND(cuMemHostRegister);
+ CUDA_LIBRARY_FIND(cuMemHostRegister_v2);
CUDA_LIBRARY_FIND(cuMemHostUnregister);
CUDA_LIBRARY_FIND(cuMemcpy);
CUDA_LIBRARY_FIND(cuMemcpyPeer);
@@ -426,6 +443,7 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuMipmappedArrayDestroy);
CUDA_LIBRARY_FIND(cuPointerGetAttribute);
CUDA_LIBRARY_FIND(cuPointerSetAttribute);
+ CUDA_LIBRARY_FIND(cuPointerGetAttributes);
CUDA_LIBRARY_FIND(cuStreamCreate);
CUDA_LIBRARY_FIND(cuStreamCreateWithPriority);
CUDA_LIBRARY_FIND(cuStreamGetPriority);
@@ -456,6 +474,10 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuLaunchGrid);
CUDA_LIBRARY_FIND(cuLaunchGridAsync);
CUDA_LIBRARY_FIND(cuParamSetTexRef);
+ CUDA_LIBRARY_FIND(cuOccupancyMaxActiveBlocksPerMultiprocessor);
+ CUDA_LIBRARY_FIND(cuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags);
+ CUDA_LIBRARY_FIND(cuOccupancyMaxPotentialBlockSize);
+ CUDA_LIBRARY_FIND(cuOccupancyMaxPotentialBlockSizeWithFlags);
CUDA_LIBRARY_FIND(cuTexRefSetArray);
CUDA_LIBRARY_FIND(cuTexRefSetMipmappedArray);
CUDA_LIBRARY_FIND(cuTexRefSetAddress_v2);
@@ -498,14 +520,14 @@ int cuewInit(void) {
CUDA_LIBRARY_FIND(cuGraphicsSubResourceGetMappedArray);
CUDA_LIBRARY_FIND(cuGraphicsResourceGetMappedMipmappedArray);
CUDA_LIBRARY_FIND(cuGraphicsResourceGetMappedPointer_v2);
- CUDA_LIBRARY_FIND(cuGraphicsResourceSetMapFlags);
+ CUDA_LIBRARY_FIND(cuGraphicsResourceSetMapFlags_v2);
CUDA_LIBRARY_FIND(cuGraphicsMapResources);
CUDA_LIBRARY_FIND(cuGraphicsUnmapResources);
CUDA_LIBRARY_FIND(cuGetExportTable);
CUDA_LIBRARY_FIND(cuGraphicsGLRegisterBuffer);
CUDA_LIBRARY_FIND(cuGraphicsGLRegisterImage);
- CUDA_LIBRARY_FIND(cuGLGetDevices);
+ CUDA_LIBRARY_FIND(cuGLGetDevices_v2);
CUDA_LIBRARY_FIND(cuGLCtxCreate_v2);
CUDA_LIBRARY_FIND(cuGLInit);
CUDA_LIBRARY_FIND(cuGLRegisterBufferObject);
@@ -528,10 +550,10 @@ const char *cuewErrorString(CUresult result) {
case CUDA_ERROR_OUT_OF_MEMORY: return "Out of memory";
case CUDA_ERROR_NOT_INITIALIZED: return "Driver not initialized";
case CUDA_ERROR_DEINITIALIZED: return "Driver deinitialized";
- case CUDA_ERROR_PROFILER_DISABLED: return "PROFILER_DISABLED";
- case CUDA_ERROR_PROFILER_NOT_INITIALIZED: return "PROFILER_NOT_INITIALIZED";
- case CUDA_ERROR_PROFILER_ALREADY_STARTED: return "PROFILER_ALREADY_STARTED";
- case CUDA_ERROR_PROFILER_ALREADY_STOPPED: return "PROFILER_ALREADY_STOPPED";
+ case CUDA_ERROR_PROFILER_DISABLED: return "Profiler disabled";
+ case CUDA_ERROR_PROFILER_NOT_INITIALIZED: return "Profiler not initialized";
+ case CUDA_ERROR_PROFILER_ALREADY_STARTED: return "Profiler already started";
+ case CUDA_ERROR_PROFILER_ALREADY_STOPPED: return "Profiler already stopped";
case CUDA_ERROR_NO_DEVICE: return "No CUDA-capable device available";
case CUDA_ERROR_INVALID_DEVICE: return "Invalid device";
case CUDA_ERROR_INVALID_IMAGE: return "Invalid kernel image";
@@ -548,37 +570,38 @@ const char *cuewErrorString(CUresult result) {
case CUDA_ERROR_NOT_MAPPED_AS_POINTER: return "Mapped resource not available for access as a pointer";
case CUDA_ERROR_ECC_UNCORRECTABLE: return "Uncorrectable ECC error detected";
case CUDA_ERROR_UNSUPPORTED_LIMIT: return "CUlimit not supported by device";
- case CUDA_ERROR_CONTEXT_ALREADY_IN_USE: return "CONTEXT_ALREADY_IN_USE";
- case CUDA_ERROR_PEER_ACCESS_UNSUPPORTED: return "PEER_ACCESS_UNSUPPORTED";
- case CUDA_ERROR_INVALID_PTX: return "INVALID_PTX";
+ case CUDA_ERROR_CONTEXT_ALREADY_IN_USE: return "Context already in use";
+ case CUDA_ERROR_PEER_ACCESS_UNSUPPORTED: return "Peer access unsupported";
+ case CUDA_ERROR_INVALID_PTX: return "Invalid ptx";
+ case CUDA_ERROR_INVALID_GRAPHICS_CONTEXT: return "Invalid graphics context";
case CUDA_ERROR_INVALID_SOURCE: return "Invalid source";
case CUDA_ERROR_FILE_NOT_FOUND: return "File not found";
case CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND: return "Link to a shared object failed to resolve";
case CUDA_ERROR_SHARED_OBJECT_INIT_FAILED: return "Shared object initialization failed";
- case CUDA_ERROR_OPERATING_SYSTEM: return "OPERATING_SYSTEM";
+ case CUDA_ERROR_OPERATING_SYSTEM: return "Operating system";
case CUDA_ERROR_INVALID_HANDLE: return "Invalid handle";
case CUDA_ERROR_NOT_FOUND: return "Not found";
case CUDA_ERROR_NOT_READY: return "CUDA not ready";
- case CUDA_ERROR_ILLEGAL_ADDRESS: return "ILLEGAL_ADDRESS";
+ case CUDA_ERROR_ILLEGAL_ADDRESS: return "Illegal address";
case CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES: return "Launch exceeded resources";
case CUDA_ERROR_LAUNCH_TIMEOUT: return "Launch exceeded timeout";
case CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING: return "Launch with incompatible texturing";
- case CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED: return "PEER_ACCESS_ALREADY_ENABLED";
- case CUDA_ERROR_PEER_ACCESS_NOT_ENABLED: return "PEER_ACCESS_NOT_ENABLED";
- case CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE: return "PRIMARY_CONTEXT_ACTIVE";
- case CUDA_ERROR_CONTEXT_IS_DESTROYED: return "CONTEXT_IS_DESTROYED";
- case CUDA_ERROR_ASSERT: return "ASSERT";
- case CUDA_ERROR_TOO_MANY_PEERS: return "TOO_MANY_PEERS";
- case CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED: return "HOST_MEMORY_ALREADY_REGISTERED";
- case CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED: return "HOST_MEMORY_NOT_REGISTERED";
- case CUDA_ERROR_HARDWARE_STACK_ERROR: return "HARDWARE_STACK_ERROR";
- case CUDA_ERROR_ILLEGAL_INSTRUCTION: return "ILLEGAL_INSTRUCTION";
- case CUDA_ERROR_MISALIGNED_ADDRESS: return "MISALIGNED_ADDRESS";
- case CUDA_ERROR_INVALID_ADDRESS_SPACE: return "INVALID_ADDRESS_SPACE";
- case CUDA_ERROR_INVALID_PC: return "INVALID_PC";
+ case CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED: return "Peer access already enabled";
+ case CUDA_ERROR_PEER_ACCESS_NOT_ENABLED: return "Peer access not enabled";
+ case CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE: return "Primary context active";
+ case CUDA_ERROR_CONTEXT_IS_DESTROYED: return "Context is destroyed";
+ case CUDA_ERROR_ASSERT: return "Assert";
+ case CUDA_ERROR_TOO_MANY_PEERS: return "Too many peers";
+ case CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED: return "Host memory already registered";
+ case CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED: return "Host memory not registered";
+ case CUDA_ERROR_HARDWARE_STACK_ERROR: return "Hardware stack error";
+ case CUDA_ERROR_ILLEGAL_INSTRUCTION: return "Illegal instruction";
+ case CUDA_ERROR_MISALIGNED_ADDRESS: return "Misaligned address";
+ case CUDA_ERROR_INVALID_ADDRESS_SPACE: return "Invalid address space";
+ case CUDA_ERROR_INVALID_PC: return "Invalid pc";
case CUDA_ERROR_LAUNCH_FAILED: return "Launch failed";
- case CUDA_ERROR_NOT_PERMITTED: return "NOT_PERMITTED";
- case CUDA_ERROR_NOT_SUPPORTED: return "NOT_SUPPORTED";
+ case CUDA_ERROR_NOT_PERMITTED: return "Not permitted";
+ case CUDA_ERROR_NOT_SUPPORTED: return "Not supported";
case CUDA_ERROR_UNKNOWN: return "Unknown error";
default: return "Unknown CUDA error value";
}
@@ -686,7 +709,7 @@ int cuewCompilerVersion(void) {
while (!feof(pipe)) {
if (fgets(buf, sizeof(buf), pipe) != NULL) {
- strncat(output, buf, sizeof(output) - strlen(output) - 1 );
+ strncat(output, buf, sizeof(output) - strlen(output) - 1);
}
}
diff --git a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h
index 6a3ade81089..1a8bf7a1c87 100644
--- a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h
+++ b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h
@@ -197,7 +197,7 @@ class CameraIntrinsics {
double *normalized_x,
double *normalized_y) const = 0;
- // Distort an image using the current camera instrinsics
+ // Distort an image using the current camera intrinsics
//
// The distorted image is computed in output_buffer using samples from
// input_buffer. Both buffers should be width x height x channels sized.
@@ -226,7 +226,7 @@ class CameraIntrinsics {
int channels,
PixelType *output_buffer);
- // Undistort an image using the current camera instrinsics
+ // Undistort an image using the current camera intrinsics
//
// The undistorted image is computed in output_buffer using samples from
// input_buffer. Both buffers should be width x height x channels sized.
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index 4ee3dff7695..275524f788f 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -32,6 +32,7 @@ add_subdirectory(opencolorio)
add_subdirectory(mikktspace)
add_subdirectory(raskter)
add_subdirectory(glew-mx)
+add_subdirectory(eigen)
if(WITH_AUDASPACE)
add_subdirectory(audaspace)
@@ -73,10 +74,6 @@ if(WITH_BULLET)
add_subdirectory(rigidbody)
endif()
-if(WITH_OPENNL)
- add_subdirectory(opennl)
-endif()
-
if(WITH_OPENSUBDIV)
add_subdirectory(opensubdiv)
endif()
diff --git a/intern/SConscript b/intern/SConscript
index 124afd4bbb9..736242102cc 100644
--- a/intern/SConscript
+++ b/intern/SConscript
@@ -35,8 +35,8 @@ SConscript(['string/SConscript',
'memutil/SConscript/',
'iksolver/SConscript',
'itasc/SConscript',
+ 'eigen/SConscript',
'opencolorio/SConscript',
- 'opennl/SConscript',
'mikktspace/SConscript',
'smoke/SConscript',
'raskter/SConscript'])
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
index ba961f0cb78..ff2c526bf49 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
@@ -389,9 +389,7 @@ void AUD_FFMPEGReader::seek(int position)
int length = AUD_DEFAULT_BUFFER_SIZE;
AUD_Buffer buffer(length * AUD_SAMPLE_SIZE(m_specs));
bool eos;
- for(int len = position - m_position;
- length == AUD_DEFAULT_BUFFER_SIZE;
- len -= AUD_DEFAULT_BUFFER_SIZE)
+ for(int len = position - m_position; len > 0; len -= AUD_DEFAULT_BUFFER_SIZE)
{
if(len < AUD_DEFAULT_BUFFER_SIZE)
length = len;
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 5bbdeb6061b..74dee206c0e 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -107,6 +107,32 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket b_socket)
}
}
+#ifdef WITH_OSL
+static ShaderSocketType convert_osl_socket_type(OSL::OSLQuery& query,
+ BL::NodeSocket b_socket)
+{
+ ShaderSocketType socket_type = convert_socket_type(b_socket);
+#if OSL_LIBRARY_VERSION_CODE < 10701
+ (void) query;
+#else
+ if(socket_type == SHADER_SOCKET_VECTOR) {
+ /* TODO(sergey): Do we need compatible_name() here? */
+ const OSL::OSLQuery::Parameter *param = query.getparam(b_socket.name());
+ assert(param != NULL);
+ if(param != NULL) {
+ if(param->type.vecsemantics == TypeDesc::POINT) {
+ socket_type = SHADER_SOCKET_POINT;
+ }
+ else if(param->type.vecsemantics == TypeDesc::NORMAL) {
+ socket_type = SHADER_SOCKET_NORMAL;
+ }
+ }
+ }
+#endif
+ return socket_type;
+}
+#endif /* WITH_OSL */
+
static void set_default_value(ShaderInput *input, BL::NodeSocket b_sock, BL::BlendData b_data, BL::ID b_id)
{
/* copy values for non linked inputs */
@@ -184,6 +210,7 @@ static ShaderNode *add_node(Scene *scene,
BL::RenderEngine b_engine,
BL::BlendData b_data,
BL::Scene b_scene,
+ const bool background,
ShaderGraph *graph,
BL::ShaderNodeTree b_ntree,
BL::ShaderNode b_node)
@@ -193,8 +220,13 @@ static ShaderNode *add_node(Scene *scene,
/* existing blender nodes */
if(b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
BL::ShaderNodeRGBCurve b_curve_node(b_node);
+ BL::CurveMapping mapping(b_curve_node.mapping());
RGBCurvesNode *curves = new RGBCurvesNode();
- curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, true);
+ curvemapping_color_to_array(mapping,
+ curves->curves,
+ RAMP_TABLE_SIZE,
+ true);
+ curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x);
node = curves;
}
if(b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
@@ -507,6 +539,23 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeScript b_script_node(b_node);
OSLScriptNode *script_node = new OSLScriptNode();
+ OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
+ string bytecode_hash = b_script_node.bytecode_hash();
+
+ /* Gather additional information from the shader, such as
+ * input/output type info needed for proper node construction.
+ */
+ OSL::OSLQuery query;
+#if OSL_LIBRARY_VERSION_CODE >= 10701
+ if(!bytecode_hash.empty()) {
+ query.open_bytecode(b_script_node.bytecode());
+ }
+ else {
+ !OSLShaderManager::osl_query(query, b_script_node.filepath());
+ }
+ /* TODO(sergey): Add proper query info error parsing. */
+#endif
+
/* Generate inputs/outputs from node sockets
*
* Note: the node sockets are generated from OSL parameters,
@@ -519,7 +568,7 @@ static ShaderNode *add_node(Scene *scene,
for(b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
script_node->input_names.push_back(ustring(b_input->name()));
ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(),
- convert_socket_type(*b_input));
+ convert_osl_socket_type(query, *b_input));
set_default_value(input, *b_input, b_data, b_ntree);
}
@@ -528,13 +577,10 @@ static ShaderNode *add_node(Scene *scene,
for(b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
script_node->output_names.push_back(ustring(b_output->name()));
script_node->add_output(script_node->output_names.back().c_str(),
- convert_socket_type(*b_output));
+ convert_osl_socket_type(query, *b_output));
}
/* load bytecode or filepath */
- OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
- string bytecode_hash = b_script_node.bytecode_hash();
-
if(!bytecode_hash.empty()) {
/* loaded bytecode if not already done */
if(!manager->shader_test_loaded(bytecode_hash))
@@ -763,6 +809,8 @@ static ShaderNode *add_node(Scene *scene,
/* TODO(sergey): Use more proper update flag. */
if(true) {
+ int settings = background ? 1 : 0; /* 1 - render settings, 0 - vewport settings. */
+ b_point_density_node.cache_point_density(b_scene, settings);
scene->image_manager->tag_reload_image(
point_density->filename,
point_density->builtin_data,
@@ -852,6 +900,7 @@ static void add_nodes(Scene *scene,
BL::RenderEngine b_engine,
BL::BlendData b_data,
BL::Scene b_scene,
+ const bool background,
ShaderGraph *graph,
BL::ShaderNodeTree b_ntree,
const ProxyMap &proxy_input_map,
@@ -937,6 +986,7 @@ static void add_nodes(Scene *scene,
b_engine,
b_data,
b_scene,
+ background,
graph,
b_group_ntree,
group_proxy_input_map,
@@ -984,6 +1034,7 @@ static void add_nodes(Scene *scene,
b_engine,
b_data,
b_scene,
+ background,
graph,
b_ntree,
BL::ShaderNode(*b_node));
@@ -1046,6 +1097,7 @@ static void add_nodes(Scene *scene,
BL::RenderEngine b_engine,
BL::BlendData b_data,
BL::Scene b_scene,
+ const bool background,
ShaderGraph *graph,
BL::ShaderNodeTree b_ntree)
{
@@ -1054,6 +1106,7 @@ static void add_nodes(Scene *scene,
b_engine,
b_data,
b_scene,
+ background,
graph,
b_ntree,
empty_proxy_map,
@@ -1083,7 +1136,7 @@ void BlenderSync::sync_materials(bool update_all)
if(b_mat->use_nodes() && b_mat->node_tree()) {
BL::ShaderNodeTree b_ntree(b_mat->node_tree());
- add_nodes(scene, b_engine, b_data, b_scene, graph, b_ntree);
+ add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
}
else {
ShaderNode *closure, *out;
@@ -1126,7 +1179,7 @@ void BlenderSync::sync_world(bool update_all)
if(b_world && b_world.use_nodes() && b_world.node_tree()) {
BL::ShaderNodeTree b_ntree(b_world.node_tree());
- add_nodes(scene, b_engine, b_data, b_scene, graph, b_ntree);
+ add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
/* volume */
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
@@ -1217,7 +1270,7 @@ void BlenderSync::sync_lamps(bool update_all)
BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
- add_nodes(scene, b_engine, b_data, b_scene, graph, b_ntree);
+ add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
}
else {
ShaderNode *closure, *out;
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 2e9e9266404..029d0af0fd2 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -62,6 +62,29 @@ static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size
}
}
+static inline void curvemap_minmax_curve(/*const*/ BL::CurveMap& curve,
+ float *min_x,
+ float *max_x)
+{
+ *min_x = min(*min_x, curve.points[0].location()[0]);
+ *max_x = max(*max_x, curve.points[curve.points.length() - 1].location()[0]);
+}
+
+static inline void curvemapping_minmax(/*const*/ BL::CurveMapping& cumap,
+ bool rgb_curve,
+ float *min_x,
+ float *max_x)
+{
+ /* const int num_curves = cumap.curves.length(); */ /* Gives linking error so far. */
+ const int num_curves = rgb_curve? 4: 3;
+ *min_x = FLT_MAX;
+ *max_x = -FLT_MAX;
+ for(int i = 0; i < num_curves; ++i) {
+ BL::CurveMap map(cumap.curves[i]);
+ curvemap_minmax_curve(map, min_x, max_x);
+ }
+}
+
static inline void curvemapping_to_array(BL::CurveMapping cumap, float *data, int size)
{
cumap.update();
@@ -72,8 +95,29 @@ static inline void curvemapping_to_array(BL::CurveMapping cumap, float *data, in
}
}
-static inline void curvemapping_color_to_array(BL::CurveMapping cumap, float4 *data, int size, bool rgb_curve)
+static inline void curvemapping_color_to_array(BL::CurveMapping cumap,
+ float4 *data,
+ int size,
+ bool rgb_curve)
{
+ float min_x = 0.0f, max_x = 1.0f;
+ /* TODO(sergey): Vector curve mapping is still clipping to 0..1. */
+ if(rgb_curve) {
+ /* TODO(sergey): There is no easy way to automatically guess what is
+ * the range to be used here for the case when mapping is applied on
+ * top of another mapping (i.e. R curve applied on top of common
+ * one).
+ *
+ * Using largest possible range form all curves works correct for the
+ * cases like vector curves and should be good enough heuristic for
+ * the color curves as well.
+ *
+ * There might be some better estimations here tho.
+ */
+ curvemapping_minmax(cumap, rgb_curve, &min_x, &max_x);
+ }
+ const float range_x = max_x - min_x;
+
cumap.update();
BL::CurveMap mapR = cumap.curves[0];
@@ -84,7 +128,7 @@ static inline void curvemapping_color_to_array(BL::CurveMapping cumap, float4 *d
BL::CurveMap mapI = cumap.curves[3];
for(int i = 0; i < size; i++) {
- float t = (float)i/(float)(size-1);
+ float t = min_x + (float)i/(float)(size-1) * range_x;
data[i][0] = mapR.evaluate(mapI.evaluate(t));
data[i][1] = mapG.evaluate(mapI.evaluate(t));
@@ -93,7 +137,7 @@ static inline void curvemapping_color_to_array(BL::CurveMapping cumap, float4 *d
}
else {
for(int i = 0; i < size; i++) {
- float t = (float)i/(float)(size-1);
+ float t = min_x + (float)i/(float)(size-1) * range_x;
data[i][0] = mapR.evaluate(t);
data[i][1] = mapG.evaluate(t);
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index eea82b1f102..d9d6fd77ecb 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -304,8 +304,9 @@ public:
}
#endif
- if(getenv("CYCLES_CUDA_EXTRA_CFLAGS")) {
- command += string(" ") + getenv("CYCLES_CUDA_EXTRA_CFLAGS");
+ const char* extra_cflags = getenv("CYCLES_CUDA_EXTRA_CFLAGS");
+ if(extra_cflags) {
+ command += string(" ") + string(extra_cflags);
}
#ifdef WITH_CYCLES_DEBUG
@@ -829,7 +830,7 @@ public:
if(mem.data_type == TYPE_HALF)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, pmem.w, pmem.h, 0, GL_RGBA, GL_HALF_FLOAT, NULL);
else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pmem.w, pmem.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, pmem.w, pmem.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
diff --git a/intern/cycles/kernel/geom/geom_qbvh.h b/intern/cycles/kernel/geom/geom_qbvh.h
index 37deaac0800..2a2d7822eee 100644
--- a/intern/cycles/kernel/geom/geom_qbvh.h
+++ b/intern/cycles/kernel/geom/geom_qbvh.h
@@ -19,7 +19,7 @@ struct QBVHStackItem {
float dist;
};
-/* TOOD(sergey): Investigate if using instrinsics helps for both
+/* TOOD(sergey): Investigate if using intrinsics helps for both
* stack item swap and float comparison.
*/
ccl_device_inline void qbvh_item_swap(QBVHStackItem *__restrict a,
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
index d37e593005c..5947945ccc6 100644
--- a/intern/cycles/kernel/geom/geom_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -382,7 +382,6 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
float3 D = ray->D;
float t = isect->t;
-#ifdef __INTERSECTION_REFINE__
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
Transform tfm = ccl_fetch(sd, ob_itfm);
@@ -399,6 +398,7 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
P = P + D*t;
+#ifdef __INTERSECTION_REFINE__
const float4 tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0),
tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1),
tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2);
@@ -410,6 +410,7 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
float rt = dot(edge2, qvec) / dot(edge1, pvec);
P = P + D*rt;
+#endif /* __INTERSECTION_REFINE__ */
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
@@ -424,9 +425,6 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
}
return P;
-#else
- return P + D*t;
-#endif
}
#undef IDX
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index 2dc87fffcbc..29eca865384 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -339,6 +339,23 @@ ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L)
#endif
}
+ccl_device_inline void path_radiance_copy_indirect(PathRadiance *L,
+ const PathRadiance *L_src)
+{
+#ifdef __PASSES__
+ if(L->use_light_pass) {
+ L->path_diffuse = L_src->path_diffuse;
+ L->path_glossy = L_src->path_glossy;
+ L->path_transmission = L_src->path_transmission;
+ L->path_subsurface = L_src->path_subsurface;
+ L->path_scatter = L_src->path_scatter;
+
+ L->direct_emission = L_src->direct_emission;
+ L->indirect = L_src->indirect;
+ }
+#endif
+}
+
ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L)
{
float3 L_sum;
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index 3efd7ecca5f..715c11c7ea0 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -65,6 +65,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
if((is_combined || is_sss_sample) && (sd->flag & SD_BSSRDF)) {
/* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
SubsurfaceIndirectRays ss_indirect;
+ kernel_path_subsurface_init_indirect(&ss_indirect);
if(kernel_path_subsurface_scatter(kg,
sd,
&L_sample,
@@ -77,10 +78,9 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
while(ss_indirect.num_rays) {
kernel_path_subsurface_setup_indirect(kg,
&ss_indirect,
- &L_sample,
&state,
&ray,
- &ray,
+ &L_sample,
&throughput);
kernel_path_indirect(kg,
&rng,
@@ -89,6 +89,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
state.num_samples,
&state,
&L_sample);
+ kernel_path_subsurface_accum_indirect(&ss_indirect, &L_sample);
}
is_sss_sample = true;
}
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index de9e8d77ec8..3863cf221c5 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -99,23 +99,23 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd,
return false;
/* evaluate BSDF at shading point */
- float bsdf_pdf;
#ifdef __VOLUME__
if(ccl_fetch(sd, prim) != PRIM_NONE)
- shader_bsdf_eval(kg, sd, ls->D, eval, &bsdf_pdf);
- else
+ shader_bsdf_eval(kg, sd, ls->D, eval, ls->pdf, ls->shader & SHADER_USE_MIS);
+ else {
+ float bsdf_pdf;
shader_volume_phase_eval(kg, sd, ls->D, eval, &bsdf_pdf);
+ if(ls->shader & SHADER_USE_MIS) {
+ /* Multiple importance sampling. */
+ float mis_weight = power_heuristic(ls->pdf, bsdf_pdf);
+ light_eval *= mis_weight;
+ }
+ }
#else
- shader_bsdf_eval(kg, sd, ls->D, eval, &bsdf_pdf);
+ shader_bsdf_eval(kg, sd, ls->D, eval, ls->pdf, ls->shader & SHADER_USE_MIS);
#endif
- if(ls->shader & SHADER_USE_MIS) {
- /* multiple importance sampling */
- float mis_weight = power_heuristic(ls->pdf, bsdf_pdf);
- light_eval *= mis_weight;
- }
-
bsdf_eval_mul(eval, light_eval/ls->pdf);
#ifdef __PASSES__
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 885782f1a67..82cad788eb0 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -452,7 +452,7 @@ ccl_device bool kernel_path_subsurface_scatter(
* the second one should be converted to a diffuse BSDF to
* avoid this.
*/
- kernel_assert(ss_indirect->num_rays == 0);
+ kernel_assert(!ss_indirect->tracing);
uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb);
@@ -485,9 +485,10 @@ ccl_device bool kernel_path_subsurface_scatter(
sc,
false);
- PathState *hit_state = &ss_indirect->state;
+ PathState *hit_state = &ss_indirect->state[ss_indirect->num_rays];
Ray *hit_ray = &ss_indirect->rays[ss_indirect->num_rays];
float3 *hit_tp = &ss_indirect->throughputs[ss_indirect->num_rays];
+ PathRadiance *hit_L = &ss_indirect->L[ss_indirect->num_rays];
*hit_state = *state;
*hit_ray = *ray;
@@ -495,67 +496,97 @@ ccl_device bool kernel_path_subsurface_scatter(
hit_state->rng_offset += PRNG_BOUNCE_NUM;
- kernel_path_surface_connect_light(kg, rng, sd, *hit_tp, state, L);
+ path_radiance_init(hit_L, kernel_data.film.use_light_pass);
+ hit_L->direct_throughput = L->direct_throughput;
+ path_radiance_copy_indirect(hit_L, L);
+
+ kernel_path_surface_connect_light(kg, rng, sd, *hit_tp, state, hit_L);
if(kernel_path_surface_bounce(kg,
rng,
sd,
hit_tp,
hit_state,
- L,
+ hit_L,
hit_ray))
{
#ifdef __LAMP_MIS__
hit_state->ray_t = 0.0f;
#endif
+
+#ifdef __VOLUME__
+ if(ss_indirect->need_update_volume_stack) {
+ Ray volume_ray = *ray;
+ /* Setup ray from previous surface point to the new one. */
+ volume_ray.D = normalize_len(hit_ray->P - volume_ray.P,
+ &volume_ray.t);
+
+ kernel_volume_stack_update_for_subsurface(
+ kg,
+ &volume_ray,
+ hit_state->volume_stack);
+ }
+#endif
+ path_radiance_reset_indirect(L);
ss_indirect->num_rays++;
}
+ else {
+ path_radiance_accum_sample(L, hit_L, 1);
+ }
}
return true;
}
return false;
}
+ccl_device_inline void kernel_path_subsurface_init_indirect(
+ SubsurfaceIndirectRays *ss_indirect)
+{
+ ss_indirect->tracing = false;
+ ss_indirect->num_rays = 0;
+}
+
+ccl_device void kernel_path_subsurface_accum_indirect(
+ SubsurfaceIndirectRays *ss_indirect,
+ PathRadiance *L)
+{
+ if(ss_indirect->tracing) {
+ path_radiance_sum_indirect(L);
+ path_radiance_accum_sample(&ss_indirect->direct_L, L, 1);
+ if(ss_indirect->num_rays == 0) {
+ *L = ss_indirect->direct_L;
+ }
+ }
+}
+
ccl_device void kernel_path_subsurface_setup_indirect(
KernelGlobals *kg,
SubsurfaceIndirectRays *ss_indirect,
- PathRadiance *L,
PathState *state,
- Ray *orig_ray,
Ray *ray,
+ PathRadiance *L,
float3 *throughput)
{
+ if(!ss_indirect->tracing) {
+ ss_indirect->direct_L = *L;
+ }
+ ss_indirect->tracing = true;
+
/* Setup state, ray and throughput for indirect SSS rays. */
ss_indirect->num_rays--;
Ray *indirect_ray = &ss_indirect->rays[ss_indirect->num_rays];
+ PathRadiance *indirect_L = &ss_indirect->L[ss_indirect->num_rays];
- *state = ss_indirect->state;
- *throughput = ss_indirect->throughputs[ss_indirect->num_rays];
-
-#ifdef __VOLUME__
- if(ss_indirect->need_update_volume_stack) {
- Ray volume_ray = *orig_ray;
-
- /* Setup ray from previous surface point to the new one. */
- volume_ray.D = normalize_len(indirect_ray->P - volume_ray.P,
- &volume_ray.t);
-
- kernel_volume_stack_update_for_subsurface(kg,
- &volume_ray,
- state->volume_stack);
- }
-#endif
-
+ *state = ss_indirect->state[ss_indirect->num_rays];
*ray = *indirect_ray;
+ *L = *indirect_L;
+ *throughput = ss_indirect->throughputs[ss_indirect->num_rays];
- /* For render passes, sum and reset indirect light pass variables
- * for the next samples.
- */
- path_radiance_sum_indirect(L);
- path_radiance_reset_indirect(L);
+ state->rng_offset += ss_indirect->num_rays * PRNG_BOUNCE_NUM;
}
-#endif
+
+#endif /* __SUBSURFACE__ */
ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, ccl_global float *buffer)
{
@@ -576,13 +607,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __SUBSURFACE__
SubsurfaceIndirectRays ss_indirect;
- ss_indirect.num_rays = 0;
-
- /* TODO(sergey): Avoid having explicit copy of the pre-subsurface scatter
- * ray by storing an updated version of state in the ss_indirect which will
- * be updated to the new volume stack.
- */
- Ray ss_orig_ray;
+ kernel_path_subsurface_init_indirect(&ss_indirect);
for(;;) {
#endif
@@ -833,11 +858,10 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
&throughput,
&ss_indirect))
{
- ss_orig_ray = ray;
break;
}
}
-#endif
+#endif /* __SUBSURFACE__ */
/* direct lighting */
kernel_path_surface_connect_light(kg, rng, &sd, throughput, &state, &L);
@@ -848,23 +872,24 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
}
#ifdef __SUBSURFACE__
+ kernel_path_subsurface_accum_indirect(&ss_indirect, &L);
+
/* Trace indirect subsurface rays by restarting the loop. this uses less
* stack memory than invoking kernel_path_indirect.
*/
if(ss_indirect.num_rays) {
kernel_path_subsurface_setup_indirect(kg,
&ss_indirect,
- &L,
&state,
- &ss_orig_ray,
&ray,
+ &L,
&throughput);
}
else {
break;
}
}
-#endif
+#endif /* __SUBSURFACE__ */
float3 L_sum = path_radiance_clamp_and_sum(kg, &L);
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 6b560f5fdb2..25e5822a21b 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -516,12 +516,52 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderDa
*pdf = (sum_sample_weight > 0.0f)? sum_pdf/sum_sample_weight: 0.0f;
}
-ccl_device void shader_bsdf_eval(KernelGlobals *kg, ShaderData *sd,
- const float3 omega_in, BsdfEval *eval, float *pdf)
+#ifdef __BRANCHED_PATH__
+ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg,
+ const ShaderData *sd,
+ const float3 omega_in,
+ BsdfEval *result_eval,
+ float light_pdf,
+ bool use_mis)
+{
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ if(CLOSURE_IS_BSDF(sc->type)) {
+ float bsdf_pdf = 0.0f;
+ float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
+ if(bsdf_pdf != 0.0f) {
+ float mis_weight = use_mis? power_heuristic(light_pdf, bsdf_pdf): 1.0f;
+ bsdf_eval_accum(result_eval,
+ sc->type,
+ eval * sc->weight * mis_weight);
+ }
+ }
+ }
+}
+#endif
+
+ccl_device void shader_bsdf_eval(KernelGlobals *kg,
+ ShaderData *sd,
+ const float3 omega_in,
+ BsdfEval *eval,
+ float light_pdf,
+ bool use_mis)
{
bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
- _shader_bsdf_multi_eval(kg, sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
+#ifdef __BRANCHED_PATH__
+ if(kernel_data.integrator.branched)
+ _shader_bsdf_multi_eval_branched(kg, sd, omega_in, eval, light_pdf, use_mis);
+ else
+#endif
+ {
+ float pdf;
+ _shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, -1, eval, 0.0f, 0.0f);
+ if(use_mis) {
+ float weight = power_heuristic(light_pdf, pdf);
+ bsdf_eval_mul(eval, make_float3(weight, weight, weight));
+ }
+ }
}
ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index b9928561791..27a341aa37a 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -288,14 +288,14 @@ ccl_device int subsurface_scatter_multi_intersect(
sd->object,
lcg_state,
BSSRDF_MAX_HITS);
- /* TODO(sergey): Investigate whether scene_intersect_subsurface() could
- * indeed return more than BSSRDF_MAX_HITS hits.
- */
int num_eval_hits = min(ss_isect->num_hits, BSSRDF_MAX_HITS);
for(int hit = 0; hit < num_eval_hits; hit++) {
/* Quickly retrieve P and Ng without setting up ShaderData. */
- float3 hit_P = ray->P + ss_isect->hits[hit].t * ray->D;
+ float3 hit_P = triangle_refine_subsurface(kg,
+ sd,
+ &ss_isect->hits[hit],
+ ray);
float3 hit_Ng = ss_isect->Ng[hit];
if(ss_isect->hits[hit].object != OBJECT_NONE) {
object_normal_transform(kg, sd, &hit_Ng);
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index bef00355c5e..04d013ceb9c 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -761,7 +761,7 @@ struct SubsurfaceIntersection
float3 weight[BSSRDF_MAX_HITS];
int num_hits;
- Intersection hits[BSSRDF_MAX_HITS];
+ struct Intersection hits[BSSRDF_MAX_HITS];
float3 Ng[BSSRDF_MAX_HITS];
};
@@ -769,11 +769,14 @@ struct SubsurfaceIntersection
struct SubsurfaceIndirectRays
{
bool need_update_volume_stack;
- PathState state;
+ bool tracing;
+ PathState state[BSSRDF_MAX_HITS];
+ struct PathRadiance direct_L;
int num_rays;
- Ray rays[BSSRDF_MAX_HITS];
+ struct Ray rays[BSSRDF_MAX_HITS];
float3 throughputs[BSSRDF_MAX_HITS];
+ struct PathRadiance L[BSSRDF_MAX_HITS];
};
/* Constant Kernel Data
diff --git a/intern/cycles/kernel/kernels/cuda/kernel.cu b/intern/cycles/kernel/kernels/cuda/kernel.cu
index bcd55b8c676..3929b676f07 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel.cu
+++ b/intern/cycles/kernel/kernels/cuda/kernel.cu
@@ -65,8 +65,8 @@
#define CUDA_KERNEL_MAX_REGISTERS 63
#define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
-/* 5.0 and 5.2 */
-#elif __CUDA_ARCH__ == 500 || __CUDA_ARCH__ == 520
+/* 5.0, 5.2 and 5.3 */
+#elif __CUDA_ARCH__ == 500 || __CUDA_ARCH__ == 520 || __CUDA_ARCH__ == 530
#define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536
#define CUDA_MULTIPROCESSOR_MAX_BLOCKS 32
#define CUDA_BLOCK_MAX_THREADS 1024
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 81931463cad..568ea566bc8 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -102,7 +102,7 @@ foreach(_file ${SRC_OSL})
string(REPLACE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} _OSO_FILE ${_OSO_FILE})
add_custom_command(
OUTPUT ${_OSO_FILE}
- COMMAND ${OSL_COMPILER} -q -O2 -I"${CMAKE_CURRENT_SOURCE_DIR}" ${_OSL_FILE}
+ COMMAND ${OSL_COMPILER} -q -O2 -I"${CMAKE_CURRENT_SOURCE_DIR}" -o ${_OSO_FILE} ${_OSL_FILE}
DEPENDS ${_OSL_FILE} ${SRC_OSL_HEADERS})
list(APPEND SRC_OSO
${_OSO_FILE}
diff --git a/intern/cycles/kernel/shaders/node_rgb_curves.osl b/intern/cycles/kernel/shaders/node_rgb_curves.osl
index 60cb273ba98..0427c001f6d 100644
--- a/intern/cycles/kernel/shaders/node_rgb_curves.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_curves.osl
@@ -19,6 +19,21 @@
float ramp_lookup(color ramp[RAMP_TABLE_SIZE], float at, int component)
{
+ if (at < 0.0 || at > 1.0) {
+ float t0, dy;
+ if(at < 0.0) {
+ t0 = ramp[0][component];
+ dy = t0 - ramp[1][component];
+ at = -at;
+ }
+ else {
+ t0 = ramp[RAMP_TABLE_SIZE - 1][component];
+ dy = t0 - ramp[RAMP_TABLE_SIZE - 2][component];
+ at = at - 1.0;
+ }
+ return t0 + dy * at * (RAMP_TABLE_SIZE - 1);
+ }
+
float f = clamp(at, 0.0, 1.0) * (RAMP_TABLE_SIZE - 1);
/* clamp int as well in case of NaN */
@@ -37,14 +52,18 @@ float ramp_lookup(color ramp[RAMP_TABLE_SIZE], float at, int component)
shader node_rgb_curves(
color ramp[RAMP_TABLE_SIZE] = {0.0},
+ float min_x = 0.0,
+ float max_x = 1.0,
color ColorIn = 0.0,
float Fac = 0.0,
output color ColorOut = 0.0)
{
- ColorOut[0] = ramp_lookup(ramp, ColorIn[0], 0);
- ColorOut[1] = ramp_lookup(ramp, ColorIn[1], 1);
- ColorOut[2] = ramp_lookup(ramp, ColorIn[2], 2);
+ color c = (ColorIn - color(min_x, min_x, min_x)) / (max_x - min_x);
+
+ ColorOut[0] = ramp_lookup(ramp, c[0], 0);
+ ColorOut[1] = ramp_lookup(ramp, c[1], 1);
+ ColorOut[2] = ramp_lookup(ramp, c[2], 2);
ColorOut = mix(ColorIn, ColorOut, Fac);
}
diff --git a/intern/cycles/kernel/svm/svm_ramp.h b/intern/cycles/kernel/svm/svm_ramp.h
index 062ab013b1f..48d969947f5 100644
--- a/intern/cycles/kernel/svm/svm_ramp.h
+++ b/intern/cycles/kernel/svm/svm_ramp.h
@@ -19,8 +19,27 @@
CCL_NAMESPACE_BEGIN
-ccl_device float4 rgb_ramp_lookup(KernelGlobals *kg, int offset, float f, bool interpolate)
+ccl_device float4 rgb_ramp_lookup(KernelGlobals *kg,
+ int offset,
+ float f,
+ bool interpolate,
+ bool extrapolate)
{
+ if((f < 0.0f || f > 1.0f) && extrapolate) {
+ float4 t0, dy;
+ if(f < 0.0f) {
+ t0 = fetch_node_float(kg, offset);
+ dy = t0 - fetch_node_float(kg, offset + 1);
+ f = -f;
+ }
+ else {
+ t0 = fetch_node_float(kg, offset + RAMP_TABLE_SIZE - 1);
+ dy = t0 - fetch_node_float(kg, offset + RAMP_TABLE_SIZE - 2);
+ f = f - 1.0f;
+ }
+ return t0 + dy * f * (RAMP_TABLE_SIZE-1);
+ }
+
f = saturate(f)*(RAMP_TABLE_SIZE-1);
/* clamp int as well in case of NaN */
@@ -43,7 +62,7 @@ ccl_device void svm_node_rgb_ramp(KernelGlobals *kg, ShaderData *sd, float *stac
decode_node_uchar4(node.y, &fac_offset, &color_offset, &alpha_offset, NULL);
float fac = stack_load_float(stack, fac_offset);
- float4 color = rgb_ramp_lookup(kg, *offset, fac, interpolate);
+ float4 color = rgb_ramp_lookup(kg, *offset, fac, interpolate, false);
if(stack_valid(color_offset))
stack_store_float3(stack, color_offset, float4_to_float3(color));
@@ -55,16 +74,24 @@ ccl_device void svm_node_rgb_ramp(KernelGlobals *kg, ShaderData *sd, float *stac
ccl_device void svm_node_rgb_curves(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint fac_offset = node.y;
- uint color_offset = node.z;
- uint out_offset = node.w;
+ uint fac_offset, color_offset, out_offset;
+ decode_node_uchar4(node.y,
+ &fac_offset,
+ &color_offset,
+ &out_offset,
+ NULL);
float fac = stack_load_float(stack, fac_offset);
float3 color = stack_load_float3(stack, color_offset);
- float r = rgb_ramp_lookup(kg, *offset, color.x, true).x;
- float g = rgb_ramp_lookup(kg, *offset, color.y, true).y;
- float b = rgb_ramp_lookup(kg, *offset, color.z, true).z;
+ const float min_x = __int_as_float(node.z),
+ max_x = __int_as_float(node.w);
+ const float range_x = max_x - min_x;
+ color = (color - make_float3(min_x, min_x, min_x)) / range_x;
+
+ float r = rgb_ramp_lookup(kg, *offset, color.x, true, true).x;
+ float g = rgb_ramp_lookup(kg, *offset, color.y, true, true).y;
+ float b = rgb_ramp_lookup(kg, *offset, color.z, true, true).z;
color = (1.0f - fac)*color + fac*make_float3(r, g, b);
stack_store_float3(stack, out_offset, color);
@@ -81,9 +108,9 @@ ccl_device void svm_node_vector_curves(KernelGlobals *kg, ShaderData *sd, float
float fac = stack_load_float(stack, fac_offset);
float3 color = stack_load_float3(stack, color_offset);
- float r = rgb_ramp_lookup(kg, *offset, (color.x + 1.0f)*0.5f, true).x;
- float g = rgb_ramp_lookup(kg, *offset, (color.y + 1.0f)*0.5f, true).y;
- float b = rgb_ramp_lookup(kg, *offset, (color.z + 1.0f)*0.5f, true).z;
+ float r = rgb_ramp_lookup(kg, *offset, (color.x + 1.0f)*0.5f, true, false).x;
+ float g = rgb_ramp_lookup(kg, *offset, (color.y + 1.0f)*0.5f, true, false).y;
+ float b = rgb_ramp_lookup(kg, *offset, (color.z + 1.0f)*0.5f, true, false).z;
color = (1.0f - fac)*color + fac*make_float3(r*2.0f - 1.0f, g*2.0f - 1.0f, b*2.0f - 1.0f);
stack_store_float3(stack, out_offset, color);
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index e888cb37137..def43876ada 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -22,9 +22,37 @@
#include "util_algorithm.h"
#include "util_debug.h"
#include "util_foreach.h"
+#include "util_queue.h"
CCL_NAMESPACE_BEGIN
+namespace {
+
+bool check_node_inputs_has_links(const ShaderNode *node)
+{
+ foreach(const ShaderInput *in, node->inputs) {
+ if(in->link) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool check_node_inputs_traversed(const ShaderNode *node,
+ const ShaderNodeSet& done)
+{
+ foreach(const ShaderInput *in, node->inputs) {
+ if(in->link) {
+ if(done.find(in->link->parent) == done.end()) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+} /* namespace */
+
/* Input and Output */
ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
@@ -297,7 +325,7 @@ void ShaderGraph::finalize(Scene *scene,
finalized = true;
}
else if(do_simplify) {
- simplify_nodes(scene);
+ simplify_settings(scene);
}
}
@@ -562,11 +590,64 @@ void ShaderGraph::remove_unneeded_nodes()
}
}
+/* Step 2: Constant folding.
+ * Try to constant fold some nodes, and pipe result directly to
+ * the input socket of connected nodes.
+ */
+void ShaderGraph::constant_fold()
+{
+ ShaderNodeSet done, scheduled;
+ queue<ShaderNode*> traverse_queue;
+
+ /* Schedule nodes which doesn't have any dependencies. */
+ foreach(ShaderNode *node, nodes) {
+ if(!check_node_inputs_has_links(node)) {
+ traverse_queue.push(node);
+ scheduled.insert(node);
+ }
+ }
+
+ while(!traverse_queue.empty()) {
+ ShaderNode *node = traverse_queue.front();
+ traverse_queue.pop();
+ done.insert(node);
+ foreach(ShaderOutput *output, node->outputs) {
+ /* Schedule node which was depending on the value,
+ * when possible. Do it before disconnect.
+ */
+ foreach(ShaderInput *input, output->links) {
+ if(scheduled.find(input->parent) != scheduled.end()) {
+ /* Node might not be optimized yet but scheduled already
+ * by other dependencies. No need to re-schedule it.
+ */
+ continue;
+ }
+ /* Schedule node if its inputs are fully done. */
+ if(check_node_inputs_traversed(input->parent, done)) {
+ traverse_queue.push(input->parent);
+ scheduled.insert(input->parent);
+ }
+ }
+ /* Optimize current node. */
+ float3 optimized_value = make_float3(0.0f, 0.0f, 0.0f);
+ if(node->constant_fold(output, &optimized_value)) {
+ /* Apply optimized value to connected sockets. */
+ vector<ShaderInput*> links(output->links);
+ foreach(ShaderInput *input, links) {
+ /* Assign value and disconnect the optimizedinput. */
+ input->value = optimized_value;
+ disconnect(input);
+ }
+ }
+ }
+ }
+}
+
/* Step 3: Simplification.*/
-void ShaderGraph::simplify_nodes(Scene *scene)
+void ShaderGraph::simplify_settings(Scene *scene)
{
foreach(ShaderNode *node, nodes) {
- node->optimize(scene);
+ node->simplify_settings(scene);
}
}
@@ -597,7 +678,7 @@ void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<b
void ShaderGraph::clean(Scene *scene)
{
/* Graph simplification:
- * 1: Remove unnecesarry nodes
+ * 1: Remove unnecessary nodes
* 2: Constant folding
* 3: Simplification
* 4: De-duplication
@@ -607,10 +688,10 @@ void ShaderGraph::clean(Scene *scene)
remove_unneeded_nodes();
/* 2: Constant folding. */
- /* TODO(dingto): Implement */
+ constant_fold();
/* 3: Simplification. */
- simplify_nodes(scene);
+ simplify_settings(scene);
/* 4: De-duplication. */
/* TODO(dingto): Implement */
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 6ad40720d4c..420648f6425 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -197,7 +197,15 @@ public:
virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
virtual void compile(SVMCompiler& compiler) = 0;
virtual void compile(OSLCompiler& compiler) = 0;
- virtual void optimize(Scene * /*scene*/) {};
+
+ /* ** Node optimization ** */
+ /* Check whether the node can be replaced with single constant. */
+ virtual bool constant_fold(ShaderOutput * /*socket*/, float3 * /*optimized_value*/) { return false; }
+
+ /* Simplify settings used by artists to the ones which are simpler to
+ * evaluate in the kernel but keep the final result unchanged.
+ */
+ virtual void simplify_settings(Scene * /*scene*/) {};
virtual bool has_surface_emission() { return false; }
virtual bool has_surface_transparent() { return false; }
@@ -307,7 +315,8 @@ protected:
void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack);
void clean(Scene *scene);
- void simplify_nodes(Scene *scene);
+ void simplify_settings(Scene *scene);
+ void constant_fold();
void bump_from_displacement();
void refine_bump_nodes();
void default_inputs(bool do_osl);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index d89e74837c7..22eb3f239e6 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1881,7 +1881,7 @@ GlossyBsdfNode::GlossyBsdfNode()
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f);
}
-void GlossyBsdfNode::optimize(Scene *scene)
+void GlossyBsdfNode::simplify_settings(Scene *scene)
{
if(distribution_orig == "") {
distribution_orig = distribution;
@@ -1950,7 +1950,7 @@ GlassBsdfNode::GlassBsdfNode()
add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f);
}
-void GlassBsdfNode::optimize(Scene *scene)
+void GlassBsdfNode::simplify_settings(Scene *scene)
{
if(distribution_orig == "") {
distribution_orig = distribution;
@@ -2019,7 +2019,7 @@ RefractionBsdfNode::RefractionBsdfNode()
add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f);
}
-void RefractionBsdfNode::optimize(Scene *scene)
+void RefractionBsdfNode::simplify_settings(Scene *scene)
{
if(distribution_orig == "") {
distribution_orig = distribution;
@@ -3177,6 +3177,13 @@ ValueNode::ValueNode()
add_output("Value", SHADER_SOCKET_FLOAT);
}
+bool ValueNode::constant_fold(ShaderOutput * /*socket*/,
+ float3 *optimized_value)
+{
+ *optimized_value = make_float3(value, value, value);
+ return true;
+}
+
void ValueNode::compile(SVMCompiler& compiler)
{
ShaderOutput *val_out = output("Value");
@@ -3201,6 +3208,13 @@ ColorNode::ColorNode()
add_output("Color", SHADER_SOCKET_COLOR);
}
+bool ColorNode::constant_fold(ShaderOutput * /*socket*/,
+ float3 *optimized_value)
+{
+ *optimized_value = value;
+ return true;
+}
+
void ColorNode::compile(SVMCompiler& compiler)
{
ShaderOutput *color_out = output("Color");
@@ -3955,6 +3969,21 @@ BlackbodyNode::BlackbodyNode()
add_output("Color", SHADER_SOCKET_COLOR);
}
+bool BlackbodyNode::constant_fold(ShaderOutput *socket, float3 *optimized_value)
+{
+ ShaderInput *temperature_in = input("Temperature");
+
+ if(socket == output("Color")) {
+ if(temperature_in->link == NULL) {
+ *optimized_value = svm_math_blackbody_color(temperature_in->value.x);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
void BlackbodyNode::compile(SVMCompiler& compiler)
{
ShaderInput *temperature_in = input("Temperature");
@@ -3962,15 +3991,8 @@ void BlackbodyNode::compile(SVMCompiler& compiler)
compiler.stack_assign(color_out);
- if(temperature_in->link == NULL) {
- float3 color = svm_math_blackbody_color(temperature_in->value.x);
- compiler.add_node(NODE_VALUE_V, color_out->stack_offset);
- compiler.add_node(NODE_VALUE_V, color);
- }
- else {
- compiler.stack_assign(temperature_in);
- compiler.add_node(NODE_BLACKBODY, temperature_in->stack_offset, color_out->stack_offset);
- }
+ compiler.stack_assign(temperature_in);
+ compiler.add_node(NODE_BLACKBODY, temperature_in->stack_offset, color_out->stack_offset);
}
void BlackbodyNode::compile(OSLCompiler& compiler)
@@ -4054,28 +4076,36 @@ static ShaderEnum math_type_init()
ShaderEnum MathNode::type_enum = math_type_init();
-void MathNode::compile(SVMCompiler& compiler)
+bool MathNode::constant_fold(ShaderOutput *socket, float3 *optimized_value)
{
ShaderInput *value1_in = input("Value1");
ShaderInput *value2_in = input("Value2");
- ShaderOutput *value_out = output("Value");
- compiler.stack_assign(value_out);
+ if(socket == output("Value")) {
+ /* Optimize math node without links to a single value. */
+ if(value1_in->link == NULL && value2_in->link == NULL) {
+ optimized_value->x = svm_math((NodeMath)type_enum[type],
+ value1_in->value.x,
+ value2_in->value.x);
- /* Optimize math node without links to a single value node. */
- if(value1_in->link == NULL && value2_in->link == NULL) {
- float optimized_value = svm_math((NodeMath)type_enum[type],
- value1_in->value.x,
- value2_in->value.x);
- if(use_clamp) {
- optimized_value = saturate(optimized_value);
+ if(use_clamp) {
+ optimized_value->x = saturate(optimized_value->x);
+ }
+
+ return true;
}
- compiler.add_node(NODE_VALUE_F,
- __float_as_int(optimized_value),
- value_out->stack_offset);
- return;
}
+ return false;
+}
+
+void MathNode::compile(SVMCompiler& compiler)
+{
+ ShaderInput *value1_in = input("Value1");
+ ShaderInput *value2_in = input("Value2");
+ ShaderOutput *value_out = output("Value");
+
+ compiler.stack_assign(value_out);
compiler.stack_assign(value1_in);
compiler.stack_assign(value2_in);
@@ -4124,6 +4154,35 @@ static ShaderEnum vector_math_type_init()
ShaderEnum VectorMathNode::type_enum = vector_math_type_init();
+bool VectorMathNode::constant_fold(ShaderOutput *socket, float3 *optimized_value)
+{
+ ShaderInput *vector1_in = input("Vector1");
+ ShaderInput *vector2_in = input("Vector2");
+
+ float value;
+ float3 vector;
+
+ /* Optimize vector math node without links to a single value node. */
+ if(vector1_in->link == NULL && vector2_in->link == NULL) {
+ svm_vector_math(&value,
+ &vector,
+ (NodeVectorMath)type_enum[type],
+ vector1_in->value,
+ vector2_in->value);
+
+ if(socket == output("Value")) {
+ optimized_value->x = value;
+ return true;
+ }
+ else if(socket == output("Vector")) {
+ *optimized_value = vector;
+ return true;
+ }
+ }
+
+ return false;
+}
+
void VectorMathNode::compile(SVMCompiler& compiler)
{
ShaderInput *vector1_in = input("Vector1");
@@ -4134,25 +4193,6 @@ void VectorMathNode::compile(SVMCompiler& compiler)
compiler.stack_assign(value_out);
compiler.stack_assign(vector_out);
- /* Optimize vector math node without links to a single value node. */
- if(vector1_in->link == NULL && vector2_in->link == NULL) {
- float optimized_value;
- float3 optimized_vector;
- svm_vector_math(&optimized_value,
- &optimized_vector,
- (NodeVectorMath)type_enum[type],
- vector1_in->value,
- vector2_in->value);
-
- compiler.add_node(NODE_VALUE_F,
- __float_as_int(optimized_value),
- value_out->stack_offset);
-
- compiler.add_node(NODE_VALUE_V, vector_out->stack_offset);
- compiler.add_node(NODE_VALUE_V, optimized_vector);
- return;
- }
-
compiler.stack_assign(vector1_in);
compiler.stack_assign(vector2_in);
@@ -4290,6 +4330,9 @@ RGBCurvesNode::RGBCurvesNode()
add_input("Fac", SHADER_SOCKET_FLOAT);
add_input("Color", SHADER_SOCKET_COLOR);
add_output("Color", SHADER_SOCKET_COLOR);
+
+ min_x = 0.0f;
+ max_x = 1.0f;
}
void RGBCurvesNode::compile(SVMCompiler& compiler)
@@ -4302,7 +4345,12 @@ void RGBCurvesNode::compile(SVMCompiler& compiler)
compiler.stack_assign(color_in);
compiler.stack_assign(color_out);
- compiler.add_node(NODE_RGB_CURVES, fac_in->stack_offset, color_in->stack_offset, color_out->stack_offset);
+ compiler.add_node(NODE_RGB_CURVES,
+ compiler.encode_uchar4(fac_in->stack_offset,
+ color_in->stack_offset,
+ color_out->stack_offset),
+ __float_as_int(min_x),
+ __float_as_int(max_x));
compiler.add_array(curves, RAMP_TABLE_SIZE);
}
@@ -4317,6 +4365,8 @@ void RGBCurvesNode::compile(OSLCompiler& compiler)
}
compiler.parameter_color_array("ramp", ramp, RAMP_TABLE_SIZE);
+ compiler.parameter("min_x", min_x);
+ compiler.parameter("max_x", max_x);
compiler.add(this, "node_rgb_curves");
}
@@ -4452,6 +4502,7 @@ void OSLScriptNode::compile(SVMCompiler& /*compiler*/)
void OSLScriptNode::compile(OSLCompiler& compiler)
{
+#if defined(WITH_OSL) && (OSL_LIBRARY_VERSION_CODE < 10701)
/* XXX fix for #36790:
* point and normal parameters are reflected as generic SOCK_VECTOR sockets
* on the node. Socket fixed input values need to be copied explicitly here for
@@ -4471,6 +4522,7 @@ void OSLScriptNode::compile(OSLCompiler& compiler)
}
}
}
+#endif
if(!filepath.empty())
compiler.add(this, filepath.c_str(), true);
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 4f4061286cb..51efbc37f38 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -311,7 +311,7 @@ class GlossyBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(GlossyBsdfNode)
- void optimize(Scene *scene);
+ void simplify_settings(Scene *scene);
bool has_integrator_dependency();
ustring distribution, distribution_orig;
@@ -322,7 +322,7 @@ class GlassBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(GlassBsdfNode)
- void optimize(Scene *scene);
+ void simplify_settings(Scene *scene);
bool has_integrator_dependency();
ustring distribution, distribution_orig;
@@ -333,7 +333,7 @@ class RefractionBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(RefractionBsdfNode)
- void optimize(Scene *scene);
+ void simplify_settings(Scene *scene);
bool has_integrator_dependency();
ustring distribution, distribution_orig;
@@ -485,6 +485,8 @@ class ValueNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ValueNode)
+ bool constant_fold(ShaderOutput *socket, float3 *optimized_value);
+
float value;
};
@@ -492,6 +494,8 @@ class ColorNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ColorNode)
+ bool constant_fold(ShaderOutput *socket, float3 *optimized_value);
+
float3 value;
};
@@ -636,6 +640,7 @@ public:
class BlackbodyNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BlackbodyNode)
+ bool constant_fold(ShaderOutput *socket, float3 *optimized_value);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
@@ -644,6 +649,7 @@ class MathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ bool constant_fold(ShaderOutput *socket, float3 *optimized_value);
bool use_clamp;
@@ -663,6 +669,7 @@ class VectorMathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorMathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ bool constant_fold(ShaderOutput *socket, float3 *optimized_value);
ustring type;
static ShaderEnum type_enum;
@@ -700,6 +707,7 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float4 curves[RAMP_TABLE_SIZE];
+ float min_x, max_x;
};
class VectorCurvesNode : public ShaderNode {
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 851e5ac0b72..a1ff6809f67 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -126,7 +126,6 @@ class SceneParams {
public:
ShadingSystem shadingsystem;
enum BVHType { BVH_DYNAMIC, BVH_STATIC } bvh_type;
- bool use_bvh_cache;
bool use_bvh_spatial_split;
bool use_qbvh;
bool persistent_data;
@@ -135,7 +134,6 @@ public:
{
shadingsystem = SHADINGSYSTEM_SVM;
bvh_type = BVH_DYNAMIC;
- use_bvh_cache = false;
use_bvh_spatial_split = false;
use_qbvh = false;
persistent_data = false;
@@ -144,7 +142,6 @@ public:
bool modified(const SceneParams& params)
{ return !(shadingsystem == params.shadingsystem
&& bvh_type == params.bvh_type
- && use_bvh_cache == params.use_bvh_cache
&& use_bvh_spatial_split == params.use_bvh_spatial_split
&& use_qbvh == params.use_qbvh
&& persistent_data == params.persistent_data); }
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index a4c7e7ef969..b8a5b4d44e0 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -528,9 +528,11 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
find_dependencies(cl1deps, done, cl1in);
find_dependencies(cl2deps, done, cl2in);
+ ShaderNodeIDComparator node_id_comp;
set_intersection(cl1deps.begin(), cl1deps.end(),
cl2deps.begin(), cl2deps.end(),
- std::inserter(shareddeps, shareddeps.begin()));
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
/* it's possible some nodes are not shared between this mix node
* inputs, but still needed to be always executed, this mainly
@@ -542,10 +544,12 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
find_dependencies(rootdeps, done, in, node);
set_intersection(rootdeps.begin(), rootdeps.end(),
cl1deps.begin(), cl1deps.end(),
- std::inserter(shareddeps, shareddeps.begin()));
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
set_intersection(rootdeps.begin(), rootdeps.end(),
cl2deps.begin(), cl2deps.end(),
- std::inserter(shareddeps, shareddeps.begin()));
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
}
}
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index e103cfa4eee..47ac2800d6d 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -58,6 +58,7 @@ set(SRC_HEADERS
util_param.h
util_path.h
util_progress.h
+ util_queue.h
util_set.h
util_simd.h
util_sseb.h
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 7d6dfd34e0e..4a676d0d7b5 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -351,7 +351,7 @@ ccl_device_inline float2 normalize_len(const float2 a, float *t)
ccl_device_inline float2 safe_normalize(const float2 a)
{
float t = len(a);
- return (t)? a/t: a;
+ return (t != 0.0f)? a/t: a;
}
ccl_device_inline bool operator==(const float2 a, const float2 b)
@@ -553,7 +553,7 @@ ccl_device_inline float3 normalize_len(const float3 a, float *t)
ccl_device_inline float3 safe_normalize(const float3 a)
{
float t = len(a);
- return (t)? a/t: a;
+ return (t != 0.0f)? a/t: a;
}
#ifndef __KERNEL_OPENCL__
@@ -866,7 +866,7 @@ ccl_device_inline float4 normalize(const float4 a)
ccl_device_inline float4 safe_normalize(const float4 a)
{
float t = len(a);
- return (t)? a/t: a;
+ return (t != 0.0f)? a/t: a;
}
ccl_device_inline float4 min(float4 a, float4 b)
diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h
index 867de78e7a6..efe0698e1dc 100644
--- a/intern/cycles/util/util_math_fast.h
+++ b/intern/cycles/util/util_math_fast.h
@@ -247,7 +247,7 @@ ccl_device float fast_sinpif(float x)
* The basic idea of this approximation starts with the coarse approximation:
* sin(pi*x) ~= f(x) = 4 * (x - x * abs(x))
*
- * This approximation always _over_ estimates the target. On the otherhand,
+ * This approximation always _over_ estimates the target. On the other hand,
* the curve:
* sin(pi*x) ~= f(x) * abs(f(x)) / 4
*
diff --git a/intern/cycles/util/util_queue.h b/intern/cycles/util/util_queue.h
new file mode 100644
index 00000000000..f4c802785f9
--- /dev/null
+++ b/intern/cycles/util/util_queue.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UTIL_QUEUE_H__
+#define __UTIL_QUEUE_H__
+
+#include <queue>
+
+CCL_NAMESPACE_BEGIN
+
+using std::queue;
+
+CCL_NAMESPACE_END
+
+#endif /* __UTIL_LIST_H__ */
+
diff --git a/extern/Eigen3/CMakeLists.txt b/intern/eigen/CMakeLists.txt
index e3b63881aca..5811b71de94 100644
--- a/extern/Eigen3/CMakeLists.txt
+++ b/intern/eigen/CMakeLists.txt
@@ -28,16 +28,19 @@ set(INC
)
set(INC_SYS
+ ${EIGEN3_INCLUDE_DIRS}
)
set(SRC
- eigen3_capi.h
+ eigen_capi.h
intern/eigenvalues.cc
+ intern/linear_solver.cc
intern/svd.cc
intern/eigenvalues.h
+ intern/linear_solver.h
intern/svd.h
)
-blender_add_lib(extern_eigen3 "${SRC}" "${INC}" "${INC_SYS}")
+blender_add_lib(bf_intern_eigen "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/Eigen3/SConscript b/intern/eigen/SConscript
index 2dc2d623768..0c98ec1837d 100644
--- a/extern/Eigen3/SConscript
+++ b/intern/eigen/SConscript
@@ -29,7 +29,7 @@ Import('env')
sources = env.Glob('intern/*.cc')
-incs = '.'
+incs = '. #/extern/Eigen3'
defs = []
-env.BlenderLib('extern_eigen3', sources, Split(incs), defs, libtype=['extern','player'], priority=[10, 185])
+env.BlenderLib('bf_intern_eigen', sources, Split(incs), defs, libtype=['extern','player'], priority=[10, 185])
diff --git a/extern/Eigen3/eigen3_capi.h b/intern/eigen/eigen_capi.h
index f8a7b3cbb77..be42e340274 100644
--- a/extern/Eigen3/eigen3_capi.h
+++ b/intern/eigen/eigen_capi.h
@@ -24,10 +24,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __EIGEN3_C_API_H__
-#define __EIGEN3_C_API_H__
+#ifndef __EIGEN_C_API_H__
+#define __EIGEN_C_API_H__
#include "intern/eigenvalues.h"
+#include "intern/linear_solver.h"
#include "intern/svd.h"
-#endif /* __EIGEN3_C_API_H__ */
+#endif /* __EIGEN_C_API_H__ */
diff --git a/extern/Eigen3/intern/eigenvalues.cc b/intern/eigen/intern/eigenvalues.cc
index dcaaee8e9c2..57942a4dc55 100644
--- a/extern/Eigen3/intern/eigenvalues.cc
+++ b/intern/eigen/intern/eigenvalues.cc
@@ -45,7 +45,7 @@ using Eigen::Map;
using Eigen::Success;
-bool EG3_self_adjoint_eigen_solve(const int size, const float *matrix, float *r_eigen_values, float *r_eigen_vectors)
+bool EIG_self_adjoint_eigen_solve(const int size, const float *matrix, float *r_eigen_values, float *r_eigen_vectors)
{
SelfAdjointEigenSolver<MatrixXf> eigen_solver;
diff --git a/extern/Eigen3/intern/eigenvalues.h b/intern/eigen/intern/eigenvalues.h
index 93fc06c2339..5c08ab5be39 100644
--- a/extern/Eigen3/intern/eigenvalues.h
+++ b/intern/eigen/intern/eigenvalues.h
@@ -31,7 +31,7 @@
extern "C" {
#endif
-bool EG3_self_adjoint_eigen_solve(const int size, const float *matrix, float *r_eigen_values, float *r_eigen_vectors);
+bool EIG_self_adjoint_eigen_solve(const int size, const float *matrix, float *r_eigen_values, float *r_eigen_vectors);
#ifdef __cplusplus
}
diff --git a/intern/eigen/intern/linear_solver.cc b/intern/eigen/intern/linear_solver.cc
new file mode 100644
index 00000000000..181b278b9c0
--- /dev/null
+++ b/intern/eigen/intern/linear_solver.cc
@@ -0,0 +1,354 @@
+/*
+ * Sparse linear solver.
+ * Copyright (C) 2004 Bruno Levy
+ * Copyright (C) 2005-2015 Blender Foundation
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ */
+
+#include "linear_solver.h"
+
+#include <Eigen/Sparse>
+
+#include <algorithm>
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <vector>
+
+/* Eigen data structures */
+
+typedef Eigen::SparseMatrix<double, Eigen::ColMajor> EigenSparseMatrix;
+typedef Eigen::SparseLU<EigenSparseMatrix> EigenSparseLU;
+typedef Eigen::VectorXd EigenVectorX;
+typedef Eigen::Triplet<double> EigenTriplet;
+
+/* Linear Solver data structure */
+
+struct LinearSolver
+{
+ struct Coeff
+ {
+ Coeff()
+ {
+ index = 0;
+ value = 0.0;
+ }
+
+ int index;
+ double value;
+ };
+
+ struct Variable
+ {
+ Variable()
+ {
+ memset(value, 0, sizeof(value));
+ locked = false;
+ index = 0;
+ }
+
+ double value[4];
+ bool locked;
+ int index;
+ std::vector<Coeff> a;
+ };
+
+ enum State
+ {
+ STATE_VARIABLES_CONSTRUCT,
+ STATE_MATRIX_CONSTRUCT,
+ STATE_MATRIX_SOLVED
+ };
+
+ LinearSolver(int num_rows_, int num_variables_, int num_rhs_, bool lsq_)
+ {
+ assert(num_variables_ > 0);
+ assert(num_rhs_ <= 4);
+
+ state = STATE_VARIABLES_CONSTRUCT;
+ m = 0;
+ n = 0;
+ sparseLU = NULL;
+ num_variables = num_variables_;
+ num_rhs = num_rhs_;
+ num_rows = num_rows_;
+ least_squares = lsq_;
+
+ variable.resize(num_variables);
+ }
+
+ ~LinearSolver()
+ {
+ delete sparseLU;
+ }
+
+ State state;
+
+ int n;
+ int m;
+
+ std::vector<EigenTriplet> Mtriplets;
+ EigenSparseMatrix M;
+ EigenSparseMatrix MtM;
+ std::vector<EigenVectorX> b;
+ std::vector<EigenVectorX> x;
+
+ EigenSparseLU *sparseLU;
+
+ int num_variables;
+ std::vector<Variable> variable;
+
+ int num_rows;
+ int num_rhs;
+
+ bool least_squares;
+};
+
+LinearSolver *EIG_linear_solver_new(int num_rows, int num_columns, int num_rhs)
+{
+ return new LinearSolver(num_rows, num_columns, num_rhs, false);
+}
+
+LinearSolver *EIG_linear_least_squares_solver_new(int num_rows, int num_columns, int num_rhs)
+{
+ return new LinearSolver(num_rows, num_columns, num_rhs, true);
+}
+
+void EIG_linear_solver_delete(LinearSolver *solver)
+{
+ delete solver;
+}
+
+/* Variables */
+
+void EIG_linear_solver_variable_set(LinearSolver *solver, int rhs, int index, double value)
+{
+ solver->variable[index].value[rhs] = value;
+}
+
+double EIG_linear_solver_variable_get(LinearSolver *solver, int rhs, int index)
+{
+ return solver->variable[index].value[rhs];
+}
+
+void EIG_linear_solver_variable_lock(LinearSolver *solver, int index)
+{
+ if (!solver->variable[index].locked) {
+ assert(solver->state == LinearSolver::STATE_VARIABLES_CONSTRUCT);
+ solver->variable[index].locked = true;
+ }
+}
+
+static void linear_solver_variables_to_vector(LinearSolver *solver)
+{
+ int num_rhs = solver->num_rhs;
+
+ for (int i = 0; i < solver->num_variables; i++) {
+ LinearSolver::Variable* v = &solver->variable[i];
+ if (!v->locked) {
+ for (int j = 0; j < num_rhs; j++)
+ solver->x[j][v->index] = v->value[j];
+ }
+ }
+}
+
+static void linear_solver_vector_to_variables(LinearSolver *solver)
+{
+ int num_rhs = solver->num_rhs;
+
+ for (int i = 0; i < solver->num_variables; i++) {
+ LinearSolver::Variable* v = &solver->variable[i];
+ if (!v->locked) {
+ for (int j = 0; j < num_rhs; j++)
+ v->value[j] = solver->x[j][v->index];
+ }
+ }
+}
+
+/* Matrix */
+
+static void linear_solver_ensure_matrix_construct(LinearSolver *solver)
+{
+ /* transition to matrix construction if necessary */
+ if (solver->state == LinearSolver::STATE_VARIABLES_CONSTRUCT) {
+ int n = 0;
+
+ for (int i = 0; i < solver->num_variables; i++) {
+ if (solver->variable[i].locked)
+ solver->variable[i].index = ~0;
+ else
+ solver->variable[i].index = n++;
+ }
+
+ int m = (solver->num_rows == 0)? n: solver->num_rows;
+
+ solver->m = m;
+ solver->n = n;
+
+ assert(solver->least_squares || m == n);
+
+ /* reserve reasonable estimate */
+ solver->Mtriplets.clear();
+ solver->Mtriplets.reserve(std::max(m, n)*3);
+
+ solver->b.resize(solver->num_rhs);
+ solver->x.resize(solver->num_rhs);
+
+ for (int i = 0; i < solver->num_rhs; i++) {
+ solver->b[i].setZero(m);
+ solver->x[i].setZero(n);
+ }
+
+ linear_solver_variables_to_vector(solver);
+
+ solver->state = LinearSolver::STATE_MATRIX_CONSTRUCT;
+ }
+}
+
+void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double value)
+{
+ if (solver->state == LinearSolver::STATE_MATRIX_SOLVED)
+ return;
+
+ linear_solver_ensure_matrix_construct(solver);
+
+ if (!solver->least_squares && solver->variable[row].locked);
+ else if (solver->variable[col].locked) {
+ if (!solver->least_squares)
+ row = solver->variable[row].index;
+
+ LinearSolver::Coeff coeff;
+ coeff.index = row;
+ coeff.value = value;
+ solver->variable[col].a.push_back(coeff);
+ }
+ else {
+ if (!solver->least_squares)
+ row = solver->variable[row].index;
+ col = solver->variable[col].index;
+
+ /* direct insert into matrix is too slow, so use triplets */
+ EigenTriplet triplet(row, col, value);
+ solver->Mtriplets.push_back(triplet);
+ }
+}
+
+/* Right hand side */
+
+void EIG_linear_solver_right_hand_side_add(LinearSolver *solver, int rhs, int index, double value)
+{
+ linear_solver_ensure_matrix_construct(solver);
+
+ if (solver->least_squares) {
+ solver->b[rhs][index] += value;
+ }
+ else if (!solver->variable[index].locked) {
+ index = solver->variable[index].index;
+ solver->b[rhs][index] += value;
+ }
+}
+
+/* Solve */
+
+bool EIG_linear_solver_solve(LinearSolver *solver)
+{
+ bool result = true;
+
+ assert(solver->state != LinearSolver::STATE_VARIABLES_CONSTRUCT);
+
+ if (solver->state == LinearSolver::STATE_MATRIX_CONSTRUCT) {
+ /* create matrix from triplets */
+ solver->M.resize(solver->m, solver->n);
+ solver->M.setFromTriplets(solver->Mtriplets.begin(), solver->Mtriplets.end());
+ solver->Mtriplets.clear();
+
+ /* create least squares matrix */
+ if (solver->least_squares)
+ solver->MtM = solver->M.transpose() * solver->M;
+
+ /* convert M to compressed column format */
+ EigenSparseMatrix& M = (solver->least_squares)? solver->MtM: solver->M;
+ M.makeCompressed();
+
+ /* perform sparse LU factorization */
+ EigenSparseLU *sparseLU = new EigenSparseLU();
+ solver->sparseLU = sparseLU;
+
+ sparseLU->compute(M);
+ result = (sparseLU->info() == Eigen::Success);
+
+ solver->state = LinearSolver::STATE_MATRIX_SOLVED;
+ }
+
+ if (result) {
+ /* solve for each right hand side */
+ for (int rhs = 0; rhs < solver->num_rhs; rhs++) {
+ /* modify for locked variables */
+ EigenVectorX& b = solver->b[rhs];
+
+ for (int i = 0; i < solver->num_variables; i++) {
+ LinearSolver::Variable *variable = &solver->variable[i];
+
+ if (variable->locked) {
+ std::vector<LinearSolver::Coeff>& a = variable->a;
+
+ for (int j = 0; j < a.size(); j++)
+ b[a[j].index] -= a[j].value*variable->value[rhs];
+ }
+ }
+
+ /* solve */
+ if (solver->least_squares) {
+ EigenVectorX Mtb = solver->M.transpose() * b;
+ solver->x[rhs] = solver->sparseLU->solve(Mtb);
+ }
+ else {
+ EigenVectorX& b = solver->b[rhs];
+ solver->x[rhs] = solver->sparseLU->solve(b);
+ }
+
+ if (solver->sparseLU->info() != Eigen::Success)
+ result = false;
+ }
+
+ if (result)
+ linear_solver_vector_to_variables(solver);
+ }
+
+ /* clear for next solve */
+ for (int rhs = 0; rhs < solver->num_rhs; rhs++)
+ solver->b[rhs].setZero(solver->m);
+
+ return result;
+}
+
+/* Debugging */
+
+void EIG_linear_solver_print_matrix(LinearSolver *solver)
+{
+ std::cout << "A:" << solver->M << std::endl;
+
+ for (int rhs = 0; rhs < solver->num_rhs; rhs++)
+ std::cout << "b " << rhs << ":" << solver->b[rhs] << std::endl;
+
+ if (solver->MtM.rows() && solver->MtM.cols())
+ std::cout << "AtA:" << solver->MtM << std::endl;
+}
+
diff --git a/intern/eigen/intern/linear_solver.h b/intern/eigen/intern/linear_solver.h
new file mode 100644
index 00000000000..2dbea4d6f68
--- /dev/null
+++ b/intern/eigen/intern/linear_solver.h
@@ -0,0 +1,71 @@
+/*
+ * Sparse linear solver.
+ * Copyright (C) 2004 Bruno Levy
+ * Copyright (C) 2005-2015 Blender Foundation
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Solvers for Ax = b and AtAx = Atb */
+
+typedef struct LinearSolver LinearSolver;
+
+LinearSolver *EIG_linear_solver_new(
+ int num_rows,
+ int num_columns,
+ int num_right_hand_sides);
+
+LinearSolver *EIG_linear_least_squares_solver_new(
+ int num_rows,
+ int num_columns,
+ int num_right_hand_sides);
+
+void EIG_linear_solver_delete(LinearSolver *solver);
+
+/* Variables (x). Any locking must be done before matrix construction. */
+
+void EIG_linear_solver_variable_set(LinearSolver *solver, int rhs, int index, double value);
+double EIG_linear_solver_variable_get(LinearSolver *solver, int rhs, int index);
+void EIG_linear_solver_variable_lock(LinearSolver *solver, int index);
+
+/* Matrix (A) and right hand side (b) */
+
+void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double value);
+void EIG_linear_solver_right_hand_side_add(LinearSolver *solver, int rhs, int index, double value);
+
+/* Solve. Repeated solves are supported, by changing b between solves. */
+
+bool EIG_linear_solver_solve(LinearSolver *solver);
+
+/* Debugging */
+
+void EIG_linear_solver_print_matrix(LinearSolver *solver);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/extern/Eigen3/intern/svd.cc b/intern/eigen/intern/svd.cc
index e39a8261edb..04929cff798 100644
--- a/extern/Eigen3/intern/svd.cc
+++ b/intern/eigen/intern/svd.cc
@@ -32,6 +32,9 @@
# pragma GCC diagnostic ignored "-Wlogical-op"
#endif
+#ifdef __EIGEN3_SVD_C_API_CC__ /* quiet warning */
+#endif
+
#include <Eigen/Core>
#include <Eigen/SVD>
@@ -48,7 +51,7 @@ using Eigen::MatrixXf;
using Eigen::VectorXf;
using Eigen::Map;
-void EG3_svd_square_matrix(const int size, const float *matrix, float *r_U, float *r_S, float *r_V)
+void EIG_svd_square_matrix(const int size, const float *matrix, float *r_U, float *r_S, float *r_V)
{
/* Since our matrix is squared, we can use thinU/V. */
unsigned int flags = (r_U ? ComputeThinU : 0) | (r_V ? ComputeThinV : 0);
diff --git a/extern/Eigen3/intern/svd.h b/intern/eigen/intern/svd.h
index 0ac51108977..feadcc3520a 100644
--- a/extern/Eigen3/intern/svd.h
+++ b/intern/eigen/intern/svd.h
@@ -31,7 +31,7 @@
extern "C" {
#endif
-void EG3_svd_square_matrix(const int size, const float *matrix, float *r_U, float *r_S, float *r_V);
+void EIG_svd_square_matrix(const int size, const float *matrix, float *r_U, float *r_S, float *r_V);
#ifdef __cplusplus
}
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 54ac9d27bc7..7247753c655 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -626,7 +626,7 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
m_wantNumOfAASamples,
m_hWnd,
m_hDC,
- WGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
3, 2,
GHOST_OPENGL_WGL_CONTEXT_FLAGS,
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
@@ -646,8 +646,14 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
m_wantNumOfAASamples,
m_hWnd,
m_hDC,
+#if 1
0, // profile bit
- 0, 0,
+ 2, 1, // GL version requested
+#else
+ // switch to this for Blender 2.8 development
+ WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
+ 3, 2,
+#endif
GHOST_OPENGL_WGL_CONTEXT_FLAGS,
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
#else
@@ -684,8 +690,14 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
m_wantNumOfAASamples,
m_hWnd,
m_hDC,
+#if 1
0, // profile bit
- 0, 0,
+ 2, 1, // GL version requested
+#else
+ // switch to this for Blender 2.8 development
+ EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
+ 3, 2,
+#endif
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
diff --git a/intern/iksolver/CMakeLists.txt b/intern/iksolver/CMakeLists.txt
index 9476e0379e9..67e7aa6abd3 100644
--- a/intern/iksolver/CMakeLists.txt
+++ b/intern/iksolver/CMakeLists.txt
@@ -29,7 +29,7 @@ set(INC
)
set(INC_SYS
- ../moto/include
+ ${EIGEN3_INCLUDE_DIRS}
)
set(SRC
@@ -38,38 +38,12 @@ set(SRC
intern/IK_QSegment.cpp
intern/IK_QTask.cpp
intern/IK_Solver.cpp
- intern/MT_ExpMap.cpp
extern/IK_solver.h
intern/IK_QJacobian.h
intern/IK_QJacobianSolver.h
intern/IK_QSegment.h
intern/IK_QTask.h
- intern/MT_ExpMap.h
- intern/TNT/cholesky.h
- intern/TNT/cmat.h
- intern/TNT/fcscmat.h
- intern/TNT/fmat.h
- intern/TNT/fortran.h
- intern/TNT/fspvec.h
- intern/TNT/index.h
- intern/TNT/lapack.h
- intern/TNT/lu.h
- intern/TNT/qr.h
- intern/TNT/region1d.h
- intern/TNT/region2d.h
- intern/TNT/stopwatch.h
- intern/TNT/subscript.h
- intern/TNT/svd.h
- intern/TNT/tnt.h
- intern/TNT/tntmath.h
- intern/TNT/tntreqs.h
- intern/TNT/transv.h
- intern/TNT/triang.h
- intern/TNT/trisolve.h
- intern/TNT/vec.h
- intern/TNT/vecadaptor.h
- intern/TNT/version.h
)
blender_add_lib(bf_intern_iksolver "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/iksolver/SConscript b/intern/iksolver/SConscript
index ba973ad5fd5..12d9d14712b 100644
--- a/intern/iksolver/SConscript
+++ b/intern/iksolver/SConscript
@@ -29,7 +29,7 @@ Import ('env')
sources = env.Glob('intern/*.cpp')
-incs = 'intern ../moto/include ../memutil'
+incs = 'intern #/extern/Eigen3'
env.BlenderLib ('bf_intern_iksolver', sources, Split(incs), [], libtype=['intern','player'], priority=[100,90] )
diff --git a/intern/iksolver/intern/IK_Math.h b/intern/iksolver/intern/IK_Math.h
new file mode 100644
index 00000000000..78d99837c43
--- /dev/null
+++ b/intern/iksolver/intern/IK_Math.h
@@ -0,0 +1,261 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Original author: Laurence
+ * Contributor(s): Brecht
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#pragma once
+
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+
+#include <cmath>
+
+using Eigen::Affine3d;
+using Eigen::Matrix3d;
+using Eigen::MatrixXd;
+using Eigen::Vector3d;
+using Eigen::VectorXd;
+
+static const double IK_EPSILON = 1e-20;
+
+static inline bool FuzzyZero(double x)
+{
+ return fabs(x) < IK_EPSILON;
+}
+
+static inline double Clamp(const double x, const double min, const double max)
+{
+ return (x < min) ? min : (x > max) ? max : x;
+}
+
+static inline Eigen::Matrix3d CreateMatrix(double xx, double xy, double xz,
+ double yx, double yy, double yz,
+ double zx, double zy, double zz)
+{
+ Eigen::Matrix3d M;
+ M(0, 0) = xx; M(0, 1) = xy; M(0, 2) = xz;
+ M(1, 0) = yx; M(1, 1) = yy; M(1, 2) = yz;
+ M(2, 0) = zx; M(2, 1) = zy; M(2, 2) = zz;
+ return M;
+}
+
+static inline Eigen::Matrix3d RotationMatrix(double sine, double cosine, int axis)
+{
+ if (axis == 0)
+ return CreateMatrix(1.0, 0.0, 0.0,
+ 0.0, cosine, -sine,
+ 0.0, sine, cosine);
+ else if (axis == 1)
+ return CreateMatrix(cosine, 0.0, sine,
+ 0.0, 1.0, 0.0,
+ -sine, 0.0, cosine);
+ else
+ return CreateMatrix(cosine, -sine, 0.0,
+ sine, cosine, 0.0,
+ 0.0, 0.0, 1.0);
+}
+
+static inline Eigen::Matrix3d RotationMatrix(double angle, int axis)
+{
+ return RotationMatrix(sin(angle), cos(angle), axis);
+}
+
+
+static inline double EulerAngleFromMatrix(const Eigen::Matrix3d& R, int axis)
+{
+ double t = sqrt(R(0, 0) * R(0, 0) + R(0, 1) * R(0, 1));
+
+ if (t > 16.0 * IK_EPSILON) {
+ if (axis == 0) return -atan2(R(1, 2), R(2, 2));
+ else if (axis == 1) return atan2(-R(0, 2), t);
+ else return -atan2(R(0, 1), R(0, 0));
+ }
+ else {
+ if (axis == 0) return -atan2(-R(2, 1), R(1, 1));
+ else if (axis == 1) return atan2(-R(0, 2), t);
+ else return 0.0f;
+ }
+}
+
+static inline double safe_acos(double f)
+{
+ // acos that does not return NaN with rounding errors
+ if (f <= -1.0)
+ return M_PI;
+ else if (f >= 1.0)
+ return 0.0;
+ else
+ return acos(f);
+}
+
+static inline Eigen::Vector3d normalize(const Eigen::Vector3d& v)
+{
+ // a sane normalize function that doesn't give (1, 0, 0) in case
+ // of a zero length vector
+ double len = v.norm();
+ return FuzzyZero(len) ? Eigen::Vector3d(0, 0, 0) : Eigen::Vector3d(v / len);
+}
+
+static inline double angle(const Eigen::Vector3d& v1, const Eigen::Vector3d& v2)
+{
+ return safe_acos(v1.dot(v2));
+}
+
+static inline double ComputeTwist(const Eigen::Matrix3d& R)
+{
+ // qy and qw are the y and w components of the quaternion from R
+ double qy = R(0, 2) - R(2, 0);
+ double qw = R(0, 0) + R(1, 1) + R(2, 2) + 1;
+
+ double tau = 2.0 * atan2(qy, qw);
+
+ return tau;
+}
+
+static inline Eigen::Matrix3d ComputeTwistMatrix(double tau)
+{
+ return RotationMatrix(tau, 1);
+}
+
+static inline void RemoveTwist(Eigen::Matrix3d& R)
+{
+ // compute twist parameter
+ double tau = ComputeTwist(R);
+
+ // compute twist matrix
+ Eigen::Matrix3d T = ComputeTwistMatrix(tau);
+
+ // remove twist
+ R = R * T.transpose();
+}
+
+static inline Eigen::Vector3d SphericalRangeParameters(const Eigen::Matrix3d& R)
+{
+ // compute twist parameter
+ double tau = ComputeTwist(R);
+
+ // compute swing parameters
+ double num = 2.0 * (1.0 + R(1, 1));
+
+ // singularity at pi
+ if (fabs(num) < IK_EPSILON)
+ // TODO: this does now rotation of size pi over z axis, but could
+ // be any axis, how to deal with this i'm not sure, maybe don't
+ // enforce limits at all then
+ return Eigen::Vector3d(0.0, tau, 1.0);
+
+ num = 1.0 / sqrt(num);
+ double ax = -R(2, 1) * num;
+ double az = R(0, 1) * num;
+
+ return Eigen::Vector3d(ax, tau, az);
+}
+
+static inline Eigen::Matrix3d ComputeSwingMatrix(double ax, double az)
+{
+ // length of (ax, 0, az) = sin(theta/2)
+ double sine2 = ax * ax + az * az;
+ double cosine2 = sqrt((sine2 >= 1.0) ? 0.0 : 1.0 - sine2);
+
+ // compute swing matrix
+ Eigen::Matrix3d S(Eigen::Quaterniond(-cosine2, ax, 0.0, az));
+
+ return S;
+}
+
+static inline Eigen::Vector3d MatrixToAxisAngle(const Eigen::Matrix3d& R)
+{
+ Eigen::Vector3d delta = Eigen::Vector3d(R(2, 1) - R(1, 2),
+ R(0, 2) - R(2, 0),
+ R(1, 0) - R(0, 1));
+
+ double c = safe_acos((R(0, 0) + R(1, 1) + R(2, 2) - 1) / 2);
+ double l = delta.norm();
+
+ if (!FuzzyZero(l))
+ delta *= c / l;
+
+ return delta;
+}
+
+static inline bool EllipseClamp(double& ax, double& az, double *amin, double *amax)
+{
+ double xlim, zlim, x, z;
+
+ if (ax < 0.0) {
+ x = -ax;
+ xlim = -amin[0];
+ }
+ else {
+ x = ax;
+ xlim = amax[0];
+ }
+
+ if (az < 0.0) {
+ z = -az;
+ zlim = -amin[1];
+ }
+ else {
+ z = az;
+ zlim = amax[1];
+ }
+
+ if (FuzzyZero(xlim) || FuzzyZero(zlim)) {
+ if (x <= xlim && z <= zlim)
+ return false;
+
+ if (x > xlim)
+ x = xlim;
+ if (z > zlim)
+ z = zlim;
+ }
+ else {
+ double invx = 1.0 / (xlim * xlim);
+ double invz = 1.0 / (zlim * zlim);
+
+ if ((x * x * invx + z * z * invz) <= 1.0)
+ return false;
+
+ if (FuzzyZero(x)) {
+ x = 0.0;
+ z = zlim;
+ }
+ else {
+ double rico = z / x;
+ double old_x = x;
+ x = sqrt(1.0 / (invx + invz * rico * rico));
+ if (old_x < 0.0)
+ x = -x;
+ z = rico * x;
+ }
+ }
+
+ ax = (ax < 0.0) ? -x : x;
+ az = (az < 0.0) ? -z : z;
+
+ return true;
+}
+
diff --git a/intern/iksolver/intern/IK_QJacobian.cpp b/intern/iksolver/intern/IK_QJacobian.cpp
index bb7b7c5c0b8..2925cadf435 100644
--- a/intern/iksolver/intern/IK_QJacobian.cpp
+++ b/intern/iksolver/intern/IK_QJacobian.cpp
@@ -32,7 +32,6 @@
#include "IK_QJacobian.h"
-#include "TNT/svd.h"
IK_QJacobian::IK_QJacobian()
: m_sdls(true), m_min_damp(1.0)
@@ -48,74 +47,66 @@ void IK_QJacobian::ArmMatrices(int dof, int task_size)
m_dof = dof;
m_task_size = task_size;
- m_jacobian.newsize(task_size, dof);
- m_jacobian = 0;
+ m_jacobian.resize(task_size, dof);
+ m_jacobian.setZero();
- m_alpha.newsize(dof);
- m_alpha = 0;
+ m_alpha.resize(dof);
+ m_alpha.setZero();
- m_null.newsize(dof, dof);
+ m_nullspace.resize(dof, dof);
- m_d_theta.newsize(dof);
- m_d_theta_tmp.newsize(dof);
- m_d_norm_weight.newsize(dof);
+ m_d_theta.resize(dof);
+ m_d_theta_tmp.resize(dof);
+ m_d_norm_weight.resize(dof);
- m_norm.newsize(dof);
- m_norm = 0.0;
+ m_norm.resize(dof);
+ m_norm.setZero();
- m_beta.newsize(task_size);
+ m_beta.resize(task_size);
- m_weight.newsize(dof);
- m_weight_sqrt.newsize(dof);
- m_weight = 1.0;
- m_weight_sqrt = 1.0;
+ m_weight.resize(dof);
+ m_weight_sqrt.resize(dof);
+ m_weight.setOnes();
+ m_weight_sqrt.setOnes();
if (task_size >= dof) {
m_transpose = false;
- m_jacobian_tmp.newsize(task_size, dof);
+ m_jacobian_tmp.resize(task_size, dof);
- m_svd_u.newsize(task_size, dof);
- m_svd_v.newsize(dof, dof);
- m_svd_w.newsize(dof);
+ m_svd_u.resize(task_size, dof);
+ m_svd_v.resize(dof, dof);
+ m_svd_w.resize(dof);
- m_work1.newsize(task_size);
- m_work2.newsize(dof);
-
- m_svd_u_t.newsize(dof, task_size);
- m_svd_u_beta.newsize(dof);
+ m_svd_u_beta.resize(dof);
}
else {
// use the SVD of the transpose jacobian, it works just as well
// as the original, and often allows using smaller matrices.
m_transpose = true;
- m_jacobian_tmp.newsize(dof, task_size);
-
- m_svd_u.newsize(task_size, task_size);
- m_svd_v.newsize(dof, task_size);
- m_svd_w.newsize(task_size);
+ m_jacobian_tmp.resize(dof, task_size);
- m_work1.newsize(dof);
- m_work2.newsize(task_size);
+ m_svd_u.resize(task_size, task_size);
+ m_svd_v.resize(dof, task_size);
+ m_svd_w.resize(task_size);
- m_svd_u_t.newsize(task_size, task_size);
- m_svd_u_beta.newsize(task_size);
+ m_svd_u_beta.resize(task_size);
}
}
-void IK_QJacobian::SetBetas(int id, int, const MT_Vector3& v)
+void IK_QJacobian::SetBetas(int id, int, const Vector3d& v)
{
m_beta[id + 0] = v.x();
m_beta[id + 1] = v.y();
m_beta[id + 2] = v.z();
}
-void IK_QJacobian::SetDerivatives(int id, int dof_id, const MT_Vector3& v, MT_Scalar norm_weight)
+void IK_QJacobian::SetDerivatives(int id, int dof_id, const Vector3d& v, double norm_weight)
{
- m_jacobian[id + 0][dof_id] = v.x() * m_weight_sqrt[dof_id];
- m_jacobian[id + 1][dof_id] = v.y() * m_weight_sqrt[dof_id];
- m_jacobian[id + 2][dof_id] = v.z() * m_weight_sqrt[dof_id];
+ m_jacobian(id + 0, dof_id) = v.x() * m_weight_sqrt[dof_id];
+ m_jacobian(id + 1, dof_id) = v.y() * m_weight_sqrt[dof_id];
+ m_jacobian(id + 2, dof_id) = v.z() * m_weight_sqrt[dof_id];
m_d_norm_weight[dof_id] = norm_weight;
}
@@ -125,14 +116,18 @@ void IK_QJacobian::Invert()
if (m_transpose) {
// SVD will decompose Jt into V*W*Ut with U,V orthogonal and W diagonal,
// so J = U*W*Vt and Jinv = V*Winv*Ut
- TNT::transpose(m_jacobian, m_jacobian_tmp);
- TNT::SVD(m_jacobian_tmp, m_svd_v, m_svd_w, m_svd_u, m_work1, m_work2);
+ Eigen::JacobiSVD<MatrixXd> svd(m_jacobian.transpose(), Eigen::ComputeThinU | Eigen::ComputeThinV);
+ m_svd_u = svd.matrixV();
+ m_svd_w = svd.singularValues();
+ m_svd_v = svd.matrixU();
}
else {
// SVD will decompose J into U*W*Vt with U,V orthogonal and W diagonal,
// so Jinv = V*Winv*Ut
- m_jacobian_tmp = m_jacobian;
- TNT::SVD(m_jacobian_tmp, m_svd_u, m_svd_w, m_svd_v, m_work1, m_work2);
+ Eigen::JacobiSVD<MatrixXd> svd(m_jacobian, Eigen::ComputeThinU | Eigen::ComputeThinV);
+ m_svd_u = svd.matrixU();
+ m_svd_w = svd.singularValues();
+ m_svd_v = svd.matrixV();
}
if (m_sdls)
@@ -143,7 +138,7 @@ void IK_QJacobian::Invert()
bool IK_QJacobian::ComputeNullProjection()
{
- MT_Scalar epsilon = 1e-10;
+ double epsilon = 1e-10;
// compute null space projection based on V
int i, j, rank = 0;
@@ -154,26 +149,24 @@ bool IK_QJacobian::ComputeNullProjection()
if (rank < m_task_size)
return false;
- TMatrix basis(m_svd_v.num_rows(), rank);
- TMatrix basis_t(rank, m_svd_v.num_rows());
+ MatrixXd basis(m_svd_v.rows(), rank);
int b = 0;
for (i = 0; i < m_svd_w.size(); i++)
if (m_svd_w[i] > epsilon) {
- for (j = 0; j < m_svd_v.num_rows(); j++)
- basis[j][b] = m_svd_v[j][i];
+ for (j = 0; j < m_svd_v.rows(); j++)
+ basis(j, b) = m_svd_v(j, i);
b++;
}
- TNT::transpose(basis, basis_t);
- TNT::matmult(m_null, basis, basis_t);
+ m_nullspace = basis * basis.transpose();
- for (i = 0; i < m_null.num_rows(); i++)
- for (j = 0; j < m_null.num_cols(); j++)
+ for (i = 0; i < m_nullspace.rows(); i++)
+ for (j = 0; j < m_nullspace.cols(); j++)
if (i == j)
- m_null[i][j] = 1.0 - m_null[i][j];
+ m_nullspace(i, j) = 1.0 - m_nullspace(i, j);
else
- m_null[i][j] = -m_null[i][j];
+ m_nullspace(i, j) = -m_nullspace(i, j);
return true;
}
@@ -184,7 +177,7 @@ void IK_QJacobian::SubTask(IK_QJacobian& jacobian)
return;
// restrict lower priority jacobian
- jacobian.Restrict(m_d_theta, m_null);
+ jacobian.Restrict(m_d_theta, m_nullspace);
// add angle update from lower priority
jacobian.Invert();
@@ -197,19 +190,15 @@ void IK_QJacobian::SubTask(IK_QJacobian& jacobian)
m_d_theta[i] = m_d_theta[i] + /*m_min_damp * */ jacobian.AngleUpdate(i);
}
-void IK_QJacobian::Restrict(TVector& d_theta, TMatrix& null)
+void IK_QJacobian::Restrict(VectorXd& d_theta, MatrixXd& nullspace)
{
// subtract part already moved by higher task from beta
- TVector beta_sub(m_beta.size());
-
- TNT::matmult(beta_sub, m_jacobian, d_theta);
- m_beta = m_beta - beta_sub;
+ m_beta = m_beta - m_jacobian * d_theta;
// note: should we be using the norm of the unrestricted jacobian for SDLS?
// project jacobian on to null space of higher priority task
- TMatrix jacobian_copy(m_jacobian);
- TNT::matmult(m_jacobian, jacobian_copy, null);
+ m_jacobian = m_jacobian * nullspace;
}
void IK_QJacobian::InvertSDLS()
@@ -230,20 +219,20 @@ void IK_QJacobian::InvertSDLS()
// DLS. The SDLS damps individual singular values, instead of using a single
// damping term.
- MT_Scalar max_angle_change = MT_PI / 4.0;
- MT_Scalar epsilon = 1e-10;
+ double max_angle_change = M_PI / 4.0;
+ double epsilon = 1e-10;
int i, j;
- m_d_theta = 0;
+ m_d_theta.setZero();
m_min_damp = 1.0;
for (i = 0; i < m_dof; i++) {
m_norm[i] = 0.0;
for (j = 0; j < m_task_size; j += 3) {
- MT_Scalar n = 0.0;
- n += m_jacobian[j][i] * m_jacobian[j][i];
- n += m_jacobian[j + 1][i] * m_jacobian[j + 1][i];
- n += m_jacobian[j + 2][i] * m_jacobian[j + 2][i];
+ double n = 0.0;
+ n += m_jacobian(j, i) * m_jacobian(j, i);
+ n += m_jacobian(j + 1, i) * m_jacobian(j + 1, i);
+ n += m_jacobian(j + 2, i) * m_jacobian(j + 2, i);
m_norm[i] += sqrt(n);
}
}
@@ -252,40 +241,40 @@ void IK_QJacobian::InvertSDLS()
if (m_svd_w[i] <= epsilon)
continue;
- MT_Scalar wInv = 1.0 / m_svd_w[i];
- MT_Scalar alpha = 0.0;
- MT_Scalar N = 0.0;
+ double wInv = 1.0 / m_svd_w[i];
+ double alpha = 0.0;
+ double N = 0.0;
// compute alpha and N
- for (j = 0; j < m_svd_u.num_rows(); j += 3) {
- alpha += m_svd_u[j][i] * m_beta[j];
- alpha += m_svd_u[j + 1][i] * m_beta[j + 1];
- alpha += m_svd_u[j + 2][i] * m_beta[j + 2];
+ for (j = 0; j < m_svd_u.rows(); j += 3) {
+ alpha += m_svd_u(j, i) * m_beta[j];
+ alpha += m_svd_u(j + 1, i) * m_beta[j + 1];
+ alpha += m_svd_u(j + 2, i) * m_beta[j + 2];
// note: for 1 end effector, N will always be 1, since U is
// orthogonal, .. so could be optimized
- MT_Scalar tmp;
- tmp = m_svd_u[j][i] * m_svd_u[j][i];
- tmp += m_svd_u[j + 1][i] * m_svd_u[j + 1][i];
- tmp += m_svd_u[j + 2][i] * m_svd_u[j + 2][i];
+ double tmp;
+ tmp = m_svd_u(j, i) * m_svd_u(j, i);
+ tmp += m_svd_u(j + 1, i) * m_svd_u(j + 1, i);
+ tmp += m_svd_u(j + 2, i) * m_svd_u(j + 2, i);
N += sqrt(tmp);
}
alpha *= wInv;
// compute M, dTheta and max_dtheta
- MT_Scalar M = 0.0;
- MT_Scalar max_dtheta = 0.0, abs_dtheta;
+ double M = 0.0;
+ double max_dtheta = 0.0, abs_dtheta;
for (j = 0; j < m_d_theta.size(); j++) {
- MT_Scalar v = m_svd_v[j][i];
- M += MT_abs(v) * m_norm[j];
+ double v = m_svd_v(j, i);
+ M += fabs(v) * m_norm[j];
// compute tmporary dTheta's
m_d_theta_tmp[j] = v * alpha;
// find largest absolute dTheta
// multiply with weight to prevent unnecessary damping
- abs_dtheta = MT_abs(m_d_theta_tmp[j]) * m_weight_sqrt[j];
+ abs_dtheta = fabs(m_d_theta_tmp[j]) * m_weight_sqrt[j];
if (abs_dtheta > max_dtheta)
max_dtheta = abs_dtheta;
}
@@ -293,18 +282,18 @@ void IK_QJacobian::InvertSDLS()
M *= wInv;
// compute damping term and damp the dTheta's
- MT_Scalar gamma = max_angle_change;
+ double gamma = max_angle_change;
if (N < M)
gamma *= N / M;
- MT_Scalar damp = (gamma < max_dtheta) ? gamma / max_dtheta : 1.0;
+ double damp = (gamma < max_dtheta) ? gamma / max_dtheta : 1.0;
for (j = 0; j < m_d_theta.size(); j++) {
// slight hack: we do 0.80*, so that if there is some oscillation,
// the system can still converge (for joint limits). also, it's
// better to go a little to slow than to far
- MT_Scalar dofdamp = damp / m_weight[j];
+ double dofdamp = damp / m_weight[j];
if (dofdamp > 1.0) dofdamp = 1.0;
m_d_theta[j] += 0.80 * dofdamp * m_d_theta_tmp[j];
@@ -315,19 +304,19 @@ void IK_QJacobian::InvertSDLS()
}
// weight + prevent from doing angle updates with angles > max_angle_change
- MT_Scalar max_angle = 0.0, abs_angle;
+ double max_angle = 0.0, abs_angle;
for (j = 0; j < m_dof; j++) {
m_d_theta[j] *= m_weight[j];
- abs_angle = MT_abs(m_d_theta[j]);
+ abs_angle = fabs(m_d_theta[j]);
if (abs_angle > max_angle)
max_angle = abs_angle;
}
if (max_angle > max_angle_change) {
- MT_Scalar damp = (max_angle_change) / (max_angle_change + max_angle);
+ double damp = (max_angle_change) / (max_angle_change + max_angle);
for (j = 0; j < m_dof; j++)
m_d_theta[j] *= damp;
@@ -353,12 +342,12 @@ void IK_QJacobian::InvertDLS()
// find the smallest non-zero W value, anything below epsilon is
// treated as zero
- MT_Scalar epsilon = 1e-10;
- MT_Scalar max_angle_change = 0.1;
- MT_Scalar x_length = sqrt(TNT::dot_prod(m_beta, m_beta));
+ double epsilon = 1e-10;
+ double max_angle_change = 0.1;
+ double x_length = sqrt(m_beta.dot(m_beta));
int i, j;
- MT_Scalar w_min = MT_INFINITY;
+ double w_min = std::numeric_limits<double>::max();
for (i = 0; i < m_svd_w.size(); i++) {
if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min)
@@ -367,8 +356,8 @@ void IK_QJacobian::InvertDLS()
// compute lambda damping term
- MT_Scalar d = x_length / max_angle_change;
- MT_Scalar lambda;
+ double d = x_length / max_angle_change;
+ double lambda;
if (w_min <= d / 2)
lambda = d / 2;
@@ -386,20 +375,19 @@ void IK_QJacobian::InvertDLS()
// rather than matrix*matrix products
// compute Ut*Beta
- TNT::transpose(m_svd_u, m_svd_u_t);
- TNT::matmult(m_svd_u_beta, m_svd_u_t, m_beta);
+ m_svd_u_beta = m_svd_u.transpose() * m_beta;
- m_d_theta = 0.0;
+ m_d_theta.setZero();
for (i = 0; i < m_svd_w.size(); i++) {
if (m_svd_w[i] > epsilon) {
- MT_Scalar wInv = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
+ double wInv = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
// compute V*Winv*Ut*Beta
m_svd_u_beta[i] *= wInv;
for (j = 0; j < m_d_theta.size(); j++)
- m_d_theta[j] += m_svd_v[j][i] * m_svd_u_beta[i];
+ m_d_theta[j] += m_svd_v(j, i) * m_svd_u_beta[i];
}
}
@@ -407,31 +395,31 @@ void IK_QJacobian::InvertDLS()
m_d_theta[j] *= m_weight[j];
}
-void IK_QJacobian::Lock(int dof_id, MT_Scalar delta)
+void IK_QJacobian::Lock(int dof_id, double delta)
{
int i;
for (i = 0; i < m_task_size; i++) {
- m_beta[i] -= m_jacobian[i][dof_id] * delta;
- m_jacobian[i][dof_id] = 0.0;
+ m_beta[i] -= m_jacobian(i, dof_id) * delta;
+ m_jacobian(i, dof_id) = 0.0;
}
m_norm[dof_id] = 0.0; // unneeded
m_d_theta[dof_id] = 0.0;
}
-MT_Scalar IK_QJacobian::AngleUpdate(int dof_id) const
+double IK_QJacobian::AngleUpdate(int dof_id) const
{
return m_d_theta[dof_id];
}
-MT_Scalar IK_QJacobian::AngleUpdateNorm() const
+double IK_QJacobian::AngleUpdateNorm() const
{
int i;
- MT_Scalar mx = 0.0, dtheta_abs;
+ double mx = 0.0, dtheta_abs;
for (i = 0; i < m_d_theta.size(); i++) {
- dtheta_abs = MT_abs(m_d_theta[i] * m_d_norm_weight[i]);
+ dtheta_abs = fabs(m_d_theta[i] * m_d_norm_weight[i]);
if (dtheta_abs > mx)
mx = dtheta_abs;
}
@@ -439,7 +427,7 @@ MT_Scalar IK_QJacobian::AngleUpdateNorm() const
return mx;
}
-void IK_QJacobian::SetDoFWeight(int dof, MT_Scalar weight)
+void IK_QJacobian::SetDoFWeight(int dof, double weight)
{
m_weight[dof] = weight;
m_weight_sqrt[dof] = sqrt(weight);
diff --git a/intern/iksolver/intern/IK_QJacobian.h b/intern/iksolver/intern/IK_QJacobian.h
index b4b5a0402e6..f541866c6a7 100644
--- a/intern/iksolver/intern/IK_QJacobian.h
+++ b/intern/iksolver/intern/IK_QJacobian.h
@@ -31,44 +31,36 @@
* \ingroup iksolver
*/
+#pragma once
-#ifndef __IK_QJACOBIAN_H__
-
-#define __IK_QJACOBIAN_H__
-
-#include "TNT/cmat.h"
-#include <vector>
-#include "MT_Vector3.h"
+#include "IK_Math.h"
class IK_QJacobian
{
public:
- typedef TNT::Matrix<MT_Scalar> TMatrix;
- typedef TNT::Vector<MT_Scalar> TVector;
-
IK_QJacobian();
~IK_QJacobian();
// Call once to initialize
void ArmMatrices(int dof, int task_size);
- void SetDoFWeight(int dof, MT_Scalar weight);
+ void SetDoFWeight(int dof, double weight);
// Iteratively called
- void SetBetas(int id, int size, const MT_Vector3& v);
- void SetDerivatives(int id, int dof_id, const MT_Vector3& v, MT_Scalar norm_weight);
+ void SetBetas(int id, int size, const Vector3d& v);
+ void SetDerivatives(int id, int dof_id, const Vector3d& v, double norm_weight);
void Invert();
- MT_Scalar AngleUpdate(int dof_id) const;
- MT_Scalar AngleUpdateNorm() const;
+ double AngleUpdate(int dof_id) const;
+ double AngleUpdateNorm() const;
// DoF locking for inner clamping loop
- void Lock(int dof_id, MT_Scalar delta);
+ void Lock(int dof_id, double delta);
// Secondary task
bool ComputeNullProjection();
- void Restrict(TVector& d_theta, TMatrix& null);
+ void Restrict(VectorXd& d_theta, MatrixXd& nullspace);
void SubTask(IK_QJacobian& jacobian);
private:
@@ -80,41 +72,35 @@ private:
bool m_transpose;
// the jacobian matrix and it's null space projector
- TMatrix m_jacobian, m_jacobian_tmp;
- TMatrix m_null;
+ MatrixXd m_jacobian, m_jacobian_tmp;
+ MatrixXd m_nullspace;
/// the vector of intermediate betas
- TVector m_beta;
+ VectorXd m_beta;
/// the vector of computed angle changes
- TVector m_d_theta;
- TVector m_d_norm_weight;
+ VectorXd m_d_theta;
+ VectorXd m_d_norm_weight;
/// space required for SVD computation
+ VectorXd m_svd_w;
+ MatrixXd m_svd_v;
+ MatrixXd m_svd_u;
- TVector m_svd_w;
- TMatrix m_svd_v;
- TMatrix m_svd_u;
- TVector m_work1;
- TVector m_work2;
-
- TMatrix m_svd_u_t;
- TVector m_svd_u_beta;
+ VectorXd m_svd_u_beta;
// space required for SDLS
bool m_sdls;
- TVector m_norm;
- TVector m_d_theta_tmp;
- MT_Scalar m_min_damp;
+ VectorXd m_norm;
+ VectorXd m_d_theta_tmp;
+ double m_min_damp;
// null space task vector
- TVector m_alpha;
+ VectorXd m_alpha;
// dof weighting
- TVector m_weight;
- TVector m_weight_sqrt;
+ VectorXd m_weight;
+ VectorXd m_weight_sqrt;
};
-#endif
-
diff --git a/intern/iksolver/intern/IK_QJacobianSolver.cpp b/intern/iksolver/intern/IK_QJacobianSolver.cpp
index 75f51f566c9..b78270eb87f 100644
--- a/intern/iksolver/intern/IK_QJacobianSolver.cpp
+++ b/intern/iksolver/intern/IK_QJacobianSolver.cpp
@@ -32,8 +32,8 @@
#include <stdio.h>
+
#include "IK_QJacobianSolver.h"
-#include "MT_Quaternion.h"
//#include "analyze.h"
IK_QJacobianSolver::IK_QJacobianSolver()
@@ -43,10 +43,10 @@ IK_QJacobianSolver::IK_QJacobianSolver()
m_rootmatrix.setIdentity();
}
-MT_Scalar IK_QJacobianSolver::ComputeScale()
+double IK_QJacobianSolver::ComputeScale()
{
std::vector<IK_QSegment *>::iterator seg;
- MT_Scalar length = 0.0f;
+ double length = 0.0f;
for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
length += (*seg)->MaxExtension();
@@ -57,7 +57,7 @@ MT_Scalar IK_QJacobianSolver::ComputeScale()
return 1.0 / length;
}
-void IK_QJacobianSolver::Scale(MT_Scalar scale, std::list<IK_QTask *>& tasks)
+void IK_QJacobianSolver::Scale(double scale, std::list<IK_QTask *>& tasks)
{
std::list<IK_QTask *>::iterator task;
std::vector<IK_QSegment *>::iterator seg;
@@ -68,7 +68,7 @@ void IK_QJacobianSolver::Scale(MT_Scalar scale, std::list<IK_QTask *>& tasks)
for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
(*seg)->Scale(scale);
- m_rootmatrix.getOrigin() *= scale;
+ m_rootmatrix.translation() *= scale;
m_goal *= scale;
m_polegoal *= scale;
}
@@ -102,7 +102,7 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *>& tasks)
// compute task id's and assing weights to task
int primary_size = 0, primary = 0;
int secondary_size = 0, secondary = 0;
- MT_Scalar primary_weight = 0.0, secondary_weight = 0.0;
+ double primary_weight = 0.0, secondary_weight = 0.0;
std::list<IK_QTask *>::iterator task;
for (task = tasks.begin(); task != tasks.end(); task++) {
@@ -122,15 +122,15 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *>& tasks)
}
}
- if (primary_size == 0 || MT_fuzzyZero(primary_weight))
+ if (primary_size == 0 || FuzzyZero(primary_weight))
return false;
m_secondary_enabled = (secondary > 0);
// rescale weights of tasks to sum up to 1
- MT_Scalar primary_rescale = 1.0 / primary_weight;
- MT_Scalar secondary_rescale;
- if (MT_fuzzyZero(secondary_weight))
+ double primary_rescale = 1.0 / primary_weight;
+ double secondary_rescale;
+ if (FuzzyZero(secondary_weight))
secondary_rescale = 0.0;
else
secondary_rescale = 1.0 / secondary_weight;
@@ -159,7 +159,7 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *>& tasks)
return true;
}
-void IK_QJacobianSolver::SetPoleVectorConstraint(IK_QSegment *tip, MT_Vector3& goal, MT_Vector3& polegoal, float poleangle, bool getangle)
+void IK_QJacobianSolver::SetPoleVectorConstraint(IK_QSegment *tip, Vector3d& goal, Vector3d& polegoal, float poleangle, bool getangle)
{
m_poleconstraint = true;
m_poletip = tip;
@@ -169,27 +169,6 @@ void IK_QJacobianSolver::SetPoleVectorConstraint(IK_QSegment *tip, MT_Vector3& g
m_getpoleangle = getangle;
}
-static MT_Scalar safe_acos(MT_Scalar f)
-{
- // acos that does not return NaN with rounding errors
- if (f <= -1.0) return MT_PI;
- else if (f >= 1.0) return 0.0;
- else return acos(f);
-}
-
-static MT_Vector3 normalize(const MT_Vector3& v)
-{
- // a sane normalize function that doesn't give (1, 0, 0) in case
- // of a zero length vector, like MT_Vector3.normalize
- MT_Scalar len = v.length();
- return MT_fuzzyZero(len) ? MT_Vector3(0, 0, 0) : v / len;
-}
-
-static float angle(const MT_Vector3& v1, const MT_Vector3& v2)
-{
- return safe_acos(v1.dot(v2));
-}
-
void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTask *>& tasks)
{
// this function will be called before and after solving. calling it before
@@ -215,37 +194,38 @@ void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTa
// get positions and rotations
root->UpdateTransform(m_rootmatrix);
- const MT_Vector3 rootpos = root->GlobalStart();
- const MT_Vector3 endpos = m_poletip->GlobalEnd();
- const MT_Matrix3x3& rootbasis = root->GlobalTransform().getBasis();
+ const Vector3d rootpos = root->GlobalStart();
+ const Vector3d endpos = m_poletip->GlobalEnd();
+ const Matrix3d& rootbasis = root->GlobalTransform().linear();
// construct "lookat" matrices (like gluLookAt), based on a direction and
// an up vector, with the direction going from the root to the end effector
// and the up vector going from the root to the pole constraint position.
- MT_Vector3 dir = normalize(endpos - rootpos);
- MT_Vector3 rootx = rootbasis.getColumn(0);
- MT_Vector3 rootz = rootbasis.getColumn(2);
- MT_Vector3 up = rootx * cos(m_poleangle) + rootz *sin(m_poleangle);
+ Vector3d dir = normalize(endpos - rootpos);
+ Vector3d rootx = rootbasis.col(0);
+ Vector3d rootz = rootbasis.col(2);
+ Vector3d up = rootx * cos(m_poleangle) + rootz *sin(m_poleangle);
// in post, don't rotate towards the goal but only correct the pole up
- MT_Vector3 poledir = (m_getpoleangle) ? dir : normalize(m_goal - rootpos);
- MT_Vector3 poleup = normalize(m_polegoal - rootpos);
+ Vector3d poledir = (m_getpoleangle) ? dir : normalize(m_goal - rootpos);
+ Vector3d poleup = normalize(m_polegoal - rootpos);
- MT_Matrix3x3 mat, polemat;
+ Matrix3d mat, polemat;
- mat[0] = normalize(MT_cross(dir, up));
- mat[1] = MT_cross(mat[0], dir);
- mat[2] = -dir;
+ mat.row(0) = normalize(dir.cross(up));
+ mat.row(1) = mat.row(0).cross(dir);
+ mat.row(2) = -dir;
- polemat[0] = normalize(MT_cross(poledir, poleup));
- polemat[1] = MT_cross(polemat[0], poledir);
- polemat[2] = -poledir;
+ polemat.row(0) = normalize(poledir.cross(poleup));
+ polemat.row(1) = polemat.row(0).cross(poledir);
+ polemat.row(2) = -poledir;
if (m_getpoleangle) {
// we compute the pole angle that to rotate towards the target
- m_poleangle = angle(mat[1], polemat[1]);
+ m_poleangle = angle(mat.row(1), polemat.row(1));
- if (rootz.dot(mat[1] * cos(m_poleangle) + mat[0] * sin(m_poleangle)) > 0.0)
+ double dt = rootz.dot(mat.row(1) * cos(m_poleangle) + mat.row(0) * sin(m_poleangle));
+ if (dt > 0.0)
m_poleangle = -m_poleangle;
// solve again, with the pole angle we just computed
@@ -257,18 +237,20 @@ void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTa
// desired rotation based on the pole vector constraint. we use
// transpose instead of inverse because we have orthogonal matrices
// anyway, and in case of a singular matrix we don't get NaN's.
- MT_Transform trans(MT_Point3(0, 0, 0), polemat.transposed() * mat);
+ Affine3d trans;
+ trans.linear() = polemat.transpose() * mat;
+ trans.translation() = Vector3d(0, 0, 0);
m_rootmatrix = trans * m_rootmatrix;
}
}
-bool IK_QJacobianSolver::UpdateAngles(MT_Scalar& norm)
+bool IK_QJacobianSolver::UpdateAngles(double& norm)
{
// assing each segment a unique id for the jacobian
std::vector<IK_QSegment *>::iterator seg;
IK_QSegment *qseg, *minseg = NULL;
- MT_Scalar minabsdelta = 1e10, absdelta;
- MT_Vector3 delta, mindelta;
+ double minabsdelta = 1e10, absdelta;
+ Vector3d delta, mindelta;
bool locked = false, clamp[3];
int i, mindof = 0;
@@ -280,9 +262,9 @@ bool IK_QJacobianSolver::UpdateAngles(MT_Scalar& norm)
if (qseg->UpdateAngle(m_jacobian, delta, clamp)) {
for (i = 0; i < qseg->NumberOfDoF(); i++) {
if (clamp[i] && !qseg->Locked(i)) {
- absdelta = MT_abs(delta[i]);
+ absdelta = fabs(delta[i]);
- if (absdelta < MT_EPSILON) {
+ if (absdelta < IK_EPSILON) {
qseg->Lock(i, m_jacobian, delta);
locked = true;
}
@@ -320,7 +302,7 @@ bool IK_QJacobianSolver::UpdateAngles(MT_Scalar& norm)
bool IK_QJacobianSolver::Solve(
IK_QSegment *root,
std::list<IK_QTask *> tasks,
- const MT_Scalar,
+ const double,
const int max_iterations
)
{
@@ -349,7 +331,7 @@ bool IK_QJacobianSolver::Solve(
(*task)->ComputeJacobian(m_jacobian_sub);
}
- MT_Scalar norm = 0.0;
+ double norm = 0.0;
do {
// invert jacobian
@@ -372,7 +354,7 @@ bool IK_QJacobianSolver::Solve(
(*seg)->UnLock();
// compute angle update norm
- MT_Scalar maxnorm = m_jacobian.AngleUpdateNorm();
+ double maxnorm = m_jacobian.AngleUpdateNorm();
if (maxnorm > norm)
norm = maxnorm;
@@ -384,7 +366,7 @@ bool IK_QJacobianSolver::Solve(
}
if (m_poleconstraint)
- root->PrependBasis(m_rootmatrix.getBasis());
+ root->PrependBasis(m_rootmatrix.linear());
Scale(1.0f / scale, tasks);
diff --git a/intern/iksolver/intern/IK_QJacobianSolver.h b/intern/iksolver/intern/IK_QJacobianSolver.h
index 646f952b9ff..545ef91c710 100644
--- a/intern/iksolver/intern/IK_QJacobianSolver.h
+++ b/intern/iksolver/intern/IK_QJacobianSolver.h
@@ -30,10 +30,7 @@
* \ingroup iksolver
*/
-
-#ifndef __IK_QJACOBIANSOLVER_H__
-
-#define __IK_QJACOBIANSOLVER_H__
+#pragma once
/**
* @author Laurence Bourn
@@ -43,8 +40,7 @@
#include <vector>
#include <list>
-#include "MT_Vector3.h"
-#include "MT_Transform.h"
+#include "IK_Math.h"
#include "IK_QJacobian.h"
#include "IK_QSegment.h"
#include "IK_QTask.h"
@@ -56,8 +52,8 @@ public:
~IK_QJacobianSolver() {}
// setup pole vector constraint
- void SetPoleVectorConstraint(IK_QSegment *tip, MT_Vector3& goal,
- MT_Vector3& polegoal, float poleangle, bool getangle);
+ void SetPoleVectorConstraint(IK_QSegment *tip, Vector3d& goal,
+ Vector3d& polegoal, float poleangle, bool getangle);
float GetPoleAngle() { return m_poleangle; }
// call setup once before solving, if it fails don't solve
@@ -67,17 +63,17 @@ public:
bool Solve(
IK_QSegment *root,
std::list<IK_QTask*> tasks,
- const MT_Scalar tolerance,
+ const double tolerance,
const int max_iterations
);
private:
void AddSegmentList(IK_QSegment *seg);
- bool UpdateAngles(MT_Scalar& norm);
+ bool UpdateAngles(double& norm);
void ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTask*>& tasks);
- MT_Scalar ComputeScale();
- void Scale(MT_Scalar scale, std::list<IK_QTask*>& tasks);
+ double ComputeScale();
+ void Scale(double scale, std::list<IK_QTask*>& tasks);
private:
@@ -88,15 +84,13 @@ private:
std::vector<IK_QSegment*> m_segments;
- MT_Transform m_rootmatrix;
+ Affine3d m_rootmatrix;
bool m_poleconstraint;
bool m_getpoleangle;
- MT_Vector3 m_goal;
- MT_Vector3 m_polegoal;
+ Vector3d m_goal;
+ Vector3d m_polegoal;
float m_poleangle;
IK_QSegment *m_poletip;
};
-#endif
-
diff --git a/intern/iksolver/intern/IK_QSegment.cpp b/intern/iksolver/intern/IK_QSegment.cpp
index e511d8233a2..23b094db279 100644
--- a/intern/iksolver/intern/IK_QSegment.cpp
+++ b/intern/iksolver/intern/IK_QSegment.cpp
@@ -32,192 +32,6 @@
#include "IK_QSegment.h"
-#include <cmath>
-
-// Utility functions
-
-static MT_Matrix3x3 RotationMatrix(MT_Scalar sine, MT_Scalar cosine, int axis)
-{
- if (axis == 0)
- return MT_Matrix3x3(1.0, 0.0, 0.0,
- 0.0, cosine, -sine,
- 0.0, sine, cosine);
- else if (axis == 1)
- return MT_Matrix3x3(cosine, 0.0, sine,
- 0.0, 1.0, 0.0,
- -sine, 0.0, cosine);
- else
- return MT_Matrix3x3(cosine, -sine, 0.0,
- sine, cosine, 0.0,
- 0.0, 0.0, 1.0);
-}
-
-static MT_Matrix3x3 RotationMatrix(MT_Scalar angle, int axis)
-{
- return RotationMatrix(sin(angle), cos(angle), axis);
-}
-
-
-static MT_Scalar EulerAngleFromMatrix(const MT_Matrix3x3& R, int axis)
-{
- MT_Scalar t = sqrt(R[0][0] * R[0][0] + R[0][1] * R[0][1]);
-
- if (t > 16.0 * MT_EPSILON) {
- if (axis == 0) return -atan2(R[1][2], R[2][2]);
- else if (axis == 1) return atan2(-R[0][2], t);
- else return -atan2(R[0][1], R[0][0]);
- }
- else {
- if (axis == 0) return -atan2(-R[2][1], R[1][1]);
- else if (axis == 1) return atan2(-R[0][2], t);
- else return 0.0f;
- }
-}
-
-static MT_Scalar safe_acos(MT_Scalar f)
-{
- if (f <= -1.0)
- return MT_PI;
- else if (f >= 1.0)
- return 0.0;
- else
- return acos(f);
-}
-
-static MT_Scalar ComputeTwist(const MT_Matrix3x3& R)
-{
- // qy and qw are the y and w components of the quaternion from R
- MT_Scalar qy = R[0][2] - R[2][0];
- MT_Scalar qw = R[0][0] + R[1][1] + R[2][2] + 1;
-
- MT_Scalar tau = 2.0 * atan2(qy, qw);
-
- return tau;
-}
-
-static MT_Matrix3x3 ComputeTwistMatrix(MT_Scalar tau)
-{
- return RotationMatrix(tau, 1);
-}
-
-static void RemoveTwist(MT_Matrix3x3& R)
-{
- // compute twist parameter
- MT_Scalar tau = ComputeTwist(R);
-
- // compute twist matrix
- MT_Matrix3x3 T = ComputeTwistMatrix(tau);
-
- // remove twist
- R = R * T.transposed();
-}
-
-static MT_Vector3 SphericalRangeParameters(const MT_Matrix3x3& R)
-{
- // compute twist parameter
- MT_Scalar tau = ComputeTwist(R);
-
- // compute swing parameters
- MT_Scalar num = 2.0 * (1.0 + R[1][1]);
-
- // singularity at pi
- if (MT_abs(num) < MT_EPSILON)
- // TODO: this does now rotation of size pi over z axis, but could
- // be any axis, how to deal with this i'm not sure, maybe don't
- // enforce limits at all then
- return MT_Vector3(0.0, tau, 1.0);
-
- num = 1.0 / sqrt(num);
- MT_Scalar ax = -R[2][1] * num;
- MT_Scalar az = R[0][1] * num;
-
- return MT_Vector3(ax, tau, az);
-}
-
-static MT_Matrix3x3 ComputeSwingMatrix(MT_Scalar ax, MT_Scalar az)
-{
- // length of (ax, 0, az) = sin(theta/2)
- MT_Scalar sine2 = ax * ax + az * az;
- MT_Scalar cosine2 = sqrt((sine2 >= 1.0) ? 0.0 : 1.0 - sine2);
-
- // compute swing matrix
- MT_Matrix3x3 S(MT_Quaternion(ax, 0.0, az, -cosine2));
-
- return S;
-}
-
-static MT_Vector3 MatrixToAxisAngle(const MT_Matrix3x3& R)
-{
- MT_Vector3 delta = MT_Vector3(R[2][1] - R[1][2],
- R[0][2] - R[2][0],
- R[1][0] - R[0][1]);
-
- MT_Scalar c = safe_acos((R[0][0] + R[1][1] + R[2][2] - 1) / 2);
- MT_Scalar l = delta.length();
-
- if (!MT_fuzzyZero(l))
- delta *= c / l;
-
- return delta;
-}
-
-static bool EllipseClamp(MT_Scalar& ax, MT_Scalar& az, MT_Scalar *amin, MT_Scalar *amax)
-{
- MT_Scalar xlim, zlim, x, z;
-
- if (ax < 0.0) {
- x = -ax;
- xlim = -amin[0];
- }
- else {
- x = ax;
- xlim = amax[0];
- }
-
- if (az < 0.0) {
- z = -az;
- zlim = -amin[1];
- }
- else {
- z = az;
- zlim = amax[1];
- }
-
- if (MT_fuzzyZero(xlim) || MT_fuzzyZero(zlim)) {
- if (x <= xlim && z <= zlim)
- return false;
-
- if (x > xlim)
- x = xlim;
- if (z > zlim)
- z = zlim;
- }
- else {
- MT_Scalar invx = 1.0 / (xlim * xlim);
- MT_Scalar invz = 1.0 / (zlim * zlim);
-
- if ((x * x * invx + z * z * invz) <= 1.0)
- return false;
-
- if (MT_fuzzyZero(x)) {
- x = 0.0;
- z = zlim;
- }
- else {
- MT_Scalar rico = z / x;
- MT_Scalar old_x = x;
- x = sqrt(1.0 / (invx + invz * rico * rico));
- if (old_x < 0.0)
- x = -x;
- z = rico * x;
- }
- }
-
- ax = (ax < 0.0) ? -x : x;
- az = (az < 0.0) ? -z : z;
-
- return true;
-}
// IK_QSegment
@@ -230,10 +44,10 @@ IK_QSegment::IK_QSegment(int num_DoF, bool translational)
m_max_extension = 0.0;
- m_start = MT_Vector3(0, 0, 0);
+ m_start = Vector3d(0, 0, 0);
m_rest_basis.setIdentity();
m_basis.setIdentity();
- m_translation = MT_Vector3(0, 0, 0);
+ m_translation = Vector3d(0, 0, 0);
m_orig_basis = m_basis;
m_orig_translation = m_translation;
@@ -252,13 +66,13 @@ void IK_QSegment::Reset()
}
void IK_QSegment::SetTransform(
- const MT_Vector3& start,
- const MT_Matrix3x3& rest_basis,
- const MT_Matrix3x3& basis,
- const MT_Scalar length
+ const Vector3d& start,
+ const Matrix3d& rest_basis,
+ const Matrix3d& basis,
+ const double length
)
{
- m_max_extension = start.length() + length;
+ m_max_extension = start.norm() + length;
m_start = start;
m_rest_basis = rest_basis;
@@ -266,16 +80,16 @@ void IK_QSegment::SetTransform(
m_orig_basis = basis;
SetBasis(basis);
- m_translation = MT_Vector3(0, length, 0);
+ m_translation = Vector3d(0, length, 0);
m_orig_translation = m_translation;
}
-MT_Matrix3x3 IK_QSegment::BasisChange() const
+Matrix3d IK_QSegment::BasisChange() const
{
- return m_orig_basis.transposed() * m_basis;
+ return m_orig_basis.transpose() * m_basis;
}
-MT_Vector3 IK_QSegment::TranslationChange() const
+Vector3d IK_QSegment::TranslationChange() const
{
return m_translation - m_orig_translation;
}
@@ -327,13 +141,13 @@ void IK_QSegment::RemoveChild(IK_QSegment *child)
}
}
-void IK_QSegment::UpdateTransform(const MT_Transform& global)
+void IK_QSegment::UpdateTransform(const Affine3d& global)
{
// compute the global transform at the end of the segment
- m_global_start = global.getOrigin() + global.getBasis() * m_start;
+ m_global_start = global.translation() + global.linear() * m_start;
- m_global_transform.setOrigin(m_global_start);
- m_global_transform.setBasis(global.getBasis() * m_rest_basis * m_basis);
+ m_global_transform.translation() = m_global_start;
+ m_global_transform.linear() = global.linear() * m_rest_basis * m_basis;
m_global_transform.translate(m_translation);
// update child transforms
@@ -341,18 +155,18 @@ void IK_QSegment::UpdateTransform(const MT_Transform& global)
seg->UpdateTransform(m_global_transform);
}
-void IK_QSegment::PrependBasis(const MT_Matrix3x3& mat)
+void IK_QSegment::PrependBasis(const Matrix3d& mat)
{
m_basis = m_rest_basis.inverse() * mat * m_rest_basis * m_basis;
}
-void IK_QSegment::Scale(MT_Scalar scale)
+void IK_QSegment::Scale(double scale)
{
m_start *= scale;
m_translation *= scale;
m_orig_translation *= scale;
m_global_start *= scale;
- m_global_transform.getOrigin() *= scale;
+ m_global_transform.translation() *= scale;
m_max_extension *= scale;
}
@@ -363,19 +177,19 @@ IK_QSphericalSegment::IK_QSphericalSegment()
{
}
-MT_Vector3 IK_QSphericalSegment::Axis(int dof) const
+Vector3d IK_QSphericalSegment::Axis(int dof) const
{
- return m_global_transform.getBasis().getColumn(dof);
+ return m_global_transform.linear().col(dof);
}
-void IK_QSphericalSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
+void IK_QSphericalSegment::SetLimit(int axis, double lmin, double lmax)
{
if (lmin > lmax)
return;
if (axis == 1) {
- lmin = MT_clamp(lmin, -MT_PI, MT_PI);
- lmax = MT_clamp(lmax, -MT_PI, MT_PI);
+ lmin = Clamp(lmin, -M_PI, M_PI);
+ lmax = Clamp(lmax, -M_PI, M_PI);
m_min_y = lmin;
m_max_y = lmax;
@@ -384,8 +198,8 @@ void IK_QSphericalSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
}
else {
// clamp and convert to axis angle parameters
- lmin = MT_clamp(lmin, -MT_PI, MT_PI);
- lmax = MT_clamp(lmax, -MT_PI, MT_PI);
+ lmin = Clamp(lmin, -M_PI, M_PI);
+ lmax = Clamp(lmax, -M_PI, M_PI);
lmin = sin(lmin * 0.5);
lmax = sin(lmax * 0.5);
@@ -403,17 +217,17 @@ void IK_QSphericalSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
}
}
-void IK_QSphericalSegment::SetWeight(int axis, MT_Scalar weight)
+void IK_QSphericalSegment::SetWeight(int axis, double weight)
{
m_weight[axis] = weight;
}
-bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp)
+bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp)
{
if (m_locked[0] && m_locked[1] && m_locked[2])
return false;
- MT_Vector3 dq;
+ Vector3d dq;
dq.x() = jacobian.AngleUpdate(m_DoF_id);
dq.y() = jacobian.AngleUpdate(m_DoF_id + 1);
dq.z() = jacobian.AngleUpdate(m_DoF_id + 2);
@@ -421,27 +235,27 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3&
// Directly update the rotation matrix, with Rodrigues' rotation formula,
// to avoid singularities and allow smooth integration.
- MT_Scalar theta = dq.length();
+ double theta = dq.norm();
- if (!MT_fuzzyZero(theta)) {
- MT_Vector3 w = dq * (1.0 / theta);
+ if (!FuzzyZero(theta)) {
+ Vector3d w = dq * (1.0 / theta);
- MT_Scalar sine = sin(theta);
- MT_Scalar cosine = cos(theta);
- MT_Scalar cosineInv = 1 - cosine;
+ double sine = sin(theta);
+ double cosine = cos(theta);
+ double cosineInv = 1 - cosine;
- MT_Scalar xsine = w.x() * sine;
- MT_Scalar ysine = w.y() * sine;
- MT_Scalar zsine = w.z() * sine;
+ double xsine = w.x() * sine;
+ double ysine = w.y() * sine;
+ double zsine = w.z() * sine;
- MT_Scalar xxcosine = w.x() * w.x() * cosineInv;
- MT_Scalar xycosine = w.x() * w.y() * cosineInv;
- MT_Scalar xzcosine = w.x() * w.z() * cosineInv;
- MT_Scalar yycosine = w.y() * w.y() * cosineInv;
- MT_Scalar yzcosine = w.y() * w.z() * cosineInv;
- MT_Scalar zzcosine = w.z() * w.z() * cosineInv;
+ double xxcosine = w.x() * w.x() * cosineInv;
+ double xycosine = w.x() * w.y() * cosineInv;
+ double xzcosine = w.x() * w.z() * cosineInv;
+ double yycosine = w.y() * w.y() * cosineInv;
+ double yzcosine = w.y() * w.z() * cosineInv;
+ double zzcosine = w.z() * w.z() * cosineInv;
- MT_Matrix3x3 M(
+ Matrix3d M = CreateMatrix(
cosine + xxcosine, -zsine + xycosine, ysine + xzcosine,
zsine + xycosine, cosine + yycosine, -xsine + yzcosine,
-ysine + xzcosine, xsine + yzcosine, cosine + zzcosine);
@@ -455,7 +269,7 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3&
if (m_limit_y == false && m_limit_x == false && m_limit_z == false)
return false;
- MT_Vector3 a = SphericalRangeParameters(m_new_basis);
+ Vector3d a = SphericalRangeParameters(m_new_basis);
if (m_locked[0])
a.x() = m_locked_ax;
@@ -464,7 +278,7 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3&
if (m_locked[2])
a.z() = m_locked_az;
- MT_Scalar ax = a.x(), ay = a.y(), az = a.z();
+ double ax = a.x(), ay = a.y(), az = a.z();
clamp[0] = clamp[1] = clamp[2] = false;
@@ -512,7 +326,7 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3&
m_new_basis = ComputeSwingMatrix(ax, az) * ComputeTwistMatrix(ay);
- delta = MatrixToAxisAngle(m_basis.transposed() * m_new_basis);
+ delta = MatrixToAxisAngle(m_basis.transpose() * m_new_basis);
if (!(m_locked[0] || m_locked[2]) && (clamp[0] || clamp[2])) {
m_locked_ax = ax;
@@ -525,7 +339,7 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3&
return true;
}
-void IK_QSphericalSegment::Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta)
+void IK_QSphericalSegment::Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta)
{
if (dof == 1) {
m_locked[1] = true;
@@ -557,7 +371,7 @@ IK_QRevoluteSegment::IK_QRevoluteSegment(int axis)
{
}
-void IK_QRevoluteSegment::SetBasis(const MT_Matrix3x3& basis)
+void IK_QRevoluteSegment::SetBasis(const Matrix3d& basis)
{
if (m_axis == 1) {
m_angle = ComputeTwist(basis);
@@ -569,12 +383,12 @@ void IK_QRevoluteSegment::SetBasis(const MT_Matrix3x3& basis)
}
}
-MT_Vector3 IK_QRevoluteSegment::Axis(int) const
+Vector3d IK_QRevoluteSegment::Axis(int) const
{
- return m_global_transform.getBasis().getColumn(m_axis);
+ return m_global_transform.linear().col(m_axis);
}
-bool IK_QRevoluteSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp)
+bool IK_QRevoluteSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp)
{
if (m_locked[0])
return false;
@@ -599,7 +413,7 @@ bool IK_QRevoluteSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3&
return true;
}
-void IK_QRevoluteSegment::Lock(int, IK_QJacobian& jacobian, MT_Vector3& delta)
+void IK_QRevoluteSegment::Lock(int, IK_QJacobian& jacobian, Vector3d& delta)
{
m_locked[0] = true;
jacobian.Lock(m_DoF_id, delta[0]);
@@ -611,14 +425,14 @@ void IK_QRevoluteSegment::UpdateAngleApply()
m_basis = RotationMatrix(m_angle, m_axis);
}
-void IK_QRevoluteSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
+void IK_QRevoluteSegment::SetLimit(int axis, double lmin, double lmax)
{
if (lmin > lmax || m_axis != axis)
return;
// clamp and convert to axis angle parameters
- lmin = MT_clamp(lmin, -MT_PI, MT_PI);
- lmax = MT_clamp(lmax, -MT_PI, MT_PI);
+ lmin = Clamp(lmin, -M_PI, M_PI);
+ lmax = Clamp(lmax, -M_PI, M_PI);
m_min = lmin;
m_max = lmax;
@@ -626,7 +440,7 @@ void IK_QRevoluteSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
m_limit = true;
}
-void IK_QRevoluteSegment::SetWeight(int axis, MT_Scalar weight)
+void IK_QRevoluteSegment::SetWeight(int axis, double weight)
{
if (axis == m_axis)
m_weight[0] = weight;
@@ -639,23 +453,23 @@ IK_QSwingSegment::IK_QSwingSegment()
{
}
-void IK_QSwingSegment::SetBasis(const MT_Matrix3x3& basis)
+void IK_QSwingSegment::SetBasis(const Matrix3d& basis)
{
m_basis = basis;
RemoveTwist(m_basis);
}
-MT_Vector3 IK_QSwingSegment::Axis(int dof) const
+Vector3d IK_QSwingSegment::Axis(int dof) const
{
- return m_global_transform.getBasis().getColumn((dof == 0) ? 0 : 2);
+ return m_global_transform.linear().col((dof == 0) ? 0 : 2);
}
-bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp)
+bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp)
{
if (m_locked[0] && m_locked[1])
return false;
- MT_Vector3 dq;
+ Vector3d dq;
dq.x() = jacobian.AngleUpdate(m_DoF_id);
dq.y() = 0.0;
dq.z() = jacobian.AngleUpdate(m_DoF_id + 1);
@@ -663,23 +477,23 @@ bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& del
// Directly update the rotation matrix, with Rodrigues' rotation formula,
// to avoid singularities and allow smooth integration.
- MT_Scalar theta = dq.length();
+ double theta = dq.norm();
- if (!MT_fuzzyZero(theta)) {
- MT_Vector3 w = dq * (1.0 / theta);
+ if (!FuzzyZero(theta)) {
+ Vector3d w = dq * (1.0 / theta);
- MT_Scalar sine = sin(theta);
- MT_Scalar cosine = cos(theta);
- MT_Scalar cosineInv = 1 - cosine;
+ double sine = sin(theta);
+ double cosine = cos(theta);
+ double cosineInv = 1 - cosine;
- MT_Scalar xsine = w.x() * sine;
- MT_Scalar zsine = w.z() * sine;
+ double xsine = w.x() * sine;
+ double zsine = w.z() * sine;
- MT_Scalar xxcosine = w.x() * w.x() * cosineInv;
- MT_Scalar xzcosine = w.x() * w.z() * cosineInv;
- MT_Scalar zzcosine = w.z() * w.z() * cosineInv;
+ double xxcosine = w.x() * w.x() * cosineInv;
+ double xzcosine = w.x() * w.z() * cosineInv;
+ double zzcosine = w.z() * w.z() * cosineInv;
- MT_Matrix3x3 M(
+ Matrix3d M = CreateMatrix(
cosine + xxcosine, -zsine, xzcosine,
zsine, cosine, -xsine,
xzcosine, xsine, cosine + zzcosine);
@@ -694,8 +508,8 @@ bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& del
if (m_limit_x == false && m_limit_z == false)
return false;
- MT_Vector3 a = SphericalRangeParameters(m_new_basis);
- MT_Scalar ax = 0, az = 0;
+ Vector3d a = SphericalRangeParameters(m_new_basis);
+ double ax = 0, az = 0;
clamp[0] = clamp[1] = false;
@@ -732,13 +546,13 @@ bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& del
m_new_basis = ComputeSwingMatrix(ax, az);
- delta = MatrixToAxisAngle(m_basis.transposed() * m_new_basis);
+ delta = MatrixToAxisAngle(m_basis.transpose() * m_new_basis);
delta[1] = delta[2]; delta[2] = 0.0;
return true;
}
-void IK_QSwingSegment::Lock(int, IK_QJacobian& jacobian, MT_Vector3& delta)
+void IK_QSwingSegment::Lock(int, IK_QJacobian& jacobian, Vector3d& delta)
{
m_locked[0] = m_locked[1] = true;
jacobian.Lock(m_DoF_id, delta[0]);
@@ -750,20 +564,20 @@ void IK_QSwingSegment::UpdateAngleApply()
m_basis = m_new_basis;
}
-void IK_QSwingSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
+void IK_QSwingSegment::SetLimit(int axis, double lmin, double lmax)
{
if (lmin > lmax)
return;
// clamp and convert to axis angle parameters
- lmin = MT_clamp(lmin, -MT_PI, MT_PI);
- lmax = MT_clamp(lmax, -MT_PI, MT_PI);
+ lmin = Clamp(lmin, -M_PI, M_PI);
+ lmax = Clamp(lmax, -M_PI, M_PI);
lmin = sin(lmin * 0.5);
lmax = sin(lmax * 0.5);
// put center of ellispe in the middle between min and max
- MT_Scalar offset = 0.5 * (lmin + lmax);
+ double offset = 0.5 * (lmin + lmax);
//lmax = lmax - offset;
if (axis == 0) {
@@ -784,7 +598,7 @@ void IK_QSwingSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
}
}
-void IK_QSwingSegment::SetWeight(int axis, MT_Scalar weight)
+void IK_QSwingSegment::SetWeight(int axis, double weight)
{
if (axis == 0)
m_weight[0] = weight;
@@ -800,7 +614,7 @@ IK_QElbowSegment::IK_QElbowSegment(int axis)
{
}
-void IK_QElbowSegment::SetBasis(const MT_Matrix3x3& basis)
+void IK_QElbowSegment::SetBasis(const Matrix3d& basis)
{
m_basis = basis;
@@ -811,22 +625,22 @@ void IK_QElbowSegment::SetBasis(const MT_Matrix3x3& basis)
m_basis = RotationMatrix(m_angle, m_axis) * ComputeTwistMatrix(m_twist);
}
-MT_Vector3 IK_QElbowSegment::Axis(int dof) const
+Vector3d IK_QElbowSegment::Axis(int dof) const
{
if (dof == 0) {
- MT_Vector3 v;
+ Vector3d v;
if (m_axis == 0)
- v = MT_Vector3(m_cos_twist, 0, m_sin_twist);
+ v = Vector3d(m_cos_twist, 0, m_sin_twist);
else
- v = MT_Vector3(-m_sin_twist, 0, m_cos_twist);
+ v = Vector3d(-m_sin_twist, 0, m_cos_twist);
- return m_global_transform.getBasis() * v;
+ return m_global_transform.linear() * v;
}
else
- return m_global_transform.getBasis().getColumn(1);
+ return m_global_transform.linear().col(1);
}
-bool IK_QElbowSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp)
+bool IK_QElbowSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp)
{
if (m_locked[0] && m_locked[1])
return false;
@@ -870,7 +684,7 @@ bool IK_QElbowSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& del
return (clamp[0] || clamp[1]);
}
-void IK_QElbowSegment::Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta)
+void IK_QElbowSegment::Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta)
{
if (dof == 0) {
m_locked[0] = true;
@@ -890,20 +704,20 @@ void IK_QElbowSegment::UpdateAngleApply()
m_sin_twist = sin(m_twist);
m_cos_twist = cos(m_twist);
- MT_Matrix3x3 A = RotationMatrix(m_angle, m_axis);
- MT_Matrix3x3 T = RotationMatrix(m_sin_twist, m_cos_twist, 1);
+ Matrix3d A = RotationMatrix(m_angle, m_axis);
+ Matrix3d T = RotationMatrix(m_sin_twist, m_cos_twist, 1);
m_basis = A * T;
}
-void IK_QElbowSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
+void IK_QElbowSegment::SetLimit(int axis, double lmin, double lmax)
{
if (lmin > lmax)
return;
// clamp and convert to axis angle parameters
- lmin = MT_clamp(lmin, -MT_PI, MT_PI);
- lmax = MT_clamp(lmax, -MT_PI, MT_PI);
+ lmin = Clamp(lmin, -M_PI, M_PI);
+ lmax = Clamp(lmax, -M_PI, M_PI);
if (axis == 1) {
m_min_twist = lmin;
@@ -917,7 +731,7 @@ void IK_QElbowSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
}
}
-void IK_QElbowSegment::SetWeight(int axis, MT_Scalar weight)
+void IK_QElbowSegment::SetWeight(int axis, double weight)
{
if (axis == m_axis)
m_weight[0] = weight;
@@ -963,16 +777,16 @@ IK_QTranslateSegment::IK_QTranslateSegment()
m_limit[0] = m_limit[1] = m_limit[2] = false;
}
-MT_Vector3 IK_QTranslateSegment::Axis(int dof) const
+Vector3d IK_QTranslateSegment::Axis(int dof) const
{
- return m_global_transform.getBasis().getColumn(m_axis[dof]);
+ return m_global_transform.linear().col(m_axis[dof]);
}
-bool IK_QTranslateSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp)
+bool IK_QTranslateSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp)
{
int dof_id = m_DoF_id, dof = 0, i, clamped = false;
- MT_Vector3 dx(0.0, 0.0, 0.0);
+ Vector3d dx(0.0, 0.0, 0.0);
for (i = 0; i < 3; i++) {
if (!m_axis_enabled[i]) {
@@ -1011,13 +825,13 @@ void IK_QTranslateSegment::UpdateAngleApply()
m_translation = m_new_translation;
}
-void IK_QTranslateSegment::Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta)
+void IK_QTranslateSegment::Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta)
{
m_locked[dof] = true;
jacobian.Lock(m_DoF_id + dof, delta[dof]);
}
-void IK_QTranslateSegment::SetWeight(int axis, MT_Scalar weight)
+void IK_QTranslateSegment::SetWeight(int axis, double weight)
{
int i;
@@ -1026,7 +840,7 @@ void IK_QTranslateSegment::SetWeight(int axis, MT_Scalar weight)
m_weight[i] = weight;
}
-void IK_QTranslateSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
+void IK_QTranslateSegment::SetLimit(int axis, double lmin, double lmax)
{
if (lmax < lmin)
return;
@@ -1036,7 +850,7 @@ void IK_QTranslateSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
m_limit[axis] = true;
}
-void IK_QTranslateSegment::Scale(MT_Scalar scale)
+void IK_QTranslateSegment::Scale(double scale)
{
int i;
diff --git a/intern/iksolver/intern/IK_QSegment.h b/intern/iksolver/intern/IK_QSegment.h
index b40bf3739ff..74f157aa763 100644
--- a/intern/iksolver/intern/IK_QSegment.h
+++ b/intern/iksolver/intern/IK_QSegment.h
@@ -30,13 +30,9 @@
* \ingroup iksolver
*/
+#pragma once
-#ifndef __IK_QSEGMENT_H__
-#define __IK_QSEGMENT_H__
-
-#include "MT_Vector3.h"
-#include "MT_Transform.h"
-#include "MT_Matrix4x4.h"
+#include "IK_Math.h"
#include "IK_QJacobian.h"
#include <vector>
@@ -50,8 +46,7 @@
* Here we define the local coordinates of a joint as
* local_transform =
* translate(tr1) * rotation(A) * rotation(q) * translate(0,length,0)
- * We use the standard moto column ordered matrices. You can read
- * this as:
+ * You can read this as:
* - first translate by (0,length,0)
* - multiply by the rotation matrix derived from the current
* angle parameterization q.
@@ -73,10 +68,10 @@ public:
// length: length of this segment
void SetTransform(
- const MT_Vector3& start,
- const MT_Matrix3x3& rest_basis,
- const MT_Matrix3x3& basis,
- const MT_Scalar length
+ const Vector3d& start,
+ const Matrix3d& rest_basis,
+ const Matrix3d& basis,
+ const double length
);
// tree structure access
@@ -109,22 +104,22 @@ public:
{ m_DoF_id = dof_id; }
// the max distance of the end of this bone from the local origin.
- const MT_Scalar MaxExtension() const
+ const double MaxExtension() const
{ return m_max_extension; }
// the change in rotation and translation w.r.t. the rest pose
- MT_Matrix3x3 BasisChange() const;
- MT_Vector3 TranslationChange() const;
+ Matrix3d BasisChange() const;
+ Vector3d TranslationChange() const;
// the start and end of the segment
- const MT_Point3 &GlobalStart() const
+ const Vector3d GlobalStart() const
{ return m_global_start; }
- const MT_Point3 &GlobalEnd() const
- { return m_global_transform.getOrigin(); }
+ const Vector3d GlobalEnd() const
+ { return m_global_transform.translation(); }
// the global transformation at the end of the segment
- const MT_Transform &GlobalTransform() const
+ const Affine3d &GlobalTransform() const
{ return m_global_transform; }
// is a translational segment?
@@ -139,38 +134,38 @@ public:
{ m_locked[0] = m_locked[1] = m_locked[2] = false; }
// per dof joint weighting
- MT_Scalar Weight(int dof) const
+ double Weight(int dof) const
{ return m_weight[dof]; }
- void ScaleWeight(int dof, MT_Scalar scale)
+ void ScaleWeight(int dof, double scale)
{ m_weight[dof] *= scale; }
// recursively update the global coordinates of this segment, 'global'
// is the global transformation from the parent segment
- void UpdateTransform(const MT_Transform &global);
+ void UpdateTransform(const Affine3d &global);
// get axis from rotation matrix for derivative computation
- virtual MT_Vector3 Axis(int dof) const=0;
+ virtual Vector3d Axis(int dof) const=0;
// update the angles using the dTheta's computed using the jacobian matrix
- virtual bool UpdateAngle(const IK_QJacobian&, MT_Vector3&, bool*)=0;
- virtual void Lock(int, IK_QJacobian&, MT_Vector3&) {}
+ virtual bool UpdateAngle(const IK_QJacobian&, Vector3d&, bool*)=0;
+ virtual void Lock(int, IK_QJacobian&, Vector3d&) {}
virtual void UpdateAngleApply()=0;
// set joint limits
- virtual void SetLimit(int, MT_Scalar, MT_Scalar) {}
+ virtual void SetLimit(int, double, double) {}
// set joint weights (per axis)
- virtual void SetWeight(int, MT_Scalar) {}
+ virtual void SetWeight(int, double) {}
- virtual void SetBasis(const MT_Matrix3x3& basis) { m_basis = basis; }
+ virtual void SetBasis(const Matrix3d& basis) { m_basis = basis; }
// functions needed for pole vector constraint
- void PrependBasis(const MT_Matrix3x3& mat);
+ void PrependBasis(const Matrix3d& mat);
void Reset();
// scale
- virtual void Scale(MT_Scalar scale);
+ virtual void Scale(double scale);
protected:
@@ -188,28 +183,28 @@ protected:
// full transform =
// start * rest_basis * basis * translation
- MT_Vector3 m_start;
- MT_Matrix3x3 m_rest_basis;
- MT_Matrix3x3 m_basis;
- MT_Vector3 m_translation;
+ Vector3d m_start;
+ Matrix3d m_rest_basis;
+ Matrix3d m_basis;
+ Vector3d m_translation;
// original basis
- MT_Matrix3x3 m_orig_basis;
- MT_Vector3 m_orig_translation;
+ Matrix3d m_orig_basis;
+ Vector3d m_orig_translation;
// maximum extension of this segment
- MT_Scalar m_max_extension;
+ double m_max_extension;
// accumulated transformations starting from root
- MT_Point3 m_global_start;
- MT_Transform m_global_transform;
+ Vector3d m_global_start;
+ Affine3d m_global_transform;
// number degrees of freedom, (first) id of this segments DOF's
int m_num_DoF, m_DoF_id;
bool m_locked[3];
bool m_translational;
- MT_Scalar m_weight[3];
+ double m_weight[3];
};
class IK_QSphericalSegment : public IK_QSegment
@@ -217,23 +212,23 @@ class IK_QSphericalSegment : public IK_QSegment
public:
IK_QSphericalSegment();
- MT_Vector3 Axis(int dof) const;
+ Vector3d Axis(int dof) const;
- bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
- void Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta);
+ bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
+ void Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta);
void UpdateAngleApply();
- bool ComputeClampRotation(MT_Vector3& clamp);
+ bool ComputeClampRotation(Vector3d& clamp);
- void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
- void SetWeight(int axis, MT_Scalar weight);
+ void SetLimit(int axis, double lmin, double lmax);
+ void SetWeight(int axis, double weight);
private:
- MT_Matrix3x3 m_new_basis;
+ Matrix3d m_new_basis;
bool m_limit_x, m_limit_y, m_limit_z;
- MT_Scalar m_min[2], m_max[2];
- MT_Scalar m_min_y, m_max_y, m_max_x, m_max_z, m_offset_x, m_offset_z;
- MT_Scalar m_locked_ax, m_locked_ay, m_locked_az;
+ double m_min[2], m_max[2];
+ double m_min_y, m_max_y, m_max_x, m_max_z, m_offset_x, m_offset_z;
+ double m_locked_ax, m_locked_ay, m_locked_az;
};
class IK_QNullSegment : public IK_QSegment
@@ -241,11 +236,11 @@ class IK_QNullSegment : public IK_QSegment
public:
IK_QNullSegment();
- bool UpdateAngle(const IK_QJacobian&, MT_Vector3&, bool*) { return false; }
+ bool UpdateAngle(const IK_QJacobian&, Vector3d&, bool*) { return false; }
void UpdateAngleApply() {}
- MT_Vector3 Axis(int) const { return MT_Vector3(0, 0, 0); }
- void SetBasis(const MT_Matrix3x3&) { m_basis.setIdentity(); }
+ Vector3d Axis(int) const { return Vector3d(0, 0, 0); }
+ void SetBasis(const Matrix3d&) { m_basis.setIdentity(); }
};
class IK_QRevoluteSegment : public IK_QSegment
@@ -254,21 +249,21 @@ public:
// axis: the axis of the DoF, in range 0..2
IK_QRevoluteSegment(int axis);
- MT_Vector3 Axis(int dof) const;
+ Vector3d Axis(int dof) const;
- bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
- void Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta);
+ bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
+ void Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta);
void UpdateAngleApply();
- void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
- void SetWeight(int axis, MT_Scalar weight);
- void SetBasis(const MT_Matrix3x3& basis);
+ void SetLimit(int axis, double lmin, double lmax);
+ void SetWeight(int axis, double weight);
+ void SetBasis(const Matrix3d& basis);
private:
int m_axis;
- MT_Scalar m_angle, m_new_angle;
+ double m_angle, m_new_angle;
bool m_limit;
- MT_Scalar m_min, m_max;
+ double m_min, m_max;
};
class IK_QSwingSegment : public IK_QSegment
@@ -277,21 +272,21 @@ public:
// XZ DOF, uses one direct rotation
IK_QSwingSegment();
- MT_Vector3 Axis(int dof) const;
+ Vector3d Axis(int dof) const;
- bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
- void Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta);
+ bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
+ void Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta);
void UpdateAngleApply();
- void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
- void SetWeight(int axis, MT_Scalar weight);
- void SetBasis(const MT_Matrix3x3& basis);
+ void SetLimit(int axis, double lmin, double lmax);
+ void SetWeight(int axis, double weight);
+ void SetBasis(const Matrix3d& basis);
private:
- MT_Matrix3x3 m_new_basis;
+ Matrix3d m_new_basis;
bool m_limit_x, m_limit_z;
- MT_Scalar m_min[2], m_max[2];
- MT_Scalar m_max_x, m_max_z, m_offset_x, m_offset_z;
+ double m_min[2], m_max[2];
+ double m_max_x, m_max_z, m_offset_x, m_offset_z;
};
class IK_QElbowSegment : public IK_QSegment
@@ -301,24 +296,24 @@ public:
// X or Z, then rotate around Y (twist)
IK_QElbowSegment(int axis);
- MT_Vector3 Axis(int dof) const;
+ Vector3d Axis(int dof) const;
- bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
- void Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta);
+ bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
+ void Lock(int dof, IK_QJacobian& jacobian, Vector3d& delta);
void UpdateAngleApply();
- void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
- void SetWeight(int axis, MT_Scalar weight);
- void SetBasis(const MT_Matrix3x3& basis);
+ void SetLimit(int axis, double lmin, double lmax);
+ void SetWeight(int axis, double weight);
+ void SetBasis(const Matrix3d& basis);
private:
int m_axis;
- MT_Scalar m_twist, m_angle, m_new_twist, m_new_angle;
- MT_Scalar m_cos_twist, m_sin_twist;
+ double m_twist, m_angle, m_new_twist, m_new_angle;
+ double m_cos_twist, m_sin_twist;
bool m_limit, m_limit_twist;
- MT_Scalar m_min, m_max, m_min_twist, m_max_twist;
+ double m_min, m_max, m_min_twist, m_max_twist;
};
class IK_QTranslateSegment : public IK_QSegment
@@ -329,23 +324,21 @@ public:
IK_QTranslateSegment(int axis1, int axis2);
IK_QTranslateSegment();
- MT_Vector3 Axis(int dof) const;
+ Vector3d Axis(int dof) const;
- bool UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp);
- void Lock(int, IK_QJacobian&, MT_Vector3&);
+ bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d& delta, bool *clamp);
+ void Lock(int, IK_QJacobian&, Vector3d&);
void UpdateAngleApply();
- void SetWeight(int axis, MT_Scalar weight);
- void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
+ void SetWeight(int axis, double weight);
+ void SetLimit(int axis, double lmin, double lmax);
- void Scale(MT_Scalar scale);
+ void Scale(double scale);
private:
int m_axis[3];
bool m_axis_enabled[3], m_limit[3];
- MT_Vector3 m_new_translation;
- MT_Scalar m_min[3], m_max[3];
+ Vector3d m_new_translation;
+ double m_min[3], m_max[3];
};
-#endif
-
diff --git a/intern/iksolver/intern/IK_QTask.cpp b/intern/iksolver/intern/IK_QTask.cpp
index 0ba716ff59d..d7c73865789 100644
--- a/intern/iksolver/intern/IK_QTask.cpp
+++ b/intern/iksolver/intern/IK_QTask.cpp
@@ -51,7 +51,7 @@ IK_QTask::IK_QTask(
IK_QPositionTask::IK_QPositionTask(
bool primary,
const IK_QSegment *segment,
- const MT_Vector3& goal
+ const Vector3d& goal
) :
IK_QTask(3, primary, true, segment), m_goal(goal)
{
@@ -73,10 +73,10 @@ IK_QPositionTask::IK_QPositionTask(
void IK_QPositionTask::ComputeJacobian(IK_QJacobian& jacobian)
{
// compute beta
- const MT_Vector3& pos = m_segment->GlobalEnd();
+ const Vector3d& pos = m_segment->GlobalEnd();
- MT_Vector3 d_pos = m_goal - pos;
- MT_Scalar length = d_pos.length();
+ Vector3d d_pos = m_goal - pos;
+ double length = d_pos.norm();
if (length > m_clamp_length)
d_pos = (m_clamp_length / length) * d_pos;
@@ -88,26 +88,26 @@ void IK_QPositionTask::ComputeJacobian(IK_QJacobian& jacobian)
const IK_QSegment *seg;
for (seg = m_segment; seg; seg = seg->Parent()) {
- MT_Vector3 p = seg->GlobalStart() - pos;
+ Vector3d p = seg->GlobalStart() - pos;
for (i = 0; i < seg->NumberOfDoF(); i++) {
- MT_Vector3 axis = seg->Axis(i) * m_weight;
+ Vector3d axis = seg->Axis(i) * m_weight;
if (seg->Translational())
jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e2);
else {
- MT_Vector3 pa = p.cross(axis);
+ Vector3d pa = p.cross(axis);
jacobian.SetDerivatives(m_id, seg->DoFId() + i, pa, 1e0);
}
}
}
}
-MT_Scalar IK_QPositionTask::Distance() const
+double IK_QPositionTask::Distance() const
{
- const MT_Vector3& pos = m_segment->GlobalEnd();
- MT_Vector3 d_pos = m_goal - pos;
- return d_pos.length();
+ const Vector3d& pos = m_segment->GlobalEnd();
+ Vector3d d_pos = m_goal - pos;
+ return d_pos.norm();
}
// IK_QOrientationTask
@@ -115,7 +115,7 @@ MT_Scalar IK_QPositionTask::Distance() const
IK_QOrientationTask::IK_QOrientationTask(
bool primary,
const IK_QSegment *segment,
- const MT_Matrix3x3& goal
+ const Matrix3d& goal
) :
IK_QTask(3, primary, true, segment), m_goal(goal), m_distance(0.0)
{
@@ -124,17 +124,16 @@ IK_QOrientationTask::IK_QOrientationTask(
void IK_QOrientationTask::ComputeJacobian(IK_QJacobian& jacobian)
{
// compute betas
- const MT_Matrix3x3& rot = m_segment->GlobalTransform().getBasis();
+ const Matrix3d& rot = m_segment->GlobalTransform().linear();
- MT_Matrix3x3 d_rotm = m_goal * rot.transposed();
- d_rotm.transpose();
+ Matrix3d d_rotm = (m_goal * rot.transpose()).transpose();
- MT_Vector3 d_rot;
- d_rot = -0.5 * MT_Vector3(d_rotm[2][1] - d_rotm[1][2],
- d_rotm[0][2] - d_rotm[2][0],
- d_rotm[1][0] - d_rotm[0][1]);
+ Vector3d d_rot;
+ d_rot = -0.5 * Vector3d(d_rotm(2, 1) - d_rotm(1, 2),
+ d_rotm(0, 2) - d_rotm(2, 0),
+ d_rotm(1, 0) - d_rotm(0, 1));
- m_distance = d_rot.length();
+ m_distance = d_rot.norm();
jacobian.SetBetas(m_id, m_size, m_weight * d_rot);
@@ -146,9 +145,9 @@ void IK_QOrientationTask::ComputeJacobian(IK_QJacobian& jacobian)
for (i = 0; i < seg->NumberOfDoF(); i++) {
if (seg->Translational())
- jacobian.SetDerivatives(m_id, seg->DoFId() + i, MT_Vector3(0, 0, 0), 1e2);
+ jacobian.SetDerivatives(m_id, seg->DoFId() + i, Vector3d(0, 0, 0), 1e2);
else {
- MT_Vector3 axis = seg->Axis(i) * m_weight;
+ Vector3d axis = seg->Axis(i) * m_weight;
jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e0);
}
}
@@ -160,18 +159,18 @@ void IK_QOrientationTask::ComputeJacobian(IK_QJacobian& jacobian)
IK_QCenterOfMassTask::IK_QCenterOfMassTask(
bool primary,
const IK_QSegment *segment,
- const MT_Vector3& goal_center
+ const Vector3d& goal_center
) :
IK_QTask(3, primary, true, segment), m_goal_center(goal_center)
{
m_total_mass_inv = ComputeTotalMass(m_segment);
- if (!MT_fuzzyZero(m_total_mass_inv))
+ if (!FuzzyZero(m_total_mass_inv))
m_total_mass_inv = 1.0 / m_total_mass_inv;
}
-MT_Scalar IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
+double IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
{
- MT_Scalar mass = /*seg->Mass()*/ 1.0;
+ double mass = /*seg->Mass()*/ 1.0;
const IK_QSegment *seg;
for (seg = segment->Child(); seg; seg = seg->Sibling())
@@ -180,9 +179,9 @@ MT_Scalar IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
return mass;
}
-MT_Vector3 IK_QCenterOfMassTask::ComputeCenter(const IK_QSegment *segment)
+Vector3d IK_QCenterOfMassTask::ComputeCenter(const IK_QSegment *segment)
{
- MT_Vector3 center = /*seg->Mass()**/ segment->GlobalStart();
+ Vector3d center = /*seg->Mass()**/ segment->GlobalStart();
const IK_QSegment *seg;
for (seg = segment->Child(); seg; seg = seg->Sibling())
@@ -191,19 +190,19 @@ MT_Vector3 IK_QCenterOfMassTask::ComputeCenter(const IK_QSegment *segment)
return center;
}
-void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian& jacobian, MT_Vector3& center, const IK_QSegment *segment)
+void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian& jacobian, Vector3d& center, const IK_QSegment *segment)
{
int i;
- MT_Vector3 p = center - segment->GlobalStart();
+ Vector3d p = center - segment->GlobalStart();
for (i = 0; i < segment->NumberOfDoF(); i++) {
- MT_Vector3 axis = segment->Axis(i) * m_weight;
+ Vector3d axis = segment->Axis(i) * m_weight;
axis *= /*segment->Mass()**/ m_total_mass_inv;
if (segment->Translational())
jacobian.SetDerivatives(m_id, segment->DoFId() + i, axis, 1e2);
else {
- MT_Vector3 pa = axis.cross(p);
+ Vector3d pa = axis.cross(p);
jacobian.SetDerivatives(m_id, segment->DoFId() + i, pa, 1e0);
}
}
@@ -215,12 +214,12 @@ void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian& jacobian, MT_Vector3& c
void IK_QCenterOfMassTask::ComputeJacobian(IK_QJacobian& jacobian)
{
- MT_Vector3 center = ComputeCenter(m_segment) * m_total_mass_inv;
+ Vector3d center = ComputeCenter(m_segment) * m_total_mass_inv;
// compute beta
- MT_Vector3 d_pos = m_goal_center - center;
+ Vector3d d_pos = m_goal_center - center;
- m_distance = d_pos.length();
+ m_distance = d_pos.norm();
#if 0
if (m_distance > m_clamp_length)
@@ -233,7 +232,7 @@ void IK_QCenterOfMassTask::ComputeJacobian(IK_QJacobian& jacobian)
JacobianSegment(jacobian, center, m_segment);
}
-MT_Scalar IK_QCenterOfMassTask::Distance() const
+double IK_QCenterOfMassTask::Distance() const
{
return m_distance;
}
diff --git a/intern/iksolver/intern/IK_QTask.h b/intern/iksolver/intern/IK_QTask.h
index baf1c346d62..141e6d41b47 100644
--- a/intern/iksolver/intern/IK_QTask.h
+++ b/intern/iksolver/intern/IK_QTask.h
@@ -30,13 +30,9 @@
* \ingroup iksolver
*/
+#pragma once
-#ifndef __IK_QTASK_H__
-#define __IK_QTASK_H__
-
-#include "MT_Vector3.h"
-#include "MT_Transform.h"
-#include "MT_Matrix4x4.h"
+#include "IK_Math.h"
#include "IK_QJacobian.h"
#include "IK_QSegment.h"
@@ -66,19 +62,19 @@ public:
bool Active() const
{ return m_active; }
- MT_Scalar Weight() const
+ double Weight() const
{ return m_weight*m_weight; }
- void SetWeight(MT_Scalar weight)
+ void SetWeight(double weight)
{ m_weight = sqrt(weight); }
virtual void ComputeJacobian(IK_QJacobian& jacobian)=0;
- virtual MT_Scalar Distance() const=0;
+ virtual double Distance() const=0;
virtual bool PositionTask() const { return false; }
- virtual void Scale(MT_Scalar) {}
+ virtual void Scale(double) {}
protected:
int m_id;
@@ -86,7 +82,7 @@ protected:
bool m_primary;
bool m_active;
const IK_QSegment *m_segment;
- MT_Scalar m_weight;
+ double m_weight;
};
class IK_QPositionTask : public IK_QTask
@@ -95,19 +91,19 @@ public:
IK_QPositionTask(
bool primary,
const IK_QSegment *segment,
- const MT_Vector3& goal
+ const Vector3d& goal
);
void ComputeJacobian(IK_QJacobian& jacobian);
- MT_Scalar Distance() const;
+ double Distance() const;
bool PositionTask() const { return true; }
- void Scale(MT_Scalar scale) { m_goal *= scale; m_clamp_length *= scale; }
+ void Scale(double scale) { m_goal *= scale; m_clamp_length *= scale; }
private:
- MT_Vector3 m_goal;
- MT_Scalar m_clamp_length;
+ Vector3d m_goal;
+ double m_clamp_length;
};
class IK_QOrientationTask : public IK_QTask
@@ -116,15 +112,15 @@ public:
IK_QOrientationTask(
bool primary,
const IK_QSegment *segment,
- const MT_Matrix3x3& goal
+ const Matrix3d& goal
);
- MT_Scalar Distance() const { return m_distance; }
+ double Distance() const { return m_distance; }
void ComputeJacobian(IK_QJacobian& jacobian);
private:
- MT_Matrix3x3 m_goal;
- MT_Scalar m_distance;
+ Matrix3d m_goal;
+ double m_distance;
};
@@ -134,24 +130,22 @@ public:
IK_QCenterOfMassTask(
bool primary,
const IK_QSegment *segment,
- const MT_Vector3& center
+ const Vector3d& center
);
void ComputeJacobian(IK_QJacobian& jacobian);
- MT_Scalar Distance() const;
+ double Distance() const;
- void Scale(MT_Scalar scale) { m_goal_center *= scale; m_distance *= scale; }
+ void Scale(double scale) { m_goal_center *= scale; m_distance *= scale; }
private:
- MT_Scalar ComputeTotalMass(const IK_QSegment *segment);
- MT_Vector3 ComputeCenter(const IK_QSegment *segment);
- void JacobianSegment(IK_QJacobian& jacobian, MT_Vector3& center, const IK_QSegment *segment);
+ double ComputeTotalMass(const IK_QSegment *segment);
+ Vector3d ComputeCenter(const IK_QSegment *segment);
+ void JacobianSegment(IK_QJacobian& jacobian, Vector3d& center, const IK_QSegment *segment);
- MT_Vector3 m_goal_center;
- MT_Scalar m_total_mass_inv;
- MT_Scalar m_distance;
+ Vector3d m_goal_center;
+ double m_total_mass_inv;
+ double m_distance;
};
-#endif
-
diff --git a/intern/iksolver/intern/IK_Solver.cpp b/intern/iksolver/intern/IK_Solver.cpp
index eb18cde3356..cefb8c7ed7b 100644
--- a/intern/iksolver/intern/IK_Solver.cpp
+++ b/intern/iksolver/intern/IK_Solver.cpp
@@ -154,19 +154,19 @@ void IK_SetTransform(IK_Segment *seg, float start[3], float rest[][3], float bas
{
IK_QSegment *qseg = (IK_QSegment *)seg;
- MT_Vector3 mstart(start);
- // convert from blender column major to moto row major
- MT_Matrix3x3 mbasis(basis[0][0], basis[1][0], basis[2][0],
- basis[0][1], basis[1][1], basis[2][1],
- basis[0][2], basis[1][2], basis[2][2]);
- MT_Matrix3x3 mrest(rest[0][0], rest[1][0], rest[2][0],
- rest[0][1], rest[1][1], rest[2][1],
- rest[0][2], rest[1][2], rest[2][2]);
- MT_Scalar mlength(length);
+ Vector3d mstart(start[0], start[1], start[2]);
+ // convert from blender column major
+ Matrix3d mbasis = CreateMatrix(basis[0][0], basis[1][0], basis[2][0],
+ basis[0][1], basis[1][1], basis[2][1],
+ basis[0][2], basis[1][2], basis[2][2]);
+ Matrix3d mrest = CreateMatrix(rest[0][0], rest[1][0], rest[2][0],
+ rest[0][1], rest[1][1], rest[2][1],
+ rest[0][2], rest[1][2], rest[2][2]);
+ double mlength(length);
if (qseg->Composite()) {
- MT_Vector3 cstart(0, 0, 0);
- MT_Matrix3x3 cbasis;
+ Vector3d cstart(0, 0, 0);
+ Matrix3d cbasis;
cbasis.setIdentity();
qseg->SetTransform(mstart, mrest, mbasis, 0.0);
@@ -205,7 +205,7 @@ void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness)
stiffness = (1.0 - IK_STRETCH_STIFF_EPS);
IK_QSegment *qseg = (IK_QSegment *)seg;
- MT_Scalar weight = 1.0f - stiffness;
+ double weight = 1.0f - stiffness;
if (axis >= IK_TRANS_X) {
if (!qseg->Translational()) {
@@ -230,18 +230,18 @@ void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3])
if (qseg->Translational() && qseg->Composite())
qseg = qseg->Composite();
- const MT_Matrix3x3& change = qseg->BasisChange();
-
- // convert from moto row major to blender column major
- basis_change[0][0] = (float)change[0][0];
- basis_change[1][0] = (float)change[0][1];
- basis_change[2][0] = (float)change[0][2];
- basis_change[0][1] = (float)change[1][0];
- basis_change[1][1] = (float)change[1][1];
- basis_change[2][1] = (float)change[1][2];
- basis_change[0][2] = (float)change[2][0];
- basis_change[1][2] = (float)change[2][1];
- basis_change[2][2] = (float)change[2][2];
+ const Matrix3d& change = qseg->BasisChange();
+
+ // convert to blender column major
+ basis_change[0][0] = (float)change(0, 0);
+ basis_change[1][0] = (float)change(0, 1);
+ basis_change[2][0] = (float)change(0, 2);
+ basis_change[0][1] = (float)change(1, 0);
+ basis_change[1][1] = (float)change(1, 1);
+ basis_change[2][1] = (float)change(1, 2);
+ basis_change[0][2] = (float)change(2, 0);
+ basis_change[1][2] = (float)change(2, 1);
+ basis_change[2][2] = (float)change(2, 2);
}
void IK_GetTranslationChange(IK_Segment *seg, float *translation_change)
@@ -251,7 +251,7 @@ void IK_GetTranslationChange(IK_Segment *seg, float *translation_change)
if (!qseg->Translational() && qseg->Composite())
qseg = qseg->Composite();
- const MT_Vector3& change = qseg->TranslationChange();
+ const Vector3d& change = qseg->TranslationChange();
translation_change[0] = (float)change[0];
translation_change[1] = (float)change[1];
@@ -296,7 +296,7 @@ void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float w
if (qtip->Composite())
qtip = qtip->Composite();
- MT_Vector3 pos(goal);
+ Vector3d pos(goal[0], goal[1], goal[2]);
IK_QTask *ee = new IK_QPositionTask(true, qtip, pos);
ee->SetWeight(weight);
@@ -315,10 +315,10 @@ void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[
if (qtip->Composite())
qtip = qtip->Composite();
- // convert from blender column major to moto row major
- MT_Matrix3x3 rot(goal[0][0], goal[1][0], goal[2][0],
- goal[0][1], goal[1][1], goal[2][1],
- goal[0][2], goal[1][2], goal[2][2]);
+ // convert from blender column major
+ Matrix3d rot = CreateMatrix(goal[0][0], goal[1][0], goal[2][0],
+ goal[0][1], goal[1][1], goal[2][1],
+ goal[0][2], goal[1][2], goal[2][2]);
IK_QTask *orient = new IK_QOrientationTask(true, qtip, rot);
orient->SetWeight(weight);
@@ -337,8 +337,8 @@ void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float
if (qtip->Composite())
qtip = qtip->Composite();
- MT_Vector3 qgoal(goal);
- MT_Vector3 qpolegoal(polegoal);
+ Vector3d qgoal(goal[0], goal[1], goal[2]);
+ Vector3d qpolegoal(polegoal[0], polegoal[1], polegoal[2]);
qsolver->solver.SetPoleVectorConstraint(
qtip, qgoal, qpolegoal, poleangle, getangle);
@@ -363,8 +363,8 @@ static void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float
IK_QSolver *qsolver = (IK_QSolver *)solver;
IK_QSegment *qroot = (IK_QSegment *)root;
- // convert from blender column major to moto row major
- MT_Vector3 center(goal);
+ // convert from blender column major
+ Vector3d center(goal);
IK_QTask *com = new IK_QCenterOfMassTask(true, qroot, center);
com->SetWeight(weight);
@@ -382,7 +382,7 @@ int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations)
IK_QSegment *root = qsolver->root;
IK_QJacobianSolver& jacobian = qsolver->solver;
std::list<IK_QTask *>& tasks = qsolver->tasks;
- MT_Scalar tol = tolerance;
+ double tol = tolerance;
if (!jacobian.Setup(root, tasks))
return 0;
diff --git a/intern/iksolver/intern/MT_ExpMap.cpp b/intern/iksolver/intern/MT_ExpMap.cpp
deleted file mode 100644
index b2b13acebeb..00000000000
--- a/intern/iksolver/intern/MT_ExpMap.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Original Author: Laurence
- * Contributor(s): Brecht
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file iksolver/intern/MT_ExpMap.cpp
- * \ingroup iksolver
- */
-
-
-#include "MT_ExpMap.h"
-
-/**
- * Set the exponential map from a quaternion. The quaternion must be non-zero.
- */
-
-void
-MT_ExpMap::
-setRotation(
- const MT_Quaternion &q)
-{
- // ok first normalize the quaternion
- // then compute theta the axis-angle and the normalized axis v
- // scale v by theta and that's it hopefully!
-
- m_q = q.normalized();
- m_v = MT_Vector3(m_q.x(), m_q.y(), m_q.z());
-
- MT_Scalar cosp = m_q.w();
- m_sinp = m_v.length();
- m_v /= m_sinp;
-
- m_theta = atan2(double(m_sinp), double(cosp));
- m_v *= m_theta;
-}
-
-/**
- * Convert from an exponential map to a quaternion
- * representation
- */
-
-const MT_Quaternion&
-MT_ExpMap::
-getRotation() const
-{
- return m_q;
-}
-
-/**
- * Convert the exponential map to a 3x3 matrix
- */
-
-MT_Matrix3x3
-MT_ExpMap::
-getMatrix() const
-{
- return MT_Matrix3x3(m_q);
-}
-
-/**
- * Update & reparameterizate the exponential map
- */
-
-void
-MT_ExpMap::
-update(
- const MT_Vector3& dv)
-{
- m_v += dv;
-
- angleUpdated();
-}
-
-/**
- * Compute the partial derivatives of the exponential
- * map (dR/de - where R is a 3x3 rotation matrix formed
- * from the map) and return them as a 3x3 matrix
- */
-
-void
-MT_ExpMap::
-partialDerivatives(
- MT_Matrix3x3& dRdx,
- MT_Matrix3x3& dRdy,
- MT_Matrix3x3& dRdz) const
-{
- MT_Quaternion dQdx[3];
-
- compute_dQdVi(dQdx);
-
- compute_dRdVi(dQdx[0], dRdx);
- compute_dRdVi(dQdx[1], dRdy);
- compute_dRdVi(dQdx[2], dRdz);
-}
-
-void
-MT_ExpMap::
-compute_dRdVi(
- const MT_Quaternion &dQdvi,
- MT_Matrix3x3 & dRdvi) const
-{
- MT_Scalar prod[9];
-
- /* This efficient formulation is arrived at by writing out the
- * entire chain rule product dRdq * dqdv in terms of 'q' and
- * noticing that all the entries are formed from sums of just
- * nine products of 'q' and 'dqdv' */
-
- prod[0] = -MT_Scalar(4) * m_q.x() * dQdvi.x();
- prod[1] = -MT_Scalar(4) * m_q.y() * dQdvi.y();
- prod[2] = -MT_Scalar(4) * m_q.z() * dQdvi.z();
- prod[3] = MT_Scalar(2) * (m_q.y() * dQdvi.x() + m_q.x() * dQdvi.y());
- prod[4] = MT_Scalar(2) * (m_q.w() * dQdvi.z() + m_q.z() * dQdvi.w());
- prod[5] = MT_Scalar(2) * (m_q.z() * dQdvi.x() + m_q.x() * dQdvi.z());
- prod[6] = MT_Scalar(2) * (m_q.w() * dQdvi.y() + m_q.y() * dQdvi.w());
- prod[7] = MT_Scalar(2) * (m_q.z() * dQdvi.y() + m_q.y() * dQdvi.z());
- prod[8] = MT_Scalar(2) * (m_q.w() * dQdvi.x() + m_q.x() * dQdvi.w());
-
- /* first row, followed by second and third */
- dRdvi[0][0] = prod[1] + prod[2];
- dRdvi[0][1] = prod[3] - prod[4];
- dRdvi[0][2] = prod[5] + prod[6];
-
- dRdvi[1][0] = prod[3] + prod[4];
- dRdvi[1][1] = prod[0] + prod[2];
- dRdvi[1][2] = prod[7] - prod[8];
-
- dRdvi[2][0] = prod[5] - prod[6];
- dRdvi[2][1] = prod[7] + prod[8];
- dRdvi[2][2] = prod[0] + prod[1];
-}
-
-// compute partial derivatives dQ/dVi
-
-void
-MT_ExpMap::
-compute_dQdVi(
- MT_Quaternion *dQdX) const
-{
- /* This is an efficient implementation of the derivatives given
- * in Appendix A of the paper with common subexpressions factored out */
-
- MT_Scalar sinc, termCoeff;
-
- if (m_theta < MT_EXPMAP_MINANGLE) {
- sinc = 0.5 - m_theta * m_theta / 48.0;
- termCoeff = (m_theta * m_theta / 40.0 - 1.0) / 24.0;
- }
- else {
- MT_Scalar cosp = m_q.w();
- MT_Scalar ang = 1.0 / m_theta;
-
- sinc = m_sinp * ang;
- termCoeff = ang * ang * (0.5 * cosp - sinc);
- }
-
- for (int i = 0; i < 3; i++) {
- MT_Quaternion& dQdx = dQdX[i];
- int i2 = (i + 1) % 3;
- int i3 = (i + 2) % 3;
-
- MT_Scalar term = m_v[i] * termCoeff;
-
- dQdx[i] = term * m_v[i] + sinc;
- dQdx[i2] = term * m_v[i2];
- dQdx[i3] = term * m_v[i3];
- dQdx.w() = -0.5 * m_v[i] * sinc;
- }
-}
-
-// reParametize away from singularity, updating
-// m_v and m_theta
-
-void
-MT_ExpMap::
-reParametrize()
-{
- if (m_theta > MT_PI) {
- MT_Scalar scl = m_theta;
- if (m_theta > MT_2_PI) { /* first get theta into range 0..2PI */
- m_theta = MT_Scalar(fmod(m_theta, MT_2_PI));
- scl = m_theta / scl;
- m_v *= scl;
- }
- if (m_theta > MT_PI) {
- scl = m_theta;
- m_theta = MT_2_PI - m_theta;
- scl = MT_Scalar(1.0) - MT_2_PI / scl;
- m_v *= scl;
- }
- }
-}
-
-// compute cached variables
-
-void
-MT_ExpMap::
-angleUpdated()
-{
- m_theta = m_v.length();
-
- reParametrize();
-
- // compute quaternion, sinp and cosp
-
- if (m_theta < MT_EXPMAP_MINANGLE) {
- m_sinp = MT_Scalar(0.0);
-
- /* Taylor Series for sinc */
- MT_Vector3 temp = m_v * MT_Scalar(MT_Scalar(.5) - m_theta * m_theta / MT_Scalar(48.0));
- m_q.x() = temp.x();
- m_q.y() = temp.y();
- m_q.z() = temp.z();
- m_q.w() = MT_Scalar(1.0);
- }
- else {
- m_sinp = MT_Scalar(sin(.5 * m_theta));
-
- /* Taylor Series for sinc */
- MT_Vector3 temp = m_v * (m_sinp / m_theta);
- m_q.x() = temp.x();
- m_q.y() = temp.y();
- m_q.z() = temp.z();
- m_q.w() = MT_Scalar(cos(0.5 * m_theta));
- }
-}
-
diff --git a/intern/iksolver/intern/MT_ExpMap.h b/intern/iksolver/intern/MT_ExpMap.h
deleted file mode 100644
index 65bbe4d4ad5..00000000000
--- a/intern/iksolver/intern/MT_ExpMap.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Original author: Laurence
- * Contributor(s): Brecht
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file iksolver/intern/MT_ExpMap.h
- * \ingroup iksolver
- */
-
-
-#ifndef MT_ExpMap_H
-#define MT_ExpMap_H
-
-#include <MT_assert.h>
-
-#include "MT_Vector3.h"
-#include "MT_Quaternion.h"
-#include "MT_Matrix4x4.h"
-
-const MT_Scalar MT_EXPMAP_MINANGLE (1e-7);
-
-/**
- * MT_ExpMap an exponential map parameterization of rotations
- * in 3D. This implementation is derived from the paper
- * "F. Sebastian Grassia. Practical parameterization of
- * rotations using the exponential map. Journal of Graphics Tools,
- * 3(3):29-48, 1998" Please go to http://www.acm.org/jgt/papers/Grassia98/
- * for a thorough description of the theory and sample code used
- * to derive this class.
- *
- * Basic overview of why this class is used.
- * In an IK system we need to paramterize the joint angles in some
- * way. Typically 2 parameterizations are used.
- * - Euler Angles
- * These suffer from singularities in the parameterization known
- * as gimbal lock. They also do not interpolate well. For every
- * set of euler angles there is exactly 1 corresponding 3d rotation.
- * - Quaternions.
- * Great for interpolating. Only unit quaternions are valid rotations
- * means that in a differential ik solver we often stray outside of
- * this manifold into invalid rotations. Means we have to do a lot
- * of nasty normalizations all the time. Does not suffer from
- * gimbal lock problems. More expensive to compute partial derivatives
- * as there are 4 of them.
- *
- * So exponential map is similar to a quaternion axis/angle
- * representation but we store the angle as the length of the
- * axis. So require only 3 parameters. Means that all exponential
- * maps are valid rotations. Suffers from gimbal lock. But it's
- * possible to detect when gimbal lock is near and reparameterize
- * away from it. Also nice for interpolating.
- * Exponential maps are share some of the useful properties of
- * euler and quaternion parameterizations. And are very useful
- * for differential IK solvers.
- */
-
-class MT_ExpMap {
-public:
-
- /**
- * Default constructor
- * @warning there is no initialization in the
- * default constructor
- */
-
- MT_ExpMap() {}
- MT_ExpMap(const MT_Vector3& v) : m_v(v) { angleUpdated(); }
-
- MT_ExpMap(const float v[3]) : m_v(v) { angleUpdated(); }
- MT_ExpMap(const double v[3]) : m_v(v) { angleUpdated(); }
-
- MT_ExpMap(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
- m_v(x, y, z) { angleUpdated(); }
-
- /**
- * Construct an exponential map from a quaternion
- */
-
- MT_ExpMap(
- const MT_Quaternion &q
- ) {
- setRotation(q);
- }
-
- /**
- * Accessors
- * Decided not to inherit from MT_Vector3 but rather
- * this class contains an MT_Vector3. This is because
- * it is very dangerous to use MT_Vector3 functions
- * on this class and some of them have no direct meaning.
- */
-
- const
- MT_Vector3 &
- vector(
- ) const {
- return m_v;
- }
-
- /**
- * Set the exponential map from a quaternion
- */
-
- void
- setRotation(
- const MT_Quaternion &q
- );
-
- /**
- * Convert from an exponential map to a quaternion
- * representation
- */
-
- const MT_Quaternion&
- getRotation(
- ) const;
-
- /**
- * Convert the exponential map to a 3x3 matrix
- */
-
- MT_Matrix3x3
- getMatrix(
- ) const;
-
- /**
- * Update (and reparameterize) the expontial map
- * @param dv delta update values.
- */
-
- void
- update(
- const MT_Vector3& dv
- );
-
- /**
- * Compute the partial derivatives of the exponential
- * map (dR/de - where R is a 4x4 matrix formed
- * from the map) and return them as a 4x4 matrix
- */
-
- void
- partialDerivatives(
- MT_Matrix3x3& dRdx,
- MT_Matrix3x3& dRdy,
- MT_Matrix3x3& dRdz
- ) const ;
-
-private :
-
- // m_v contains the exponential map, the other variables are
- // cached for efficiency
-
- MT_Vector3 m_v;
- MT_Scalar m_theta, m_sinp;
- MT_Quaternion m_q;
-
- // private methods
-
- // Compute partial derivatives dR (3x3 rotation matrix) / dVi (EM vector)
- // given the partial derivative dQ (Quaternion) / dVi (ith element of EM vector)
-
- void
- compute_dRdVi(
- const MT_Quaternion &dQdV,
- MT_Matrix3x3 & dRdVi
- ) const;
-
- // compute partial derivatives dQ/dVi
-
- void
- compute_dQdVi(
- MT_Quaternion *dQdX
- ) const ;
-
- // reparametrize away from singularity
-
- void
- reParametrize(
- );
-
- // (re-)compute cached variables
-
- void
- angleUpdated(
- );
-};
-
-#endif
-
diff --git a/intern/iksolver/intern/TNT/cholesky.h b/intern/iksolver/intern/TNT/cholesky.h
deleted file mode 100644
index 89c7dc64d5b..00000000000
--- a/intern/iksolver/intern/TNT/cholesky.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- */
-
-/*
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-#ifndef CHOLESKY_H
-#define CHOLESKY_H
-
-#include <cmath>
-
-// index method
-
-namespace TNT
-{
-
-
-//
-// Only upper part of A is used. Cholesky factor is returned in
-// lower part of L. Returns 0 if successful, 1 otherwise.
-//
-template <class SPDMatrix, class SymmMatrix>
-int Cholesky_upper_factorization(SPDMatrix &A, SymmMatrix &L)
-{
- Subscript M = A.dim(1);
- Subscript N = A.dim(2);
-
- assert(M == N); // make sure A is square
-
- // readjust size of L, if necessary
-
- if (M != L.dim(1) || N != L.dim(2))
- L = SymmMatrix(N,N);
-
- Subscript i,j,k;
-
-
- typename SPDMatrix::element_type dot=0;
-
-
- for (j=1; j<=N; j++) // form column j of L
- {
- dot= 0;
-
- for (i=1; i<j; i++) // for k= 1 TO j-1
- dot = dot + L(j,i)*L(j,i);
-
- L(j,j) = A(j,j) - dot;
-
- for (i=j+1; i<=N; i++)
- {
- dot = 0;
- for (k=1; k<j; k++)
- dot = dot + L(i,k)*L(j,k);
- L(i,j) = A(j,i) - dot;
- }
-
- if (L(j,j) <= 0.0) return 1;
-
- L(j,j) = sqrt( L(j,j) );
-
- for (i=j+1; i<=N; i++)
- L(i,j) = L(i,j) / L(j,j);
-
- }
-
- return 0;
-}
-
-
-
-
-}
-// namespace TNT
-
-#endif
-// CHOLESKY_H
-
diff --git a/intern/iksolver/intern/TNT/cmat.h b/intern/iksolver/intern/TNT/cmat.h
deleted file mode 100644
index fd3a1851262..00000000000
--- a/intern/iksolver/intern/TNT/cmat.h
+++ /dev/null
@@ -1,614 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// C compatible matrix: row-oriented, 0-based [i][j] and 1-based (i,j) indexing
-//
-
-#ifndef CMAT_H
-#define CMAT_H
-
-#include "subscript.h"
-#include "vec.h"
-#include <stdlib.h>
-#include <assert.h>
-#include <iostream>
-#ifdef TNT_USE_REGIONS
-#include "region2d.h"
-#endif
-
-namespace TNT
-{
-
-template <class T>
-class Matrix
-{
-
-
- public:
-
- typedef Subscript size_type;
- typedef T value_type;
- typedef T element_type;
- typedef T* pointer;
- typedef T* iterator;
- typedef T& reference;
- typedef const T* const_iterator;
- typedef const T& const_reference;
-
- Subscript lbound() const { return 1;}
-
- protected:
- Subscript m_;
- Subscript n_;
- Subscript mn_; // total size
- T* v_;
- T** row_;
- T* vm1_ ; // these point to the same data, but are 1-based
- T** rowm1_;
-
- // internal helper function to create the array
- // of row pointers
-
- void initialize(Subscript M, Subscript N)
- {
- mn_ = M*N;
- m_ = M;
- n_ = N;
-
- v_ = new T[mn_];
- row_ = new T*[M];
- rowm1_ = new T*[M];
-
- assert(v_ != NULL);
- assert(row_ != NULL);
- assert(rowm1_ != NULL);
-
- T* p = v_;
- vm1_ = v_ - 1;
- for (Subscript i=0; i<M; i++)
- {
- row_[i] = p;
- rowm1_[i] = p-1;
- p += N ;
-
- }
-
- rowm1_ -- ; // compensate for 1-based offset
- }
-
- void copy(const T* v)
- {
- Subscript N = m_ * n_;
- Subscript i;
-
-#ifdef TNT_UNROLL_LOOPS
- Subscript Nmod4 = N & 3;
- Subscript N4 = N - Nmod4;
-
- for (i=0; i<N4; i+=4)
- {
- v_[i] = v[i];
- v_[i+1] = v[i+1];
- v_[i+2] = v[i+2];
- v_[i+3] = v[i+3];
- }
-
- for (i=N4; i< N; i++)
- v_[i] = v[i];
-#else
-
- for (i=0; i< N; i++)
- v_[i] = v[i];
-#endif
- }
-
- void set(const T& val)
- {
- Subscript N = m_ * n_;
- Subscript i;
-
-#ifdef TNT_UNROLL_LOOPS
- Subscript Nmod4 = N & 3;
- Subscript N4 = N - Nmod4;
-
- for (i=0; i<N4; i+=4)
- {
- v_[i] = val;
- v_[i+1] = val;
- v_[i+2] = val;
- v_[i+3] = val;
- }
-
- for (i=N4; i< N; i++)
- v_[i] = val;
-#else
-
- for (i=0; i< N; i++)
- v_[i] = val;
-
-#endif
- }
-
-
-
- void destroy()
- {
- /* do nothing, if no memory has been previously allocated */
- if (v_ == NULL) return ;
-
- /* if we are here, then matrix was previously allocated */
- if (v_ != NULL) delete [] (v_);
- if (row_ != NULL) delete [] (row_);
-
- /* return rowm1_ back to original value */
- rowm1_ ++;
- if (rowm1_ != NULL ) delete [] (rowm1_);
- }
-
-
- public:
-
- operator T**(){ return row_; }
- operator T**() const { return row_; }
-
-
- Subscript size() const { return mn_; }
-
- // constructors
-
- Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {}
-
- Matrix(const Matrix<T> &A)
- {
- initialize(A.m_, A.n_);
- copy(A.v_);
- }
-
- Matrix(Subscript M, Subscript N, const T& value = T())
- {
- initialize(M,N);
- set(value);
- }
-
- Matrix(Subscript M, Subscript N, const T* v)
- {
- initialize(M,N);
- copy(v);
- }
-
-
- // destructor
- //
- ~Matrix()
- {
- destroy();
- }
-
-
- // reallocating
- //
- Matrix<T>& newsize(Subscript M, Subscript N)
- {
- if (num_rows() == M && num_cols() == N)
- return *this;
-
- destroy();
- initialize(M,N);
-
- return *this;
- }
-
- void
- diagonal(Vector<T> &diag)
- {
- int sz = diag.dim();
- newsize(sz,sz);
- set(0);
-
- Subscript i;
- for (i = 0; i < sz; i++) {
- row_[i][i] = diag[i];
- }
- }
-
-
-
- // assignments
- //
- Matrix<T>& operator=(const Matrix<T> &A)
- {
- if (v_ == A.v_)
- return *this;
-
- if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc
- copy(A.v_);
-
- else
- {
- destroy();
- initialize(A.m_, A.n_);
- copy(A.v_);
- }
-
- return *this;
- }
-
- Matrix<T>& operator=(const T& scalar)
- {
- set(scalar);
- return *this;
- }
-
-
- Subscript dim(Subscript d) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( d >= 1);
- assert( d <= 2);
-#endif
- return (d==1) ? m_ : ((d==2) ? n_ : 0);
- }
-
- Subscript num_rows() const { return m_; }
- Subscript num_cols() const { return n_; }
-
-
-
-
- inline T* operator[](Subscript i)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(0<=i);
- assert(i < m_) ;
-#endif
- return row_[i];
- }
-
- inline const T* operator[](Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(0<=i);
- assert(i < m_) ;
-#endif
- return row_[i];
- }
-
- inline reference operator()(Subscript i)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i <= mn_) ;
-#endif
- return vm1_[i];
- }
-
- inline const_reference operator()(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i <= mn_) ;
-#endif
- return vm1_[i];
- }
-
-
-
- inline reference operator()(Subscript i, Subscript j)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i <= m_) ;
- assert(1<=j);
- assert(j <= n_);
-#endif
- return rowm1_[i][j];
- }
-
-
-
- inline const_reference operator() (Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i <= m_) ;
- assert(1<=j);
- assert(j <= n_);
-#endif
- return rowm1_[i][j];
- }
-
-
-
-#ifdef TNT_USE_REGIONS
-
- typedef Region2D<Matrix<T> > Region;
-
-
- Region operator()(const Index1D &I, const Index1D &J)
- {
- return Region(*this, I,J);
- }
-
-
- typedef const_Region2D< Matrix<T> > const_Region;
- const_Region operator()(const Index1D &I, const Index1D &J) const
- {
- return const_Region(*this, I,J);
- }
-
-#endif
-
-
-};
-
-
-/* *************************** I/O ********************************/
-
-template <class T>
-std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
-{
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- s << M << " " << N << "\n";
-
- for (Subscript i=0; i<M; i++)
- {
- for (Subscript j=0; j<N; j++)
- {
- s << A[i][j] << " ";
- }
- s << "\n";
- }
-
-
- return s;
-}
-
-template <class T>
-std::istream& operator>>(std::istream &s, Matrix<T> &A)
-{
-
- Subscript M, N;
-
- s >> M >> N;
-
- if ( !(M == A.num_rows() && N == A.num_cols() ))
- {
- A.newsize(M,N);
- }
-
-
- for (Subscript i=0; i<M; i++)
- for (Subscript j=0; j<N; j++)
- {
- s >> A[i][j];
- }
-
-
- return s;
-}
-
-// *******************[ basic matrix algorithms ]***************************
-
-template <class T>
-Matrix<T> operator+(const Matrix<T> &A,
- const Matrix<T> &B)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(M==B.num_rows());
- assert(N==B.num_cols());
-
- Matrix<T> tmp(M,N);
- Subscript i,j;
-
- for (i=0; i<M; i++)
- for (j=0; j<N; j++)
- tmp[i][j] = A[i][j] + B[i][j];
-
- return tmp;
-}
-
-template <class T>
-Matrix<T> operator-(const Matrix<T> &A,
- const Matrix<T> &B)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(M==B.num_rows());
- assert(N==B.num_cols());
-
- Matrix<T> tmp(M,N);
- Subscript i,j;
-
- for (i=0; i<M; i++)
- for (j=0; j<N; j++)
- tmp[i][j] = A[i][j] - B[i][j];
-
- return tmp;
-}
-
-template <class T>
-Matrix<T> mult_element(const Matrix<T> &A,
- const Matrix<T> &B)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(M==B.num_rows());
- assert(N==B.num_cols());
-
- Matrix<T> tmp(M,N);
- Subscript i,j;
-
- for (i=0; i<M; i++)
- for (j=0; j<N; j++)
- tmp[i][j] = A[i][j] * B[i][j];
-
- return tmp;
-}
-
-template <class T>
-void transpose(const Matrix<T> &A, Matrix<T> &S)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(M==S.num_cols());
- assert(N==S.num_rows());
-
- Subscript i, j;
-
- for (i=0; i<M; i++)
- for (j=0; j<N; j++)
- S[j][i] = A[i][j];
-
-}
-
-
-template <class T>
-inline void matmult(Matrix<T>& C, const Matrix<T> &A,
- const Matrix<T> &B)
-{
-
- assert(A.num_cols() == B.num_rows());
-
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
- Subscript K = B.num_cols();
-
- C.newsize(M,K);
-
- T sum;
-
- const T* row_i;
- const T* col_k;
-
- for (Subscript i=0; i<M; i++)
- for (Subscript k=0; k<K; k++)
- {
- row_i = &(A[i][0]);
- col_k = &(B[0][k]);
- sum = 0;
- for (Subscript j=0; j<N; j++)
- {
- sum += *row_i * *col_k;
- row_i++;
- col_k += K;
- }
- C[i][k] = sum;
- }
-
-}
-
-template <class T>
-void matmult(Vector<T> &y, const Matrix<T> &A, const Vector<T> &x)
-{
-
-#ifdef TNT_BOUNDS_CHECK
- assert(A.num_cols() == x.dim());
- assert(A.num_rows() == y.dim());
-#endif
-
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- T sum;
-
- for (Subscript i=0; i<M; i++)
- {
- sum = 0;
- const T* rowi = A[i];
- for (Subscript j=0; j<N; j++)
- sum = sum + rowi[j] * x[j];
-
- y[i] = sum;
- }
-}
-
-template <class T>
-inline void matmultdiag(
- Matrix<T>& C,
- const Matrix<T> &A,
- const Vector<T> &diag
-){
-#ifdef TNT_BOUNDS_CHECK
- assert(A.num_cols() ==A.num_rows()== diag.dim());
-#endif
-
- Subscript M = A.num_rows();
- Subscript K = diag.dim();
-
- C.newsize(M,K);
-
- const T* row_i;
- const T* col_k;
-
- for (Subscript i=0; i<M; i++) {
- for (Subscript k=0; k<K; k++)
- {
- C[i][k] = A[i][k] * diag[k];
- }
- }
-}
-
-
-template <class T>
-inline void matmultdiag(
- Matrix<T>& C,
- const Vector<T> &diag,
- const Matrix<T> &A
-){
-#ifdef TNT_BOUNDS_CHECK
- assert(A.num_cols() ==A.num_rows()== diag.dim());
-#endif
-
- Subscript M = A.num_rows();
- Subscript K = diag.dim();
-
- C.newsize(M,K);
-
- for (Subscript i=0; i<M; i++) {
-
- const T diag_element = diag[i];
-
- for (Subscript k=0; k<K; k++)
- {
- C[i][k] = A[i][k] * diag_element;
- }
- }
-}
-
-} // namespace TNT
-
-#endif // CMAT_H
-
diff --git a/intern/iksolver/intern/TNT/fcscmat.h b/intern/iksolver/intern/TNT/fcscmat.h
deleted file mode 100644
index 8865dc7a039..00000000000
--- a/intern/iksolver/intern/TNT/fcscmat.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// Templated compressed sparse column matrix (Fortran conventions).
-// uses 1-based offsets in storing row indices.
-// Used primarily to interface with Fortran sparse matrix libaries.
-// (CANNOT BE USED AS AN STL CONTAINER.)
-
-
-#ifndef FCSCMAT_H
-#define FCSCMAT_H
-
-#include <iostream>
-#include <cassert>
-#include "tnt.h"
-#include "vec.h"
-
-using namespace std;
-
-namespace TNT
-{
-
-template <class T>
-class Fortran_Sparse_Col_Matrix
-{
-
- protected:
-
- Vector<T> val_; // data values (nz_ elements)
- Vector<Subscript> rowind_; // row_ind (nz_ elements)
- Vector<Subscript> colptr_; // col_ptr (n_+1 elements)
-
- int nz_; // number of nonzeros
- Subscript m_; // global dimensions
- Subscript n_;
-
- public:
-
-
- Fortran_Sparse_Col_Matrix(void);
- Fortran_Sparse_Col_Matrix(const Fortran_Sparse_Col_Matrix<T> &S)
- : val_(S.val_), rowind_(S.rowind_), colptr_(S.colptr_), nz_(S.nz_),
- m_(S.m_), n_(S.n_) {};
- Fortran_Sparse_Col_Matrix(Subscript M, Subscript N,
- Subscript nz, const T *val, const Subscript *r,
- const Subscript *c) : val_(nz, val), rowind_(nz, r),
- colptr_(N+1, c), nz_(nz), m_(M), n_(N) {};
-
- Fortran_Sparse_Col_Matrix(Subscript M, Subscript N,
- Subscript nz, char *val, char *r,
- char *c) : val_(nz, val), rowind_(nz, r),
- colptr_(N+1, c), nz_(nz), m_(M), n_(N) {};
-
- Fortran_Sparse_Col_Matrix(Subscript M, Subscript N,
- Subscript nz, const T *val, Subscript *r, Subscript *c)
- : val_(nz, val), rowind_(nz, r), colptr_(N+1, c), nz_(nz),
- m_(M), n_(N) {};
-
- ~Fortran_Sparse_Col_Matrix() {};
-
-
- T & val(Subscript i) { return val_(i); }
- const T & val(Subscript i) const { return val_(i); }
-
- Subscript & row_ind(Subscript i) { return rowind_(i); }
- const Subscript & row_ind(Subscript i) const { return rowind_(i); }
-
- Subscript col_ptr(Subscript i) { return colptr_(i);}
- const Subscript col_ptr(Subscript i) const { return colptr_(i);}
-
-
- Subscript num_cols() const { return m_;}
- Subscript num_rows() const { return n_; }
-
- Subscript dim(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( 1 <= i );
- assert( i <= 2 );
-#endif
- if (i==1) return m_;
- else if (i==2) return m_;
- else return 0;
- }
-
- Subscript num_nonzeros() const {return nz_;};
- Subscript lbound() const {return 1;}
-
-
-
- Fortran_Sparse_Col_Matrix& operator=(const
- Fortran_Sparse_Col_Matrix &C)
- {
- val_ = C.val_;
- rowind_ = C.rowind_;
- colptr_ = C.colptr_;
- nz_ = C.nz_;
- m_ = C.m_;
- n_ = C.n_;
-
- return *this;
- }
-
- Fortran_Sparse_Col_Matrix& newsize(Subscript M, Subscript N,
- Subscript nz)
- {
- val_.newsize(nz);
- rowind_.newsize(nz);
- colptr_.newsize(N+1);
- return *this;
- }
-};
-
-template <class T>
-ostream& operator<<(ostream &s, const Fortran_Sparse_Col_Matrix<T> &A)
-{
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- s << M << " " << N << " " << A.num_nonzeros() << endl;
-
-
- for (Subscript k=1; k<=N; k++)
- {
- Subscript start = A.col_ptr(k);
- Subscript end = A.col_ptr(k+1);
-
- for (Subscript i= start; i<end; i++)
- {
- s << A.row_ind(i) << " " << k << " " << A.val(i) << endl;
- }
- }
-
- return s;
-}
-
-
-} // namespace TNT
-
-#endif /* FCSCMAT_H */
-
diff --git a/intern/iksolver/intern/TNT/fmat.h b/intern/iksolver/intern/TNT/fmat.h
deleted file mode 100644
index edb64003143..00000000000
--- a/intern/iksolver/intern/TNT/fmat.h
+++ /dev/null
@@ -1,569 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// Fortran-compatible matrix: column oriented, 1-based (i,j) indexing
-
-#ifndef FMAT_H
-#define FMAT_H
-
-#include "subscript.h"
-#include "vec.h"
-#include <cstdlib>
-#include <cassert>
-#include <iostream>
-#ifdef TNT_USE_REGIONS
-#include "region2d.h"
-#endif
-
-// simple 1-based, column oriented Matrix class
-
-namespace TNT
-{
-
-template <class T>
-class Fortran_Matrix
-{
-
-
- public:
-
- typedef T value_type;
- typedef T element_type;
- typedef T* pointer;
- typedef T* iterator;
- typedef T& reference;
- typedef const T* const_iterator;
- typedef const T& const_reference;
-
- Subscript lbound() const { return 1;}
-
- protected:
- T* v_; // these are adjusted to simulate 1-offset
- Subscript m_;
- Subscript n_;
- T** col_; // these are adjusted to simulate 1-offset
-
- // internal helper function to create the array
- // of row pointers
-
- void initialize(Subscript M, Subscript N)
- {
- // adjust col_[] pointers so that they are 1-offset:
- // col_[j][i] is really col_[j-1][i-1];
- //
- // v_[] is the internal contiguous array, it is still 0-offset
- //
- v_ = new T[M*N];
- col_ = new T*[N];
-
- assert(v_ != NULL);
- assert(col_ != NULL);
-
-
- m_ = M;
- n_ = N;
- T* p = v_ - 1;
- for (Subscript i=0; i<N; i++)
- {
- col_[i] = p;
- p += M ;
-
- }
- col_ --;
- }
-
- void copy(const T* v)
- {
- Subscript N = m_ * n_;
- Subscript i;
-
-#ifdef TNT_UNROLL_LOOPS
- Subscript Nmod4 = N & 3;
- Subscript N4 = N - Nmod4;
-
- for (i=0; i<N4; i+=4)
- {
- v_[i] = v[i];
- v_[i+1] = v[i+1];
- v_[i+2] = v[i+2];
- v_[i+3] = v[i+3];
- }
-
- for (i=N4; i< N; i++)
- v_[i] = v[i];
-#else
-
- for (i=0; i< N; i++)
- v_[i] = v[i];
-#endif
- }
-
- void set(const T& val)
- {
- Subscript N = m_ * n_;
- Subscript i;
-
-#ifdef TNT_UNROLL_LOOPS
- Subscript Nmod4 = N & 3;
- Subscript N4 = N - Nmod4;
-
- for (i=0; i<N4; i+=4)
- {
- v_[i] = val;
- v_[i+1] = val;
- v_[i+2] = val;
- v_[i+3] = val;
- }
-
- for (i=N4; i< N; i++)
- v_[i] = val;
-#else
-
- for (i=0; i< N; i++)
- v_[i] = val;
-
-#endif
- }
-
-
-
- void destroy()
- {
- /* do nothing, if no memory has been previously allocated */
- if (v_ == NULL) return ;
-
- /* if we are here, then matrix was previously allocated */
- delete [] (v_);
- col_ ++; // changed back to 0-offset
- delete [] (col_);
- }
-
-
- public:
-
- T* begin() { return v_; }
- const T* begin() const { return v_;}
-
- T* end() { return v_ + m_*n_; }
- const T* end() const { return v_ + m_*n_; }
-
-
- // constructors
-
- Fortran_Matrix() : v_(0), m_(0), n_(0), col_(0) {};
- Fortran_Matrix(const Fortran_Matrix<T> &A)
- {
- initialize(A.m_, A.n_);
- copy(A.v_);
- }
-
- Fortran_Matrix(Subscript M, Subscript N, const T& value = T())
- {
- initialize(M,N);
- set(value);
- }
-
- Fortran_Matrix(Subscript M, Subscript N, const T* v)
- {
- initialize(M,N);
- copy(v);
- }
-
-
- // destructor
- ~Fortran_Matrix()
- {
- destroy();
- }
-
-
- // assignments
- //
- Fortran_Matrix<T>& operator=(const Fortran_Matrix<T> &A)
- {
- if (v_ == A.v_)
- return *this;
-
- if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc
- copy(A.v_);
-
- else
- {
- destroy();
- initialize(A.m_, A.n_);
- copy(A.v_);
- }
-
- return *this;
- }
-
- Fortran_Matrix<T>& operator=(const T& scalar)
- {
- set(scalar);
- return *this;
- }
-
-
- Subscript dim(Subscript d) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( d >= 1);
- assert( d <= 2);
-#endif
- return (d==1) ? m_ : ((d==2) ? n_ : 0);
- }
-
- Subscript num_rows() const { return m_; }
- Subscript num_cols() const { return n_; }
-
- Fortran_Matrix<T>& newsize(Subscript M, Subscript N)
- {
- if (num_rows() == M && num_cols() == N)
- return *this;
-
- destroy();
- initialize(M,N);
-
- return *this;
- }
-
-
-
- // 1-based element access
- //
- inline reference operator()(Subscript i, Subscript j)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i <= m_) ;
- assert(1<=j);
- assert(j <= n_);
-#endif
- return col_[j][i];
- }
-
- inline const_reference operator() (Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i <= m_) ;
- assert(1<=j);
- assert(j <= n_);
-#endif
- return col_[j][i];
- }
-
-
-#ifdef TNT_USE_REGIONS
-
- typedef Region2D<Fortran_Matrix<T> > Region;
- typedef const_Region2D< Fortran_Matrix<T> > const_Region;
-
- Region operator()(const Index1D &I, const Index1D &J)
- {
- return Region(*this, I,J);
- }
-
- const_Region operator()(const Index1D &I, const Index1D &J) const
- {
- return const_Region(*this, I,J);
- }
-
-#endif
-
-
-};
-
-
-/* *************************** I/O ********************************/
-
-template <class T>
-std::ostream& operator<<(std::ostream &s, const Fortran_Matrix<T> &A)
-{
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- s << M << " " << N << "\n";
-
- for (Subscript i=1; i<=M; i++)
- {
- for (Subscript j=1; j<=N; j++)
- {
- s << A(i,j) << " ";
- }
- s << "\n";
- }
-
-
- return s;
-}
-
-template <class T>
-std::istream& operator>>(std::istream &s, Fortran_Matrix<T> &A)
-{
-
- Subscript M, N;
-
- s >> M >> N;
-
- if ( !(M == A.num_rows() && N == A.num_cols()))
- {
- A.newsize(M,N);
- }
-
-
- for (Subscript i=1; i<=M; i++)
- for (Subscript j=1; j<=N; j++)
- {
- s >> A(i,j);
- }
-
-
- return s;
-}
-
-// *******************[ basic matrix algorithms ]***************************
-
-
-template <class T>
-Fortran_Matrix<T> operator+(const Fortran_Matrix<T> &A,
- const Fortran_Matrix<T> &B)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(M==B.num_rows());
- assert(N==B.num_cols());
-
- Fortran_Matrix<T> tmp(M,N);
- Subscript i,j;
-
- for (i=1; i<=M; i++)
- for (j=1; j<=N; j++)
- tmp(i,j) = A(i,j) + B(i,j);
-
- return tmp;
-}
-
-template <class T>
-Fortran_Matrix<T> operator-(const Fortran_Matrix<T> &A,
- const Fortran_Matrix<T> &B)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(M==B.num_rows());
- assert(N==B.num_cols());
-
- Fortran_Matrix<T> tmp(M,N);
- Subscript i,j;
-
- for (i=1; i<=M; i++)
- for (j=1; j<=N; j++)
- tmp(i,j) = A(i,j) - B(i,j);
-
- return tmp;
-}
-
-// element-wise multiplication (use matmult() below for matrix
-// multiplication in the linear algebra sense.)
-//
-//
-template <class T>
-Fortran_Matrix<T> mult_element(const Fortran_Matrix<T> &A,
- const Fortran_Matrix<T> &B)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(M==B.num_rows());
- assert(N==B.num_cols());
-
- Fortran_Matrix<T> tmp(M,N);
- Subscript i,j;
-
- for (i=1; i<=M; i++)
- for (j=1; j<=N; j++)
- tmp(i,j) = A(i,j) * B(i,j);
-
- return tmp;
-}
-
-
-template <class T>
-Fortran_Matrix<T> transpose(const Fortran_Matrix<T> &A)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- Fortran_Matrix<T> S(N,M);
- Subscript i, j;
-
- for (i=1; i<=M; i++)
- for (j=1; j<=N; j++)
- S(j,i) = A(i,j);
-
- return S;
-}
-
-
-
-template <class T>
-inline Fortran_Matrix<T> matmult(const Fortran_Matrix<T> &A,
- const Fortran_Matrix<T> &B)
-{
-
-#ifdef TNT_BOUNDS_CHECK
- assert(A.num_cols() == B.num_rows());
-#endif
-
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
- Subscript K = B.num_cols();
-
- Fortran_Matrix<T> tmp(M,K);
- T sum;
-
- for (Subscript i=1; i<=M; i++)
- for (Subscript k=1; k<=K; k++)
- {
- sum = 0;
- for (Subscript j=1; j<=N; j++)
- sum = sum + A(i,j) * B(j,k);
-
- tmp(i,k) = sum;
- }
-
- return tmp;
-}
-
-template <class T>
-inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T> &A,
- const Fortran_Matrix<T> &B)
-{
- return matmult(A,B);
-}
-
-template <class T>
-inline int matmult(Fortran_Matrix<T>& C, const Fortran_Matrix<T> &A,
- const Fortran_Matrix<T> &B)
-{
-
- assert(A.num_cols() == B.num_rows());
-
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
- Subscript K = B.num_cols();
-
- C.newsize(M,K); // adjust shape of C, if necessary
-
-
- T sum;
-
- const T* row_i;
- const T* col_k;
-
- for (Subscript i=1; i<=M; i++)
- {
- for (Subscript k=1; k<=K; k++)
- {
- row_i = &A(i,1);
- col_k = &B(1,k);
- sum = 0;
- for (Subscript j=1; j<=N; j++)
- {
- sum += *row_i * *col_k;
- row_i += M;
- col_k ++;
- }
-
- C(i,k) = sum;
- }
-
- }
-
- return 0;
-}
-
-
-template <class T>
-Vector<T> matmult(const Fortran_Matrix<T> &A, const Vector<T> &x)
-{
-
-#ifdef TNT_BOUNDS_CHECK
- assert(A.num_cols() == x.dim());
-#endif
-
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- Vector<T> tmp(M);
- T sum;
-
- for (Subscript i=1; i<=M; i++)
- {
- sum = 0;
- for (Subscript j=1; j<=N; j++)
- sum = sum + A(i,j) * x(j);
-
- tmp(i) = sum;
- }
-
- return tmp;
-}
-
-template <class T>
-inline Vector<T> operator*(const Fortran_Matrix<T> &A, const Vector<T> &x)
-{
- return matmult(A,x);
-}
-
-template <class T>
-inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T> &A, const T &x)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- Subscript MN = M*N;
-
- Fortran_Matrix<T> res(M,N);
- const T* a = A.begin();
- T* t = res.begin();
- T* tend = res.end();
-
- for (t=res.begin(); t < tend; t++, a++)
- *t = *a * x;
-
- return res;
-}
-
-} // namespace TNT
-
-#endif // FMAT_H
-
diff --git a/intern/iksolver/intern/TNT/fortran.h b/intern/iksolver/intern/TNT/fortran.h
deleted file mode 100644
index c58a859741b..00000000000
--- a/intern/iksolver/intern/TNT/fortran.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// Header file to define C/Fortran conventions (Platform specific)
-
-#ifndef FORTRAN_H
-#define FORTRAN_H
-
-// help map between C/C++ data types and Fortran types
-
-typedef int Fortran_integer;
-typedef float Fortran_float;
-typedef double Fortran_double;
-
-
-typedef Fortran_double *fda_; // (in/out) double precision array
-typedef const Fortran_double *cfda_; // (in) double precsion array
-
-typedef Fortran_double *fd_; // (in/out) single double precision
-typedef const Fortran_double *cfd_; // (in) single double precision
-
-typedef Fortran_float *ffa_; // (in/out) float precision array
-typedef const Fortran_float *cffa_; // (in) float precsion array
-
-typedef Fortran_float *ff_; // (in/out) single float precision
-typedef const Fortran_float *cff_; // (in) single float precision
-
-typedef Fortran_integer *fia_; // (in/out) single integer array
-typedef const Fortran_integer *cfia_; // (in) single integer array
-
-typedef Fortran_integer *fi_; // (in/out) single integer
-typedef const Fortran_integer *cfi_; // (in) single integer
-
-typedef char *fch_; // (in/out) single character
-typedef char *cfch_; // (in) single character
-
-
-#ifndef TNT_SUBSCRIPT_TYPE
-#define TNT_SUBSCRIPT_TYPE TNT::Fortran_integer
-#endif
-
-#endif // FORTRAN_H
-
diff --git a/intern/iksolver/intern/TNT/fspvec.h b/intern/iksolver/intern/TNT/fspvec.h
deleted file mode 100644
index 8b14fa89216..00000000000
--- a/intern/iksolver/intern/TNT/fspvec.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-// Templated sparse vector (Fortran conventions).
-// Used primarily to interface with Fortran sparse matrix libaries.
-// (CANNOT BE USED AS AN STL CONTAINER.)
-
-#ifndef FSPVEC_H
-#define FSPVEC_H
-
-#include "tnt.h"
-#include "vec.h"
-#include <cstdlib>
-#include <cassert>
-#include <iostream>
-
-using namespace std;
-
-namespace TNT
-{
-
-template <class T>
-class Fortran_Sparse_Vector
-{
-
-
- public:
-
- typedef Subscript size_type;
- typedef T value_type;
- typedef T element_type;
- typedef T* pointer;
- typedef T* iterator;
- typedef T& reference;
- typedef const T* const_iterator;
- typedef const T& const_reference;
-
- Subscript lbound() const { return 1;}
-
- protected:
- Vector<T> val_;
- Vector<Subscript> index_;
- Subscript dim_; // prescribed dimension
-
-
- public:
-
- // size and shape information
-
- Subscript dim() const { return dim_; }
- Subscript num_nonzeros() const { return val_.dim(); }
-
- // access
-
- T& val(Subscript i) { return val_(i); }
- const T& val(Subscript i) const { return val_(i); }
-
- Subscript &index(Subscript i) { return index_(i); }
- const Subscript &index(Subscript i) const { return index_(i); }
-
- // constructors
-
- Fortran_Sparse_Vector() : val_(), index_(), dim_(0) {};
- Fortran_Sparse_Vector(Subscript N, Subscript nz) : val_(nz),
- index_(nz), dim_(N) {};
- Fortran_Sparse_Vector(Subscript N, Subscript nz, const T *values,
- const Subscript *indices): val_(nz, values), index_(nz, indices),
- dim_(N) {}
-
- Fortran_Sparse_Vector(const Fortran_Sparse_Vector<T> &S):
- val_(S.val_), index_(S.index_), dim_(S.dim_) {}
-
- // initialize from string, e.g.
- //
- // Fortran_Sparse_Vector<T> A(N, 2, "1.0 2.1", "1 3");
- //
- Fortran_Sparse_Vector(Subscript N, Subscript nz, char *v,
- char *ind) : val_(nz, v), index_(nz, ind), dim_(N) {}
-
- // assignments
-
- Fortran_Sparse_Vector<T> & newsize(Subscript N, Subscript nz)
- {
- val_.newsize(nz);
- index_.newsize(nz);
- dim_ = N;
- return *this;
- }
-
- Fortran_Sparse_Vector<T> & operator=( const Fortran_Sparse_Vector<T> &A)
- {
- val_ = A.val_;
- index_ = A.index_;
- dim_ = A.dim_;
-
- return *this;
- }
-
- // methods
-
-
-
-};
-
-
-/* *************************** I/O ********************************/
-
-template <class T>
-ostream& operator<<(ostream &s, const Fortran_Sparse_Vector<T> &A)
-{
- // output format is : N nz val1 ind1 val2 ind2 ...
- Subscript nz=A.num_nonzeros();
-
- s << A.dim() << " " << nz << endl;
-
- for (Subscript i=1; i<=nz; i++)
- s << A.val(i) << " " << A.index(i) << endl;
- s << endl;
-
- return s;
-}
-
-
-template <class T>
-istream& operator>>(istream &s, Fortran_Sparse_Vector<T> &A)
-{
- // output format is : N nz val1 ind1 val2 ind2 ...
-
- Subscript N;
- Subscript nz;
-
- s >> N >> nz;
-
- A.newsize(N, nz);
-
- for (Subscript i=1; i<=nz; i++)
- s >> A.val(i) >> A.index(i);
-
-
- return s;
-}
-
-} // namespace TNT
-
-#endif // FSPVEC_H
-
diff --git a/intern/iksolver/intern/TNT/index.h b/intern/iksolver/intern/TNT/index.h
deleted file mode 100644
index 1abe20ba729..00000000000
--- a/intern/iksolver/intern/TNT/index.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// Vector/Matrix/Array Index Module
-
-#ifndef INDEX_H
-#define INDEX_H
-
-#include "subscript.h"
-
-namespace TNT
-{
-
-class Index1D
-{
- Subscript lbound_;
- Subscript ubound_;
-
- public:
-
- Subscript lbound() const { return lbound_; }
- Subscript ubound() const { return ubound_; }
-
- Index1D(const Index1D &D) : lbound_(D.lbound_), ubound_(D.ubound_) {}
- Index1D(Subscript i1, Subscript i2) : lbound_(i1), ubound_(i2) {}
-
- Index1D & operator=(const Index1D &D)
- {
- lbound_ = D.lbound_;
- ubound_ = D.ubound_;
- return *this;
- }
-
-};
-
-inline Index1D operator+(const Index1D &D, Subscript i)
-{
- return Index1D(i+D.lbound(), i+D.ubound());
-}
-
-inline Index1D operator+(Subscript i, const Index1D &D)
-{
- return Index1D(i+D.lbound(), i+D.ubound());
-}
-
-
-
-inline Index1D operator-(Index1D &D, Subscript i)
-{
- return Index1D(D.lbound()-i, D.ubound()-i);
-}
-
-inline Index1D operator-(Subscript i, Index1D &D)
-{
- return Index1D(i-D.lbound(), i-D.ubound());
-}
-
-} // namespace TNT
-
-#endif
-
diff --git a/intern/iksolver/intern/TNT/lapack.h b/intern/iksolver/intern/TNT/lapack.h
deleted file mode 100644
index e015fa9b617..00000000000
--- a/intern/iksolver/intern/TNT/lapack.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// Header file for Fortran Lapack
-
-#ifndef LAPACK_H
-#define LAPACK_H
-
-// This file incomplete and included here to only demonstrate the
-// basic framework for linking with the Fortran Lapack routines.
-
-#include "fortran.h"
-#include "vec.h"
-#include "fmat.h"
-
-
-#define F77_DGESV dgesv_
-#define F77_DGELS dgels_
-#define F77_DSYEV dsyev_
-#define F77_DGEEV dgeev_
-
-extern "C"
-{
-
- // linear equations (general) using LU factorizaiton
- //
- void F77_DGESV(cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda,
- fia_ ipiv, fda_ b, cfi_ ldb, fi_ info);
-
- // solve linear least squares using QR or LU factorization
- //
- void F77_DGELS(cfch_ trans, cfi_ M,
- cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda, fda_ B, cfi_ ldb, fda_ work,
- cfi_ lwork, fi_ info);
-
- // solve symmetric eigenvalues
- //
- void F77_DSYEV( cfch_ jobz, cfch_ uplo, cfi_ N, fda_ A, cfi_ lda,
- fda_ W, fda_ work, cfi_ lwork, fi_ info);
-
- // solve unsymmetric eigenvalues
- //
- void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
- fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
- cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
-
-}
-
-// solve linear equations using LU factorization
-
-using namespace TNT;
-
-Vector<double> Lapack_LU_linear_solve(const Fortran_Matrix<double> &A,
- const Vector<double> &b)
-{
- const Fortran_integer one=1;
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- Fortran_Matrix<double> Tmp(A);
- Vector<double> x(b);
- Vector<Fortran_integer> index(M);
- Fortran_integer info = 0;
-
- F77_DGESV(&N, &one, &Tmp(1,1), &M, &index(1), &x(1), &M, &info);
-
- if (info != 0) return Vector<double>(0);
- else
- return x;
-}
-
-// solve linear least squares problem using QR factorization
-//
-Vector<double> Lapack_LLS_QR_linear_solve(const Fortran_Matrix<double> &A,
- const Vector<double> &b)
-{
- const Fortran_integer one=1;
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- Fortran_Matrix<double> Tmp(A);
- Vector<double> x(b);
- Fortran_integer info = 0;
-
- char transp = 'N';
- Fortran_integer lwork = 5 * (M+N); // temporary work space
- Vector<double> work(lwork);
-
- F77_DGELS(&transp, &M, &N, &one, &Tmp(1,1), &M, &x(1), &M, &work(1),
- &lwork, &info);
-
- if (info != 0) return Vector<double>(0);
- else
- return x;
-}
-
-// *********************** Eigenvalue problems *******************
-
-// solve symmetric eigenvalue problem (eigenvalues only)
-//
-Vector<double> Upper_symmetric_eigenvalue_solve(const Fortran_Matrix<double> &A)
-{
- char jobz = 'N';
- char uplo = 'U';
- Subscript N = A.num_rows();
-
- assert(N == A.num_cols());
-
- Vector<double> eigvals(N);
- Fortran_integer worksize = 3*N;
- Fortran_integer info = 0;
- Vector<double> work(worksize);
- Fortran_Matrix<double> Tmp = A;
-
- F77_DSYEV(&jobz, &uplo, &N, &Tmp(1,1), &N, eigvals.begin(), work.begin(),
- &worksize, &info);
-
- if (info != 0) return Vector<double>();
- else
- return eigvals;
-}
-
-
-// solve unsymmetric eigenvalue problems
-//
-int eigenvalue_solve(const Fortran_Matrix<double> &A,
- Vector<double> &wr, Vector<double> &wi)
-{
- char jobvl = 'N';
- char jobvr = 'N';
-
- Fortran_integer N = A.num_rows();
-
-
- assert(N == A.num_cols());
-
- if (N<1) return 1;
-
- Fortran_Matrix<double> vl(1,N); /* should be NxN ? **** */
- Fortran_Matrix<double> vr(1,N);
- Fortran_integer one = 1;
-
- Fortran_integer worksize = 5*N;
- Fortran_integer info = 0;
- Vector<double> work(worksize, 0.0);
- Fortran_Matrix<double> Tmp = A;
-
- wr.newsize(N);
- wi.newsize(N);
-
-// void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
-// fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
-// cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
-
- F77_DGEEV(&jobvl, &jobvr, &N, &Tmp(1,1), &N, &(wr(1)),
- &(wi(1)), &(vl(1,1)), &one, &(vr(1,1)), &one,
- &(work(1)), &worksize, &info);
-
- return (info==0 ? 0: 1);
-}
-
-#endif // LAPACK_H
-
diff --git a/intern/iksolver/intern/TNT/lu.h b/intern/iksolver/intern/TNT/lu.h
deleted file mode 100644
index f64172bd31f..00000000000
--- a/intern/iksolver/intern/TNT/lu.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-#ifndef LU_H
-#define LU_H
-
-// Solve system of linear equations Ax = b.
-//
-// Typical usage:
-//
-// Matrix(double) A;
-// Vector(Subscript) ipiv;
-// Vector(double) b;
-//
-// 1) LU_Factor(A,ipiv);
-// 2) LU_Solve(A,ipiv,b);
-//
-// Now b has the solution x. Note that both A and b
-// are overwritten. If these values need to be preserved,
-// one can make temporary copies, as in
-//
-// O) Matrix(double) T = A;
-// 1) LU_Factor(T,ipiv);
-// 1a) Vector(double) x=b;
-// 2) LU_Solve(T,ipiv,x);
-//
-// See details below.
-//
-
-
-// for fabs()
-//
-#include <cmath>
-
-// right-looking LU factorization algorithm (unblocked)
-//
-// Factors matrix A into lower and upper triangular matrices
-// (L and U respectively) in solving the linear equation Ax=b.
-//
-//
-// Args:
-//
-// A (input/output) Matrix(1:n, 1:n) In input, matrix to be
-// factored. On output, overwritten with lower and
-// upper triangular factors.
-//
-// indx (output) Vector(1:n) Pivot vector. Describes how
-// the rows of A were reordered to increase
-// numerical stability.
-//
-// Return value:
-//
-// int (0 if successful, 1 otherwise)
-//
-//
-
-
-namespace TNT
-{
-
-template <class MaTRiX, class VecToRSubscript>
-int LU_factor( MaTRiX &A, VecToRSubscript &indx)
-{
- assert(A.lbound() == 1); // currently for 1-offset
- assert(indx.lbound() == 1); // vectors and matrices
-
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- if (M == 0 || N==0) return 0;
- if (indx.dim() != M)
- indx.newsize(M);
-
- Subscript i=0,j=0,k=0;
- Subscript jp=0;
-
- typename MaTRiX::element_type t;
-
- Subscript minMN = (M < N ? M : N) ; // min(M,N);
-
- for (j=1; j<= minMN; j++)
- {
-
- // find pivot in column j and test for singularity.
-
- jp = j;
- t = fabs(A(j,j));
- for (i=j+1; i<=M; i++)
- if ( fabs(A(i,j)) > t)
- {
- jp = i;
- t = fabs(A(i,j));
- }
-
- indx(j) = jp;
-
- // jp now has the index of maximum element
- // of column j, below the diagonal
-
- if ( A(jp,j) == 0 )
- return 1; // factorization failed because of zero pivot
-
-
- if (jp != j) // swap rows j and jp
- for (k=1; k<=N; k++)
- {
- t = A(j,k);
- A(j,k) = A(jp,k);
- A(jp,k) =t;
- }
-
- if (j<M) // compute elements j+1:M of jth column
- {
- // note A(j,j), was A(jp,p) previously which was
- // guarranteed not to be zero (Label #1)
- //
- typename MaTRiX::element_type recp = 1.0 / A(j,j);
-
- for (k=j+1; k<=M; k++)
- A(k,j) *= recp;
- }
-
-
- if (j < minMN)
- {
- // rank-1 update to trailing submatrix: E = E - x*y;
- //
- // E is the region A(j+1:M, j+1:N)
- // x is the column vector A(j+1:M,j)
- // y is row vector A(j,j+1:N)
-
- Subscript ii,jj;
-
- for (ii=j+1; ii<=M; ii++)
- for (jj=j+1; jj<=N; jj++)
- A(ii,jj) -= A(ii,j)*A(j,jj);
- }
- }
-
- return 0;
-}
-
-
-
-
-template <class MaTRiX, class VecToR, class VecToRSubscripts>
-int LU_solve(const MaTRiX &A, const VecToRSubscripts &indx, VecToR &b)
-{
- assert(A.lbound() == 1); // currently for 1-offset
- assert(indx.lbound() == 1); // vectors and matrices
- assert(b.lbound() == 1);
-
- Subscript i,ii=0,ip,j;
- Subscript n = b.dim();
- typename MaTRiX::element_type sum = 0.0;
-
- for (i=1;i<=n;i++)
- {
- ip=indx(i);
- sum=b(ip);
- b(ip)=b(i);
- if (ii)
- for (j=ii;j<=i-1;j++)
- sum -= A(i,j)*b(j);
- else if (sum) ii=i;
- b(i)=sum;
- }
- for (i=n;i>=1;i--)
- {
- sum=b(i);
- for (j=i+1;j<=n;j++)
- sum -= A(i,j)*b(j);
- b(i)=sum/A(i,i);
- }
-
- return 0;
-}
-
-} // namespace TNT
-
-#endif // LU_H
-
diff --git a/intern/iksolver/intern/TNT/qr.h b/intern/iksolver/intern/TNT/qr.h
deleted file mode 100644
index 9df34e2d7cc..00000000000
--- a/intern/iksolver/intern/TNT/qr.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-#ifndef QR_H
-#define QR_H
-
-// Classical QR factorization example, based on Stewart[1973].
-//
-//
-// This algorithm computes the factorization of a matrix A
-// into a product of an orthognal matrix (Q) and an upper triangular
-// matrix (R), such that QR = A.
-//
-// Parameters:
-//
-// A (in): Matrix(1:N, 1:N)
-//
-// Q (output): Matrix(1:N, 1:N), collection of Householder
-// column vectors Q1, Q2, ... QN
-//
-// R (output): upper triangular Matrix(1:N, 1:N)
-//
-// Returns:
-//
-// 0 if successful, 1 if A is detected to be singular
-//
-
-
-#include <cmath> //for sqrt() & fabs()
-#include "tntmath.h" // for sign()
-
-// Classical QR factorization, based on Stewart[1973].
-//
-//
-// This algorithm computes the factorization of a matrix A
-// into a product of an orthognal matrix (Q) and an upper triangular
-// matrix (R), such that QR = A.
-//
-// Parameters:
-//
-// A (in/out): On input, A is square, Matrix(1:N, 1:N), that represents
-// the matrix to be factored.
-//
-// On output, Q and R is encoded in the same Matrix(1:N,1:N)
-// in the following manner:
-//
-// R is contained in the upper triangular section of A,
-// except that R's main diagonal is in D. The lower
-// triangular section of A represents Q, where each
-// column j is the vector Qj = I - uj*uj'/pi_j.
-//
-// C (output): vector of Pi[j]
-// D (output): main diagonal of R, i.e. D(i) is R(i,i)
-//
-// Returns:
-//
-// 0 if successful, 1 if A is detected to be singular
-//
-
-namespace TNT
-{
-
-template <class MaTRiX, class Vector>
-int QR_factor(MaTRiX &A, Vector& C, Vector &D)
-{
- assert(A.lbound() == 1); // ensure these are all
- assert(C.lbound() == 1); // 1-based arrays and vectors
- assert(D.lbound() == 1);
-
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(M == N); // make sure A is square
-
- Subscript i,j,k;
- typename MaTRiX::element_type eta, sigma, sum;
-
- // adjust the shape of C and D, if needed...
-
- if (N != C.size()) C.newsize(N);
- if (N != D.size()) D.newsize(N);
-
- for (k=1; k<N; k++)
- {
- // eta = max |M(i,k)|, for k <= i <= n
- //
- eta = 0;
- for (i=k; i<=N; i++)
- {
- double absA = fabs(A(i,k));
- eta = ( absA > eta ? absA : eta );
- }
-
- if (eta == 0) // matrix is singular
- {
- cerr << "QR: k=" << k << "\n";
- return 1;
- }
-
- // form Qk and premiltiply M by it
- //
- for(i=k; i<=N; i++)
- A(i,k) = A(i,k) / eta;
-
- sum = 0;
- for (i=k; i<=N; i++)
- sum = sum + A(i,k)*A(i,k);
- sigma = sign(A(k,k)) * sqrt(sum);
-
-
- A(k,k) = A(k,k) + sigma;
- C(k) = sigma * A(k,k);
- D(k) = -eta * sigma;
-
- for (j=k+1; j<=N; j++)
- {
- sum = 0;
- for (i=k; i<=N; i++)
- sum = sum + A(i,k)*A(i,j);
- sum = sum / C(k);
-
- for (i=k; i<=N; i++)
- A(i,j) = A(i,j) - sum * A(i,k);
- }
-
- D(N) = A(N,N);
- }
-
- return 0;
-}
-
-// modified form of upper triangular solve, except that the main diagonal
-// of R (upper portion of A) is in D.
-//
-template <class MaTRiX, class Vector>
-int R_solve(const MaTRiX &A, /*const*/ Vector &D, Vector &b)
-{
- assert(A.lbound() == 1); // ensure these are all
- assert(D.lbound() == 1); // 1-based arrays and vectors
- assert(b.lbound() == 1);
-
- Subscript i,j;
- Subscript N = A.num_rows();
-
- assert(N == A.num_cols());
- assert(N == D.dim());
- assert(N == b.dim());
-
- typename MaTRiX::element_type sum;
-
- if (D(N) == 0)
- return 1;
-
- b(N) = b(N) /
- D(N);
-
- for (i=N-1; i>=1; i--)
- {
- if (D(i) == 0)
- return 1;
- sum = 0;
- for (j=i+1; j<=N; j++)
- sum = sum + A(i,j)*b(j);
- b(i) = ( b(i) - sum ) /
- D(i);
- }
-
- return 0;
-}
-
-
-template <class MaTRiX, class Vector>
-int QR_solve(const MaTRiX &A, const Vector &c, /*const*/ Vector &d,
- Vector &b)
-{
- assert(A.lbound() == 1); // ensure these are all
- assert(c.lbound() == 1); // 1-based arrays and vectors
- assert(d.lbound() == 1);
-
- Subscript N=A.num_rows();
-
- assert(N == A.num_cols());
- assert(N == c.dim());
- assert(N == d.dim());
- assert(N == b.dim());
-
- Subscript i,j;
- typename MaTRiX::element_type sum, tau;
-
- for (j=1; j<N; j++)
- {
- // form Q'*b
- sum = 0;
- for (i=j; i<=N; i++)
- sum = sum + A(i,j)*b(i);
- if (c(j) == 0)
- return 1;
- tau = sum / c(j);
- for (i=j; i<=N; i++)
- b(i) = b(i) - tau * A(i,j);
- }
- return R_solve(A, d, b); // solve Rx = Q'b
-}
-
-} // namespace TNT
-
-#endif // QR_H
-
diff --git a/intern/iksolver/intern/TNT/region1d.h b/intern/iksolver/intern/TNT/region1d.h
deleted file mode 100644
index 8acaac3ae23..00000000000
--- a/intern/iksolver/intern/TNT/region1d.h
+++ /dev/null
@@ -1,375 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-
-#ifndef REGION1D_H
-#define REGION1D_H
-
-
-#include "subscript.h"
-#include "index.h"
-#include <iostream>
-#include <cassert>
-
-namespace TNT
-{
-
-template <class Array1D>
-class const_Region1D;
-
-template <class Array1D>
-class Region1D
-{
- protected:
-
- Array1D & A_;
- Subscript offset_; // 0-based
- Subscript dim_;
-
- typedef typename Array1D::element_type T;
-
- public:
- const Array1D & array() const { return A_; }
-
- Subscript offset() const { return offset_;}
- Subscript dim() const { return dim_; }
-
- Subscript offset(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(i==TNT_BASE_OFFSET);
-#endif
- return offset_;
- }
-
- Subscript dim(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(i== TNT_BASE_OFFSET);
-#endif
- return offset_;
- }
-
-
- Region1D(Array1D &A, Subscript i1, Subscript i2) : A_(A)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <= i1 );
- assert(i2 <= A.dim() + (TNT_BASE_OFFSET-1));
- assert(i1 <= i2);
-#endif
- offset_ = i1 - TNT_BASE_OFFSET;
- dim_ = i2-i1 + 1;
- }
-
- Region1D(Array1D &A, const Index1D &I) : A_(A)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <=I.lbound());
- assert(I.ubound() <= A.dim() + (TNT_BASE_OFFSET-1));
- assert(I.lbound() <= I.ubound());
-#endif
- offset_ = I.lbound() - TNT_BASE_OFFSET;
- dim_ = I.ubound() - I.lbound() + 1;
- }
-
- Region1D(Region1D<Array1D> &A, Subscript i1, Subscript i2) :
- A_(A.A_)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <= i1 );
- assert(i2 <= A.dim() + (TNT_BASE_OFFSET - 1));
- assert(i1 <= i2);
-#endif
- // (old-offset) (new-offset)
- //
- offset_ = (i1 - TNT_BASE_OFFSET) + A.offset_;
- dim_ = i2-i1 + 1;
- }
-
- Region1D<Array1D> operator()(Subscript i1, Subscript i2)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <= i1);
- assert(i2 <= dim() + (TNT_BASE_OFFSET -1));
- assert(i1 <= i2);
-#endif
- // offset_ is 0-based, so no need for
- // ( - TNT_BASE_OFFSET)
- //
- return Region1D<Array1D>(A_, i1+offset_,
- offset_ + i2);
- }
-
-
- Region1D<Array1D> operator()(const Index1D &I)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET<=I.lbound());
- assert(I.ubound() <= dim() + (TNT_BASE_OFFSET-1));
- assert(I.lbound() <= I.ubound());
-#endif
- return Region1D<Array1D>(A_, I.lbound()+offset_,
- offset_ + I.ubound());
- }
-
-
-
-
- T & operator()(Subscript i)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <= i);
- assert(i <= dim() + (TNT_BASE_OFFSET-1));
-#endif
- return A_(i+offset_);
- }
-
- const T & operator() (Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <= i);
- assert(i <= dim() + (TNT_BASE_OFFSET-1));
-#endif
- return A_(i+offset_);
- }
-
-
- Region1D<Array1D> & operator=(const Region1D<Array1D> &R)
- {
- // make sure both sides conform
- assert(dim() == R.dim());
-
- Subscript N = dim();
- Subscript i;
- Subscript istart = TNT_BASE_OFFSET;
- Subscript iend = istart + N-1;
-
- for (i=istart; i<=iend; i++)
- (*this)(i) = R(i);
-
- return *this;
- }
-
-
-
- Region1D<Array1D> & operator=(const const_Region1D<Array1D> &R)
- {
- // make sure both sides conform
- assert(dim() == R.dim());
-
- Subscript N = dim();
- Subscript i;
- Subscript istart = TNT_BASE_OFFSET;
- Subscript iend = istart + N-1;
-
- for (i=istart; i<=iend; i++)
- (*this)(i) = R(i);
-
- return *this;
-
- }
-
-
- Region1D<Array1D> & operator=(const T& t)
- {
- Subscript N=dim();
- Subscript i;
- Subscript istart = TNT_BASE_OFFSET;
- Subscript iend = istart + N-1;
-
- for (i=istart; i<= iend; i++)
- (*this)(i) = t;
-
- return *this;
-
- }
-
-
- Region1D<Array1D> & operator=(const Array1D &R)
- {
- // make sure both sides conform
- Subscript N = dim();
- assert(dim() == R.dim());
-
- Subscript i;
- Subscript istart = TNT_BASE_OFFSET;
- Subscript iend = istart + N-1;
-
- for (i=istart; i<=iend; i++)
- (*this)(i) = R(i);
-
- return *this;
-
- }
-
-};
-
-template <class Array1D>
-std::ostream& operator<<(std::ostream &s, Region1D<Array1D> &A)
-{
- Subscript N=A.dim();
- Subscript istart = TNT_BASE_OFFSET;
- Subscript iend = N - 1 + TNT_BASE_OFFSET;
-
- for (Subscript i=istart; i<=iend; i++)
- s << A(i) << endl;
-
- return s;
-}
-
-
-/* --------- class const_Region1D ------------ */
-
-template <class Array1D>
-class const_Region1D
-{
- protected:
-
- const Array1D & A_;
- Subscript offset_; // 0-based
- Subscript dim_;
- typedef typename Array1D::element_type T;
-
- public:
- const Array1D & array() const { return A_; }
-
- Subscript offset() const { return offset_;}
- Subscript dim() const { return dim_; }
-
- Subscript offset(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(i==TNT_BASE_OFFSET);
-#endif
- return offset_;
- }
-
- Subscript dim(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(i== TNT_BASE_OFFSET);
-#endif
- return offset_;
- }
-
-
- const_Region1D(const Array1D &A, Subscript i1, Subscript i2) : A_(A)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <= i1 );
- assert(i2 <= A.dim() + (TNT_BASE_OFFSET-1));
- assert(i1 <= i2);
-#endif
- offset_ = i1 - TNT_BASE_OFFSET;
- dim_ = i2-i1 + 1;
- }
-
- const_Region1D(const Array1D &A, const Index1D &I) : A_(A)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <=I.lbound());
- assert(I.ubound() <= A.dim() + (TNT_BASE_OFFSET-1));
- assert(I.lbound() <= I.ubound());
-#endif
- offset_ = I.lbound() - TNT_BASE_OFFSET;
- dim_ = I.ubound() - I.lbound() + 1;
- }
-
- const_Region1D(const_Region1D<Array1D> &A, Subscript i1, Subscript i2) :
- A_(A.A_)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <= i1 );
- assert(i2 <= A.dim() + (TNT_BASE_OFFSET - 1));
- assert(i1 <= i2);
-#endif
- // (old-offset) (new-offset)
- //
- offset_ = (i1 - TNT_BASE_OFFSET) + A.offset_;
- dim_ = i2-i1 + 1;
- }
-
- const_Region1D<Array1D> operator()(Subscript i1, Subscript i2)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <= i1);
- assert(i2 <= dim() + (TNT_BASE_OFFSET -1));
- assert(i1 <= i2);
-#endif
- // offset_ is 0-based, so no need for
- // ( - TNT_BASE_OFFSET)
- //
- return const_Region1D<Array1D>(A_, i1+offset_,
- offset_ + i2);
- }
-
-
- const_Region1D<Array1D> operator()(const Index1D &I)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET<=I.lbound());
- assert(I.ubound() <= dim() + (TNT_BASE_OFFSET-1));
- assert(I.lbound() <= I.ubound());
-#endif
- return const_Region1D<Array1D>(A_, I.lbound()+offset_,
- offset_ + I.ubound());
- }
-
-
- const T & operator() (Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(TNT_BASE_OFFSET <= i);
- assert(i <= dim() + (TNT_BASE_OFFSET-1));
-#endif
- return A_(i+offset_);
- }
-
-
-
-
-};
-
-template <class Array1D>
-std::ostream& operator<<(std::ostream &s, const_Region1D<Array1D> &A)
-{
- Subscript N=A.dim();
-
- for (Subscript i=1; i<=N; i++)
- s << A(i) << endl;
-
- return s;
-}
-
-
-} // namespace TNT
-
-#endif // const_Region1D_H
-
diff --git a/intern/iksolver/intern/TNT/region2d.h b/intern/iksolver/intern/TNT/region2d.h
deleted file mode 100644
index 6af50262382..00000000000
--- a/intern/iksolver/intern/TNT/region2d.h
+++ /dev/null
@@ -1,471 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-// 2D Regions for arrays and matrices
-
-#ifndef REGION2D_H
-#define REGION2D_H
-
-#include "index.h"
-#include <iostream>
-#include <cassert>
-
-namespace TNT
-{
-
-template <class Array2D>
-class const_Region2D;
-
-
-template <class Array2D>
-class Region2D
-{
- protected:
-
- Array2D & A_;
- Subscript offset_[2]; // 0-offset internally
- Subscript dim_[2];
-
- public:
- typedef typename Array2D::value_type T;
- typedef Subscript size_type;
- typedef T value_type;
- typedef T element_type;
- typedef T* pointer;
- typedef T* iterator;
- typedef T& reference;
- typedef const T* const_iterator;
- typedef const T& const_reference;
-
- Array2D & array() { return A_; }
- const Array2D & array() const { return A_; }
- Subscript lbound() const { return A_.lbound(); }
- Subscript num_rows() const { return dim_[0]; }
- Subscript num_cols() const { return dim_[1]; }
- Subscript offset(Subscript i) const // 1-offset
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( A_.lbound() <= i);
- assert( i<= dim_[0] + A_.lbound()-1);
-#endif
- return offset_[i-A_.lbound()];
- }
-
- Subscript dim(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( A_.lbound() <= i);
- assert( i<= dim_[0] + A_.lbound()-1);
-#endif
- return dim_[i-A_.lbound()];
- }
-
-
-
- Region2D(Array2D &A, Subscript i1, Subscript i2, Subscript j1,
- Subscript j2) : A_(A)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( i1 <= i2 );
- assert( j1 <= j2);
- assert( A.lbound() <= i1);
- assert( i2<= A.dim(A.lbound()) + A.lbound()-1);
- assert( A.lbound() <= j1);
- assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 );
-#endif
-
-
- offset_[0] = i1-A.lbound();
- offset_[1] = j1-A.lbound();
- dim_[0] = i2-i1+1;
- dim_[1] = j2-j1+1;
- }
-
- Region2D(Array2D &A, const Index1D &I, const Index1D &J) : A_(A)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( I.lbound() <= I.ubound() );
- assert( J.lbound() <= J.ubound() );
- assert( A.lbound() <= I.lbound());
- assert( I.ubound()<= A.dim(A.lbound()) + A.lbound()-1);
- assert( A.lbound() <= J.lbound());
- assert( J.ubound() <= A.dim(A.lbound()+1) + A.lbound()-1 );
-#endif
-
- offset_[0] = I.lbound()-A.lbound();
- offset_[1] = J.lbound()-A.lbound();
- dim_[0] = I.ubound() - I.lbound() + 1;
- dim_[1] = J.ubound() - J.lbound() + 1;
- }
-
- Region2D(Region2D<Array2D> &A, Subscript i1, Subscript i2,
- Subscript j1, Subscript j2) : A_(A.A_)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( i1 <= i2 );
- assert( j1 <= j2);
- assert( A.lbound() <= i1);
- assert( i2<= A.dim(A.lbound()) + A.lbound()-1);
- assert( A.lbound() <= j1);
- assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 );
-#endif
- offset_[0] = (i1 - A.lbound()) + A.offset_[0];
- offset_[1] = (j1 - A.lbound()) + A.offset_[1];
- dim_[0] = i2-i1 + 1;
- dim_[1] = j2-j1+1;
- }
-
- Region2D<Array2D> operator()(Subscript i1, Subscript i2,
- Subscript j1, Subscript j2)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( i1 <= i2 );
- assert( j1 <= j2);
- assert( A_.lbound() <= i1);
- assert( i2<= dim_[0] + A_.lbound()-1);
- assert( A_.lbound() <= j1);
- assert( j2<= dim_[1] + A_.lbound()-1 );
-#endif
- return Region2D<Array2D>(A_,
- i1+offset_[0], offset_[0] + i2,
- j1+offset_[1], offset_[1] + j2);
- }
-
-
- Region2D<Array2D> operator()(const Index1D &I,
- const Index1D &J)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( I.lbound() <= I.ubound() );
- assert( J.lbound() <= J.ubound() );
- assert( A_.lbound() <= I.lbound());
- assert( I.ubound()<= dim_[0] + A_.lbound()-1);
- assert( A_.lbound() <= J.lbound());
- assert( J.ubound() <= dim_[1] + A_.lbound()-1 );
-#endif
-
- return Region2D<Array2D>(A_, I.lbound()+offset_[0],
- offset_[0] + I.ubound(), offset_[1]+J.lbound(),
- offset_[1] + J.ubound());
- }
-
- inline T & operator()(Subscript i, Subscript j)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( A_.lbound() <= i);
- assert( i<= dim_[0] + A_.lbound()-1);
- assert( A_.lbound() <= j);
- assert( j<= dim_[1] + A_.lbound()-1 );
-#endif
- return A_(i+offset_[0], j+offset_[1]);
- }
-
- inline const T & operator() (Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( A_.lbound() <= i);
- assert( i<= dim_[0] + A_.lbound()-1);
- assert( A_.lbound() <= j);
- assert( j<= dim_[1] + A_.lbound()-1 );
-#endif
- return A_(i+offset_[0], j+offset_[1]);
- }
-
-
- Region2D<Array2D> & operator=(const Region2D<Array2D> &R)
- {
- Subscript M = num_rows();
- Subscript N = num_cols();
-
- // make sure both sides conform
- assert(M == R.num_rows());
- assert(N == R.num_cols());
-
-
- Subscript start = R.lbound();
- Subscript Mend = start + M - 1;
- Subscript Nend = start + N - 1;
- for (Subscript i=start; i<=Mend; i++)
- for (Subscript j=start; j<=Nend; j++)
- (*this)(i,j) = R(i,j);
-
- return *this;
- }
-
- Region2D<Array2D> & operator=(const const_Region2D<Array2D> &R)
- {
- Subscript M = num_rows();
- Subscript N = num_cols();
-
- // make sure both sides conform
- assert(M == R.num_rows());
- assert(N == R.num_cols());
-
-
- Subscript start = R.lbound();
- Subscript Mend = start + M - 1;
- Subscript Nend = start + N - 1;
- for (Subscript i=start; i<=Mend; i++)
- for (Subscript j=start; j<=Nend; j++)
- (*this)(i,j) = R(i,j);
-
- return *this;
- }
-
- Region2D<Array2D> & operator=(const Array2D &R)
- {
- Subscript M = num_rows();
- Subscript N = num_cols();
-
- // make sure both sides conform
- assert(M == R.num_rows());
- assert(N == R.num_cols());
-
-
- Subscript start = R.lbound();
- Subscript Mend = start + M - 1;
- Subscript Nend = start + N - 1;
- for (Subscript i=start; i<=Mend; i++)
- for (Subscript j=start; j<=Nend; j++)
- (*this)(i,j) = R(i,j);
-
- return *this;
- }
-
- Region2D<Array2D> & operator=(const T &scalar)
- {
- Subscript start = lbound();
- Subscript Mend = lbound() + num_rows() - 1;
- Subscript Nend = lbound() + num_cols() - 1;
-
-
- for (Subscript i=start; i<=Mend; i++)
- for (Subscript j=start; j<=Nend; j++)
- (*this)(i,j) = scalar;
-
- return *this;
- }
-
-};
-
-//************************
-
-template <class Array2D>
-class const_Region2D
-{
- protected:
-
- const Array2D & A_;
- Subscript offset_[2]; // 0-offset internally
- Subscript dim_[2];
-
- public:
- typedef typename Array2D::value_type T;
- typedef T value_type;
- typedef T element_type;
- typedef const T* const_iterator;
- typedef const T& const_reference;
-
- const Array2D & array() const { return A_; }
- Subscript lbound() const { return A_.lbound(); }
- Subscript num_rows() const { return dim_[0]; }
- Subscript num_cols() const { return dim_[1]; }
- Subscript offset(Subscript i) const // 1-offset
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( TNT_BASE_OFFSET <= i);
- assert( i<= dim_[0] + TNT_BASE_OFFSET-1);
-#endif
- return offset_[i-TNT_BASE_OFFSET];
- }
-
- Subscript dim(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( TNT_BASE_OFFSET <= i);
- assert( i<= dim_[0] + TNT_BASE_OFFSET-1);
-#endif
- return dim_[i-TNT_BASE_OFFSET];
- }
-
-
- const_Region2D(const Array2D &A, Subscript i1, Subscript i2,
- Subscript j1, Subscript j2) : A_(A)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( i1 <= i2 );
- assert( j1 <= j2);
- assert( TNT_BASE_OFFSET <= i1);
- assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1);
- assert( TNT_BASE_OFFSET <= j1);
- assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 );
-#endif
-
- offset_[0] = i1-TNT_BASE_OFFSET;
- offset_[1] = j1-TNT_BASE_OFFSET;
- dim_[0] = i2-i1+1;
- dim_[1] = j2-j1+1;
- }
-
- const_Region2D(const Array2D &A, const Index1D &I, const Index1D &J)
- : A_(A)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( I.lbound() <= I.ubound() );
- assert( J.lbound() <= J.ubound() );
- assert( TNT_BASE_OFFSET <= I.lbound());
- assert( I.ubound()<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1);
- assert( TNT_BASE_OFFSET <= J.lbound());
- assert( J.ubound() <= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 );
-#endif
-
- offset_[0] = I.lbound()-TNT_BASE_OFFSET;
- offset_[1] = J.lbound()-TNT_BASE_OFFSET;
- dim_[0] = I.ubound() - I.lbound() + 1;
- dim_[1] = J.ubound() - J.lbound() + 1;
- }
-
-
- const_Region2D(const_Region2D<Array2D> &A, Subscript i1,
- Subscript i2,
- Subscript j1, Subscript j2) : A_(A.A_)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( i1 <= i2 );
- assert( j1 <= j2);
- assert( TNT_BASE_OFFSET <= i1);
- assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1);
- assert( TNT_BASE_OFFSET <= j1);
- assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 );
-#endif
- offset_[0] = (i1 - TNT_BASE_OFFSET) + A.offset_[0];
- offset_[1] = (j1 - TNT_BASE_OFFSET) + A.offset_[1];
- dim_[0] = i2-i1 + 1;
- dim_[1] = j2-j1+1;
- }
-
- const_Region2D<Array2D> operator()(Subscript i1, Subscript i2,
- Subscript j1, Subscript j2)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( i1 <= i2 );
- assert( j1 <= j2);
- assert( TNT_BASE_OFFSET <= i1);
- assert( i2<= dim_[0] + TNT_BASE_OFFSET-1);
- assert( TNT_BASE_OFFSET <= j1);
- assert( j2<= dim_[0] + TNT_BASE_OFFSET-1 );
-#endif
- return const_Region2D<Array2D>(A_,
- i1+offset_[0], offset_[0] + i2,
- j1+offset_[1], offset_[1] + j2);
- }
-
-
- const_Region2D<Array2D> operator()(const Index1D &I,
- const Index1D &J)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( I.lbound() <= I.ubound() );
- assert( J.lbound() <= J.ubound() );
- assert( TNT_BASE_OFFSET <= I.lbound());
- assert( I.ubound()<= dim_[0] + TNT_BASE_OFFSET-1);
- assert( TNT_BASE_OFFSET <= J.lbound());
- assert( J.ubound() <= dim_[1] + TNT_BASE_OFFSET-1 );
-#endif
-
- return const_Region2D<Array2D>(A_, I.lbound()+offset_[0],
- offset_[0] + I.ubound(), offset_[1]+J.lbound(),
- offset_[1] + J.ubound());
- }
-
-
- inline const T & operator() (Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( TNT_BASE_OFFSET <= i);
- assert( i<= dim_[0] + TNT_BASE_OFFSET-1);
- assert( TNT_BASE_OFFSET <= j);
- assert( j<= dim_[1] + TNT_BASE_OFFSET-1 );
-#endif
- return A_(i+offset_[0], j+offset_[1]);
- }
-
-};
-
-
-// ************** std::ostream algorithms *******************************
-
-template <class Array2D>
-std::ostream& operator<<(std::ostream &s, const const_Region2D<Array2D> &A)
-{
- Subscript start = A.lbound();
- Subscript Mend=A.lbound()+ A.num_rows() - 1;
- Subscript Nend=A.lbound() + A.num_cols() - 1;
-
-
- s << A.num_rows() << " " << A.num_cols() << "\n";
- for (Subscript i=start; i<=Mend; i++)
- {
- for (Subscript j=start; j<=Nend; j++)
- {
- s << A(i,j) << " ";
- }
- s << "\n";
- }
-
-
- return s;
-}
-
-template <class Array2D>
-std::ostream& operator<<(std::ostream &s, const Region2D<Array2D> &A)
-{
- Subscript start = A.lbound();
- Subscript Mend=A.lbound()+ A.num_rows() - 1;
- Subscript Nend=A.lbound() + A.num_cols() - 1;
-
-
- s << A.num_rows() << " " << A.num_cols() << "\n";
- for (Subscript i=start; i<=Mend; i++)
- {
- for (Subscript j=start; j<=Nend; j++)
- {
- s << A(i,j) << " ";
- }
- s << "\n";
- }
-
-
- return s;
-
-}
-
-} // namespace TNT
-
-#endif // REGION2D_H
-
diff --git a/intern/iksolver/intern/TNT/stopwatch.h b/intern/iksolver/intern/TNT/stopwatch.h
deleted file mode 100644
index 55cd532d6a4..00000000000
--- a/intern/iksolver/intern/TNT/stopwatch.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-#ifndef STPWATCH_H
-#define STPWATCH_H
-
-// for clock() and CLOCKS_PER_SEC
-#include <ctime>
-
-namespace TNT
-{
-
-/* Simple stopwatch object:
-
- void start() : start timing
- double stop() : stop timing
- void reset() : set elapsed time to 0.0
- double read() : read elapsed time (in seconds)
-
-*/
-
-inline double seconds(void)
-{
- static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
- return ( (double) clock() ) * secs_per_tick;
-}
-
-
-class stopwatch {
- private:
- int running;
- double last_time;
- double total;
-
- public:
- stopwatch() : running(0), last_time(0.0), total(0.0) {}
- void reset() { running = 0; last_time = 0.0; total=0.0; }
- void start() { if (!running) { last_time = seconds(); running = 1;}}
- double stop() { if (running)
- {
- total += seconds() - last_time;
- running = 0;
- }
- return total;
- }
- double read() { if (running)
- {
- total+= seconds() - last_time;
- last_time = seconds();
- }
- return total;
- }
-
-};
-
-} // namespace TNT
-
-#endif
-
diff --git a/intern/iksolver/intern/TNT/subscript.h b/intern/iksolver/intern/TNT/subscript.h
deleted file mode 100644
index 75555e1c0b6..00000000000
--- a/intern/iksolver/intern/TNT/subscript.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-#ifndef SUBSCRPT_H
-#define SUBSCRPT_H
-
-
-//---------------------------------------------------------------------
-// This definition describes the default TNT data type used for
-// indexing into TNT matrices and vectors. The data type should
-// be wide enough to index into large arrays. It defaults to an
-// "int", but can be overriden at compile time redefining TNT_SUBSCRIPT_TYPE,
-// e.g.
-//
-// g++ -DTNT_SUBSCRIPT_TYPE='unsigned int' ...
-//
-//---------------------------------------------------------------------
-//
-
-#ifndef TNT_SUBSCRIPT_TYPE
-#define TNT_SUBSCRIPT_TYPE int
-#endif
-
-namespace TNT
-{
- typedef TNT_SUBSCRIPT_TYPE Subscript;
-}
-
-
-// () indexing in TNT means 1-offset, i.e. x(1) and A(1,1) are the
-// first elements. This offset is left as a macro for future
-// purposes, but should not be changed in the current release.
-//
-//
-#define TNT_BASE_OFFSET (1)
-
-#endif
-
diff --git a/intern/iksolver/intern/TNT/svd.h b/intern/iksolver/intern/TNT/svd.h
deleted file mode 100644
index cfff73caa3f..00000000000
--- a/intern/iksolver/intern/TNT/svd.h
+++ /dev/null
@@ -1,435 +0,0 @@
-/**
- */
-
-#ifndef SVD_H
-
-#define SVD_H
-
-// Compute the Single Value Decomposition of an arbitrary matrix A
-// That is compute the 3 matrices U,W,V with U column orthogonal (m,n)
-// ,W a diagonal matrix and V an orthogonal square matrix s.t.
-// A = U.W.Vt. From this decomposition it is trivial to compute the
-// inverse of A as Ainv = V.Winv.tranpose(U).
-//
-// s = diagonal elements of W
-// work1 = workspace, length must be A.num_rows
-// work2 = workspace, length must be A.num_cols
-
-#include "tntmath.h"
-
-#define SVD_MAX_ITER 200
-
-namespace TNT
-{
-
-template <class MaTRiX, class VecToR >
-void SVD(MaTRiX &A, MaTRiX &U, VecToR &s, MaTRiX &V, VecToR &work1, VecToR &work2, int maxiter=SVD_MAX_ITER) {
-
- int m = A.num_rows();
- int n = A.num_cols();
- int nu = min(m,n);
-
- VecToR& work = work1;
- VecToR& e = work2;
-
- U = 0;
- s = 0;
-
- int i=0, j=0, k=0;
-
- // Reduce A to bidiagonal form, storing the diagonal elements
- // in s and the super-diagonal elements in e.
-
- int nct = min(m-1,n);
- int nrt = max(0,min(n-2,m));
- for (k = 0; k < max(nct,nrt); k++) {
- if (k < nct) {
-
- // Compute the transformation for the k-th column and
- // place the k-th diagonal in s[k].
- // Compute 2-norm of k-th column without under/overflow.
- s[k] = 0;
- for (i = k; i < m; i++) {
- s[k] = hypot(s[k],A[i][k]);
- }
- if (s[k] != 0.0) {
- if (A[k][k] < 0.0) {
- s[k] = -s[k];
- }
- for (i = k; i < m; i++) {
- A[i][k] /= s[k];
- }
- A[k][k] += 1.0;
- }
- s[k] = -s[k];
- }
- for (j = k+1; j < n; j++) {
- if ((k < nct) && (s[k] != 0.0)) {
-
- // Apply the transformation.
-
- typename MaTRiX::value_type t = 0;
- for (i = k; i < m; i++) {
- t += A[i][k]*A[i][j];
- }
- t = -t/A[k][k];
- for (i = k; i < m; i++) {
- A[i][j] += t*A[i][k];
- }
- }
-
- // Place the k-th row of A into e for the
- // subsequent calculation of the row transformation.
-
- e[j] = A[k][j];
- }
- if (k < nct) {
-
- // Place the transformation in U for subsequent back
- // multiplication.
-
- for (i = k; i < m; i++)
- U[i][k] = A[i][k];
- }
- if (k < nrt) {
-
- // Compute the k-th row transformation and place the
- // k-th super-diagonal in e[k].
- // Compute 2-norm without under/overflow.
- e[k] = 0;
- for (i = k+1; i < n; i++) {
- e[k] = hypot(e[k],e[i]);
- }
- if (e[k] != 0.0) {
- if (e[k+1] < 0.0) {
- e[k] = -e[k];
- }
- for (i = k+1; i < n; i++) {
- e[i] /= e[k];
- }
- e[k+1] += 1.0;
- }
- e[k] = -e[k];
- if ((k+1 < m) & (e[k] != 0.0)) {
-
- // Apply the transformation.
-
- for (i = k+1; i < m; i++) {
- work[i] = 0.0;
- }
- for (j = k+1; j < n; j++) {
- for (i = k+1; i < m; i++) {
- work[i] += e[j]*A[i][j];
- }
- }
- for (j = k+1; j < n; j++) {
- typename MaTRiX::value_type t = -e[j]/e[k+1];
- for (i = k+1; i < m; i++) {
- A[i][j] += t*work[i];
- }
- }
- }
-
- // Place the transformation in V for subsequent
- // back multiplication.
-
- for (i = k+1; i < n; i++)
- V[i][k] = e[i];
- }
- }
-
- // Set up the final bidiagonal matrix or order p.
-
- int p = min(n,m+1);
- if (nct < n) {
- s[nct] = A[nct][nct];
- }
- if (m < p) {
- s[p-1] = 0.0;
- }
- if (nrt+1 < p) {
- e[nrt] = A[nrt][p-1];
- }
- e[p-1] = 0.0;
-
- // If required, generate U.
-
- for (j = nct; j < nu; j++) {
- for (i = 0; i < m; i++) {
- U[i][j] = 0.0;
- }
- U[j][j] = 1.0;
- }
- for (k = nct-1; k >= 0; k--) {
- if (s[k] != 0.0) {
- for (j = k+1; j < nu; j++) {
- typename MaTRiX::value_type t = 0;
- for (i = k; i < m; i++) {
- t += U[i][k]*U[i][j];
- }
- t = -t/U[k][k];
- for (i = k; i < m; i++) {
- U[i][j] += t*U[i][k];
- }
- }
- for (i = k; i < m; i++ ) {
- U[i][k] = -U[i][k];
- }
- U[k][k] = 1.0 + U[k][k];
- for (i = 0; i < k-1; i++) {
- U[i][k] = 0.0;
- }
- } else {
- for (i = 0; i < m; i++) {
- U[i][k] = 0.0;
- }
- U[k][k] = 1.0;
- }
- }
-
- // If required, generate V.
-
- for (k = n-1; k >= 0; k--) {
- if ((k < nrt) & (e[k] != 0.0)) {
- for (j = k+1; j < nu; j++) {
- typename MaTRiX::value_type t = 0;
- for (i = k+1; i < n; i++) {
- t += V[i][k]*V[i][j];
- }
- t = -t/V[k+1][k];
- for (i = k+1; i < n; i++) {
- V[i][j] += t*V[i][k];
- }
- }
- }
- for (i = 0; i < n; i++) {
- V[i][k] = 0.0;
- }
- V[k][k] = 1.0;
- }
-
- // Main iteration loop for the singular values.
-
- int pp = p-1;
- int iter = 0;
- typename MaTRiX::value_type eps = pow(2.0,-52.0);
- while (p > 0) {
- int kase=0;
- k=0;
-
- // Test for maximum iterations to avoid infinite loop
- if(maxiter == 0)
- break;
- maxiter--;
-
- // This section of the program inspects for
- // negligible elements in the s and e arrays. On
- // completion the variables kase and k are set as follows.
-
- // kase = 1 if s(p) and e[k-1] are negligible and k<p
- // kase = 2 if s(k) is negligible and k<p
- // kase = 3 if e[k-1] is negligible, k<p, and
- // s(k), ..., s(p) are not negligible (qr step).
- // kase = 4 if e(p-1) is negligible (convergence).
-
- for (k = p-2; k >= -1; k--) {
- if (k == -1) {
- break;
- }
- if (TNT::abs(e[k]) <= eps*(TNT::abs(s[k]) + TNT::abs(s[k+1]))) {
- e[k] = 0.0;
- break;
- }
- }
- if (k == p-2) {
- kase = 4;
- } else {
- int ks;
- for (ks = p-1; ks >= k; ks--) {
- if (ks == k) {
- break;
- }
- typename MaTRiX::value_type t = (ks != p ? TNT::abs(e[ks]) : 0.) +
- (ks != k+1 ? TNT::abs(e[ks-1]) : 0.);
- if (TNT::abs(s[ks]) <= eps*t) {
- s[ks] = 0.0;
- break;
- }
- }
- if (ks == k) {
- kase = 3;
- } else if (ks == p-1) {
- kase = 1;
- } else {
- kase = 2;
- k = ks;
- }
- }
- k++;
-
- // Perform the task indicated by kase.
-
- switch (kase) {
-
- // Deflate negligible s(p).
-
- case 1: {
- typename MaTRiX::value_type f = e[p-2];
- e[p-2] = 0.0;
- for (j = p-2; j >= k; j--) {
- typename MaTRiX::value_type t = hypot(s[j],f);
- typename MaTRiX::value_type cs = s[j]/t;
- typename MaTRiX::value_type sn = f/t;
- s[j] = t;
- if (j != k) {
- f = -sn*e[j-1];
- e[j-1] = cs*e[j-1];
- }
-
- for (i = 0; i < n; i++) {
- t = cs*V[i][j] + sn*V[i][p-1];
- V[i][p-1] = -sn*V[i][j] + cs*V[i][p-1];
- V[i][j] = t;
- }
- }
- }
- break;
-
- // Split at negligible s(k).
-
- case 2: {
- typename MaTRiX::value_type f = e[k-1];
- e[k-1] = 0.0;
- for (j = k; j < p; j++) {
- typename MaTRiX::value_type t = hypot(s[j],f);
- typename MaTRiX::value_type cs = s[j]/t;
- typename MaTRiX::value_type sn = f/t;
- s[j] = t;
- f = -sn*e[j];
- e[j] = cs*e[j];
-
- for (i = 0; i < m; i++) {
- t = cs*U[i][j] + sn*U[i][k-1];
- U[i][k-1] = -sn*U[i][j] + cs*U[i][k-1];
- U[i][j] = t;
- }
- }
- }
- break;
-
- // Perform one qr step.
-
- case 3: {
-
- // Calculate the shift.
-
- typename MaTRiX::value_type scale = max(max(max(max(
- TNT::abs(s[p-1]),TNT::abs(s[p-2])),TNT::abs(e[p-2])),
- TNT::abs(s[k])),TNT::abs(e[k]));
- typename MaTRiX::value_type sp = s[p-1]/scale;
- typename MaTRiX::value_type spm1 = s[p-2]/scale;
- typename MaTRiX::value_type epm1 = e[p-2]/scale;
- typename MaTRiX::value_type sk = s[k]/scale;
- typename MaTRiX::value_type ek = e[k]/scale;
- typename MaTRiX::value_type b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0;
- typename MaTRiX::value_type c = (sp*epm1)*(sp*epm1);
- typename MaTRiX::value_type shift = 0.0;
- if ((b != 0.0) || (c != 0.0)) {
- shift = sqrt(b*b + c);
- if (b < 0.0) {
- shift = -shift;
- }
- shift = c/(b + shift);
- }
- typename MaTRiX::value_type f = (sk + sp)*(sk - sp) + shift;
- typename MaTRiX::value_type g = sk*ek;
-
- // Chase zeros.
-
- for (j = k; j < p-1; j++) {
- typename MaTRiX::value_type t = hypot(f,g);
- /* division by zero checks added to avoid NaN (brecht) */
- typename MaTRiX::value_type cs = (t == 0.0f)? 0.0f: f/t;
- typename MaTRiX::value_type sn = (t == 0.0f)? 0.0f: g/t;
- if (j != k) {
- e[j-1] = t;
- }
- f = cs*s[j] + sn*e[j];
- e[j] = cs*e[j] - sn*s[j];
- g = sn*s[j+1];
- s[j+1] = cs*s[j+1];
-
- for (i = 0; i < n; i++) {
- t = cs*V[i][j] + sn*V[i][j+1];
- V[i][j+1] = -sn*V[i][j] + cs*V[i][j+1];
- V[i][j] = t;
- }
-
- t = hypot(f,g);
- /* division by zero checks added to avoid NaN (brecht) */
- cs = (t == 0.0f)? 0.0f: f/t;
- sn = (t == 0.0f)? 0.0f: g/t;
- s[j] = t;
- f = cs*e[j] + sn*s[j+1];
- s[j+1] = -sn*e[j] + cs*s[j+1];
- g = sn*e[j+1];
- e[j+1] = cs*e[j+1];
- if (j < m-1) {
- for (i = 0; i < m; i++) {
- t = cs*U[i][j] + sn*U[i][j+1];
- U[i][j+1] = -sn*U[i][j] + cs*U[i][j+1];
- U[i][j] = t;
- }
- }
- }
- e[p-2] = f;
- iter = iter + 1;
- }
- break;
-
- // Convergence.
-
- case 4: {
-
- // Make the singular values positive.
-
- if (s[k] <= 0.0) {
- s[k] = (s[k] < 0.0 ? -s[k] : 0.0);
-
- for (i = 0; i <= pp; i++)
- V[i][k] = -V[i][k];
- }
-
- // Order the singular values.
-
- while (k < pp) {
- if (s[k] >= s[k+1]) {
- break;
- }
- typename MaTRiX::value_type t = s[k];
- s[k] = s[k+1];
- s[k+1] = t;
- if (k < n-1) {
- for (i = 0; i < n; i++) {
- t = V[i][k+1]; V[i][k+1] = V[i][k]; V[i][k] = t;
- }
- }
- if (k < m-1) {
- for (i = 0; i < m; i++) {
- t = U[i][k+1]; U[i][k+1] = U[i][k]; U[i][k] = t;
- }
- }
- k++;
- }
- iter = 0;
- p--;
- }
- break;
- }
- }
-}
-
-}
-
-#endif
-
diff --git a/intern/iksolver/intern/TNT/tnt.h b/intern/iksolver/intern/TNT/tnt.h
deleted file mode 100644
index c15ae27c547..00000000000
--- a/intern/iksolver/intern/TNT/tnt.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-#ifndef TNT_H
-#define TNT_H
-
-//---------------------------------------------------------------------
-// tnt.h TNT general header file. Defines default types
-// and conventions.
-//---------------------------------------------------------------------
-
-//---------------------------------------------------------------------
-// Include current version
-//---------------------------------------------------------------------
-#include "version.h"
-
-//---------------------------------------------------------------------
-// Define the data type used for matrix and vector Subscripts.
-// This will default to "int", but it can be overriden at compile time,
-// e.g.
-//
-// g++ -DTNT_SUBSCRIPT_TYPE='unsinged long' ...
-//
-// See subscript.h for details.
-//---------------------------------------------------------------------
-
-#include "subscript.h"
-
-
-
-//---------------------------------------------------------------------
-// Define this macro if you want TNT to ensure all refernces
-// are within the bounds of the array. This encurs a run-time
-// overhead, of course, but is recommended while developing
-// code. It can be turned off for production runs.
-//
-// #define TNT_BOUNDS_CHECK
-//---------------------------------------------------------------------
-//
-#define TNT_BOUNDS_CHECK
-#ifdef TNT_NO_BOUNDS_CHECK
-#undef TNT_BOUNDS_CHECK
-#endif
-
-//---------------------------------------------------------------------
-// Define this macro if you want to utilize matrix and vector
-// regions. This is typically on, but you can save some
-// compilation time by turning it off. If you do this and
-// attempt to use regions you will get an error message.
-//
-// #define TNT_USE_REGIONS
-//---------------------------------------------------------------------
-//
-#define TNT_USE_REGIONS
-
-//---------------------------------------------------------------------
-//
-//---------------------------------------------------------------------
-// if your system doesn't have abs() min(), and max() uncoment the following
-//---------------------------------------------------------------------
-//
-//
-//#define __NEED_ABS_MIN_MAX_
-
-#include "tntmath.h"
-
-#endif // TNT_H
-
diff --git a/intern/iksolver/intern/TNT/tntmath.h b/intern/iksolver/intern/TNT/tntmath.h
deleted file mode 100644
index be72796da59..00000000000
--- a/intern/iksolver/intern/TNT/tntmath.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// Header file for scalar math functions
-
-#ifndef TNTMATH_H
-#define TNTMATH_H
-
-// conventional functions required by several matrix algorithms
-
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-#define hypot _hypot
-#endif
-
-namespace TNT
-{
-
-struct TNTException {
- int i;
-};
-
-
-inline double abs(double t)
-{
- return ( t > 0 ? t : -t);
-}
-
-inline double min(double a, double b)
-{
- return (a < b ? a : b);
-}
-
-inline double max(double a, double b)
-{
- return (a > b ? a : b);
-}
-
-inline float abs(float t)
-{
- return ( t > 0 ? t : -t);
-}
-
-inline float min(float a, float b)
-{
- return (a < b ? a : b);
-}
-
-inline int min(int a, int b)
-{
- return (a < b ? a : b);
-}
-
-inline int max(int a, int b)
-{
- return (a > b ? a : b);
-}
-
-inline float max(float a, float b)
-{
- return (a > b ? a : b);
-}
-
-inline double sign(double a)
-{
- return (a > 0 ? 1.0 : -1.0);
-}
-
-inline double sign(double a,double b) {
- return (b >= 0.0 ? TNT::abs(a) : -TNT::abs(a));
-}
-
-inline float sign(float a,float b) {
- return (b >= 0.0f ? TNT::abs(a) : -TNT::abs(a));
-}
-
-inline float sign(float a)
-{
- return (a > 0.0 ? 1.0f : -1.0f);
-}
-
-inline float pythag(float a, float b)
-{
- float absa,absb;
- absa = abs(a);
- absb = abs(b);
-
- if (absa > absb) {
- float sqr = absb/absa;
- sqr *= sqr;
- return absa * float(sqrt(1 + sqr));
- } else {
- if (absb > float(0)) {
- float sqr = absa/absb;
- sqr *= sqr;
- return absb * float(sqrt(1 + sqr));
- } else {
- return float(0);
- }
- }
-}
-
-inline double pythag(double a, double b)
-{
- double absa,absb;
- absa = abs(a);
- absb = abs(b);
-
- if (absa > absb) {
- double sqr = absb/absa;
- sqr *= sqr;
- return absa * double(sqrt(1 + sqr));
- } else {
-
- if (absb > double(0)) {
- double sqr = absa/absb;
- sqr *= sqr;
- return absb * double(sqrt(1 + sqr));
- } else {
- return double(0);
- }
- }
-}
-
-
-} /* namespace TNT */
-
-#endif /* TNTMATH_H */
-
diff --git a/intern/iksolver/intern/TNT/tntreqs.h b/intern/iksolver/intern/TNT/tntreqs.h
deleted file mode 100644
index 2ee124d5940..00000000000
--- a/intern/iksolver/intern/TNT/tntreqs.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-// The requirements for a bare-bones vector class:
-//
-//
-// o) must have 0-based [] indexing for const and
-// non-const objects (i.e. operator[] defined)
-//
-// o) must have size() method to denote the number of
-// elements
-// o) must clean up after itself when destructed
-// (i.e. no memory leaks)
-//
-// -) must have begin() and end() methods (The begin()
-// method is necessary, because relying on
-// &v_[0] may not work on a empty vector (i.e. v_ is NULL.)
-//
-// o) must be templated
-// o) must have X::value_type defined to be the types of elements
-// o) must have X::X(const &x) copy constructor (by *value*)
-// o) must have X::X(int N) constructor to N-length vector
-// (NOTE: this constructor need *NOT* initalize elements)
-//
-// -) must have X::X(int N, T scalar) constructor to initalize
-// elements to value of "scalar".
-//
-// ( removed, because valarray<> class uses (scalar, N) rather
-// than (N, scalar) )
-// -) must have X::X(int N, const T* scalars) constructor to copy from
-// any C linear array
-//
-// ( removed, because of same reverse order of valarray<> )
-//
-// o) must have assignment A=B, by value
-//
-// NOTE: this class is *NOT* meant to be derived from,
-// so its methods (particularly indexing) need not be
-// declared virtual.
-//
-//
-// Some things it *DOES NOT* need to do are
-//
-// o) bounds checking
-// o) array referencing (e.g. reference counting)
-// o) support () indexing
-// o) I/O
-//
-
diff --git a/intern/iksolver/intern/TNT/transv.h b/intern/iksolver/intern/TNT/transv.h
deleted file mode 100644
index 5500cecff40..00000000000
--- a/intern/iksolver/intern/TNT/transv.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// Matrix Transpose Views
-
-#ifndef TRANSV_H
-#define TRANSV_H
-
-#include <iostream>
-#include <cassert>
-#include "vec.h"
-
-namespace TNT
-{
-
-template <class Array2D>
-class Transpose_View
-{
- protected:
-
- const Array2D & A_;
-
- public:
-
- typedef typename Array2D::element_type T;
- typedef T value_type;
- typedef T element_type;
- typedef T* pointer;
- typedef T* iterator;
- typedef T& reference;
- typedef const T* const_iterator;
- typedef const T& const_reference;
-
-
- const Array2D & array() const { return A_; }
- Subscript num_rows() const { return A_.num_cols();}
- Subscript num_cols() const { return A_.num_rows();}
- Subscript lbound() const { return A_.lbound(); }
- Subscript dim(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert( A_.lbound() <= i);
- assert( i<= A_.lbound()+1);
-#endif
- if (i== A_.lbound())
- return num_rows();
- else
- return num_cols();
- }
-
-
- Transpose_View(const Transpose_View<Array2D> &A) : A_(A.A_) {};
- Transpose_View(const Array2D &A) : A_(A) {};
-
-
- inline const typename Array2D::element_type & operator()(
- Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(lbound()<=i);
- assert(i<=A_.num_cols() + lbound() - 1);
- assert(lbound()<=j);
- assert(j<=A_.num_rows() + lbound() - 1);
-#endif
-
- return A_(j,i);
- }
-
-
-};
-
-template <class Matrix>
-Transpose_View<Matrix> Transpose_view(const Matrix &A)
-{
- return Transpose_View<Matrix>(A);
-}
-
-template <class Matrix, class T>
-Vector<T> matmult(
- const Transpose_View<Matrix> & A,
- const Vector<T> &B)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(B.dim() == N);
-
- Vector<T> x(N);
-
- Subscript i, j;
- T tmp = 0;
-
- for (i=1; i<=M; i++)
- {
- tmp = 0;
- for (j=1; j<=N; j++)
- tmp += A(i,j) * B(j);
- x(i) = tmp;
- }
-
- return x;
-}
-
-template <class Matrix, class T>
-inline Vector<T> operator*(const Transpose_View<Matrix> & A, const Vector<T> &B)
-{
- return matmult(A,B);
-}
-
-
-template <class Matrix>
-std::ostream& operator<<(std::ostream &s, const Transpose_View<Matrix> &A)
-{
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- Subscript start = A.lbound();
- Subscript Mend = M + A.lbound() - 1;
- Subscript Nend = N + A.lbound() - 1;
-
- s << M << " " << N << endl;
- for (Subscript i=start; i<=Mend; i++)
- {
- for (Subscript j=start; j<=Nend; j++)
- {
- s << A(i,j) << " ";
- }
- s << endl;
- }
-
-
- return s;
-}
-
-} // namespace TNT
-
-#endif // TRANSV_H
-
diff --git a/intern/iksolver/intern/TNT/triang.h b/intern/iksolver/intern/TNT/triang.h
deleted file mode 100644
index 10ec2cb18c3..00000000000
--- a/intern/iksolver/intern/TNT/triang.h
+++ /dev/null
@@ -1,637 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// Triangular Matrices (Views and Adpators)
-
-#ifndef TRIANG_H
-#define TRIANG_H
-
-// default to use lower-triangular portions of arrays
-// for symmetric matrices.
-
-namespace TNT
-{
-
-template <class MaTRiX>
-class LowerTriangularView
-{
- protected:
-
-
- const MaTRiX &A_;
- const typename MaTRiX::element_type zero_;
-
- public:
-
-
- typedef typename MaTRiX::const_reference const_reference;
- typedef const typename MaTRiX::element_type element_type;
- typedef const typename MaTRiX::element_type value_type;
- typedef element_type T;
-
- Subscript dim(Subscript d) const { return A_.dim(d); }
- Subscript lbound() const { return A_.lbound(); }
- Subscript num_rows() const { return A_.num_rows(); }
- Subscript num_cols() const { return A_.num_cols(); }
-
-
- // constructors
-
- LowerTriangularView(/*const*/ MaTRiX &A) : A_(A), zero_(0) {}
-
-
- inline const_reference get(Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(lbound()<=i);
- assert(i<=A_.num_rows() + lbound() - 1);
- assert(lbound()<=j);
- assert(j<=A_.num_cols() + lbound() - 1);
-#endif
- if (i<j)
- return zero_;
- else
- return A_(i,j);
- }
-
-
- inline const_reference operator() (Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(lbound()<=i);
- assert(i<=A_.num_rows() + lbound() - 1);
- assert(lbound()<=j);
- assert(j<=A_.num_cols() + lbound() - 1);
-#endif
- if (i<j)
- return zero_;
- else
- return A_(i,j);
- }
-
-#ifdef TNT_USE_REGIONS
-
- typedef const_Region2D< LowerTriangularView<MaTRiX> >
- const_Region;
-
- const_Region operator()(/*const*/ Index1D &I,
- /*const*/ Index1D &J) const
- {
- return const_Region(*this, I, J);
- }
-
- const_Region operator()(Subscript i1, Subscript i2,
- Subscript j1, Subscript j2) const
- {
- return const_Region(*this, i1, i2, j1, j2);
- }
-
-
-
-#endif
-// TNT_USE_REGIONS
-
-};
-
-
-/* *********** Lower_triangular_view() algorithms ****************** */
-
-template <class MaTRiX, class VecToR>
-VecToR matmult(/*const*/ LowerTriangularView<MaTRiX> &A, VecToR &x)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(N == x.dim());
-
- Subscript i, j;
- typename MaTRiX::element_type sum=0.0;
- VecToR result(M);
-
- Subscript start = A.lbound();
- Subscript Mend = M + A.lbound() -1 ;
-
- for (i=start; i<=Mend; i++)
- {
- sum = 0.0;
- for (j=start; j<=i; j++)
- sum = sum + A(i,j)*x(j);
- result(i) = sum;
- }
-
- return result;
-}
-
-template <class MaTRiX, class VecToR>
-inline VecToR operator*(/*const*/ LowerTriangularView<MaTRiX> &A, VecToR &x)
-{
- return matmult(A,x);
-}
-
-template <class MaTRiX>
-class UnitLowerTriangularView
-{
- protected:
-
- const MaTRiX &A_;
- const typename MaTRiX::element_type zero;
- const typename MaTRiX::element_type one;
-
- public:
-
- typedef typename MaTRiX::const_reference const_reference;
- typedef typename MaTRiX::element_type element_type;
- typedef typename MaTRiX::element_type value_type;
- typedef element_type T;
-
- Subscript lbound() const { return 1; }
- Subscript dim(Subscript d) const { return A_.dim(d); }
- Subscript num_rows() const { return A_.num_rows(); }
- Subscript num_cols() const { return A_.num_cols(); }
-
-
- // constructors
-
- UnitLowerTriangularView(/*const*/ MaTRiX &A) : A_(A), zero(0), one(1) {}
-
-
- inline const_reference get(Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i<=A_.dim(1));
- assert(1<=j);
- assert(j<=A_.dim(2));
- assert(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1));
-#endif
- if (i>j)
- return A_(i,j);
- else if (i==j)
- return one;
- else
- return zero;
- }
-
-
- inline const_reference operator() (Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i<=A_.dim(1));
- assert(1<=j);
- assert(j<=A_.dim(2));
-#endif
- if (i>j)
- return A_(i,j);
- else if (i==j)
- return one;
- else
- return zero;
- }
-
-
-#ifdef TNT_USE_REGIONS
- // These are the "index-aware" features
-
- typedef const_Region2D< UnitLowerTriangularView<MaTRiX> >
- const_Region;
-
- const_Region operator()(/*const*/ Index1D &I,
- /*const*/ Index1D &J) const
- {
- return const_Region(*this, I, J);
- }
-
- const_Region operator()(Subscript i1, Subscript i2,
- Subscript j1, Subscript j2) const
- {
- return const_Region(*this, i1, i2, j1, j2);
- }
-#endif
-// TNT_USE_REGIONS
-};
-
-template <class MaTRiX>
-LowerTriangularView<MaTRiX> Lower_triangular_view(
- /*const*/ MaTRiX &A)
-{
- return LowerTriangularView<MaTRiX>(A);
-}
-
-
-template <class MaTRiX>
-UnitLowerTriangularView<MaTRiX> Unit_lower_triangular_view(
- /*const*/ MaTRiX &A)
-{
- return UnitLowerTriangularView<MaTRiX>(A);
-}
-
-template <class MaTRiX, class VecToR>
-VecToR matmult(/*const*/ UnitLowerTriangularView<MaTRiX> &A, VecToR &x)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(N == x.dim());
-
- Subscript i, j;
- typename MaTRiX::element_type sum=0.0;
- VecToR result(M);
-
- Subscript start = A.lbound();
- Subscript Mend = M + A.lbound() -1 ;
-
- for (i=start; i<=Mend; i++)
- {
- sum = 0.0;
- for (j=start; j<i; j++)
- sum = sum + A(i,j)*x(j);
- result(i) = sum + x(i);
- }
-
- return result;
-}
-
-template <class MaTRiX, class VecToR>
-inline VecToR operator*(/*const*/ UnitLowerTriangularView<MaTRiX> &A, VecToR &x)
-{
- return matmult(A,x);
-}
-
-
-//********************** Algorithms *************************************
-
-
-
-template <class MaTRiX>
-std::ostream& operator<<(std::ostream &s, const LowerTriangularView<MaTRiX>&A)
-{
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- s << M << " " << N << endl;
-
- for (Subscript i=1; i<=M; i++)
- {
- for (Subscript j=1; j<=N; j++)
- {
- s << A(i,j) << " ";
- }
- s << endl;
- }
-
-
- return s;
-}
-
-template <class MaTRiX>
-std::ostream& operator<<(std::ostream &s,
- const UnitLowerTriangularView<MaTRiX>&A)
-{
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- s << M << " " << N << endl;
-
- for (Subscript i=1; i<=M; i++)
- {
- for (Subscript j=1; j<=N; j++)
- {
- s << A(i,j) << " ";
- }
- s << endl;
- }
-
-
- return s;
-}
-
-
-
-// ******************* Upper Triangular Section **************************
-
-template <class MaTRiX>
-class UpperTriangularView
-{
- protected:
-
-
- /*const*/ MaTRiX &A_;
- /*const*/ typename MaTRiX::element_type zero_;
-
- public:
-
-
- typedef typename MaTRiX::const_reference const_reference;
- typedef /*const*/ typename MaTRiX::element_type element_type;
- typedef /*const*/ typename MaTRiX::element_type value_type;
- typedef element_type T;
-
- Subscript dim(Subscript d) const { return A_.dim(d); }
- Subscript lbound() const { return A_.lbound(); }
- Subscript num_rows() const { return A_.num_rows(); }
- Subscript num_cols() const { return A_.num_cols(); }
-
-
- // constructors
-
- UpperTriangularView(/*const*/ MaTRiX &A) : A_(A), zero_(0) {}
-
-
- inline const_reference get(Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(lbound()<=i);
- assert(i<=A_.num_rows() + lbound() - 1);
- assert(lbound()<=j);
- assert(j<=A_.num_cols() + lbound() - 1);
-#endif
- if (i>j)
- return zero_;
- else
- return A_(i,j);
- }
-
-
- inline const_reference operator() (Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(lbound()<=i);
- assert(i<=A_.num_rows() + lbound() - 1);
- assert(lbound()<=j);
- assert(j<=A_.num_cols() + lbound() - 1);
-#endif
- if (i>j)
- return zero_;
- else
- return A_(i,j);
- }
-
-#ifdef TNT_USE_REGIONS
-
- typedef const_Region2D< UpperTriangularView<MaTRiX> >
- const_Region;
-
- const_Region operator()(const Index1D &I,
- const Index1D &J) const
- {
- return const_Region(*this, I, J);
- }
-
- const_Region operator()(Subscript i1, Subscript i2,
- Subscript j1, Subscript j2) const
- {
- return const_Region(*this, i1, i2, j1, j2);
- }
-
-
-
-#endif
-// TNT_USE_REGIONS
-
-};
-
-
-/* *********** Upper_triangular_view() algorithms ****************** */
-
-template <class MaTRiX, class VecToR>
-VecToR matmult(/*const*/ UpperTriangularView<MaTRiX> &A, VecToR &x)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(N == x.dim());
-
- Subscript i, j;
- typename VecToR::element_type sum=0.0;
- VecToR result(M);
-
- Subscript start = A.lbound();
- Subscript Mend = M + A.lbound() -1 ;
-
- for (i=start; i<=Mend; i++)
- {
- sum = 0.0;
- for (j=i; j<=N; j++)
- sum = sum + A(i,j)*x(j);
- result(i) = sum;
- }
-
- return result;
-}
-
-template <class MaTRiX, class VecToR>
-inline VecToR operator*(/*const*/ UpperTriangularView<MaTRiX> &A, VecToR &x)
-{
- return matmult(A,x);
-}
-
-template <class MaTRiX>
-class UnitUpperTriangularView
-{
- protected:
-
- const MaTRiX &A_;
- const typename MaTRiX::element_type zero;
- const typename MaTRiX::element_type one;
-
- public:
-
- typedef typename MaTRiX::const_reference const_reference;
- typedef typename MaTRiX::element_type element_type;
- typedef typename MaTRiX::element_type value_type;
- typedef element_type T;
-
- Subscript lbound() const { return 1; }
- Subscript dim(Subscript d) const { return A_.dim(d); }
- Subscript num_rows() const { return A_.num_rows(); }
- Subscript num_cols() const { return A_.num_cols(); }
-
-
- // constructors
-
- UnitUpperTriangularView(/*const*/ MaTRiX &A) : A_(A), zero(0), one(1) {}
-
-
- inline const_reference get(Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i<=A_.dim(1));
- assert(1<=j);
- assert(j<=A_.dim(2));
- assert(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1));
-#endif
- if (i<j)
- return A_(i,j);
- else if (i==j)
- return one;
- else
- return zero;
- }
-
-
- inline const_reference operator() (Subscript i, Subscript j) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i<=A_.dim(1));
- assert(1<=j);
- assert(j<=A_.dim(2));
-#endif
- if (i<j)
- return A_(i,j);
- else if (i==j)
- return one;
- else
- return zero;
- }
-
-
-#ifdef TNT_USE_REGIONS
- // These are the "index-aware" features
-
- typedef const_Region2D< UnitUpperTriangularView<MaTRiX> >
- const_Region;
-
- const_Region operator()(const Index1D &I,
- const Index1D &J) const
- {
- return const_Region(*this, I, J);
- }
-
- const_Region operator()(Subscript i1, Subscript i2,
- Subscript j1, Subscript j2) const
- {
- return const_Region(*this, i1, i2, j1, j2);
- }
-#endif
-// TNT_USE_REGIONS
-};
-
-template <class MaTRiX>
-UpperTriangularView<MaTRiX> Upper_triangular_view(
- /*const*/ MaTRiX &A)
-{
- return UpperTriangularView<MaTRiX>(A);
-}
-
-
-template <class MaTRiX>
-UnitUpperTriangularView<MaTRiX> Unit_upper_triangular_view(
- /*const*/ MaTRiX &A)
-{
- return UnitUpperTriangularView<MaTRiX>(A);
-}
-
-template <class MaTRiX, class VecToR>
-VecToR matmult(/*const*/ UnitUpperTriangularView<MaTRiX> &A, VecToR &x)
-{
- Subscript M = A.num_rows();
- Subscript N = A.num_cols();
-
- assert(N == x.dim());
-
- Subscript i, j;
- typename VecToR::element_type sum=0.0;
- VecToR result(M);
-
- Subscript start = A.lbound();
- Subscript Mend = M + A.lbound() -1 ;
-
- for (i=start; i<=Mend; i++)
- {
- sum = x(i);
- for (j=i+1; j<=N; j++)
- sum = sum + A(i,j)*x(j);
- result(i) = sum + x(i);
- }
-
- return result;
-}
-
-template <class MaTRiX, class VecToR>
-inline VecToR operator*(/*const*/ UnitUpperTriangularView<MaTRiX> &A, VecToR &x)
-{
- return matmult(A,x);
-}
-
-
-//********************** Algorithms *************************************
-
-
-
-template <class MaTRiX>
-std::ostream& operator<<(std::ostream &s,
- /*const*/ UpperTriangularView<MaTRiX>&A)
-{
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- s << M << " " << N << endl;
-
- for (Subscript i=1; i<=M; i++)
- {
- for (Subscript j=1; j<=N; j++)
- {
- s << A(i,j) << " ";
- }
- s << endl;
- }
-
-
- return s;
-}
-
-template <class MaTRiX>
-std::ostream& operator<<(std::ostream &s,
- /*const*/ UnitUpperTriangularView<MaTRiX>&A)
-{
- Subscript M=A.num_rows();
- Subscript N=A.num_cols();
-
- s << M << " " << N << endl;
-
- for (Subscript i=1; i<=M; i++)
- {
- for (Subscript j=1; j<=N; j++)
- {
- s << A(i,j) << " ";
- }
- s << endl;
- }
-
-
- return s;
-}
-
-} // namespace TNT
-
-#endif //TRIANG_H
-
diff --git a/intern/iksolver/intern/TNT/trisolve.h b/intern/iksolver/intern/TNT/trisolve.h
deleted file mode 100644
index e6e2a0afe3a..00000000000
--- a/intern/iksolver/intern/TNT/trisolve.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-// Triangular Solves
-
-#ifndef TRISLV_H
-#define TRISLV_H
-
-
-#include "triang.h"
-
-namespace TNT
-{
-
-template <class MaTriX, class VecToR>
-VecToR Lower_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
-{
- Subscript N = A.num_rows();
-
- // make sure matrix sizes agree; A must be square
-
- assert(A.num_cols() == N);
- assert(b.dim() == N);
-
- VecToR x(N);
-
- Subscript i;
- for (i=1; i<=N; i++)
- {
- typename MaTriX::element_type tmp=0;
-
- for (Subscript j=1; j<i; j++)
- tmp = tmp + A(i,j)*x(j);
-
- x(i) = (b(i) - tmp)/ A(i,i);
- }
-
- return x;
-}
-
-
-template <class MaTriX, class VecToR>
-VecToR Unit_lower_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
-{
- Subscript N = A.num_rows();
-
- // make sure matrix sizes agree; A must be square
-
- assert(A.num_cols() == N);
- assert(b.dim() == N);
-
- VecToR x(N);
-
- Subscript i;
- for (i=1; i<=N; i++)
- {
-
- typename MaTriX::element_type tmp=0;
-
- for (Subscript j=1; j<i; j++)
- tmp = tmp + A(i,j)*x(j);
-
- x(i) = b(i) - tmp;
- }
-
- return x;
-}
-
-
-template <class MaTriX, class VecToR>
-VecToR linear_solve(/*const*/ LowerTriangularView<MaTriX> &A,
- /*const*/ VecToR &b)
-{
- return Lower_triangular_solve(A, b);
-}
-
-template <class MaTriX, class VecToR>
-VecToR linear_solve(/*const*/ UnitLowerTriangularView<MaTriX> &A,
- /*const*/ VecToR &b)
-{
- return Unit_lower_triangular_solve(A, b);
-}
-
-
-
-//********************** Upper triangular section ****************
-
-template <class MaTriX, class VecToR>
-VecToR Upper_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
-{
- Subscript N = A.num_rows();
-
- // make sure matrix sizes agree; A must be square
-
- assert(A.num_cols() == N);
- assert(b.dim() == N);
-
- VecToR x(N);
-
- Subscript i;
- for (i=N; i>=1; i--)
- {
-
- typename MaTriX::element_type tmp=0;
-
- for (Subscript j=i+1; j<=N; j++)
- tmp = tmp + A(i,j)*x(j);
-
- x(i) = (b(i) - tmp)/ A(i,i);
- }
-
- return x;
-}
-
-
-template <class MaTriX, class VecToR>
-VecToR Unit_upper_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
-{
- Subscript N = A.num_rows();
-
- // make sure matrix sizes agree; A must be square
-
- assert(A.num_cols() == N);
- assert(b.dim() == N);
-
- VecToR x(N);
-
- Subscript i;
- for (i=N; i>=1; i--)
- {
-
- typename MaTriX::element_type tmp=0;
-
- for (Subscript j=i+1; j<i; j++)
- tmp = tmp + A(i,j)*x(j);
-
- x(i) = b(i) - tmp;
- }
-
- return x;
-}
-
-
-template <class MaTriX, class VecToR>
-VecToR linear_solve(/*const*/ UpperTriangularView<MaTriX> &A,
- /*const*/ VecToR &b)
-{
- return Upper_triangular_solve(A, b);
-}
-
-template <class MaTriX, class VecToR>
-VecToR linear_solve(/*const*/ UnitUpperTriangularView<MaTriX> &A,
- /*const*/ VecToR &b)
-{
- return Unit_upper_triangular_solve(A, b);
-}
-
-
-} // namespace TNT
-
-#endif // TRISLV_H
-
diff --git a/intern/iksolver/intern/TNT/vec.h b/intern/iksolver/intern/TNT/vec.h
deleted file mode 100644
index 5d4ef14bf73..00000000000
--- a/intern/iksolver/intern/TNT/vec.h
+++ /dev/null
@@ -1,491 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-// Basic TNT numerical vector (0-based [i] AND 1-based (i) indexing )
-//
-
-#ifndef VEC_H
-#define VEC_H
-
-#include "subscript.h"
-#include <stdlib.h>
-#include <assert.h>
-#include <iostream>
-
-namespace TNT
-{
-
-template <class T>
-class Vector
-{
-
-
- public:
-
- typedef Subscript size_type;
- typedef T value_type;
- typedef T element_type;
- typedef T* pointer;
- typedef T* iterator;
- typedef T& reference;
- typedef const T* const_iterator;
- typedef const T& const_reference;
-
- Subscript lbound() const { return 1;}
-
- protected:
- T* v_;
- T* vm1_; // pointer adjustment for optimzied 1-offset indexing
- Subscript n_;
-
- // internal helper function to create the array
- // of row pointers
-
- void initialize(Subscript N)
- {
- // adjust pointers so that they are 1-offset:
- // v_[] is the internal contiguous array, it is still 0-offset
- //
- assert(v_ == NULL);
- v_ = new T[N];
- assert(v_ != NULL);
- vm1_ = v_-1;
- n_ = N;
- }
-
- void copy(const T* v)
- {
- Subscript N = n_;
- Subscript i;
-
-#ifdef TNT_UNROLL_LOOPS
- Subscript Nmod4 = N & 3;
- Subscript N4 = N - Nmod4;
-
- for (i=0; i<N4; i+=4)
- {
- v_[i] = v[i];
- v_[i+1] = v[i+1];
- v_[i+2] = v[i+2];
- v_[i+3] = v[i+3];
- }
-
- for (i=N4; i< N; i++)
- v_[i] = v[i];
-#else
-
- for (i=0; i< N; i++)
- v_[i] = v[i];
-#endif
- }
-
- void set(const T& val)
- {
- Subscript N = n_;
- Subscript i;
-
-#ifdef TNT_UNROLL_LOOPS
- Subscript Nmod4 = N & 3;
- Subscript N4 = N - Nmod4;
-
- for (i=0; i<N4; i+=4)
- {
- v_[i] = val;
- v_[i+1] = val;
- v_[i+2] = val;
- v_[i+3] = val;
- }
-
- for (i=N4; i< N; i++)
- v_[i] = val;
-#else
-
- for (i=0; i< N; i++)
- v_[i] = val;
-
-#endif
- }
-
-
-
- void destroy()
- {
- /* do nothing, if no memory has been previously allocated */
- if (v_ == NULL) return ;
-
- /* if we are here, then matrix was previously allocated */
- delete [] (v_);
-
- v_ = NULL;
- vm1_ = NULL;
- }
-
-
- public:
-
- // access
-
- iterator begin() { return v_;}
- iterator end() { return v_ + n_; }
- const iterator begin() const { return v_;}
- const iterator end() const { return v_ + n_; }
-
- // destructor
-
- ~Vector()
- {
- destroy();
- }
-
- // constructors
-
- Vector() : v_(0), vm1_(0), n_(0) {}
-
- Vector(const Vector<T> &A) : v_(0), vm1_(0), n_(0)
- {
- initialize(A.n_);
- copy(A.v_);
- }
-
- Vector(Subscript N, const T& value = T()) : v_(0), vm1_(0), n_(0)
- {
- initialize(N);
- set(value);
- }
-
- Vector(Subscript N, const T* v) : v_(0), vm1_(0), n_(0)
- {
- initialize(N);
- copy(v);
- }
-
-
- // methods
- //
- Vector<T>& newsize(Subscript N)
- {
- if (n_ == N) return *this;
-
- destroy();
- initialize(N);
-
- return *this;
- }
-
-
- // assignments
- //
- Vector<T>& operator=(const Vector<T> &A)
- {
- if (v_ == A.v_)
- return *this;
-
- if (n_ == A.n_) // no need to re-alloc
- copy(A.v_);
-
- else
- {
- destroy();
- initialize(A.n_);
- copy(A.v_);
- }
-
- return *this;
- }
-
- Vector<T>& operator=(const T& scalar)
- {
- set(scalar);
- return *this;
- }
-
- inline Subscript dim() const
- {
- return n_;
- }
-
- inline Subscript size() const
- {
- return n_;
- }
-
-
- inline reference operator()(Subscript i)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i <= n_) ;
-#endif
- return vm1_[i];
- }
-
- inline const_reference operator() (Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i <= n_) ;
-#endif
- return vm1_[i];
- }
-
- inline reference operator[](Subscript i)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(0<=i);
- assert(i < n_) ;
-#endif
- return v_[i];
- }
-
- inline const_reference operator[](Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(0<=i) ;
- assert(i < n_) ;
-#endif
- return v_[i];
- }
-
-
-
-};
-
-
-/* *************************** I/O ********************************/
-
-template <class T>
-std::ostream& operator<<(std::ostream &s, const Vector<T> &A)
-{
- Subscript N=A.dim();
-
- s << N << std::endl;
-
- for (Subscript i=0; i<N; i++)
- s << A[i] << " " << std::endl;
- s << std::endl;
-
- return s;
-}
-
-template <class T>
-std::istream & operator>>(std::istream &s, Vector<T> &A)
-{
-
- Subscript N;
-
- s >> N;
-
- if ( !(N == A.size() ))
- {
- A.newsize(N);
- }
-
-
- for (Subscript i=0; i<N; i++)
- s >> A[i];
-
-
- return s;
-}
-
-// *******************[ basic matrix algorithms ]***************************
-
-
-template <class T>
-Vector<T> operator+(const Vector<T> &A,
- const Vector<T> &B)
-{
- Subscript N = A.dim();
-
- assert(N==B.dim());
-
- Vector<T> tmp(N);
- Subscript i;
-
- for (i=0; i<N; i++)
- tmp[i] = A[i] + B[i];
-
- return tmp;
-}
-
-template <class T>
-Vector<T> operator-(const Vector<T> &A,
- const Vector<T> &B)
-{
- Subscript N = A.dim();
-
- assert(N==B.dim());
-
- Vector<T> tmp(N);
- Subscript i;
-
- for (i=0; i<N; i++)
- tmp[i] = A[i] - B[i];
-
- return tmp;
-}
-
-template <class T>
-Vector<T> operator*(const Vector<T> &A,
- const Vector<T> &B)
-{
- Subscript N = A.dim();
-
- assert(N==B.dim());
-
- Vector<T> tmp(N);
- Subscript i;
-
- for (i=0; i<N; i++)
- tmp[i] = A[i] * B[i];
-
- return tmp;
-}
-
-template <class T>
-Vector<T> operator*(const Vector<T> &A,
- const T &B)
-{
- Subscript N = A.dim();
-
- Vector<T> tmp(N);
- Subscript i;
-
- for (i=0; i<N; i++)
- tmp[i] = A[i] * B;
-
- return tmp;
-}
-
-
-template <class T>
-T dot_prod(const Vector<T> &A, const Vector<T> &B)
-{
- Subscript N = A.dim();
- assert(N == B.dim());
-
- Subscript i;
- T sum = 0;
-
- for (i=0; i<N; i++)
- sum += A[i] * B[i];
-
- return sum;
-}
-
-// inplace versions of the above template functions
-
-// A = A + B
-
-template <class T>
-void vectoradd(
- Vector<T> &A,
- const Vector<T> &B)
-{
- const Subscript N = A.dim();
- assert(N==B.dim());
- Subscript i;
-
- for (i=0; i<N; i++)
- A[i] += B[i];
-}
-
-// same with separate output vector
-
-template <class T>
-void vectoradd(
- Vector<T> &C,
- const Vector<T> &A,
- const Vector<T> &B)
-{
- const Subscript N = A.dim();
- assert(N==B.dim());
- Subscript i;
-
- for (i=0; i<N; i++)
- C[i] = A[i] + B[i];
-}
-
-// A = A - B
-
-template <class T>
-void vectorsub(
- Vector<T> &A,
- const Vector<T> &B)
-{
- const Subscript N = A.dim();
- assert(N==B.dim());
- Subscript i;
-
- for (i=0; i<N; i++)
- A[i] -= B[i];
-}
-
-template <class T>
-void vectorsub(
- Vector<T> &C,
- const Vector<T> &A,
- const Vector<T> &B)
-{
- const Subscript N = A.dim();
- assert(N==B.dim());
- Subscript i;
-
- for (i=0; i<N; i++)
- C[i] = A[i] - B[i];
-}
-
-template <class T>
-void vectorscale(
- Vector<T> &C,
- const Vector<T> &A,
- const T &B)
-{
- const Subscript N = A.dim();
- Subscript i;
-
- for (i=0; i<N; i++)
- C[i] = A[i] * B;
-}
-
-template <class T>
-void vectorscale(
- Vector<T> &A,
- const T &B)
-{
- const Subscript N = A.dim();
- Subscript i;
-
- for (i=0; i<N; i++)
- A[i] *= B;
-}
-
-} /* namespace TNT */
-
-#endif // VEC_H
-
diff --git a/intern/iksolver/intern/TNT/vecadaptor.h b/intern/iksolver/intern/TNT/vecadaptor.h
deleted file mode 100644
index 77d4e2c05a4..00000000000
--- a/intern/iksolver/intern/TNT/vecadaptor.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/**
- */
-
-/*
-
-*
-* Template Numerical Toolkit (TNT): Linear Algebra Module
-*
-* Mathematical and Computational Sciences Division
-* National Institute of Technology,
-* Gaithersburg, MD USA
-*
-*
-* This software was developed at the National Institute of Standards and
-* Technology (NIST) by employees of the Federal Government in the course
-* of their official duties. Pursuant to title 17 Section 105 of the
-* United States Code, this software is not subject to copyright protection
-* and is in the public domain. The Template Numerical Toolkit (TNT) is
-* an experimental system. NIST assumes no responsibility whatsoever for
-* its use by other parties, and makes no guarantees, expressed or implied,
-* about its quality, reliability, or any other characteristic.
-*
-* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-* see http://math.nist.gov/tnt for latest updates.
-*
-*/
-
-
-
-#ifndef VECADAPTOR_H
-#define VECADAPTOR_H
-
-#include <cstdlib>
-#include <iostream>
-#include <cassert>
-
-#include "subscript.h"
-
-#ifdef TNT_USE_REGIONS
-#include "region1d.h"
-#endif
-
-namespace TNT
-{
-
-// see "tntreq.h" for TNT requirements for underlying vector
-// class. This need NOT be the STL vector<> class, but a subset
-// that provides minimal services.
-//
-// This is a container adaptor that provides the following services.
-//
-// o) adds 1-offset operator() access ([] is always 0 offset)
-// o) adds TNT_BOUNDS_CHECK to () and []
-// o) adds initialization from strings, e.g. "1.0 2.0 3.0";
-// o) adds newsize(N) function (does not preserve previous values)
-// o) adds dim() and dim(1)
-// o) adds free() function to release memory used by vector
-// o) adds regions, e.g. A(Index(1,10)) = ...
-// o) add getVector() method to return adapted container
-// o) adds simple I/O for ostreams
-
-template <class BBVec>
-class Vector_Adaptor
-{
-
- public:
- typedef typename BBVec::value_type T;
- typedef T value_type;
- typedef T element_type;
- typedef T* pointer;
- typedef T* iterator;
- typedef T& reference;
- typedef const T* const_iterator;
- typedef const T& const_reference;
-
- Subscript lbound() const { return 1; }
-
- protected:
- BBVec v_;
- T* vm1_;
-
- public:
-
- Subscript size() const { return v_.size(); }
-
- // These were removed so that the ANSI C++ valarray class
- // would work as a possible storage container.
- //
- //
- //iterator begin() { return v_.begin();}
- //iterator begin() { return &v_[0];}
- //
- //iterator end() { return v_.end(); }
- //iterator end() { return &v_[0] + v_.size(); }
- //
- //const_iterator begin() const { return v_.begin();}
- //const_iterator begin() const { return &v_[0];}
- //
- //const_iterator end() const { return v_.end(); }
- //const_iterator end() const { return &v_[0] + v_.size(); }
-
- BBVec& getVector() { return v_; }
- Subscript dim() const { return v_.size(); }
- Subscript dim(Subscript i)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(i==TNT_BASE_OFFSET);
-#endif
- return (i==TNT_BASE_OFFSET ? v_.size() : 0 );
- }
- Vector_Adaptor() : v_() {};
- Vector_Adaptor(const Vector_Adaptor<BBVec> &A) : v_(A.v_)
- {
- vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
-
- }
-
- Vector_Adaptor(Subscript N, const T& value = T()) : v_(N)
- {
- for (Subscript i=0; i<N; i++)
- v_[i] = value;
-
- vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
- }
-
- Vector_Adaptor(Subscript N, const T* values) : v_(N)
- {
- for (Subscript i=0; i<N; i++)
- v_[i] = values[i];
- vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
- }
- Vector_Adaptor(const BBVec & A) : v_(A)
- {
- vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
- }
-
- // NOTE: this assumes that BBVec(0) constructor creates an
- // null vector that does not take up space... It would be
- // great to require that BBVec have a corresponding free()
- // function, but in particular STL vectors do not.
- //
- Vector_Adaptor<BBVec>& free()
- {
- return *this = Vector_Adaptor<BBVec>(0);
- }
-
- Vector_Adaptor<BBVec>& operator=(const Vector_Adaptor<BBVec> &A)
- {
- v_ = A.v_ ;
- vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
- return *this;
- }
-
- Vector_Adaptor<BBVec>& newsize(Subscript N)
- {
- // NOTE: this is not as efficient as it could be
- // but to retain compatiblity with STL interface
- // we cannot assume underlying implementation
- // has a newsize() function.
-
- return *this = Vector_Adaptor<BBVec>(N);
-
- }
-
- Vector_Adaptor<BBVec>& operator=(const T &a)
- {
- Subscript i;
- Subscript N = v_.size();
- for (i=0; i<N; i++)
- v_[i] = a;
-
- return *this;
- }
-
- Vector_Adaptor<BBVec>& resize(Subscript N)
- {
- if (N == size()) return *this;
-
- Vector_Adaptor<BBVec> tmp(N);
- Subscript n = (N < size() ? N : size()); // min(N, size());
- Subscript i;
-
- for (i=0; i<n; i++)
- tmp[i] = v_[i];
-
-
- return (*this = tmp);
-
- }
-
-
- reference operator()(Subscript i)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i<=dim());
-#endif
- return vm1_[i];
- }
-
- const_reference operator()(Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(1<=i);
- assert(i<=dim());
-#endif
- return vm1_[i];
- }
-
- reference operator[](Subscript i)
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(0<=i);
- assert(i<dim());
-#endif
- return v_[i];
- }
-
- const_reference operator[](Subscript i) const
- {
-#ifdef TNT_BOUNDS_CHECK
- assert(0<=i);
- assert(i<dim());
-#endif
- return v_[i];
- }
-
-
-#ifdef TNT_USE_REGIONS
- // "index-aware" features, all of these are 1-based offsets
-
- typedef Region1D<Vector_Adaptor<BBVec> > Region;
-
- typedef const_Region1D< Vector_Adaptor<BBVec> > const_Region;
-
- Region operator()(const Index1D &I)
- { return Region(*this, I); }
-
- Region operator()(const Subscript i1, Subscript i2)
- { return Region(*this, i1, i2); }
-
- const_Region operator()(const Index1D &I) const
- { return const_Region(*this, I); }
-
- const_Region operator()(const Subscript i1, Subscript i2) const
- { return const_Region(*this, i1, i2); }
-#endif
-// TNT_USE_REGIONS
-
-
-};
-
-#include <iostream>
-
-template <class BBVec>
-std::ostream& operator<<(std::ostream &s, const Vector_Adaptor<BBVec> &A)
-{
- Subscript M=A.size();
-
- s << M << endl;
- for (Subscript i=1; i<=M; i++)
- s << A(i) << endl;
- return s;
-}
-
-template <class BBVec>
-std::istream& operator>>(std::istream &s, Vector_Adaptor<BBVec> &A)
-{
- Subscript N;
-
- s >> N;
-
- A.resize(N);
-
- for (Subscript i=1; i<=N; i++)
- s >> A(i);
-
- return s;
-}
-
-} // namespace TNT
-
-#endif
-
diff --git a/intern/iksolver/intern/TNT/version.h b/intern/iksolver/intern/TNT/version.h
deleted file mode 100644
index 58017dd80f9..00000000000
--- a/intern/iksolver/intern/TNT/version.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- */
-
-// Template Numerical Toolkit (TNT) for Linear Algebra
-
-//
-// BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
-// Please see http://math.nist.gov/tnt for updates
-//
-// R. Pozo
-// Mathematical and Computational Sciences Division
-// National Institute of Standards and Technology
-
-
-#ifndef TNT_VERSION_H
-#define TNT_VERSION_H
-
-
-#define TNT_MAJOR_VERSION '0'
-#define TNT_MINOR_VERSION '9'
-#define TNT_SUBMINOR_VERSION '4'
-#define TNT_VERSION_STRING "0.9.4"
-
-#endif
-
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp
deleted file mode 100644
index b138dd18725..00000000000
--- a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "GlutDrawer.h"
-
-#include "MT_assert.h"
-
-MEM_SmartPtr<GlutDrawManager> GlutDrawManager::m_s_instance = MEM_SmartPtr<GlutDrawManager>();
-
- GlutDrawManager *
-GlutDrawManager::
-Instance(
-){
- if (m_s_instance == NULL) {
- m_s_instance = new GlutDrawManager();
- }
-
- return m_s_instance;
-}
-
-
-// this is the function you should pass to glut
-
- void
-GlutDrawManager::
-Draw(
-){
- GlutDrawManager *manager = GlutDrawManager::Instance();
-
- if (manager->m_drawer != NULL) {
- manager->m_drawer->Draw();
- }
-}
-
- void
-GlutDrawManager::
-InstallDrawer(
- GlutDrawer * drawer
-){
-
- MT_assert(m_drawer == NULL);
- m_drawer = drawer;
-}
-
- void
-GlutDrawManager::
-ReleaseDrawer(
-){
- m_drawer = NULL;
-}
-
-
-GlutDrawManager::
-~GlutDrawManager(
-){
-
- delete(m_drawer);
-}
-
-
-
-
-
-
-
-
-
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h
deleted file mode 100644
index 05d2424dfea..00000000000
--- a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __GLUTDRAWER_H__
-#define __GLUTDRAWER_H__
-
-#include "MEM_NonCopyable.h"
-#include "MEM_SmartPtr.h"
-
-// So pissed off with Glut callback stuff
-// that is impossible to call objects unless they are global
-
-// inherit from GlutDrawer and installl the drawer in the singleton
-// class GlutDrawManager.
-
-class GlutDrawer {
-public :
-
- virtual
- void
- Draw(
- )= 0;
-
- virtual
- ~GlutDrawer(
- ){};
-};
-
-class GlutDrawManager : public MEM_NonCopyable{
-
-public :
-
- static
- GlutDrawManager *
- Instance(
- );
-
- // this is the function you should pass to glut
-
- static
- void
- Draw(
- );
-
- void
- InstallDrawer(
- GlutDrawer *
- );
-
- void
- ReleaseDrawer(
- );
-
- ~GlutDrawManager(
- );
-
-private :
-
- GlutDrawManager (
- ) :
- m_drawer (0)
- {
- };
-
- GlutDrawer * m_drawer;
-
- static MEM_SmartPtr<GlutDrawManager> m_s_instance;
-};
-
-#endif
-
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp
deleted file mode 100644
index 0b7a16b032b..00000000000
--- a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "GlutKeyboardManager.h"
-#include "MT_assert.h"
-
-MEM_SmartPtr<GlutKeyboardManager> GlutKeyboardManager::m_s_instance = MEM_SmartPtr<GlutKeyboardManager>();
-
- GlutKeyboardManager *
-GlutKeyboardManager::
-Instance(
-){
- if (m_s_instance == NULL) {
- m_s_instance = new GlutKeyboardManager();
- }
-
- return m_s_instance;
-}
-
-
-// this is the function you should pass to glut
-
- void
-GlutKeyboardManager::
-HandleKeyboard(
- unsigned char key,
- int x,
- int y
-){
- GlutKeyboardManager *manager = GlutKeyboardManager::Instance();
-
- if (manager->m_handler != NULL) {
- manager->m_handler->HandleKeyboard(key,x,y);
- }
-}
-
- void
-GlutKeyboardManager::
-InstallHandler(
- GlutKeyboardHandler * handler
-){
-
- MT_assert(m_handler == NULL);
- m_handler = handler;
-}
-
- void
-GlutKeyboardManager::
-ReleaseHandler(
-){
- m_handler = NULL;
-}
-
-
-GlutKeyboardManager::
-~GlutKeyboardManager(
-){
-
- delete(m_handler);
-}
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h
deleted file mode 100644
index ea39b6835f6..00000000000
--- a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __GLUTKEYBOARDMANAGER_H__
-#define __GLUTKEYBOARDMANAGER_H__
-
-#include "MEM_NonCopyable.h"
-#include "MEM_SmartPtr.h"
-
-// So pissed off with Glut callback stuff
-// that is impossible to call objects unless they are global
-
-// inherit from GlutKeyboardHandler and installl the drawer in the singleton
-// class GlutKeyboardManager.
-
-class GlutKeyboardHandler : public MEM_NonCopyable {
-public :
-
- virtual
- void
- HandleKeyboard(
- unsigned char key,
- int x,
- int y
- )= 0;
-
- virtual
- ~GlutKeyboardHandler(
- ){};
-};
-
-class GlutKeyboardManager : public MEM_NonCopyable{
-
-public :
-
- static
- GlutKeyboardManager *
- Instance(
- );
-
- // this is the function you should pass to glut
-
- static
- void
- HandleKeyboard(
- unsigned char key,
- int x,
- int y
- );
-
- void
- InstallHandler(
- GlutKeyboardHandler *
- );
-
- void
- ReleaseHandler(
- );
-
- ~GlutKeyboardManager(
- );
-
-private :
-
- GlutKeyboardManager (
- ) :
- m_handler (0)
- {
- };
-
- GlutKeyboardHandler * m_handler;
-
- static MEM_SmartPtr<GlutKeyboardManager> m_s_instance;
-};
-
-#endif
-
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp
deleted file mode 100644
index c426f933e67..00000000000
--- a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "GlutMouseManager.h"
-#include "MT_assert.h"
-
-MEM_SmartPtr<GlutMouseManager> GlutMouseManager::m_s_instance = MEM_SmartPtr<GlutMouseManager>();
-
-
- GlutMouseManager *
-GlutMouseManager::
-Instance(
-){
- if (m_s_instance == NULL) {
- m_s_instance = new GlutMouseManager();
- }
-
- return m_s_instance;
-}
-
-// these are the functions you should pass to GLUT
-
- void
-GlutMouseManager::
-Mouse(
- int button,
- int state,
- int x,
- int y
-){
- GlutMouseManager *manager = GlutMouseManager::Instance();
-
- if (manager->m_handler != NULL) {
- manager->m_handler->Mouse(button,state,x,y);
- }
-}
-
- void
-GlutMouseManager::
-Motion(
- int x,
- int y
-){
- GlutMouseManager *manager = GlutMouseManager::Instance();
-
- if (manager->m_handler != NULL) {
- manager->m_handler->Motion(x,y);
- }
-}
-
- void
-GlutMouseManager::
-InstallHandler(
- GlutMouseHandler *handler
-){
-
- MT_assert(m_handler == NULL);
- m_handler = handler;
-}
-
- void
-GlutMouseManager::
-ReleaseHandler(
-){
- m_handler = NULL;
-}
-
-GlutMouseManager::
-~GlutMouseManager(
-){
-
- delete(m_handler);
-}
-
-
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h
deleted file mode 100644
index 4a2344b7c74..00000000000
--- a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __GLUTMOUSEMANAGER_H__
-#define __GLUTMOUSEMANAGER_H__
-
-#include "MEM_NonCopyable.h"
-#include "MEM_SmartPtr.h"
-
-class GlutMouseHandler {
-public :
-
- virtual
- void
- Mouse(
- int button,
- int state,
- int x,
- int y
- ) = 0;
-
- virtual
- void
- Motion(
- int x,
- int y
- ) = 0;
-
- virtual
- ~GlutMouseHandler(
- ){};
-};
-
-class GlutMouseManager : public MEM_NonCopyable{
-
-public :
-
- static
- GlutMouseManager *
- Instance(
- );
-
- // these are the functions you should pass to GLUT
-
- static
- void
- Mouse(
- int button,
- int state,
- int x,
- int y
- );
-
- static
- void
- Motion(
- int x,
- int y
- );
-
- void
- InstallHandler(
- GlutMouseHandler *
- );
-
- void
- ReleaseHandler(
- );
-
- ~GlutMouseManager(
- );
-
-private :
-
- GlutMouseManager (
- ) :
- m_handler (0)
- {
- };
-
- GlutMouseHandler * m_handler;
-
- static MEM_SmartPtr<GlutMouseManager> m_s_instance;
-};
-
-#endif
-
diff --git a/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h b/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h
deleted file mode 100644
index f2863806112..00000000000
--- a/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h
+++ /dev/null
@@ -1,375 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __CHAINDRAWER_H__
-#define __CHAINDRAWER_H__
-
-#include "../common/GlutDrawer.h"
-#include "MyGlutMouseHandler.h"
-#include "MyGlutKeyHandler.h"
-#include "MT_Transform.h"
-# include "IK_Qsolver.h"
-# include "../intern/IK_QChain.h"
-# include "../intern/IK_QSolver_Class.h"
-#include <GL/glut.h>
-
-class ChainDrawer : public GlutDrawer
-{
-public :
- static
- ChainDrawer *
- New(
- ) {
- return new ChainDrawer();
- }
-
- void
- SetMouseHandler(
- MyGlutMouseHandler *mouse_handler
- ) {
- m_mouse_handler = mouse_handler;
- }
-
- void
- SetKeyHandler (
- MyGlutKeyHandler *key_handler
- ) {
- m_key_handler = key_handler;
- }
-
- void
- SetChain(
- IK_Chain_ExternPtr *chains,int chain_num
- ) {
- m_chain_num = chain_num;
- m_chains = chains;
- }
-
-
- // inherited from GlutDrawer
- void
- Draw(
- ) {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glPopMatrix();
- glPushMatrix();
- glRotatef(m_mouse_handler->AngleX(), 0.0, 1.0, 0.0);
- glRotatef(m_mouse_handler->AngleY(), 1.0, 0.0, 0.0);
-
- DrawScene();
- glutSwapBuffers();
-
- }
-
- ~ChainDrawer(
- ){
- // nothing to do
- };
-
-private :
-
- void
- DrawScene(
- ){
-
- // draw a little cross at the position of the key handler
- // coordinates
-
- MT_Vector3 line_x(4,0,0);
- MT_Vector3 line_y(0.0,4,0);
- MT_Vector3 line_z(0.0,0.0,4);
-
- MT_Vector3 cross_origin = m_mouse_handler->Position();
- MT_Vector3 temp;
-
- glDisable(GL_LIGHTING);
-
-
- glBegin(GL_LINES);
-
- glColor3f (1.0f,1.0f,1.0f);
-
- temp = cross_origin - line_x;
- glVertex3f(temp[0],temp[1],temp[2]);
- temp = cross_origin + line_x;
- glVertex3f(temp[0],temp[1],temp[2]);
-
- temp = cross_origin - line_y;
- glVertex3f(temp[0],temp[1],temp[2]);
- temp = cross_origin + line_y;
- glVertex3f(temp[0],temp[1],temp[2]);
-
- temp = cross_origin - line_z;
- glVertex3f(temp[0],temp[1],temp[2]);
- temp = cross_origin + line_z;
- glVertex3f(temp[0],temp[1],temp[2]);
-
- glEnd();
- glEnable(GL_LIGHTING);
-
-
- IK_Chain_ExternPtr chain;
-
- int chain_num;
- for (chain_num = 0; chain_num < m_chain_num; chain_num++) {
- chain = m_chains[chain_num];
-
-
- IK_Segment_ExternPtr segs = chain->segments;
- IK_Segment_ExternPtr seg_start = segs;
- const IK_Segment_ExternPtr seg_end = segs + chain->num_segments;
- float ogl_matrix[16];
-
- glColor3f (0.0f,1.0f,0.0f);
-
- MT_Vector3 previous_origin(0,0,0);
-
- MT_Transform global_transform;
- global_transform.setIdentity();
-
- for (; seg_start != seg_end; ++seg_start) {
-
- glPushMatrix();
-
- // fill ogl_matrix with zeros
-
- std::fill(ogl_matrix,ogl_matrix + 16,float(0));
-
- // we have to do a bit of work here to compute the chain's
- // bone values
-
- // first compute all the matrices we need
-
- MT_Transform translation;
- translation.setIdentity();
- translation.translate(MT_Vector3(0,seg_start->length,0));
-
- MT_Matrix3x3 seg_rot(
- seg_start->basis_change[0],seg_start->basis_change[1],seg_start->basis_change[2],
- seg_start->basis_change[3],seg_start->basis_change[4],seg_start->basis_change[5],
- seg_start->basis_change[6],seg_start->basis_change[7],seg_start->basis_change[8]
- );
-
- seg_rot.transpose();
-
- MT_Matrix3x3 seg_pre_rot(
- seg_start->basis[0],seg_start->basis[1],seg_start->basis[2],
- seg_start->basis[3],seg_start->basis[4],seg_start->basis[5],
- seg_start->basis[6],seg_start->basis[7],seg_start->basis[8]
- );
-
-
- MT_Transform seg_t_pre_rot(
- MT_Point3(
- seg_start->seg_start[0],
- seg_start->seg_start[1],
- seg_start->seg_start[2]
- ),
- seg_pre_rot
- );
- // start of the bone is just the current global transform
- // multiplied by the seg_start vector
-
-
-
- MT_Transform seg_t_rot(MT_Point3(0,0,0),seg_rot);
- MT_Transform seg_local = seg_t_pre_rot * seg_t_rot * translation;
-
- MT_Vector3 bone_start = global_transform *
- MT_Point3(
- seg_start->seg_start[0],
- seg_start->seg_start[1],
- seg_start->seg_start[2]
- );
-
-
- global_transform = global_transform * seg_local;
-
- global_transform.getValue(ogl_matrix);
- MT_Vector3 bone_end = global_transform.getOrigin();
-
- glMultMatrixf(ogl_matrix);
-// glutSolidSphere(0.5,5,5);
-
- glPopMatrix();
-
- glDisable(GL_LIGHTING);
-
- glBegin(GL_LINES);
-
- // draw lines of the principle axis of the local transform
-
- MT_Vector3 x_axis(1,0,0);
- MT_Vector3 y_axis(0,1,0);
- MT_Vector3 z_axis(0,0,1);
-
- x_axis = global_transform.getBasis() * x_axis * 5;
- y_axis = global_transform.getBasis() * y_axis * 5;
- z_axis = global_transform.getBasis() * z_axis * 5;
-
-
- x_axis = x_axis + bone_start;
- y_axis = y_axis + bone_start;
- z_axis = z_axis + bone_start;
-
- glColor3f(1,0,0);
-
- glVertex3f(x_axis.x(),x_axis.y(),x_axis.z());
- glVertex3f(
- bone_start.x(),
- bone_start.y(),
- bone_start.z()
- );
-
- glColor3f(0,1,0);
-
- glVertex3f(y_axis.x(),y_axis.y(),y_axis.z());
- glVertex3f(
- bone_start.x(),
- bone_start.y(),
- bone_start.z()
- );
-
- glColor3f(0,1,1);
-
- glVertex3f(z_axis.x(),z_axis.y(),z_axis.z());
- glVertex3f(
- bone_start.x(),
- bone_start.y(),
- bone_start.z()
- );
-
- glColor3f(0,0,1);
-
- glVertex3f(
- bone_start.x(),
- bone_start.y(),
- bone_start.z()
- );
- glVertex3f(bone_end[0],bone_end[1],bone_end[2]);
-
- glEnd();
- glEnable(GL_LIGHTING);
- }
-#if 0
- // draw jacobian column vectors
-
- // hack access to internals
-
- IK_Solver_Class * internals = static_cast<IK_Solver_Class *>(chain->intern);
-
- glDisable(GL_LIGHTING);
-
- glBegin(GL_LINES);
-
- const TNT::Matrix<MT_Scalar> & jac = internals->Chain().TransposedJacobian();
-
- int i = 0;
- for (i=0; i < jac.num_rows(); i++) {
- glColor3f(1,1,1);
-
- previous_origin = internals->Chain().Segments()[i/3].GlobalSegmentStart();
-
- glVertex3f(previous_origin[0],previous_origin[1],previous_origin[2]);
- glVertex3f(jac[i][0] + previous_origin[0],jac[i][1] + previous_origin[1],jac[i][2] + previous_origin[2]);
-
-
- }
- glEnd();
- glEnable(GL_LIGHTING);
-#endif
-
- }
-
- glColor3f(1.0,1.0,1.0);
-
- glDisable(GL_LIGHTING);
- glBegin(GL_LINES);
-
- MT_Scalar cube_size = 50;
- glVertex3f(cube_size,cube_size,cube_size);
- glVertex3f(-cube_size,cube_size,cube_size);
-
- glVertex3f(cube_size,-cube_size,cube_size);
- glVertex3f(-cube_size,-cube_size,cube_size);
-
- glVertex3f(cube_size,cube_size,-cube_size);
- glVertex3f(-cube_size,cube_size,-cube_size);
-
- glVertex3f(cube_size,-cube_size,-cube_size);
- glVertex3f(-cube_size,-cube_size,-cube_size);
-
-
- glVertex3f(-cube_size,cube_size,cube_size);
- glVertex3f(-cube_size,-cube_size,cube_size);
-
- glVertex3f(cube_size,cube_size,-cube_size);
- glVertex3f(cube_size,-cube_size,-cube_size);
-
- glVertex3f(cube_size,cube_size,cube_size);
- glVertex3f(cube_size,-cube_size,cube_size);
-
- glVertex3f(-cube_size,cube_size,-cube_size);
- glVertex3f(-cube_size,-cube_size,-cube_size);
-
-
- glVertex3f(cube_size,cube_size,cube_size);
- glVertex3f(cube_size,cube_size,-cube_size);
-
- glVertex3f(cube_size,-cube_size,cube_size);
- glVertex3f(cube_size,-cube_size,-cube_size);
-
- glVertex3f(-cube_size,cube_size,cube_size);
- glVertex3f(-cube_size,cube_size,-cube_size);
-
- glVertex3f(-cube_size,-cube_size,cube_size);
- glVertex3f(-cube_size,-cube_size,-cube_size);
- glEnd();
- glEnable(GL_LIGHTING);
-
- };
-
-
-
-private :
-
- MyGlutMouseHandler * m_mouse_handler;
- MyGlutKeyHandler *m_key_handler;
- IK_Chain_ExternPtr *m_chains;
-
- int m_chain_num;
- ChainDrawer (
- ) : m_chains (NULL),
- m_mouse_handler (NULL),
- m_chain_num (0)
- {
- };
-
-};
-
-#endif
-
diff --git a/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h b/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h
deleted file mode 100644
index 621e0d32869..00000000000
--- a/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __MYGLUTKEYHANDLER_H__
-#define __MYGLUTKEYHANDLER_H__
-
-#include "../common/GlutKeyboardManager.h"
-
-class MyGlutKeyHandler : public GlutKeyboardHandler
-{
-public :
- static
- MyGlutKeyHandler *
- New(
- ) {
- MEM_SmartPtr<MyGlutKeyHandler> output = new MyGlutKeyHandler();
-
- if (output == NULL
- ) {
- return NULL;
- }
- return output.Release();
-
- }
-
- void
- HandleKeyboard(
- unsigned char key,
- int x,
- int y
- ){
-
- switch (key) {
-
- case 27 :
-
- exit(0);
- }
- }
-
- ~MyGlutKeyHandler(
- )
- {
- };
-
-private :
-
- MyGlutKeyHandler(
- )
- {
- }
-
-};
-
-#endif
-
diff --git a/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h b/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h
deleted file mode 100644
index 205ce38ac23..00000000000
--- a/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __MYGLUTMOUSEHANDLER_H__
-#define __MYGLUTMOUSEHANDLER_H__
-
-#include "../common/GlutMouseManager.h"
-#include <GL/glut.h>
-#include "IK_solver.h"
-
-class MyGlutMouseHandler : public GlutMouseHandler
-{
-
-public :
-
- static
- MyGlutMouseHandler *
- New(
- ) {
- MEM_SmartPtr<MyGlutMouseHandler> output = new MyGlutMouseHandler();
- if (output == NULL
- ) {
- return NULL;
- }
- return output.Release();
-
- }
-
- void
- SetChain(
- IK_Chain_ExternPtr *chains, int num_chains
- ){
- m_chains = chains;
- m_num_chains = num_chains;
- }
-
- void
- Mouse(
- int button,
- int state,
- int x,
- int y
- ){
- if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
- m_moving = true;
- m_begin_x = x;
- m_begin_y = y;
- }
- if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
- m_moving = false;
- }
-
- if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
- m_tracking = true;
- }
- if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP) {
- m_tracking = false;
- }
-
- if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) {
- m_cg_on = true;
- }
- if (button == GLUT_MIDDLE_BUTTON && state == GLUT_UP) {
- m_cg_on = false;
- }
-
- }
-
-
- void
- Motion(
- int x,
- int y
- ){
- if (m_moving) {
- m_angle_x = m_angle_x + (x - m_begin_x);
- m_begin_x = x;
-
- m_angle_y = m_angle_y + (y - m_begin_y);
- m_begin_y = y;
-
- glutPostRedisplay();
- }
- if (m_tracking) {
-
- int w_h = glutGet((GLenum)GLUT_WINDOW_HEIGHT);
-
- y = w_h - y;
-
- double mvmatrix[16];
- double projmatrix[16];
- GLint viewport[4];
-
- double px, py, pz,sz;
-
- /* Get the matrices needed for gluUnProject */
- glGetIntegerv(GL_VIEWPORT, viewport);
- glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
- glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
-
- // work out the position of the end effector in screen space
-
- GLdouble ex,ey,ez;
- ex = m_pos.x();
- ey = m_pos.y();
- ez = m_pos.z();
-
- gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz);
- gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz);
-
- m_pos = MT_Vector3(px,py,pz);
-
- }
- if (m_tracking || m_cg_on) {
- float temp[3];
- m_pos.getValue(temp);
-
- IK_SolveChain(m_chains[0],temp,0.01,200,0.1,m_chains[1]->segments);
- IK_LoadChain(m_chains[0],m_chains[0]->segments,m_chains[0]->num_segments);
-
- glutPostRedisplay();
- }
-
-
- }
-
- const
- float
- AngleX(
- ) const {
- return m_angle_x;
- }
-
- const
- float
- AngleY(
- ) const {
- return m_angle_y;
- }
-
- const
- MT_Vector3
- Position(
- ) const {
- return m_pos;
- }
-
-
-private :
-
- MyGlutMouseHandler (
- ) :
- m_angle_x(0),
- m_angle_y(0),
- m_begin_x(0),
- m_begin_y(0),
- m_moving (false),
- m_tracking (false),
- m_pos(0,0,0),
- m_cg_on (false),
- m_chains(NULL),
- m_num_chains(0)
- {
- };
-
- float m_angle_x;
- float m_angle_y;
- float m_begin_x;
- float m_begin_y;
-
- bool m_moving;
- bool m_tracking;
- bool m_cg_on;
- MT_Vector3 m_pos;
-
- IK_Chain_ExternPtr *m_chains;
- int m_num_chains;
-
-};
-
-#endif
-
diff --git a/intern/iksolver/test/ik_glut_test/intern/main.cpp b/intern/iksolver/test/ik_glut_test/intern/main.cpp
deleted file mode 100644
index bfb9d8fa1a0..00000000000
--- a/intern/iksolver/test/ik_glut_test/intern/main.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/**
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "MEM_SmartPtr.h"
-
-#ifdef USE_QUATERNIONS
-#include "IK_Qsolver.h"
-#else
-#include "IK_solver.h"
-#endif
-
-#include <GL/glut.h>
-#include "MT_Vector3.h"
-#include "MT_Quaternion.h"
-#include "MT_Matrix3x3.h"
-#include "MyGlutMouseHandler.h"
-#include "MyGlutKeyHandler.h"
-#include "ChainDrawer.h"
-
-void init(MT_Vector3 min,MT_Vector3 max)
-{
- GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 1.0}; /* Red diffuse light. */
- GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
-
- GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 1.0}; /* Red diffuse light. */
- GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */
-
- /* Enable a single OpenGL light. */
- glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
- glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
-
- glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
- glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
-
- glEnable(GL_LIGHT0);
- glEnable(GL_LIGHT1);
- glEnable(GL_LIGHTING);
-
- /* Use depth buffering for hidden surface elimination. */
- glEnable(GL_DEPTH_TEST);
-
- /* Setup the view of the cube. */
- glMatrixMode(GL_PROJECTION);
-
- // center of the box + 3* depth of box
-
- MT_Vector3 center = (min + max) * 0.5;
- MT_Vector3 diag = max - min;
-
- float depth = diag.length();
- float distance = 2;
-
- gluPerspective(/* field of view in degree */ 40.0,
- /* aspect ratio */ 1.0,
- /* Z near */ 1.0,
- /* Z far */ distance * depth * 2
- );
- glMatrixMode(GL_MODELVIEW);
-
-
- gluLookAt(center.x(), center.y(), center.z() + distance*depth, /* eye is at (0,0,5) */
- center.x(), center.y(), center.z(), /* center is at (0,0,0) */
- 0.0, 1.0, 0.); /* up is in positive Y direction */
-
- glPushMatrix();
-
-
-}
-
-int main(int argc, char **argv)
-{
-
-
- const int seg_num = 5;
- const MT_Scalar seg_length = 15;
-
- const float seg_startA[3] = {0,0,0};
- const float seg_startB[3] = {0,-20,0};
-
- // create some segments to solve with
-
- // First chain
- //////////////
-
-
- IK_Segment_ExternPtr const segmentsA = new IK_Segment_Extern[seg_num];
- IK_Segment_ExternPtr const segmentsB = new IK_Segment_Extern[seg_num];
-
- IK_Segment_ExternPtr seg_it = segmentsA;
- IK_Segment_ExternPtr seg_itB = segmentsB;
-
-
- {
-
-// MT_Quaternion qmat(MT_Vector3(0,0,1),-3.141/2);
- MT_Quaternion qmat(MT_Vector3(0,0,1),0);
- MT_Matrix3x3 mat(qmat);
-
- seg_it->seg_start[0] = seg_startA[0];
- seg_it->seg_start[1] = seg_startA[1];
- seg_it->seg_start[2] = seg_startA[2];
-
- float temp[12];
- mat.getValue(temp);
-
- seg_it->basis[0] = temp[0];
- seg_it->basis[1] = temp[1];
- seg_it->basis[2] = temp[2];
-
- seg_it->basis[3] = temp[4];
- seg_it->basis[4] = temp[5];
- seg_it->basis[5] = temp[6];
-
- seg_it->basis[6] = temp[8];
- seg_it->basis[7] = temp[9];
- seg_it->basis[8] = temp[10];
-
- seg_it->length = seg_length;
-
- MT_Quaternion q;
- q.setEuler(0,0,0);
-
-
- MT_Matrix3x3 qrot(q);
-
- seg_it->basis_change[0] = 1;
- seg_it->basis_change[1] = 0;
- seg_it->basis_change[2] = 0;
- seg_it->basis_change[3] = 0;
- seg_it->basis_change[4] = 1;
- seg_it->basis_change[5] = 0;
- seg_it->basis_change[6] = 0;
- seg_it->basis_change[7] = 0;
- seg_it->basis_change[8] = 1;
-
-
- seg_it ++;
-
- seg_itB->seg_start[0] = seg_startA[0];
- seg_itB->seg_start[1] = seg_startA[1];
- seg_itB->seg_start[2] = seg_startA[2];
-
- seg_itB->basis[0] = temp[0];
- seg_itB->basis[1] = temp[1];
- seg_itB->basis[2] = temp[2];
-
- seg_itB->basis[3] = temp[4];
- seg_itB->basis[4] = temp[5];
- seg_itB->basis[5] = temp[6];
-
- seg_itB->basis[6] = temp[8];
- seg_itB->basis[7] = temp[9];
- seg_itB->basis[8] = temp[10];
-
- seg_itB->length = seg_length;
-
- seg_itB->basis_change[0] = 1;
- seg_itB->basis_change[1] = 0;
- seg_itB->basis_change[2] = 0;
- seg_itB->basis_change[3] = 0;
- seg_itB->basis_change[4] = 1;
- seg_itB->basis_change[5] = 0;
- seg_itB->basis_change[6] = 0;
- seg_itB->basis_change[7] = 0;
- seg_itB->basis_change[8] = 1;
-
-
- seg_itB ++;
-
-
- }
-
-
- int i;
- for (i=1; i < seg_num; ++i, ++seg_it,++seg_itB) {
-
- MT_Quaternion qmat(MT_Vector3(0,0,1),0.3);
- MT_Matrix3x3 mat(qmat);
-
- seg_it->seg_start[0] = 0;
- seg_it->seg_start[1] = 0;
- seg_it->seg_start[2] = 0;
-
- float temp[12];
- mat.getValue(temp);
-
- seg_it->basis[0] = temp[0];
- seg_it->basis[1] = temp[1];
- seg_it->basis[2] = temp[2];
-
- seg_it->basis[3] = temp[4];
- seg_it->basis[4] = temp[5];
- seg_it->basis[5] = temp[6];
-
- seg_it->basis[6] = temp[8];
- seg_it->basis[7] = temp[9];
- seg_it->basis[8] = temp[10];
-
- seg_it->length = seg_length;
-
- MT_Quaternion q;
- q.setEuler(0,0,0);
-
-
- MT_Matrix3x3 qrot(q);
-
- seg_it->basis_change[0] = 1;
- seg_it->basis_change[1] = 0;
- seg_it->basis_change[2] = 0;
- seg_it->basis_change[3] = 0;
- seg_it->basis_change[4] = 1;
- seg_it->basis_change[5] = 0;
- seg_it->basis_change[6] = 0;
- seg_it->basis_change[7] = 0;
- seg_it->basis_change[8] = 1;
-
-
- ///////////////////////////////
-
- seg_itB->seg_start[0] = 0;
- seg_itB->seg_start[1] = 0;
- seg_itB->seg_start[2] = 0;
-
- seg_itB->basis[0] = temp[0];
- seg_itB->basis[1] = temp[1];
- seg_itB->basis[2] = temp[2];
-
- seg_itB->basis[3] = temp[4];
- seg_itB->basis[4] = temp[5];
- seg_itB->basis[5] = temp[6];
-
- seg_itB->basis[6] = temp[8];
- seg_itB->basis[7] = temp[9];
- seg_itB->basis[8] = temp[10];
-
- seg_itB->length = seg_length;
-
- seg_itB->basis_change[0] = 1;
- seg_itB->basis_change[1] = 0;
- seg_itB->basis_change[2] = 0;
- seg_itB->basis_change[3] = 0;
- seg_itB->basis_change[4] = 1;
- seg_itB->basis_change[5] = 0;
- seg_itB->basis_change[6] = 0;
- seg_itB->basis_change[7] = 0;
- seg_itB->basis_change[8] = 1;
-
-
-
- }
-
- // create the chains
-
- const int num_chains = 2;
-
- IK_Chain_ExternPtr chains[num_chains];
-
- chains[0] = IK_CreateChain();
- chains[1] = IK_CreateChain();
-
- // load segments into chain
-
- IK_LoadChain(chains[0],segmentsA,seg_num);
- IK_LoadChain(chains[1],segmentsB,seg_num);
-
- // make and install a mouse handler
-
- MEM_SmartPtr<MyGlutMouseHandler> mouse_handler (MyGlutMouseHandler::New());
- GlutMouseManager::Instance()->InstallHandler(mouse_handler);
-
- mouse_handler->SetChain(chains,num_chains);
-
- // make and install a keyhandler
- MEM_SmartPtr<MyGlutKeyHandler> key_handler (MyGlutKeyHandler::New());
- GlutKeyboardManager::Instance()->InstallHandler(key_handler);
-
- // instantiate the drawing class
-
- MEM_SmartPtr<ChainDrawer> drawer (ChainDrawer::New());
- GlutDrawManager::Instance()->InstallDrawer(drawer);
-
- drawer->SetMouseHandler(mouse_handler);
- drawer->SetChain(chains,num_chains);
- drawer->SetKeyHandler(key_handler);
-
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
- glutCreateWindow("ik");
- glutDisplayFunc(GlutDrawManager::Draw);
- glutMouseFunc(GlutMouseManager::Mouse);
- glutMotionFunc(GlutMouseManager::Motion);
- glutKeyboardFunc(GlutKeyboardManager::HandleKeyboard);
-
- init(MT_Vector3(-50,-50,-50),MT_Vector3(50,50,50));
- glutMainLoop();
- return 0; /* ANSI C requires main to return int. */
-}
diff --git a/intern/memutil/CMakeLists.txt b/intern/memutil/CMakeLists.txt
index 3f9f8d6fe25..82e968853f4 100644
--- a/intern/memutil/CMakeLists.txt
+++ b/intern/memutil/CMakeLists.txt
@@ -39,11 +39,8 @@ set(SRC
MEM_Allocator.h
MEM_CacheLimiter.h
MEM_CacheLimiterC-Api.h
- MEM_NonCopyable.h
- MEM_RefCountPtr.h
MEM_RefCounted.h
MEM_RefCountedC-Api.h
- MEM_SmartPtr.h
)
blender_add_lib(bf_intern_memutil "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/memutil/MEM_NonCopyable.h b/intern/memutil/MEM_NonCopyable.h
deleted file mode 100644
index 9378ea7b69d..00000000000
--- a/intern/memutil/MEM_NonCopyable.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file memutil/MEM_NonCopyable.h
- * \ingroup memutil
- */
-
-/**
- * @file MEM_NonCopyable.h
- * Declaration of MEM_NonCopyable class.
- */
-
-#ifndef __MEM_NONCOPYABLE_H__
-#define __MEM_NONCOPYABLE_H__
-
-/**
- * Simple class that makes sure sub classes cannot
- * generate standard copy constructors.
- * If you want to make sure that your class does
- * not have any of these cheesy hidden constructors
- * inherit from this class.
- */
-
-class MEM_NonCopyable {
-protected :
-
- MEM_NonCopyable(
- ) {
- };
-
-private :
-
- MEM_NonCopyable (const MEM_NonCopyable *);
- MEM_NonCopyable (const MEM_NonCopyable &);
-};
-
-#endif
-
diff --git a/intern/memutil/MEM_RefCountPtr.h b/intern/memutil/MEM_RefCountPtr.h
deleted file mode 100644
index ea865eadd47..00000000000
--- a/intern/memutil/MEM_RefCountPtr.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file memutil/MEM_RefCountPtr.h
- * \ingroup memutil
- */
-
-/**
- * \file MEM_RefCountPtr.h
- * Declaration of MEM_RefCounted and MEM_RefCountable classes.
- * \author Laurence
- */
-
-#ifndef __MEM_REFCOUNTPTR_H__
-#define __MEM_REFCOUNTPTR_H__
-
-#include <stdlib.h> // for NULL !
-
-/**
- * \section MEM_RefCountable
- * This is a base class for reference countable objects.
- * If you want an object to be shared using a reference
- * counted system derrivce from this class. All subclasses
- * should insist that they are created on the heap, this
- * can be done by makeing all constructors private and
- * defining a static New() method that returns a ref counted
- * ptr to a new()ly allocated instance.
- *
- * \section Example subclass
- *
- * \code{.cpp}
- * class MySharedObject : public MEM_RefCountable {
- *
- * private :
- * MySharedObject() : MEM_RefCountable() { //class specific initialization};
- * MySharedObject(const MySharedObject &other) // not implemented
- * public :
- * static
- * MEM_RefCountPtr<MySharedObject>
- * New(
- * ) {
- * return MEM_RefCountPtr<MySharedObject>( new MySharedObject());
- * }
- *
- * // other member functions
- * };
- * \endcode
- *
- * Alternitively you may first wish to define a fully functional
- * class and then define a reference counting wrapper for this class.
- * This is useful when the base type can be used without reference
- * counting.
- *
- * E.g.
- *
- * \code{.cpp}
- * class UsefullClass {
- * private :
- * ...
- * public :
- *
- * UsefullClass()
- * UsefullMethod(...)
- * AnotherUsefullMethod(...)
- * };
- *
- * class RcUsefullClass : public UsefullClass, public MEM_RefCountable
- * {
- * private :
- * // Override base class public constructor --- forces
- * // use of New(...)
- * RcUsefullClass(...)
- * public :
- *
- * // Override each public constructor of UsefullClass with
- * // an equivalent static New method returning a MEM_RefCountPtr
- *
- * static
- * MEM_RefCountPtr<RcUsefullClass>
- * New(...) {
- * return MEM_RefCountPtr<RcUsefullClass> output(
- * new UsefullClass(...)
- * );
- * }
- *
- * // warning never call destructor directly allow ref counting
- * // mechanism to handle object lifetime.
- * ~RcUsefullClass();
- * };
- * \endcode
- *
- */
-
-class MEM_RefCountable {
-private :
-
- /**
- * The reference count!
- * We use mutable here because we would like to
- * share references of const objects!
- * Maybe should think about having decRef()
- * another value because we should not be deleting
- * non-const objects
- */
-
- mutable int m_count;
-
-protected :
-
- /**
- * Protected constructors
- * This class is not for direct instantiation. Sub classes
- * should only be allocated on the heap.
- */
-
- MEM_RefCountable (
- ) :
- m_count (0)
- {
- };
-
- MEM_RefCountable (
- const MEM_RefCountable &
- ) :
- m_count (0)
- {
- }
-
-public :
-
- void
- IncRef(
- ) const {
- m_count++;
- }
-
- int
- DecRef(
- ) {
- return (--m_count);
- }
-
- ~MEM_RefCountable(
- ) {
- //nothing to do
- }
-};
-
-/**
- * \section MEM_RefCountPtr
- */
-
-template
- < class T >
-class MEM_RefCountPtr {
-
-public :
-
- /**
- * Construction from reference - share ownership with
- * the right hand side.
- */
-
- MEM_RefCountPtr(
- const MEM_RefCountPtr &rhs
- ) : m_val (NULL) {
- ShareOwnership(rhs.m_val);
- }
-
- /**
- * Construction from ptr - this class shares
- * ownership of object val.
- */
-
- MEM_RefCountPtr(
- const T* val
- ) :
- m_val (NULL)
- {
- ShareOwnership(val);
- }
-
- /**
- * Default constructor
- */
-
- MEM_RefCountPtr(
- ) :
- m_val (NULL)
- {
- }
-
- /**
- * Type conversion from this class to the type
- * of a pointer to the template parameter.
- * This means you can pass an instance of this class
- * to a function expecting a ptr of type T.
- */
-
- operator T * () const {
- return m_val;
- }
-
-
- MEM_RefCountPtr & operator=(
- const MEM_RefCountPtr &rhs
- ) {
- if (this->m_val != rhs.m_val) {
- ReleaseOwnership();
- ShareOwnership(rhs.m_val);
- }
- return *this;
- }
-
- /**
- * Overload the operator -> so that it's possible to access
- * all the normal methods of the internal ptr.
- */
-
- T * operator->() const {
- return m_val;
- }
-
- /**
- * Returrn a reference to the shared object.
- */
-
- T&
- Ref(
- ) {
- return *m_val;
- }
-
-
- /**
- * Destructor - deletes object if it's ref count is zero.
- */
-
- ~MEM_RefCountPtr(
- ) {
- ReleaseOwnership();
- }
-
-private :
-
- /// The ptr owned by this class.
- T * m_val;
-
- void
- ShareOwnership(
- const T * val
- ) {
- if (val != NULL) {
- val->IncRef();
- }
- m_val = const_cast<T *>(val);
- }
-
- void
- ReleaseOwnership(
- ) {
- if (m_val) {
- if (m_val->DecRef() == 0) {
- delete(m_val);
- m_val = NULL;
- }
- }
- }
-
-};
-
-#endif
-
diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h
deleted file mode 100644
index e0d7b81290f..00000000000
--- a/intern/memutil/MEM_SmartPtr.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file memutil/MEM_SmartPtr.h
- * \ingroup memutil
- */
-
-/**
- * @file MEM_SmartPtr.h
- * Declaration of MEM_RefCounted and MEM_RefCountable classes.
- * @author Laurence
- */
-
-#ifndef __MEM_SMARTPTR_H__
-#define __MEM_SMARTPTR_H__
-
-
-#include <stdlib.h> // for NULL !
-
-
-/**
- * \section MEM_SmartPtr
- * This class defines a smart pointer similar to that defined in
- * the Standard Template Library but without the painful get()
- * semantics to access the internal c style pointer.
- *
- * It is often useful to explicitly declare ownership of memory
- * allocated on the heap within class or function scope. This
- * class helps you to encapsulate this ownership within a value
- * type. When an instance of this class goes out of scope it
- * makes sure that any memory associated with it's internal pointer
- * is deleted. It can help to inform users of an aggregate class
- * that it owns instances of it's members and these instances
- * should not be shared. This is not reliably enforceable in C++
- * but this class attempts to make the 1-1 relationship clear.
- *
- * \section Example usage
- *
- * \code{.cpp}
- * class foo {
- * ...constructors accessors etc.
- * int x[1000];
- * }
- *
- * class bar {
- * public :
- * static
- * bar *
- * New(
- * ) {
- * MEM_SmartPtr<foo> afoo = new foo();
- * MEM_SmartPtr<bar> that = new bar();
- *
- * if (foo == NULL || that == NULL) return NULL;
- *
- * that->m_foo = afoo.Release();
- * return that.Release();
- * }
- *
- * ~bar() {
- * // smart ptr takes care of deletion
- * }
- * private :
- * MEM_SmartPtr<foo> m_foo;
- * }
- * \endcode
- *
- * You may also safely construct vectors of MEM_SmartPtrs and
- * have the vector own stuff you put into it.
- *
- * e.g.
- * \code{.cpp}
- * {
- * std::vector<MEM_SmartPtr<foo> > foo_vector;
- * foo_vector.push_back( new foo());
- * foo_vector.push_back( new foo());
- *
- * foo_vector[0]->bla();
- * } // foo_vector out of scope => heap memory freed for both foos
- * \endcode
- *
- * @warning this class should only be used for objects created
- * on the heap via the new function. It will not behave correctly
- * if you pass ptrs to objects created with new[] nor with
- * objects declared on the stack. Doing this is likely to crash
- * the program or lead to memory leaks.
- */
-
-template
- < class T >
-class MEM_SmartPtr {
-
-public :
-
- /**
- * Construction from reference - this class
- * always assumes ownership from the rhs.
- */
-
- MEM_SmartPtr(
- const MEM_SmartPtr &rhs
- ) {
- m_val = rhs.Release();
- }
-
- /**
- * Construction from ptr - this class always
- * assumes that it now owns the memory associated with the
- * ptr.
- */
-
- MEM_SmartPtr(
- T* val
- ) :
- m_val (val)
- {
- }
-
- /**
- * Defalut constructor
- */
-
- MEM_SmartPtr(
- ) :
- m_val (NULL)
- {
- }
-
- /**
- * Type conversion from this class to the type
- * of a pointer to the template parameter.
- * This means you can pass an instance of this class
- * to a function expecting a ptr of type T.
- */
-
- operator T * () const {
- return m_val;
- }
-
- /**
- * Return a reference to the internal ptr class.
- * Use with care when you now that the internal ptr
- * is not NULL!
- */
-
- T &
- Ref(
- ) const {
- return *m_val;
- }
-
- /**
- * Assignment operator - ownership is transferred from rhs to lhs.
- * There is an intenional side-effect of function of transferring
- * ownership from the const parameter rhs. This is to insure
- * the 1-1 relationship.
- * The object associated with this instance is deleted if it
- * is not the same as that contained in the rhs.
- */
-
- MEM_SmartPtr & operator=(
- const MEM_SmartPtr &rhs
- ) {
- if (this->m_val != rhs.m_val) {
- delete this->m_val;
- }
-
- this->m_val = rhs.Release();
- return *this;
- }
-
- /**
- * Overload the operator -> so that it's possible to access
- * all the normal methods of the internal ptr.
- */
-
- T * operator->() const {
- return m_val;
- }
-
- /**
- * Caller takes ownership of the object - the object will not
- * be deleted when the ptr goes out of scope.
- */
-
- T *
- Release(
- ) const {
- T* temp = m_val;
- (const_cast<MEM_SmartPtr *>(this))->m_val = NULL;
- return temp;
- }
-
- /**
- * Force destruction of the internal object.
- */
-
- void
- Delete(
- ) {
- delete (m_val);
- m_val = NULL;
- }
-
- /**
- * Destructor - deletes object if it exists
- */
-
- ~MEM_SmartPtr(
- ) {
- delete (m_val);
- }
-
-private :
-
- /// The ptr owned by this class.
- T * m_val;
-};
-
-#endif
-
diff --git a/intern/moto/CMakeLists.txt b/intern/moto/CMakeLists.txt
index 8075c66b847..d17181c6809 100644
--- a/intern/moto/CMakeLists.txt
+++ b/intern/moto/CMakeLists.txt
@@ -36,7 +36,6 @@ set(SRC
intern/MT_CmMatrix4x4.cpp
intern/MT_Matrix3x3.cpp
intern/MT_Matrix4x4.cpp
- intern/MT_Plane3.cpp
intern/MT_Point3.cpp
intern/MT_Quaternion.cpp
intern/MT_Transform.cpp
@@ -45,14 +44,11 @@ set(SRC
intern/MT_Vector4.cpp
intern/MT_random.cpp
- include/GEN_List.h
- include/GEN_Map.h
include/MT_CmMatrix4x4.h
include/MT_Matrix3x3.h
include/MT_Matrix4x4.h
include/MT_MinMax.h
include/MT_Optimize.h
- include/MT_Plane3.h
include/MT_Point2.h
include/MT_Point3.h
include/MT_Quaternion.h
@@ -67,11 +63,9 @@ set(SRC
include/MT_Vector4.h
include/MT_assert.h
include/MT_random.h
- include/NM_Scalar.h
include/MT_Matrix3x3.inl
include/MT_Matrix4x4.inl
- include/MT_Plane3.inl
include/MT_Point2.inl
include/MT_Point3.inl
include/MT_Quaternion.inl
diff --git a/intern/moto/include/GEN_List.h b/intern/moto/include/GEN_List.h
deleted file mode 100644
index 3aefe5e060c..00000000000
--- a/intern/moto/include/GEN_List.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file moto/include/GEN_List.h
- * \ingroup moto
- */
-
-
-#ifndef GEN_LIST_H
-#define GEN_LIST_H
-
-class GEN_Link {
-public:
- GEN_Link() : m_next(0), m_prev(0) {}
- GEN_Link(GEN_Link *next, GEN_Link *prev) : m_next(next), m_prev(prev) {}
-
- GEN_Link *getNext() const { return m_next; }
- GEN_Link *getPrev() const { return m_prev; }
-
- bool isHead() const { return m_prev == 0; }
- bool isTail() const { return m_next == 0; }
-
- void insertBefore(GEN_Link *link) {
- m_next = link;
- m_prev = link->m_prev;
- m_next->m_prev = this;
- m_prev->m_next = this;
- }
-
- void insertAfter(GEN_Link *link) {
- m_next = link->m_next;
- m_prev = link;
- m_next->m_prev = this;
- m_prev->m_next = this;
- }
-
- void remove() {
- m_next->m_prev = m_prev;
- m_prev->m_next = m_next;
- }
-
-private:
- GEN_Link *m_next;
- GEN_Link *m_prev;
-};
-
-class GEN_List {
-public:
- GEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
-
- GEN_Link *getHead() const { return m_head.getNext(); }
- GEN_Link *getTail() const { return m_tail.getPrev(); }
-
- void addHead(GEN_Link *link) { link->insertAfter(&m_head); }
- void addTail(GEN_Link *link) { link->insertBefore(&m_tail); }
-
-private:
- GEN_Link m_head;
- GEN_Link m_tail;
-};
-
-#endif
-
diff --git a/intern/moto/include/GEN_Map.h b/intern/moto/include/GEN_Map.h
deleted file mode 100644
index 526bfdc8caf..00000000000
--- a/intern/moto/include/GEN_Map.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file moto/include/GEN_Map.h
- * \ingroup moto
- */
-
-
-#ifndef GEN_MAP_H
-#define GEN_MAP_H
-
-template <class Key, class Value>
-class GEN_Map {
-private:
- struct Entry {
- Entry (Entry *next, Key key, Value value) :
- m_next(next),
- m_key(key),
- m_value(value) {}
-
- Entry *m_next;
- Key m_key;
- Value m_value;
- };
-
-public:
- GEN_Map(int num_buckets = 100) : m_num_buckets(num_buckets) {
- m_buckets = new Entry *[num_buckets];
- for (int i = 0; i < num_buckets; ++i) {
- m_buckets[i] = 0;
- }
- }
-
- GEN_Map(const GEN_Map& map)
- {
- m_num_buckets = map.m_num_buckets;
- m_buckets = new Entry *[m_num_buckets];
-
- for (int i = 0; i < m_num_buckets; ++i) {
- m_buckets[i] = 0;
-
- for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next)
- insert(entry->m_key, entry->m_value);
- }
- }
-
- int size() {
- int count=0;
- for (int i=0;i<m_num_buckets;i++)
- {
- Entry* bucket = m_buckets[i];
- while(bucket)
- {
- bucket = bucket->m_next;
- count++;
- }
- }
- return count;
- }
-
- Value* at(int index) {
- int count=0;
- for (int i=0;i<m_num_buckets;i++)
- {
- Entry* bucket = m_buckets[i];
- while(bucket)
- {
- if (count==index)
- {
- return &bucket->m_value;
- }
- bucket = bucket->m_next;
- count++;
- }
- }
- return 0;
- }
-
- Key* getKey(int index) {
- int count=0;
- for (int i=0;i<m_num_buckets;i++)
- {
- Entry* bucket = m_buckets[i];
- while(bucket)
- {
- if (count==index)
- {
- return &bucket->m_key;
- }
- bucket = bucket->m_next;
- count++;
- }
- }
- return 0;
- }
-
- void clear() {
- for (int i = 0; i < m_num_buckets; ++i) {
- Entry *entry_ptr = m_buckets[i];
-
- while (entry_ptr != 0) {
- Entry *tmp_ptr = entry_ptr->m_next;
- delete entry_ptr;
- entry_ptr = tmp_ptr;
- }
- m_buckets[i] = 0;
- }
- }
-
- ~GEN_Map() {
- clear();
- delete [] m_buckets;
- }
-
- void insert(const Key& key, const Value& value) {
- Entry *entry_ptr = m_buckets[key.hash() % m_num_buckets];
- while ((entry_ptr != 0) && !(key == entry_ptr->m_key)) {
- entry_ptr = entry_ptr->m_next;
- }
-
- if (entry_ptr != 0) {
- entry_ptr->m_value = value;
- }
- else {
- Entry **bucket = &m_buckets[key.hash() % m_num_buckets];
- *bucket = new Entry(*bucket, key, value);
- }
- }
-
- void remove(const Key& key) {
- Entry **entry_ptr = &m_buckets[key.hash() % m_num_buckets];
- while ((*entry_ptr != 0) && !(key == (*entry_ptr)->m_key)) {
- entry_ptr = &(*entry_ptr)->m_next;
- }
-
- if (*entry_ptr != 0) {
- Entry *tmp_ptr = (*entry_ptr)->m_next;
- delete *entry_ptr;
- *entry_ptr = tmp_ptr;
- }
- }
-
- Value *operator[](Key key) {
- Entry *bucket = m_buckets[key.hash() % m_num_buckets];
- while ((bucket != 0) && !(key == bucket->m_key)) {
- bucket = bucket->m_next;
- }
- return bucket != 0 ? &bucket->m_value : 0;
- }
-
-private:
- int m_num_buckets;
- Entry **m_buckets;
-};
-
-#endif
-
diff --git a/intern/moto/include/MT_Plane3.h b/intern/moto/include/MT_Plane3.h
deleted file mode 100644
index f208b377a81..00000000000
--- a/intern/moto/include/MT_Plane3.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file moto/include/MT_Plane3.h
- * \ingroup moto
- */
-
-
-#ifndef MT_PLANE3
-#define MT_PLANE3
-
-#include "MT_Tuple4.h"
-#include "MT_Point3.h"
-
-/**
- * A simple 3d plane class.
- *
- * This class represents a plane in 3d. The internal parameterization used
- * is n.x + d =0 where n is a unit vector and d is a scalar.
- *
- * It inherits data from MT_Tuple4 please see this class for low level
- * access to the internal representation.
- *
- */
-
-class MT_Plane3 : public MT_Tuple4
-{
-public :
- /**
- * Constructor from 3 points
- */
-
- MT_Plane3(
- const MT_Vector3 &a,
- const MT_Vector3 &b,
- const MT_Vector3 &c
- );
- /**
- * Construction from vector and a point.
- */
-
- MT_Plane3(
- const MT_Vector3 &n,
- const MT_Vector3 &p
- );
-
- /**
- * Default constructor
- */
- MT_Plane3(
- );
-
- /**
- * Default constructor
- */
-
- MT_Plane3(
- const MT_Plane3 & p
- ):
- MT_Tuple4(p)
- {
- }
-
- /**
- * Return plane normal
- */
-
- MT_Vector3
- Normal(
- ) const;
-
- /**
- * Return plane scalar i.e the d from n.x + d = 0
- */
-
- MT_Scalar
- Scalar(
- ) const ;
-
- /**
- * Invert the plane - just swaps direction of normal.
- */
- void
- Invert(
- );
-
- /**
- * Assignment operator
- */
-
- MT_Plane3 &
- operator = (
- const MT_Plane3 & rhs
- );
-
- /**
- * Return the signed perpendicular distance from a point to the plane
- */
-
- MT_Scalar
- signedDistance(
- const MT_Vector3 &
- ) const;
-
-
-};
-
-#ifdef GEN_INLINED
-#include "MT_Plane3.inl"
-#endif
-
-#endif
-
diff --git a/intern/moto/include/MT_Plane3.inl b/intern/moto/include/MT_Plane3.inl
deleted file mode 100644
index 77db9b35e1d..00000000000
--- a/intern/moto/include/MT_Plane3.inl
+++ /dev/null
@@ -1,128 +0,0 @@
-#include "MT_Optimize.h"
-
-
-GEN_INLINE
-MT_Plane3::
-MT_Plane3(
- const MT_Vector3 &a,
- const MT_Vector3 &b,
- const MT_Vector3 &c
-){
- MT_Vector3 l1 = b-a;
- MT_Vector3 l2 = c-b;
-
- MT_Vector3 n = l1.cross(l2);
- n = n.safe_normalized();
- MT_Scalar d = n.dot(a);
-
- m_co[0] = n.x();
- m_co[1] = n.y();
- m_co[2] = n.z();
- m_co[3] = -d;
-}
-
-/**
- * Construction from vector and a point.
- */
-GEN_INLINE
-MT_Plane3::
-MT_Plane3(
- const MT_Vector3 &n,
- const MT_Vector3 &p
-){
-
- MT_Vector3 mn = n.safe_normalized();
- MT_Scalar md = mn.dot(p);
-
- m_co[0] = mn.x();
- m_co[1] = mn.y();
- m_co[2] = mn.z();
- m_co[3] = -md;
-}
-
-
-/**
- * Default constructor
- */
-GEN_INLINE
-MT_Plane3::
-MT_Plane3(
-):
- MT_Tuple4()
-{
- m_co[0] = MT_Scalar(1);
- m_co[1] = MT_Scalar(0);
- m_co[2] = MT_Scalar(0);
- m_co[3] = MT_Scalar(0);
-}
-
-/**
- * Return plane normal
- */
-
-GEN_INLINE
- MT_Vector3
-MT_Plane3::
-Normal(
-) const {
- return MT_Vector3(m_co[0],m_co[1],m_co[2]);
-}
-
-/**
- * Return plane scalar i.e the d from n.x + d = 0
- */
-
-GEN_INLINE
- MT_Scalar
-MT_Plane3::
-Scalar(
-) const {
- return m_co[3];
-}
-
-GEN_INLINE
- void
-MT_Plane3::
-Invert(
-) {
- m_co[0] = -m_co[0];
- m_co[1] = -m_co[1];
- m_co[2] = -m_co[2];
- m_co[3] = -m_co[3];
-}
-
-
-/**
- * Assignment operator
- */
-
-GEN_INLINE
- MT_Plane3 &
-MT_Plane3::
-operator = (
- const MT_Plane3 & rhs
-) {
- m_co[0] = rhs.m_co[0];
- m_co[1] = rhs.m_co[1];
- m_co[2] = rhs.m_co[2];
- m_co[3] = rhs.m_co[3];
- return *this;
-}
-
-/**
- * Return the distance from a point to the plane
- */
-
-GEN_INLINE
- MT_Scalar
-MT_Plane3::
-signedDistance(
- const MT_Vector3 &v
-) const {
- return Normal().dot(v) + m_co[3];
-}
-
-
-
-
-
diff --git a/intern/moto/include/MT_Scalar.h b/intern/moto/include/MT_Scalar.h
index 5c4a5c2a44a..5e516292d77 100644
--- a/intern/moto/include/MT_Scalar.h
+++ b/intern/moto/include/MT_Scalar.h
@@ -51,7 +51,6 @@
#include <float.h>
#include "MT_random.h"
-#include "NM_Scalar.h"
typedef double MT_Scalar; //this should be float !
diff --git a/intern/moto/include/NM_Scalar.h b/intern/moto/include/NM_Scalar.h
deleted file mode 100644
index 0e33979c521..00000000000
--- a/intern/moto/include/NM_Scalar.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file moto/include/NM_Scalar.h
- * \ingroup moto
- */
-
-
-#include <math.h>
-#include <iostream>
-
-template <class T>
-class NM_Scalar {
-public:
- NM_Scalar() {}
- explicit NM_Scalar(T value, T error = 0.0) :
- m_value(value), m_error(error) {}
-
- T getValue() const { return m_value; }
- T getError() const { return m_error; }
-
- operator T() const { return m_value; }
-
- NM_Scalar operator-() const {
- return NM_Scalar<T>(-m_value, m_error);
- }
-
- NM_Scalar& operator=(T value) {
- m_value = value;
- m_error = 0.0;
- return *this;
- }
-
- NM_Scalar& operator+=(const NM_Scalar& x) {
- m_value += x.m_value;
- m_error = (fabs(m_value) * (m_error + 1.0) +
- fabs(x.m_value) * (x.m_error + 1.0)) /
- fabs(m_value + x.m_value);
- return *this;
- }
-
- NM_Scalar& operator-=(const NM_Scalar& x) {
- m_value -= x.m_value;
- m_error = (fabs(m_value) * (m_error + 1.0) +
- fabs(x.m_value) * (x.m_error + 1.0)) /
- fabs(m_value - x.m_value);
- return *this;
- }
-
- NM_Scalar& operator*=(const NM_Scalar& x) {
- m_value *= x.m_value;
- m_error += x.m_error + 1.0;
- return *this;
- }
-
- NM_Scalar& operator/=(const NM_Scalar& x) {
- m_value /= x.m_value;
- m_error += x.m_error + 1.0;
- return *this;
- }
-
-private:
- T m_value;
- T m_error;
-};
-
-template <class T>
-inline NM_Scalar<T> operator+(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
- return x.getValue() == 0.0 && y.getValue() == 0.0 ?
- NM_Scalar<T>(0.0, 0.0) :
- NM_Scalar<T>(x.getValue() + y.getValue(),
- (fabs(x.getValue()) * (x.getError() + 1.0) +
- fabs(y.getValue()) * (y.getError() + 1.0)) /
- fabs(x.getValue() + y.getValue()));
-}
-
-template <class T>
-inline NM_Scalar<T> operator-(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
- return x.getValue() == 0.0 && y.getValue() == 0.0 ?
- NM_Scalar<T>(0.0, 0.0) :
- NM_Scalar<T>(x.getValue() - y.getValue(),
- (fabs(x.getValue()) * (x.getError() + 1.0) +
- fabs(y.getValue()) * (y.getError() + 1.0)) /
- fabs(x.getValue() - y.getValue()));
-}
-
-template <class T>
-inline NM_Scalar<T> operator*(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
- return NM_Scalar<T>(x.getValue() * y.getValue(),
- x.getError() + y.getError() + 1.0);
-}
-
-template <class T>
-inline NM_Scalar<T> operator/(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
- return NM_Scalar<T>(x.getValue() / y.getValue(),
- x.getError() + y.getError() + 1.0);
-}
-
-template <class T>
-inline std::ostream& operator<<(std::ostream& os, const NM_Scalar<T>& x) {
- return os << x.getValue() << '[' << x.getError() << ']';
-}
-
-template <class T>
-inline NM_Scalar<T> sqrt(const NM_Scalar<T>& x) {
- return NM_Scalar<T>(sqrt(x.getValue()),
- 0.5 * x.getError() + 1.0);
-}
-
-template <class T>
-inline NM_Scalar<T> acos(const NM_Scalar<T>& x) {
- return NM_Scalar<T>(acos(x.getValue()), x.getError() + 1.0);
-}
-
-template <class T>
-inline NM_Scalar<T> cos(const NM_Scalar<T>& x) {
- return NM_Scalar<T>(cos(x.getValue()), x.getError() + 1.0);
-}
-
-template <class T>
-inline NM_Scalar<T> sin(const NM_Scalar<T>& x) {
- return NM_Scalar<T>(sin(x.getValue()), x.getError() + 1.0);
-}
-
-template <class T>
-inline NM_Scalar<T> fabs(const NM_Scalar<T>& x) {
- return NM_Scalar<T>(fabs(x.getValue()), x.getError());
-}
-
-template <class T>
-inline NM_Scalar<T> pow(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
- return NM_Scalar<T>(pow(x.getValue(), y.getValue()),
- fabs(y.getValue()) * x.getError() + 1.0);
-}
-
diff --git a/intern/moto/intern/MT_Plane3.cpp b/intern/moto/intern/MT_Plane3.cpp
deleted file mode 100644
index 22f7cfdbded..00000000000
--- a/intern/moto/intern/MT_Plane3.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file moto/intern/MT_Plane3.cpp
- * \ingroup moto
- */
-
-
-#ifndef GEN_INLINED
-#include "MT_Plane3.h"
-#include "MT_Plane3.inl"
-#endif
-
diff --git a/intern/opennl/CMakeLists.txt b/intern/opennl/CMakeLists.txt
deleted file mode 100644
index 9416bc2b9ea..00000000000
--- a/intern/opennl/CMakeLists.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# The Original Code is Copyright (C) 2006, Blender Foundation
-# All rights reserved.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): Jacques Beaurain.
-#
-# ***** END GPL LICENSE BLOCK *****
-
-# External project, better not fix warnings.
-remove_strict_flags()
-
-# remove debug flag here since this is not a blender maintained library
-# and debug gives a lot of prints on UV unwrapping. developers can enable if they need to.
-if(MSVC)
- remove_definitions(-DDEBUG)
-else()
- add_definitions(-UDEBUG)
-endif()
-
-
-# quiet compiler warnings about undefined defines
-add_definitions(
- -DDEBUGlevel=0
- -DPRNTlevel=0
-)
-
-set(INC
- extern
-)
-
-set(INC_SYS
- ../../extern/colamd/Include
- ../../extern/Eigen3
-)
-
-set(SRC
- intern/opennl.cpp
- extern/ONL_opennl.h
-)
-
-blender_add_lib(bf_intern_opennl "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/opennl/SConscript b/intern/opennl/SConscript
deleted file mode 100644
index 99df29b780a..00000000000
--- a/intern/opennl/SConscript
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env python
-#
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# The Original Code is Copyright (C) 2006, Blender Foundation
-# All rights reserved.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): Nathan Letwory.
-#
-# ***** END GPL LICENSE BLOCK *****
-
-Import ('env')
-
-sources = env.Glob('intern/*.cpp')
-
-incs = 'extern ../../extern/colamd/Include ../../extern/Eigen3'
-
-env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['intern','player'], priority=[100,90] )
-
diff --git a/intern/opennl/extern/ONL_opennl.h b/intern/opennl/extern/ONL_opennl.h
deleted file mode 100644
index a414f40824b..00000000000
--- a/intern/opennl/extern/ONL_opennl.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/** \file opennl/extern/ONL_opennl.h
- * \ingroup opennlextern
- */
-/*
- * OpenNL: Numerical Library
- * Copyright (C) 2004 Bruno Levy
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
- *
- * Contact: Bruno Levy
- *
- * levy@loria.fr
- *
- * ISA Project
- * LORIA, INRIA Lorraine,
- * Campus Scientifique, BP 239
- * 54506 VANDOEUVRE LES NANCY CEDEX
- * FRANCE
- *
- * Note that the GNU General Public License does not permit incorporating
- * the Software into proprietary programs.
- */
-
-#ifndef nlOPENNL_H
-#define nlOPENNL_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Datatypes */
-
-typedef unsigned int NLenum;
-typedef unsigned char NLboolean;
-typedef int NLint; /* 4-byte signed */
-typedef unsigned int NLuint; /* 4-byte unsigned */
-typedef double NLdouble; /* double precision float */
-
-typedef struct NLContext NLContext;
-
-/* Constants */
-
-#define NL_FALSE 0x0
-#define NL_TRUE 0x1
-
-/* Primitives */
-
-#define NL_SYSTEM 0x0
-#define NL_MATRIX 0x1
-
-/* Solver Parameters */
-
-#define NL_SOLVER 0x100
-#define NL_NB_VARIABLES 0x101
-#define NL_LEAST_SQUARES 0x102
-#define NL_ERROR 0x108
-#define NL_NB_ROWS 0x110
-#define NL_NB_RIGHT_HAND_SIDES 0x112 /* 4 max */
-
-/* Contexts */
-
-NLContext *nlNewContext(void);
-void nlDeleteContext(NLContext *context);
-
-/* State get/set */
-
-void nlSolverParameteri(NLContext *context, NLenum pname, NLint param);
-
-/* Variables */
-
-void nlSetVariable(NLContext *context, NLuint rhsindex, NLuint index, NLdouble value);
-NLdouble nlGetVariable(NLContext *context, NLuint rhsindex, NLuint index);
-void nlLockVariable(NLContext *context, NLuint index);
-void nlUnlockVariable(NLContext *context, NLuint index);
-
-/* Begin/End */
-
-void nlBegin(NLContext *context, NLenum primitive);
-void nlEnd(NLContext *context, NLenum primitive);
-
-/* Setting elements in matrix/vector */
-
-void nlMatrixAdd(NLContext *context, NLuint row, NLuint col, NLdouble value);
-void nlRightHandSideAdd(NLContext *context, NLuint rhsindex, NLuint index, NLdouble value);
-void nlRightHandSideSet(NLContext *context, NLuint rhsindex, NLuint index, NLdouble value);
-
-/* Solve */
-
-void nlPrintMatrix(NLContext *context);
-NLboolean nlSolve(NLContext *context, NLboolean solveAgain);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/intern/opennl/intern/opennl.cpp b/intern/opennl/intern/opennl.cpp
deleted file mode 100644
index 446a1a38f0d..00000000000
--- a/intern/opennl/intern/opennl.cpp
+++ /dev/null
@@ -1,479 +0,0 @@
-/** \file opennl/intern/opennl.c
- * \ingroup opennlintern
- */
-/*
- *
- * OpenNL: Numerical Library
- * Copyright (C) 2004 Bruno Levy
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
- *
- * Contact: Bruno Levy
- *
- * levy@loria.fr
- *
- * ISA Project
- * LORIA, INRIA Lorraine,
- * Campus Scientifique, BP 239
- * 54506 VANDOEUVRE LES NANCY CEDEX
- * FRANCE
- *
- * Note that the GNU General Public License does not permit incorporating
- * the Software into proprietary programs.
- */
-
-#include "ONL_opennl.h"
-
-#include <Eigen/Sparse>
-
-#include <algorithm>
-#include <cassert>
-#include <cstdlib>
-#include <iostream>
-#include <vector>
-
-/* Eigen data structures */
-
-typedef Eigen::SparseMatrix<double, Eigen::ColMajor> EigenSparseMatrix;
-typedef Eigen::SparseLU<EigenSparseMatrix> EigenSparseSolver;
-typedef Eigen::VectorXd EigenVectorX;
-typedef Eigen::Triplet<double> EigenTriplet;
-
-/* NLContext data structure */
-
-typedef struct {
- NLuint index;
- NLdouble value;
-} NLCoeff;
-
-typedef struct {
- NLdouble value[4];
- NLboolean locked;
- NLuint index;
- std::vector<NLCoeff> a;
-} NLVariable;
-
-#define NL_STATE_INITIAL 0
-#define NL_STATE_SYSTEM 1
-#define NL_STATE_MATRIX 2
-#define NL_STATE_MATRIX_CONSTRUCTED 3
-#define NL_STATE_SYSTEM_CONSTRUCTED 4
-#define NL_STATE_SYSTEM_SOLVED 5
-
-struct NLContext {
- NLContext()
- {
- state = NL_STATE_INITIAL;
- n = 0;
- m = 0;
- sparse_solver = NULL;
- nb_variables = 0;
- nb_rhs = 1;
- nb_rows = 0;
- least_squares = false;
- solve_again = false;
- }
-
- ~NLContext()
- {
- delete sparse_solver;
- }
-
- NLenum state;
-
- NLuint n;
- NLuint m;
-
- std::vector<EigenTriplet> Mtriplets;
- EigenSparseMatrix M;
- EigenSparseMatrix MtM;
- std::vector<EigenVectorX> b;
- std::vector<EigenVectorX> Mtb;
- std::vector<EigenVectorX> x;
-
- EigenSparseSolver *sparse_solver;
-
- NLuint nb_variables;
- std::vector<NLVariable> variable;
-
- NLuint nb_rows;
- NLuint nb_rhs;
-
- NLboolean least_squares;
- NLboolean solve_again;
-};
-
-NLContext *nlNewContext(void)
-{
- return new NLContext();
-}
-
-void nlDeleteContext(NLContext *context)
-{
- delete context;
-}
-
-static void __nlCheckState(NLContext *context, NLenum state)
-{
- assert(context->state == state);
-}
-
-static void __nlTransition(NLContext *context, NLenum from_state, NLenum to_state)
-{
- __nlCheckState(context, from_state);
- context->state = to_state;
-}
-
-/* Get/Set parameters */
-
-void nlSolverParameteri(NLContext *context, NLenum pname, NLint param)
-{
- __nlCheckState(context, NL_STATE_INITIAL);
- switch(pname) {
- case NL_NB_VARIABLES: {
- assert(param > 0);
- context->nb_variables = (NLuint)param;
- } break;
- case NL_NB_ROWS: {
- assert(param > 0);
- context->nb_rows = (NLuint)param;
- } break;
- case NL_LEAST_SQUARES: {
- context->least_squares = (NLboolean)param;
- } break;
- case NL_NB_RIGHT_HAND_SIDES: {
- context->nb_rhs = (NLuint)param;
- } break;
- default: {
- assert(0);
- } break;
- }
-}
-
-/* Get/Set Lock/Unlock variables */
-
-void nlSetVariable(NLContext *context, NLuint rhsindex, NLuint index, NLdouble value)
-{
- __nlCheckState(context, NL_STATE_SYSTEM);
- context->variable[index].value[rhsindex] = value;
-}
-
-NLdouble nlGetVariable(NLContext *context, NLuint rhsindex, NLuint index)
-{
- assert(context->state != NL_STATE_INITIAL);
- return context->variable[index].value[rhsindex];
-}
-
-void nlLockVariable(NLContext *context, NLuint index)
-{
- __nlCheckState(context, NL_STATE_SYSTEM);
- context->variable[index].locked = true;
-}
-
-void nlUnlockVariable(NLContext *context, NLuint index)
-{
- __nlCheckState(context, NL_STATE_SYSTEM);
- context->variable[index].locked = false;
-}
-
-/* System construction */
-
-static void __nlVariablesToVector(NLContext *context)
-{
- NLuint i, j, nb_rhs;
-
- nb_rhs= context->nb_rhs;
-
- for(i=0; i<context->nb_variables; i++) {
- NLVariable* v = &(context->variable[i]);
- if(!v->locked) {
- for(j=0; j<nb_rhs; j++)
- context->x[j][v->index] = v->value[j];
- }
- }
-}
-
-static void __nlVectorToVariables(NLContext *context)
-{
- NLuint i, j, nb_rhs;
-
- nb_rhs= context->nb_rhs;
-
- for(i=0; i<context->nb_variables; i++) {
- NLVariable* v = &(context->variable[i]);
- if(!v->locked) {
- for(j=0; j<nb_rhs; j++)
- v->value[j] = context->x[j][v->index];
- }
- }
-}
-
-static void __nlBeginSystem(NLContext *context)
-{
- assert(context->nb_variables > 0);
-
- if (context->solve_again)
- __nlTransition(context, NL_STATE_SYSTEM_SOLVED, NL_STATE_SYSTEM);
- else {
- __nlTransition(context, NL_STATE_INITIAL, NL_STATE_SYSTEM);
-
- context->variable.resize(context->nb_variables);
- }
-}
-
-static void __nlEndSystem(NLContext *context)
-{
- __nlTransition(context, NL_STATE_MATRIX_CONSTRUCTED, NL_STATE_SYSTEM_CONSTRUCTED);
-}
-
-static void __nlBeginMatrix(NLContext *context)
-{
- NLuint i;
- NLuint m = 0, n = 0;
-
- __nlTransition(context, NL_STATE_SYSTEM, NL_STATE_MATRIX);
-
- if (!context->solve_again) {
- for(i=0; i<context->nb_variables; i++) {
- if(context->variable[i].locked)
- context->variable[i].index = ~0;
- else
- context->variable[i].index = n++;
- }
-
- m = (context->nb_rows == 0)? n: context->nb_rows;
-
- context->m = m;
- context->n = n;
-
- /* reserve reasonable estimate */
- context->Mtriplets.clear();
- context->Mtriplets.reserve(std::max(m, n)*3);
-
- context->b.resize(context->nb_rhs);
- context->x.resize(context->nb_rhs);
-
- for (i=0; i<context->nb_rhs; i++) {
- context->b[i].setZero(m);
- context->x[i].setZero(n);
- }
- }
- else {
- /* need to recompute b only, A is not constructed anymore */
- for (i=0; i<context->nb_rhs; i++)
- context->b[i].setZero(context->m);
- }
-
- __nlVariablesToVector(context);
-}
-
-static void __nlEndMatrixRHS(NLContext *context, NLuint rhs)
-{
- NLVariable *variable;
- NLuint i, j;
-
- EigenVectorX& b = context->b[rhs];
-
- for(i=0; i<context->nb_variables; i++) {
- variable = &(context->variable[i]);
-
- if(variable->locked) {
- std::vector<NLCoeff>& a = variable->a;
-
- for(j=0; j<a.size(); j++) {
- b[a[j].index] -= a[j].value*variable->value[rhs];
- }
- }
- }
-
- if(context->least_squares)
- context->Mtb[rhs] = context->M.transpose() * b;
-}
-
-static void __nlEndMatrix(NLContext *context)
-{
- __nlTransition(context, NL_STATE_MATRIX, NL_STATE_MATRIX_CONSTRUCTED);
-
- if(!context->solve_again) {
- context->M.resize(context->m, context->n);
- context->M.setFromTriplets(context->Mtriplets.begin(), context->Mtriplets.end());
- context->Mtriplets.clear();
-
- if(context->least_squares) {
- context->MtM = context->M.transpose() * context->M;
-
- context->Mtb.resize(context->nb_rhs);
- for (NLuint rhs=0; rhs<context->nb_rhs; rhs++)
- context->Mtb[rhs].setZero(context->n);
- }
- }
-
- for (NLuint rhs=0; rhs<context->nb_rhs; rhs++)
- __nlEndMatrixRHS(context, rhs);
-}
-
-void nlMatrixAdd(NLContext *context, NLuint row, NLuint col, NLdouble value)
-{
- __nlCheckState(context, NL_STATE_MATRIX);
-
- if(context->solve_again)
- return;
-
- if (!context->least_squares && context->variable[row].locked);
- else if (context->variable[col].locked) {
- if(!context->least_squares)
- row = context->variable[row].index;
-
- NLCoeff coeff = {row, value};
- context->variable[col].a.push_back(coeff);
- }
- else {
- if(!context->least_squares)
- row = context->variable[row].index;
- col = context->variable[col].index;
-
- // direct insert into matrix is too slow, so use triplets
- EigenTriplet triplet(row, col, value);
- context->Mtriplets.push_back(triplet);
- }
-}
-
-void nlRightHandSideAdd(NLContext *context, NLuint rhsindex, NLuint index, NLdouble value)
-{
- __nlCheckState(context, NL_STATE_MATRIX);
-
- if(context->least_squares) {
- context->b[rhsindex][index] += value;
- }
- else {
- if(!context->variable[index].locked) {
- index = context->variable[index].index;
- context->b[rhsindex][index] += value;
- }
- }
-}
-
-void nlRightHandSideSet(NLContext *context, NLuint rhsindex, NLuint index, NLdouble value)
-{
- __nlCheckState(context, NL_STATE_MATRIX);
-
- if(context->least_squares) {
- context->b[rhsindex][index] = value;
- }
- else {
- if(!context->variable[index].locked) {
- index = context->variable[index].index;
- context->b[rhsindex][index] = value;
- }
- }
-}
-
-void nlBegin(NLContext *context, NLenum prim)
-{
- switch(prim) {
- case NL_SYSTEM: {
- __nlBeginSystem(context);
- } break;
- case NL_MATRIX: {
- __nlBeginMatrix(context);
- } break;
- default: {
- assert(0);
- }
- }
-}
-
-void nlEnd(NLContext *context, NLenum prim)
-{
- switch(prim) {
- case NL_SYSTEM: {
- __nlEndSystem(context);
- } break;
- case NL_MATRIX: {
- __nlEndMatrix(context);
- } break;
- default: {
- assert(0);
- }
- }
-}
-
-void nlPrintMatrix(NLContext *context)
-{
- std::cout << "A:" << context->M << std::endl;
-
- for(NLuint rhs=0; rhs<context->nb_rhs; rhs++)
- std::cout << "b " << rhs << ":" << context->b[rhs] << std::endl;
-
- if (context->MtM.rows() && context->MtM.cols())
- std::cout << "AtA:" << context->MtM << std::endl;
-}
-
-/* Solving */
-
-NLboolean nlSolve(NLContext *context, NLboolean solveAgain)
-{
- NLboolean result = true;
-
- __nlCheckState(context, NL_STATE_SYSTEM_CONSTRUCTED);
-
- if (!context->solve_again) {
- EigenSparseMatrix& M = (context->least_squares)? context->MtM: context->M;
-
- assert(M.rows() == M.cols());
-
- /* Convert M to compressed column format */
- M.makeCompressed();
-
- /* Perform sparse LU factorization */
- EigenSparseSolver *sparse_solver = new EigenSparseSolver();
- context->sparse_solver = sparse_solver;
-
- sparse_solver->analyzePattern(M);
- sparse_solver->factorize(M);
-
- result = (sparse_solver->info() == Eigen::Success);
-
- /* Free M, don't need it anymore at this point */
- M.resize(0, 0);
- }
-
- if (result) {
- /* Solve each right hand side */
- for(NLuint rhs=0; rhs<context->nb_rhs; rhs++) {
- EigenVectorX& b = (context->least_squares)? context->Mtb[rhs]: context->b[rhs];
- context->x[rhs] = context->sparse_solver->solve(b);
-
- if (context->sparse_solver->info() != Eigen::Success)
- result = false;
- }
-
- if (result) {
- __nlVectorToVariables(context);
-
- if (solveAgain)
- context->solve_again = true;
-
- __nlTransition(context, NL_STATE_SYSTEM_CONSTRUCTED, NL_STATE_SYSTEM_SOLVED);
- }
- }
-
- return result;
-}
-
diff --git a/intern/opensubdiv/gpu_shader_opensubd_display.glsl b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
index 57bbfa89714..51e8ed46c34 100644
--- a/intern/opensubdiv/gpu_shader_opensubd_display.glsl
+++ b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
@@ -70,7 +70,8 @@ void main()
#if __VERSION__ < 140
#extension GL_ARB_uniform_buffer_object: require
- #extension GL_ARB_texture_buffer_object: require
+ #extension GL_ARB_texture_buffer_object: enable
+ #extension GL_EXT_texture_buffer_object: enable
#endif
uniform mat4 modelViewMatrix;
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
index f715bf32565..6c226d6cf6b 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -296,8 +296,9 @@ const struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_getGLMeshTopologyRefine
int openSubdiv_supportGPUDisplay(void)
{
// TODO: simplify extension check once Blender adopts GL 3.2
- return (GLEW_VERSION_3_2 && GLEW_ARB_compatibility) ||
- (GLEW_VERSION_3_1 && GLEW_ARB_compatibility && GLEW_EXT_geometry_shader4) ||
- (GLEW_VERSION_3_0 && GLEW_EXT_geometry_shader4 && GLEW_ARB_uniform_buffer_object && GLEW_ARB_texture_buffer_object);
+ return GPU_legacy_support() &&
+ (GLEW_VERSION_3_2 ||
+ (GLEW_VERSION_3_1 && GLEW_EXT_geometry_shader4) ||
+ (GLEW_VERSION_3_0 && GLEW_EXT_geometry_shader4 && GLEW_ARB_uniform_buffer_object && (GLEW_ARB_texture_buffer_object || GLEW_EXT_texture_buffer_object)));
/* also ARB_explicit_attrib_location? */
}
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index 8010c39647d..9d1c1b3795c 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -144,6 +144,8 @@ int openSubdiv_getAvailableEvaluators(void);
void openSubdiv_init(void);
void openSubdiv_cleanup(void);
+extern bool GPU_legacy_support(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index fc46ad05f53..698fdfee00f 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -186,24 +186,12 @@ void transpose_m3(float mat[3][3])
GLuint compileShader(GLenum shaderType,
const char *section,
+ const char *version,
const char *define)
{
char sdefine[64];
sprintf(sdefine, "#define %s\n", section);
- const char *version;
- if (GLEW_VERSION_3_2 && GLEW_ARB_compatibility) {
- version = "#version 150 compatibility\n";
- }
- else if (GLEW_VERSION_3_1 && GLEW_ARB_compatibility) {
- version = "#version 140\n"
- "#extension GL_ARB_compatibility: enable\n";
- }
- else if (GLEW_VERSION_3_0) {
- version = "#version 130\n";
- /* minimum supported for OpenSubdiv */
- }
-
const char *sources[] = {
version,
define,
@@ -230,22 +218,25 @@ GLuint compileShader(GLenum shaderType,
return shader;
}
-GLuint linkProgram(const char *define)
+GLuint linkProgram(const char *version, const char *define)
{
GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
"VERTEX_SHADER",
+ version,
define);
if (vertexShader == 0) {
return 0;
}
GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
"GEOMETRY_SHADER",
+ version,
define);
if (geometryShader == 0) {
return 0;
}
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
"FRAGMENT_SHADER",
+ version,
define);
if (fragmentShader == 0) {
return 0;
@@ -261,7 +252,7 @@ GLuint linkProgram(const char *define)
glBindAttribLocation(program, 1, "normal");
- if (!(GLEW_VERSION_3_2 && GLEW_ARB_compatibility)) {
+ if (!GLEW_VERSION_3_2) {
/* provide input/output layout info */
glProgramParameteriEXT(program,
GL_GEOMETRY_INPUT_TYPE_EXT,
@@ -381,11 +372,29 @@ bool openSubdiv_osdGLDisplayInit(void)
static bool need_init = true;
static bool init_success = false;
if (need_init) {
- g_flat_fill_solid_program = linkProgram("#define FLAT_SHADING\n");
- g_flat_fill_texture2d_program = linkProgram("#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
- g_smooth_fill_solid_program = linkProgram("#define SMOOTH_SHADING\n");
- g_smooth_fill_texture2d_program = linkProgram("#define USE_TEXTURE_2D\n#define SMOOTH_SHADING\n");
- g_wireframe_program = linkProgram("#define WIREFRAME\n");
+
+ if (!openSubdiv_supportGPUDisplay()) {
+ return false;
+ }
+
+ const char *version = "";
+ if (GLEW_VERSION_3_2) {
+ version = "#version 150 compatibility\n";
+ }
+ else if (GLEW_VERSION_3_1) {
+ version = "#version 140\n"
+ "#extension GL_ARB_compatibility: enable\n";
+ }
+ else {
+ version = "#version 130\n";
+ /* minimum supported for OpenSubdiv */
+ }
+
+ g_flat_fill_solid_program = linkProgram(version, "#define FLAT_SHADING\n");
+ g_flat_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
+ g_smooth_fill_solid_program = linkProgram(version, "#define SMOOTH_SHADING\n");
+ g_smooth_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define SMOOTH_SHADING\n");
+ g_wireframe_program = linkProgram(version, "#define WIREFRAME\n");
glGenBuffers(1, &g_lighting_ub);
glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
diff --git a/intern/opensubdiv/opensubdiv_utils_capi.cc b/intern/opensubdiv/opensubdiv_utils_capi.cc
index aac1995bdfa..c993e347587 100644
--- a/intern/opensubdiv/opensubdiv_utils_capi.cc
+++ b/intern/opensubdiv/opensubdiv_utils_capi.cc
@@ -66,8 +66,7 @@ int openSubdiv_getAvailableEvaluators(void)
#endif /* OPENSUBDIV_HAS_OPENCL */
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
- if (GLEW_VERSION_3_0 || GLEW_ARB_texture_buffer_object) {
- // TODO(merwin): remove extension check once Blender moves to 3.2 core
+ if (GLEW_VERSION_4_1) {
flags |= OPENSUBDIV_EVALUATOR_GLSL_TRANSFORM_FEEDBACK;
}
#endif /* OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK */
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py
index 7e4c9e885e7..72233571702 100644
--- a/release/scripts/modules/bpy_extras/keyconfig_utils.py
+++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py
@@ -27,15 +27,11 @@ KM_HIERARCHY = [
('Window', 'EMPTY', 'WINDOW', []), # file save, window change, exit
('Screen', 'EMPTY', 'WINDOW', [ # full screen, undo, screenshot
('Screen Editing', 'EMPTY', 'WINDOW', []), # re-sizing, action corners
+ ('Header', 'EMPTY', 'WINDOW', []), # header stuff (per region)
]),
('View2D', 'EMPTY', 'WINDOW', []), # view 2d navigation (per region)
('View2D Buttons List', 'EMPTY', 'WINDOW', []), # view 2d with buttons navigation
- ('Header', 'EMPTY', 'WINDOW', []), # header stuff (per region)
-
- ('Grease Pencil', 'EMPTY', 'WINDOW', [ # grease pencil stuff (per region)
- ('Grease Pencil Stroke Edit Mode', 'EMPTY', 'WINDOW', []),
- ]),
('3D View', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform)
('Object Mode', 'EMPTY', 'WINDOW', []),
@@ -73,10 +69,6 @@ KM_HIERARCHY = [
('3D View Generic', 'VIEW_3D', 'WINDOW', []), # toolbar and properties
]),
- ('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
- ('Markers', 'EMPTY', 'WINDOW', []), # markers (per region)
- ('Animation', 'EMPTY', 'WINDOW', []), # frame change on click, preview range (per region)
- ('Animation Channels', 'EMPTY', 'WINDOW', []),
('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [
('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', []),
]),
@@ -85,15 +77,15 @@ KM_HIERARCHY = [
('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
('NLA Generic', 'NLA_EDITOR', 'WINDOW', []),
]),
+ ('Timeline', 'TIMELINE', 'WINDOW', []),
('Image', 'IMAGE_EDITOR', 'WINDOW', [
- ('UV Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
+ ('UV Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image)
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
('UV Sculpt', 'EMPTY', 'WINDOW', []),
('Image Generic', 'IMAGE_EDITOR', 'WINDOW', []),
]),
- ('Timeline', 'TIMELINE', 'WINDOW', []),
('Outliner', 'OUTLINER', 'WINDOW', []),
('Node Editor', 'NODE_EDITOR', 'WINDOW', [
@@ -122,9 +114,17 @@ KM_HIERARCHY = [
('Clip Editor', 'CLIP_EDITOR', 'WINDOW', []),
('Clip Graph Editor', 'CLIP_EDITOR', 'WINDOW', []),
('Clip Dopesheet Editor', 'CLIP_EDITOR', 'WINDOW', []),
- ('Mask Editing', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
]),
+ ('Grease Pencil', 'EMPTY', 'WINDOW', [ # grease pencil stuff (per region)
+ ('Grease Pencil Stroke Edit Mode', 'EMPTY', 'WINDOW', []),
+ ]),
+ ('Mask Editing', 'EMPTY', 'WINDOW', []),
+ ('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
+ ('Markers', 'EMPTY', 'WINDOW', []), # markers (per region)
+ ('Animation', 'EMPTY', 'WINDOW', []), # frame change on click, preview range (per region)
+ ('Animation Channels', 'EMPTY', 'WINDOW', []),
+
('View3D Gesture Circle', 'EMPTY', 'WINDOW', []),
('Gesture Straight Line', 'EMPTY', 'WINDOW', []),
('Gesture Zoom Border', 'EMPTY', 'WINDOW', []),
@@ -163,13 +163,12 @@ def _export_properties(prefix, properties, kmi_id, lines=None):
def string_value(value):
if isinstance(value, str) or isinstance(value, bool) or isinstance(value, float) or isinstance(value, int):
- result = repr(value)
+ return repr(value)
elif getattr(value, '__len__', False):
return repr(list(value))
- else:
- print("Export key configuration: can't write ", value)
- return result
+ print("Export key configuration: can't write ", value)
+ return ""
for pname in properties.bl_rna.properties.keys():
if pname != "rna_type":
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 92dbd2dbd0e..4f71cdf7588 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -21,8 +21,8 @@
from _bpy import types as bpy_types
import _bpy
-StructRNA = bpy_types.Struct.__bases__[0]
-StructMetaPropGroup = _bpy.StructMetaPropGroup
+StructRNA = bpy_types.bpy_struct
+StructMetaPropGroup = bpy_types.bpy_struct_meta_idprop
# StructRNA = bpy_types.Struct
bpy_types.BlendDataLibraries.load = _bpy._library_load
diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py
index 195b5767189..c0d92c331b7 100644
--- a/release/scripts/modules/rna_prop_ui.py
+++ b/release/scripts/modules/rna_prop_ui.py
@@ -41,7 +41,8 @@ def rna_idprop_ui_del(item):
def rna_idprop_ui_prop_update(item, prop):
prop_rna = item.path_resolve("[\"%s\"]" % prop.replace("\"", "\\\""), False)
- prop_rna.update()
+ if isinstance(prop_rna, bpy.types.bpy_prop):
+ prop_rna.update()
def rna_idprop_ui_prop_get(item, prop, create=True):
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 63c1945d2d2..daa8ab52766 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -169,14 +169,16 @@ class AddPresetBase:
if not filepath:
return {'CANCELLED'}
- if hasattr(self, "remove"):
- self.remove(context, filepath)
- else:
- try:
+ try:
+ if hasattr(self, "remove"):
+ self.remove(context, filepath)
+ else:
os.remove(filepath)
- except:
- import traceback
- traceback.print_exc()
+ except Exception as e:
+ self.report({'ERROR'}, "Unable to remove preset: %r" % e)
+ import traceback
+ traceback.print_exc()
+ return {'CANCELLED'}
# XXX, stupid!
preset_menu_class.bl_label = "Presets"
diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py
index 237c2d55672..750a5b0bf0f 100644
--- a/release/scripts/startup/bl_operators/rigidbody.py
+++ b/release/scripts/startup/bl_operators/rigidbody.py
@@ -163,7 +163,7 @@ class BakeToKeyframes(Operator):
elif rot_mode == 'AXIS_ANGLE':
# this is a little roundabout but there's no better way right now
aa = mat.to_quaternion().to_axis_angle()
- obj.rotation_axis_angle = (aa[1], ) + aa[0][:]
+ obj.rotation_axis_angle = (aa[1], *aa[0])
else: # euler
# make sure euler rotation is compatible to previous frame
# NOTE: assume that on first frame, the starting rotation is appropriate
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 58896e898c6..98570ca5280 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -156,6 +156,15 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.label(text="Object:")
col.prop(md, "object", text="")
+ layout.prop(md, "use_bmesh")
+ if md.use_bmesh:
+ box = layout.box()
+ box.label("BMesh Options:")
+ box.prop(md, "use_bmesh_separate")
+ box.prop(md, "use_bmesh_dissolve")
+ box.prop(md, "use_bmesh_connect_regions")
+ box.prop(md, "threshold")
+
def BUILD(self, layout, ob, md):
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index eb4625d2dac..b08bff13967 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -827,11 +827,13 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
layout.template_ID(strip, "scene")
scene = strip.scene
+ layout.prop(strip, "use_sequence")
- layout.label(text="Camera Override")
- layout.template_ID(strip, "scene_camera")
+ if not strip.use_sequence:
+ layout.label(text="Camera Override")
+ layout.template_ID(strip, "scene_camera")
- layout.prop(strip, "use_grease_pencil", text="Show Grease Pencil")
+ layout.prop(strip, "use_grease_pencil", text="Show Grease Pencil")
if scene:
layout.prop(scene, "audio_volume", text="Audio Volume")
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index d8b033b94e3..70cfec9c9b3 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -527,6 +527,7 @@ class USERPREF_PT_system(Panel):
column.separator()
column.prop(system, "font_path_ui")
+ column.prop(system, "font_path_ui_mono")
if bpy.app.build_options.international:
column.prop(system, "use_international_fonts")
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index a79e6d742ae..4dc4b667a63 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2416,6 +2416,7 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.operator("mesh.bevel").vertex_only = False
layout.operator("mesh.solidify")
layout.operator("mesh.intersect")
+ layout.operator("mesh.intersect_boolean")
layout.operator("mesh.wireframe")
layout.separator()
diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
index b72b2f76750..c4d661b4c1f 100644
--- a/release/scripts/templates_py/operator_modal_view3d_raycast.py
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -2,7 +2,7 @@ import bpy
from bpy_extras import view3d_utils
-def main(context, event, ray_max=1000.0):
+def main(context, event):
"""Run this function on left mouse, execute the ray cast"""
# get the context arguments
scene = context.scene
@@ -14,7 +14,7 @@ def main(context, event, ray_max=1000.0):
view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
- ray_target = ray_origin + (view_vector * ray_max)
+ ray_target = ray_origin + view_vector
def visible_objects_and_duplis():
"""Loop over (object, matrix) pairs (mesh only)"""
@@ -39,17 +39,18 @@ def main(context, event, ray_max=1000.0):
matrix_inv = matrix.inverted()
ray_origin_obj = matrix_inv * ray_origin
ray_target_obj = matrix_inv * ray_target
+ ray_direction_obj = ray_target_obj - ray_origin_obj
# cast the ray
- hit, normal, face_index = obj.ray_cast(ray_origin_obj, ray_target_obj)
+ success, location, normal, face_index = obj.ray_cast(ray_origin_obj, ray_direction_obj)
- if face_index != -1:
- return hit, normal, face_index
+ if success:
+ return location, normal, face_index
else:
return None, None, None
# cast rays and find the closest object
- best_length_squared = ray_max * ray_max
+ best_length_squared = -1.0
best_obj = None
for obj, matrix in visible_objects_and_duplis():
@@ -59,7 +60,7 @@ def main(context, event, ray_max=1000.0):
hit_world = matrix * hit
scene.cursor_location = hit_world
length_squared = (hit_world - ray_origin).length_squared
- if length_squared < best_length_squared:
+ if best_obj is None or length_squared < best_length_squared:
best_length_squared = length_squared
best_obj = obj
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index b7d72bb28bb..6c3fd090d4a 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -55,6 +55,8 @@
#include "IMB_colormanagement.h"
+#include "GPU_basic_shader.h"
+
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -486,7 +488,7 @@ void BLF_rotation_default(float angle)
}
}
-static void blf_draw_gl__start(FontBLF *font, GLint *mode, GLint *param)
+static void blf_draw_gl__start(FontBLF *font, GLint *mode)
{
/*
* The pixmap alignment hack is handle
@@ -494,9 +496,10 @@ static void blf_draw_gl__start(FontBLF *font, GLint *mode, GLint *param)
*/
glEnable(GL_BLEND);
- glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
+
/* Save the current matrix mode. */
glGetIntegerv(GL_MATRIX_MODE, mode);
@@ -523,19 +526,10 @@ static void blf_draw_gl__start(FontBLF *font, GLint *mode, GLint *param)
/* always bind the texture for the first glyph */
font->tex_bind_state = -1;
-
- /* Save the current parameter to restore it later. */
- glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
- if (*param != GL_MODULATE)
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
-static void blf_draw_gl__end(GLint mode, GLint param)
+static void blf_draw_gl__end(GLint mode)
{
- /* and restore the original value. */
- if (param != GL_MODULATE)
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
-
glMatrixMode(GL_TEXTURE);
glPopMatrix();
@@ -545,8 +539,8 @@ static void blf_draw_gl__end(GLint mode, GLint param)
if (mode != GL_MODELVIEW)
glMatrixMode(mode);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
}
void BLF_draw_ex(
@@ -554,19 +548,19 @@ void BLF_draw_ex(
struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
- GLint mode, param;
+ GLint mode;
BLF_RESULT_CHECK_INIT(r_info);
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode, &param);
+ blf_draw_gl__start(font, &mode);
if (font->flags & BLF_WORD_WRAP) {
blf_font_draw__wrap(font, str, len, r_info);
}
else {
blf_font_draw(font, str, len, r_info);
}
- blf_draw_gl__end(mode, param);
+ blf_draw_gl__end(mode);
}
}
void BLF_draw(int fontid, const char *str, size_t len)
@@ -579,12 +573,12 @@ void BLF_draw_ascii_ex(
struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
- GLint mode, param;
+ GLint mode;
BLF_RESULT_CHECK_INIT(r_info);
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode, &param);
+ blf_draw_gl__start(font, &mode);
if (font->flags & BLF_WORD_WRAP) {
/* use non-ascii draw function for word-wrap */
blf_font_draw__wrap(font, str, len, r_info);
@@ -592,7 +586,7 @@ void BLF_draw_ascii_ex(
else {
blf_font_draw_ascii(font, str, len, r_info);
}
- blf_draw_gl__end(mode, param);
+ blf_draw_gl__end(mode);
}
}
void BLF_draw_ascii(int fontid, const char *str, size_t len)
@@ -603,13 +597,13 @@ void BLF_draw_ascii(int fontid, const char *str, size_t len)
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
{
FontBLF *font = blf_get(fontid);
- GLint mode, param;
+ GLint mode;
int columns = 0;
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode, &param);
+ blf_draw_gl__start(font, &mode);
columns = blf_font_draw_mono(font, str, len, cwidth);
- blf_draw_gl__end(mode, param);
+ blf_draw_gl__end(mode);
}
return columns;
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 215d2484c18..1c13e42f70d 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -170,12 +170,12 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
glGenTextures(1, &gc->textures[gc->cur_tex]);
glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = gc->textures[gc->cur_tex]));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gc->p2_width, gc->p2_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, gc->p2_width, gc->p2_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
}
GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 2c6e37b9ed8..3eed4b5634b 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -151,7 +151,8 @@ typedef enum DMDrawFlag {
DM_DRAW_USE_TEXPAINT_UV = (1 << 3),
DM_DRAW_SKIP_HIDDEN = (1 << 4),
DM_DRAW_SKIP_SELECT = (1 << 5),
- DM_DRAW_SELECT_USE_EDITMODE = (1 << 6)
+ DM_DRAW_SELECT_USE_EDITMODE = (1 << 6),
+ DM_DRAW_NEED_NORMALS = (1 << 7)
} DMDrawFlag;
typedef enum DMForeachFlag {
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 607f2a98939..8734eac8f24 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 276
-#define BLENDER_SUBVERSION 2
+#define BLENDER_SUBVERSION 3
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 5
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index ea63161e008..ff0b5a1d4bf 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -221,7 +221,7 @@ void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima);
bool BKE_image_is_openexr(struct Image *ima);
/* for multiple slot render, call this before render */
-void BKE_image_backup_render(struct Scene *scene, struct Image *ima);
+void BKE_image_backup_render(struct Scene *scene, struct Image *ima, bool free_current_slot);
/* for singlelayer openexr saving */
bool BKE_image_save_openexr_multiview(struct Image *ima, struct ImBuf *ibuf, const char *filepath, const int flags);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 08a55036a03..5d03a42d118 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -206,6 +206,8 @@ typedef struct bNodeType {
/* can this node be added to a node tree */
int (*poll_instance)(struct bNode *node, struct bNodeTree *nodetree);
+ /* optional handling of link insertion */
+ void (*insert_link)(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
/* Update the internal links list, for muting and disconnect operators. */
void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 5dc5ebbbd4c..5d69cb51ab1 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -98,7 +98,7 @@ void BKE_pbvh_raycast(
bool original);
bool BKE_pbvh_node_raycast(
- PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
+ PBVH *bvh, PBVHNode *node, float (*origco)[3], bool use_origco,
const float ray_start[3], const float ray_normal[3],
float *dist);
@@ -210,7 +210,7 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *bvh);
void BKE_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]);
-void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***r_gridfaces, int *r_totface);
+void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface);
void BKE_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems,
void **gridfaces,
struct DMFlagMat *flagmats, unsigned int **grid_hidden);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 48616418e67..d05df3470b5 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -35,6 +35,7 @@
struct ARegion;
struct Header;
+struct ID;
struct ListBase;
struct Menu;
struct Panel;
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 11f2d0e0816..3f2712e0ae1 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -237,6 +237,7 @@ void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, str
void BKE_sequence_free(struct Scene *scene, struct Sequence *seq);
void BKE_sequence_free_anim(struct Sequence *seq);
const char *BKE_sequence_give_name(struct Sequence *seq);
+ListBase *BKE_sequence_seqbase_get(struct Sequence *seq, int *r_offset);
void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq);
void BKE_sequence_calc_disp(struct Scene *scene, struct Sequence *seq);
void BKE_sequence_reload_new_file(struct Scene *scene, struct Sequence *seq, const bool lock_range);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index c705c7adedb..e26e5148ff6 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -74,8 +74,8 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
#include "BLI_sys_types.h" /* for intptr_t support */
#include "GPU_buffers.h"
-#include "GPU_extensions.h"
#include "GPU_glew.h"
+#include "GPU_shader.h"
#ifdef WITH_OPENSUBDIV
# include "DNA_userdef_types.h"
@@ -3529,14 +3529,11 @@ static void navmesh_drawColored(DerivedMesh *dm)
#if 0
//UI_ThemeColor(TH_WIRE);
- glDisable(GL_LIGHTING);
glLineWidth(2.0);
dm->drawEdges(dm, 0, 1);
glLineWidth(1.0);
- glEnable(GL_LIGHTING);
#endif
- glDisable(GL_LIGHTING);
/* if (GPU_buffer_legacy(dm) ) */ /* TODO - VBO draw code, not high priority - campbell */
{
DEBUG_VBO("Using legacy code. drawNavMeshColored\n");
@@ -3566,7 +3563,6 @@ static void navmesh_drawColored(DerivedMesh *dm)
}
glEnd();
}
- glEnable(GL_LIGHTING);
}
static void navmesh_DM_drawFacesTex(
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index b925094d392..836072df67d 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -57,8 +57,8 @@
#include "GPU_buffers.h"
#include "GPU_draw.h"
-#include "GPU_extensions.h"
#include "GPU_glew.h"
+#include "GPU_shader.h"
#include "WM_api.h"
@@ -445,7 +445,7 @@ static void cdDM_drawFacesSolid(
if (cddm->pbvh) {
if (cddm->pbvh_draw && BKE_pbvh_has_faces(cddm->pbvh)) {
- float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+ float (*face_nors)[3] = CustomData_get_layer(&dm->polyData, CD_NORMAL);
BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
setMaterial, false, false);
@@ -898,8 +898,7 @@ static void cdDM_drawMappedFacesGLSL(
glShadeModel(GL_SMOOTH);
- if (setDrawOptions != NULL)
- {
+ if (setDrawOptions != NULL) {
DMVertexAttribs attribs;
DEBUG_VBO("Using legacy code. cdDM_drawMappedFacesGLSL\n");
memset(&attribs, 0, sizeof(attribs));
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 7fd241eb8e3..dc50e39a862 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -55,8 +55,8 @@
#include "MEM_guardedalloc.h"
-#include "GPU_extensions.h"
#include "GPU_glew.h"
+#include "GPU_shader.h"
extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
@@ -732,8 +732,7 @@ static void emDM_drawMappedFaces(
const int lasttri = tottri - 1; /* compare agasint this a lot */
DMDrawOption draw_option;
int i, flush;
- const int skip_normals = !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
-
+ const int skip_normals = !(flag & DM_DRAW_NEED_NORMALS);
const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
unsigned char(*color_vert_array)[4] = em->derivedVertColor;
@@ -755,7 +754,8 @@ static void emDM_drawMappedFaces(
}
if (has_vcol_preview || has_fcol_preview) {
flag |= DM_DRAW_ALWAYS_SMOOTH;
- glDisable(GL_LIGHTING); /* grr */
+ /* weak, this logic should really be moved higher up */
+ setMaterial = NULL;
}
if (bmdm->vertexCos) {
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 2171f193bac..45ebada4d81 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -55,7 +55,7 @@
#include "BLI_sys_types.h" // for intptr_t support
-#include "GPU_extensions.h"
+#include "GPU_texture.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index f4fce5c0019..6ff30134210 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -2923,7 +2923,7 @@ bool BKE_image_is_openexr(struct Image *ima)
return false;
}
-void BKE_image_backup_render(Scene *scene, Image *ima)
+void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
{
/* called right before rendering, ima->renders contains render
* result pointers for everything but the current render */
@@ -2931,13 +2931,18 @@ void BKE_image_backup_render(Scene *scene, Image *ima)
int slot = ima->render_slot, last = ima->last_render_slot;
if (slot != last) {
- if (ima->renders[slot]) {
- RE_FreeRenderResult(ima->renders[slot]);
- ima->renders[slot] = NULL;
- }
-
ima->renders[last] = NULL;
RE_SwapResult(re, &ima->renders[last]);
+
+ if (ima->renders[slot]) {
+ if (free_current_slot) {
+ RE_FreeRenderResult(ima->renders[slot]);
+ ima->renders[slot] = NULL;
+ }
+ else {
+ RE_SwapResult(re, &ima->renders[slot]);
+ }
+ }
}
ima->last_render_slot = slot;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index a315a1f68ce..f1e0bc69dbc 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -192,7 +192,9 @@ void id_us_min(ID *id)
const int limit = ID_FAKE_USERS(id);
if (id->us <= limit) {
printf("ID user decrement error: %s (from '%s')\n", id->name, id->lib ? id->lib->filepath : "[Main]");
- BLI_assert(0);
+ /* We cannot assert here, because of how we 'delete' datablocks currently (setting their usercount to zero),
+ * this is weak but it's how it works for now. */
+ /* BLI_assert(0); */
id->us = limit;
}
else {
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 68e63c1ac92..d54f382f4c0 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -123,10 +123,11 @@ static void library_foreach_modifiersForeachIDLink(
}
static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID **id_pointer,
- bool UNUSED(is_reference), void *user_data)
+ bool is_reference, void *user_data)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, IDWALK_NOP);
+ const int cd_flag = is_reference ? IDWALK_USER : IDWALK_NOP;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag);
}
static void library_foreach_particlesystemsObjectLooper(
@@ -223,9 +224,8 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
CALLBACK_INVOKE(scene->set, IDWALK_NOP);
CALLBACK_INVOKE(scene->clip, IDWALK_NOP);
CALLBACK_INVOKE(scene->nodetree, IDWALK_NOP);
- if (scene->basact) {
- CALLBACK_INVOKE(scene->basact->object, IDWALK_NOP);
- }
+ /* DO NOT handle scene->basact here, it’s doubling with the loop over whole scene->base later,
+ * since basact is just a pointer to one of those items. */
CALLBACK_INVOKE(scene->obedit, IDWALK_NOP);
for (srl = scene->r.layers.first; srl; srl = srl->next) {
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 0adc894b2cc..b6895e619b0 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -1415,7 +1415,7 @@ void multires_stitch_grids(Object *ob)
int totface;
if (ccgdm->pbvh) {
- BKE_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void ***)&faces, &totface);
+ BKE_pbvh_get_grid_updates(ccgdm->pbvh, false, (void ***)&faces, &totface);
if (totface) {
ccgSubSurf_stitchFaces(ccgdm->ss, 0, faces, totface);
@@ -2227,7 +2227,7 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
dGridSize = multires_side_tot[high_mmd.totlvl];
dSkip = (dGridSize - 1) / (gridSize - 1);
-#pragma omp parallel for private(i) if (me->totface * gridSize * gridSize * 4 >= CCG_OMP_LIMIT)
+#pragma omp parallel for private(i) if (me->totloop * gridSize * gridSize >= CCG_OMP_LIMIT)
for (i = 0; i < me->totpoly; ++i) {
const int numVerts = mpoly[i].totloop;
MDisps *mdisp = &mdisps[mpoly[i].loopstart];
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 1a178fb2bdf..5a755058963 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -41,6 +41,7 @@
#include "BLI_math.h"
#include "BLI_path_util.h"
#include "BLI_rand.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -494,231 +495,296 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
BLI_rw_mutex_unlock(&oc->oceanmutex);
}
-void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount)
+typedef struct OceanSimulateData {
+ Ocean *o;
+ float t;
+ float scale;
+ float chop_amount;
+} OceanSimulateData;
+
+static void ocean_compute_htilda(void *userdata, void *UNUSED(userdata_chunk), int i)
+{
+ OceanSimulateData *osd = userdata;
+ const Ocean *o = osd->o;
+ const float scale = osd->scale;
+ const float t = osd->t;
+
+ int j;
+
+ /* note the <= _N/2 here, see the fftw doco about the mechanics of the complex->real fft storage */
+ for (j = 0; j <= o->_N / 2; ++j) {
+ fftw_complex exp_param1;
+ fftw_complex exp_param2;
+ fftw_complex conj_param;
+
+ init_complex(exp_param1, 0.0, omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
+ init_complex(exp_param2, 0.0, -omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
+ exp_complex(exp_param1, exp_param1);
+ exp_complex(exp_param2, exp_param2);
+ conj_complex(conj_param, o->_h0_minus[i * o->_N + j]);
+
+ mul_complex_c(exp_param1, o->_h0[i * o->_N + j], exp_param1);
+ mul_complex_c(exp_param2, conj_param, exp_param2);
+
+ add_comlex_c(o->_htilda[i * (1 + o->_N / 2) + j], exp_param1, exp_param2);
+ mul_complex_f(o->_fft_in[i * (1 + o->_N / 2) + j], o->_htilda[i * (1 + o->_N / 2) + j], scale);
+ }
+}
+
+static void ocean_compute_displacement_y(TaskPool *pool, void *UNUSED(taskdata), int UNUSED(threadid))
+{
+ OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ const Ocean *o = osd->o;
+
+ fftw_execute(o->_disp_y_plan);
+}
+
+static void ocean_compute_displacement_x(TaskPool *pool, void *UNUSED(taskdata), int UNUSED(threadid))
{
+ OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ const Ocean *o = osd->o;
+ const float scale = osd->scale;
+ const float chop_amount = osd->chop_amount;
int i, j;
- scale *= o->normalize_factor;
+ for (i = 0; i < o->_M; ++i) {
+ for (j = 0; j <= o->_N / 2; ++j) {
+ fftw_complex mul_param;
+ fftw_complex minus_i;
+
+ init_complex(minus_i, 0.0, -1.0);
+ init_complex(mul_param, -scale, 0);
+ mul_complex_f(mul_param, mul_param, chop_amount);
+ mul_complex_c(mul_param, mul_param, minus_i);
+ mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
+ init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
+ }
+ }
+ fftw_execute(o->_disp_x_plan);
+}
- BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
+static void ocean_compute_displacement_z(TaskPool *pool, void *UNUSED(taskdata), int UNUSED(threadid))
+{
+ OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ const Ocean *o = osd->o;
+ const float scale = osd->scale;
+ const float chop_amount = osd->chop_amount;
+ int i, j;
- /* compute a new htilda */
-#pragma omp parallel for private(i, j)
for (i = 0; i < o->_M; ++i) {
- /* note the <= _N/2 here, see the fftw doco about the mechanics of the complex->real fft storage */
for (j = 0; j <= o->_N / 2; ++j) {
- fftw_complex exp_param1;
- fftw_complex exp_param2;
- fftw_complex conj_param;
+ fftw_complex mul_param;
+ fftw_complex minus_i;
+
+ init_complex(minus_i, 0.0, -1.0);
+ init_complex(mul_param, -scale, 0);
+ mul_complex_f(mul_param, mul_param, chop_amount);
+ mul_complex_c(mul_param, mul_param, minus_i);
+ mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
+ init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
+ }
+ }
+ fftw_execute(o->_disp_z_plan);
+}
+
+static void ocean_compute_jacobian_jxx(TaskPool *pool, void *UNUSED(taskdata), int UNUSED(threadid))
+{
+ OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ const Ocean *o = osd->o;
+ const float chop_amount = osd->chop_amount;
+ int i, j;
+ for (i = 0; i < o->_M; ++i) {
+ for (j = 0; j <= o->_N / 2; ++j) {
+ fftw_complex mul_param;
+
+ /* init_complex(mul_param, -scale, 0); */
+ init_complex(mul_param, -1, 0);
+
+ mul_complex_f(mul_param, mul_param, chop_amount);
+ mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
+ init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
+ }
+ }
+ fftw_execute(o->_Jxx_plan);
- init_complex(exp_param1, 0.0, omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
- init_complex(exp_param2, 0.0, -omega(o->_k[i * (1 + o->_N / 2) + j], o->_depth) * t);
- exp_complex(exp_param1, exp_param1);
- exp_complex(exp_param2, exp_param2);
- conj_complex(conj_param, o->_h0_minus[i * o->_N + j]);
+ for (i = 0; i < o->_M; ++i) {
+ for (j = 0; j < o->_N; ++j) {
+ o->_Jxx[i * o->_N + j] += 1.0;
+ }
+ }
+}
- mul_complex_c(exp_param1, o->_h0[i * o->_N + j], exp_param1);
- mul_complex_c(exp_param2, conj_param, exp_param2);
+static void ocean_compute_jacobian_jzz(TaskPool *pool, void *UNUSED(taskdata), int UNUSED(threadid))
+{
+ OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ const Ocean *o = osd->o;
+ const float chop_amount = osd->chop_amount;
+ int i, j;
- add_comlex_c(o->_htilda[i * (1 + o->_N / 2) + j], exp_param1, exp_param2);
- mul_complex_f(o->_fft_in[i * (1 + o->_N / 2) + j], o->_htilda[i * (1 + o->_N / 2) + j], scale);
+ for (i = 0; i < o->_M; ++i) {
+ for (j = 0; j <= o->_N / 2; ++j) {
+ fftw_complex mul_param;
+
+ /* init_complex(mul_param, -scale, 0); */
+ init_complex(mul_param, -1, 0);
+
+ mul_complex_f(mul_param, mul_param, chop_amount);
+ mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
+ init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
}
}
+ fftw_execute(o->_Jzz_plan);
-#pragma omp parallel sections private(i, j)
- {
+ for (i = 0; i < o->_M; ++i) {
+ for (j = 0; j < o->_N; ++j) {
+ o->_Jzz[i * o->_N + j] += 1.0;
+ }
+ }
+}
-#pragma omp section
- {
- if (o->_do_disp_y) {
- /* y displacement */
- fftw_execute(o->_disp_y_plan);
- }
- } /* section 1 */
-
-#pragma omp section
- {
- if (o->_do_chop) {
- /* x displacement */
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j <= o->_N / 2; ++j) {
- fftw_complex mul_param;
- fftw_complex minus_i;
-
- init_complex(minus_i, 0.0, -1.0);
- init_complex(mul_param, -scale, 0);
- mul_complex_f(mul_param, mul_param, chop_amount);
- mul_complex_c(mul_param, mul_param, minus_i);
- mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param,
- ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
- 0.0f :
- o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
- init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
- }
- }
- fftw_execute(o->_disp_x_plan);
- }
- } /* section 2 */
-
-#pragma omp section
- {
- if (o->_do_chop) {
- /* z displacement */
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j <= o->_N / 2; ++j) {
- fftw_complex mul_param;
- fftw_complex minus_i;
-
- init_complex(minus_i, 0.0, -1.0);
- init_complex(mul_param, -scale, 0);
- mul_complex_f(mul_param, mul_param, chop_amount);
- mul_complex_c(mul_param, mul_param, minus_i);
- mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param,
- ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
- 0.0f :
- o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
- init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
- }
- }
- fftw_execute(o->_disp_z_plan);
- }
- } /* section 3 */
-
-#pragma omp section
- {
- if (o->_do_jacobian) {
- /* Jxx */
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j <= o->_N / 2; ++j) {
- fftw_complex mul_param;
-
- /* init_complex(mul_param, -scale, 0); */
- init_complex(mul_param, -1, 0);
-
- mul_complex_f(mul_param, mul_param, chop_amount);
- mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param,
- ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
- 0.0f :
- o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
- init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
- }
- }
- fftw_execute(o->_Jxx_plan);
+static void ocean_compute_jacobian_jxz(TaskPool *pool, void *UNUSED(taskdata), int UNUSED(threadid))
+{
+ OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ const Ocean *o = osd->o;
+ const float chop_amount = osd->chop_amount;
+ int i, j;
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j < o->_N; ++j) {
- o->_Jxx[i * o->_N + j] += 1.0;
- }
- }
- }
- } /* section 4 */
-
-#pragma omp section
- {
- if (o->_do_jacobian) {
- /* Jzz */
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j <= o->_N / 2; ++j) {
- fftw_complex mul_param;
-
- /* init_complex(mul_param, -scale, 0); */
- init_complex(mul_param, -1, 0);
-
- mul_complex_f(mul_param, mul_param, chop_amount);
- mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param,
- ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
- 0.0f :
- o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
- init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
- }
- }
- fftw_execute(o->_Jzz_plan);
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j < o->_N; ++j) {
- o->_Jzz[i * o->_N + j] += 1.0;
- }
- }
- }
- } /* section 5 */
-
-#pragma omp section
- {
- if (o->_do_jacobian) {
- /* Jxz */
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j <= o->_N / 2; ++j) {
- fftw_complex mul_param;
-
- /* init_complex(mul_param, -scale, 0); */
- init_complex(mul_param, -1, 0);
-
- mul_complex_f(mul_param, mul_param, chop_amount);
- mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param,
- ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
- 0.0f :
- o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
- init_complex(o->_fft_in_jxz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
- }
- }
- fftw_execute(o->_Jxz_plan);
- }
- } /* section 6 */
-
-#pragma omp section
- {
- /* fft normals */
- if (o->_do_normals) {
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j <= o->_N / 2; ++j) {
- fftw_complex mul_param;
-
- init_complex(mul_param, 0.0, -1.0);
- mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param, o->_kx[i]);
- init_complex(o->_fft_in_nx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
- }
- }
- fftw_execute(o->_N_x_plan);
+ for (i = 0; i < o->_M; ++i) {
+ for (j = 0; j <= o->_N / 2; ++j) {
+ fftw_complex mul_param;
+
+ /* init_complex(mul_param, -scale, 0); */
+ init_complex(mul_param, -1, 0);
+
+ mul_complex_f(mul_param, mul_param, chop_amount);
+ mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
+ init_complex(o->_fft_in_jxz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
+ }
+ }
+ fftw_execute(o->_Jxz_plan);
+}
- }
- } /* section 7 */
-
-#pragma omp section
- {
- if (o->_do_normals) {
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j <= o->_N / 2; ++j) {
- fftw_complex mul_param;
-
- init_complex(mul_param, 0.0, -1.0);
- mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param, o->_kz[i]);
- init_complex(o->_fft_in_nz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
- }
- }
- fftw_execute(o->_N_z_plan);
+static void ocean_compute_normal_x(TaskPool *pool, void *UNUSED(taskdata), int UNUSED(threadid))
+{
+ OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ const Ocean *o = osd->o;
+ int i, j;
+
+ for (i = 0; i < o->_M; ++i) {
+ for (j = 0; j <= o->_N / 2; ++j) {
+ fftw_complex mul_param;
+
+ init_complex(mul_param, 0.0, -1.0);
+ mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
+ mul_complex_f(mul_param, mul_param, o->_kx[i]);
+ init_complex(o->_fft_in_nx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
+ }
+ }
+ fftw_execute(o->_N_x_plan);
+}
+
+static void ocean_compute_normal_z(TaskPool *pool, void *UNUSED(taskdata), int UNUSED(threadid))
+{
+ OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ const Ocean *o = osd->o;
+ int i, j;
+
+ for (i = 0; i < o->_M; ++i) {
+ for (j = 0; j <= o->_N / 2; ++j) {
+ fftw_complex mul_param;
+
+ init_complex(mul_param, 0.0, -1.0);
+ mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
+ mul_complex_f(mul_param, mul_param, o->_kz[i]);
+ init_complex(o->_fft_in_nz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
+ }
+ }
+ fftw_execute(o->_N_z_plan);
+}
+
+void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount)
+{
+ TaskScheduler *scheduler = BLI_task_scheduler_get();
+ TaskPool *pool;
+
+ OceanSimulateData osd;
+
+ scale *= o->normalize_factor;
+
+ osd.o = o;
+ osd.t = t;
+ osd.scale = scale;
+ osd.chop_amount = chop_amount;
+
+ pool = BLI_task_pool_create(scheduler, &osd);
+
+ BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
+
+ /* Note about multi-threading here: we have to run a first set of computations (htilda one) before we can run
+ * all others, since they all depend on it.
+ * So we make a first parallelized forloop run for htilda, and then pack all other computations into
+ * a set of parallel tasks.
+ * This is not optimal in all cases, but remains reasonably simple and should be OK most of the time. */
+
+ /* compute a new htilda */
+ BLI_task_parallel_range(0, o->_M, &osd, ocean_compute_htilda);
+
+ if (o->_do_disp_y) {
+ BLI_task_pool_push(pool, ocean_compute_displacement_y, NULL, false, TASK_PRIORITY_HIGH);
+ }
+
+ if (o->_do_chop) {
+ BLI_task_pool_push(pool, ocean_compute_displacement_x, NULL, false, TASK_PRIORITY_HIGH);
+ BLI_task_pool_push(pool, ocean_compute_displacement_z, NULL, false, TASK_PRIORITY_HIGH);
+ }
+
+ if (o->_do_jacobian) {
+ BLI_task_pool_push(pool, ocean_compute_jacobian_jxx, NULL, false, TASK_PRIORITY_HIGH);
+ BLI_task_pool_push(pool, ocean_compute_jacobian_jzz, NULL, false, TASK_PRIORITY_HIGH);
+ BLI_task_pool_push(pool, ocean_compute_jacobian_jxz, NULL, false, TASK_PRIORITY_HIGH);
+ }
+
+ if (o->_do_normals) {
+ BLI_task_pool_push(pool, ocean_compute_normal_x, NULL, false, TASK_PRIORITY_HIGH);
+ BLI_task_pool_push(pool, ocean_compute_normal_z, NULL, false, TASK_PRIORITY_HIGH);
#if 0
- for (i = 0; i < o->_M; ++i) {
- for (j = 0; j < o->_N; ++j) {
- o->_N_y[i * o->_N + j] = 1.0f / scale;
- }
- }
- (MEM01)
-#endif
- o->_N_y = 1.0f / scale;
+ for (i = 0; i < o->_M; ++i) {
+ for (j = 0; j < o->_N; ++j) {
+ o->_N_y[i * o->_N + j] = 1.0f / scale;
}
- } /* section 8 */
+ }
+ (MEM01)
+#endif
+ o->_N_y = 1.0f / scale;
+ }
- } /* omp sections */
+ BLI_task_pool_work_and_wait(pool);
BLI_rw_mutex_unlock(&o->oceanmutex);
+
+ BLI_task_pool_free(pool);
}
static void set_height_normalize_factor(struct Ocean *oc)
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 311e928c348..16ba25e3bef 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -63,7 +63,7 @@
typedef struct PBVHStack {
PBVHNode *node;
- int revisiting;
+ bool revisiting;
} PBVHStack;
typedef struct PBVHIter {
@@ -87,8 +87,7 @@ void BB_reset(BB *bb)
/* Expand the bounding box to include a new coordinate */
void BB_expand(BB *bb, const float co[3])
{
- int i;
- for (i = 0; i < 3; ++i) {
+ for (int i = 0; i < 3; ++i) {
bb->bmin[i] = min_ff(bb->bmin[i], co[i]);
bb->bmax[i] = max_ff(bb->bmax[i], co[i]);
}
@@ -97,8 +96,7 @@ void BB_expand(BB *bb, const float co[3])
/* Expand the bounding box to include another bounding box */
void BB_expand_with_bb(BB *bb, BB *bb2)
{
- int i;
- for (i = 0; i < 3; ++i) {
+ for (int i = 0; i < 3; ++i) {
bb->bmin[i] = min_ff(bb->bmin[i], bb2->bmin[i]);
bb->bmax[i] = max_ff(bb->bmax[i], bb2->bmax[i]);
}
@@ -108,9 +106,8 @@ void BB_expand_with_bb(BB *bb, BB *bb2)
int BB_widest_axis(const BB *bb)
{
float dim[3];
- int i;
- for (i = 0; i < 3; ++i)
+ for (int i = 0; i < 3; ++i)
dim[i] = bb->bmax[i] - bb->bmin[i];
if (dim[0] > dim[1]) {
@@ -129,8 +126,7 @@ int BB_widest_axis(const BB *bb)
void BBC_update_centroid(BBC *bbc)
{
- int i;
- for (i = 0; i < 3; ++i)
+ for (int i = 0; i < 3; ++i)
bbc->bcentroid[i] = (bbc->bmin[i] + bbc->bmax[i]) * 0.5f;
}
@@ -170,13 +166,13 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
// BB_expand(&node->vb, co);
//}
-static int face_materials_match(const MPoly *f1, const MPoly *f2)
+static bool face_materials_match(const MPoly *f1, const MPoly *f2)
{
return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
(f1->mat_nr == f2->mat_nr));
}
-static int grid_materials_match(const DMFlagMat *f1, const DMFlagMat *f2)
+static bool grid_materials_match(const DMFlagMat *f1, const DMFlagMat *f2)
{
return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
(f1->mat_nr == f2->mat_nr));
@@ -279,29 +275,24 @@ static int map_insert_vert(PBVH *bvh, GHash *map,
/* Find vertices used by the faces in this node and update the draw buffers */
static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
{
- GHashIterator gh_iter;
- GHash *map;
- int i, j, totface;
bool has_visible = false;
- int (*face_vert_indices)[4];
- int *vert_indices;
node->uniq_verts = node->face_verts = 0;
- totface = node->totprim;
+ const int totface = node->totprim;
/* reserve size is rough guess */
- map = BLI_ghash_int_new_ex("build_mesh_leaf_node gh", 2 * totface);
+ GHash *map = BLI_ghash_int_new_ex("build_mesh_leaf_node gh", 2 * totface);
- face_vert_indices = MEM_callocN(sizeof(int[4]) * totface,
- "bvh node face vert indices");
+ int (*face_vert_indices)[4] = MEM_callocN(sizeof(int[4]) * totface,
+ "bvh node face vert indices");
node->face_vert_indices = (const int (*)[4])face_vert_indices;
- for (i = 0; i < totface; ++i) {
+ for (int i = 0; i < totface; ++i) {
const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]];
const int sides = 3;
- for (j = 0; j < sides; ++j) {
+ for (int j = 0; j < sides; ++j) {
face_vert_indices[i][j] =
map_insert_vert(bvh, map, &node->face_verts,
&node->uniq_verts, bvh->mloop[lt->tri[j]].v);
@@ -312,12 +303,12 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
}
}
- vert_indices = MEM_callocN(sizeof(int) *
- (node->uniq_verts + node->face_verts),
- "bvh node vert indices");
+ int *vert_indices = MEM_callocN(sizeof(int) * (node->uniq_verts + node->face_verts),
+ "bvh node vert indices");
node->vert_indices = vert_indices;
/* Build the vertex list, unique verts first */
+ GHashIterator gh_iter;
GHASH_ITER (gh_iter, map) {
void *value = BLI_ghashIterator_getValue(&gh_iter);
int ndx = GET_INT_FROM_POINTER(value);
@@ -329,10 +320,10 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
}
- for (i = 0; i < totface; ++i) {
+ for (int i = 0; i < totface; ++i) {
const int sides = 3;
- for (j = 0; j < sides; ++j) {
+ for (int j = 0; j < sides; ++j) {
if (face_vert_indices[i][j] < 0)
face_vert_indices[i][j] =
-face_vert_indices[i][j] +
@@ -350,10 +341,8 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
static void update_vb(PBVH *bvh, PBVHNode *node, BBC *prim_bbc,
int offset, int count)
{
- int i;
-
BB_reset(&node->vb);
- for (i = offset + count - 1; i >= offset; --i) {
+ for (int i = offset + count - 1; i >= offset; --i) {
BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[bvh->prim_indices[i]]));
}
node->orig_vb = node->vb;
@@ -364,19 +353,19 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
int *grid_indices, int totgrid,
int gridsize)
{
- int gridarea = (gridsize - 1) * (gridsize - 1);
- int i, x, y, totquad;
+ const int gridarea = (gridsize - 1) * (gridsize - 1);
+ int totquad = 0;
/* grid hidden layer is present, so have to check each grid for
* visibility */
- for (i = 0, totquad = 0; i < totgrid; i++) {
+ for (int i = 0; i < totgrid; i++) {
const BLI_bitmap *gh = grid_hidden[grid_indices[i]];
if (gh) {
/* grid hidden are present, have to check each element */
- for (y = 0; y < gridsize - 1; y++) {
- for (x = 0; x < gridsize - 1; x++) {
+ for (int y = 0; y < gridsize - 1; y++) {
+ for (int x = 0; x < gridsize - 1; x++) {
if (!paint_is_grid_face_hidden(gh, gridsize, x, y))
totquad++;
}
@@ -418,36 +407,34 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
/* Return zero if all primitives in the node can be drawn with the
* same material (including flat/smooth shading), non-zero otherwise */
-static int leaf_needs_material_split(PBVH *bvh, int offset, int count)
+static bool leaf_needs_material_split(PBVH *bvh, int offset, int count)
{
- int i;
-
if (count <= 1)
- return 0;
+ return false;
if (bvh->looptri) {
const MLoopTri *first = &bvh->looptri[bvh->prim_indices[offset]];
const MPoly *mp = &bvh->mpoly[first->poly];
- for (i = offset + count - 1; i > offset; --i) {
+ for (int i = offset + count - 1; i > offset; --i) {
int prim = bvh->prim_indices[i];
const MPoly *mp_other = &bvh->mpoly[bvh->looptri[prim].poly];
if (!face_materials_match(mp, mp_other)) {
- return 1;
+ return true;
}
}
}
else {
const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]];
- for (i = offset + count - 1; i > offset; --i) {
+ for (int i = offset + count - 1; i > offset; --i) {
int prim = bvh->prim_indices[i];
if (!grid_materials_match(first, &bvh->grid_flag_mats[prim]))
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
@@ -465,11 +452,11 @@ static int leaf_needs_material_split(PBVH *bvh, int offset, int count)
static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
int offset, int count)
{
- int i, axis, end, below_leaf_limit;
+ int end;
BB cb_backing;
/* Decide whether this is a leaf or not */
- below_leaf_limit = count <= bvh->leaf_limit;
+ const bool below_leaf_limit = count <= bvh->leaf_limit;
if (below_leaf_limit) {
if (!leaf_needs_material_split(bvh, offset, count)) {
build_leaf(bvh, node_index, prim_bbc, offset, count);
@@ -489,10 +476,10 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
if (!cb) {
cb = &cb_backing;
BB_reset(cb);
- for (i = offset + count - 1; i >= offset; --i)
+ for (int i = offset + count - 1; i >= offset; --i)
BB_expand(cb, prim_bbc[bvh->prim_indices[i]].bcentroid);
}
- axis = BB_widest_axis(cb);
+ const int axis = BB_widest_axis(cb);
/* Partition primitives along that axis */
end = partition_indices(bvh->prim_indices,
@@ -515,15 +502,13 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
{
- int i;
-
if (totprim != bvh->totprim) {
bvh->totprim = totprim;
if (bvh->nodes) MEM_freeN(bvh->nodes);
if (bvh->prim_indices) MEM_freeN(bvh->prim_indices);
bvh->prim_indices = MEM_callocN(sizeof(int) * totprim,
"bvh prim indices");
- for (i = 0; i < totprim; ++i)
+ for (int i = 0; i < totprim; ++i)
bvh->prim_indices[i] = i;
bvh->totnode = 0;
if (bvh->node_mem_count < 100) {
@@ -546,7 +531,6 @@ void BKE_pbvh_build_mesh(
{
BBC *prim_bbc = NULL;
BB cb;
- int i, j;
bvh->type = PBVH_FACES;
bvh->mpoly = mpoly;
@@ -563,14 +547,14 @@ void BKE_pbvh_build_mesh(
/* For each face, store the AABB and the AABB centroid */
prim_bbc = MEM_mallocN(sizeof(BBC) * looptri_num, "prim_bbc");
- for (i = 0; i < looptri_num; ++i) {
+ for (int i = 0; i < looptri_num; ++i) {
const MLoopTri *lt = &looptri[i];
const int sides = 3;
BBC *bbc = prim_bbc + i;
BB_reset((BB *)bbc);
- for (j = 0; j < sides; ++j)
+ for (int j = 0; j < sides; ++j)
BB_expand((BB *)bbc, verts[bvh->mloop[lt->tri[j]].v].co);
BBC_update_centroid(bbc);
@@ -589,10 +573,7 @@ void BKE_pbvh_build_mesh(
void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids,
int totgrid, CCGKey *key, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
{
- BBC *prim_bbc = NULL;
- BB cb;
- int gridsize = key->grid_size;
- int i, j;
+ const int gridsize = key->grid_size;
bvh->type = PBVH_GRIDS;
bvh->grids = grids;
@@ -603,18 +584,19 @@ void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids,
bvh->grid_hidden = grid_hidden;
bvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1);
+ BB cb;
BB_reset(&cb);
/* For each grid, store the AABB and the AABB centroid */
- prim_bbc = MEM_mallocN(sizeof(BBC) * totgrid, "prim_bbc");
+ BBC *prim_bbc = MEM_mallocN(sizeof(BBC) * totgrid, "prim_bbc");
- for (i = 0; i < totgrid; ++i) {
+ for (int i = 0; i < totgrid; ++i) {
CCGElem *grid = grids[i];
BBC *bbc = prim_bbc + i;
BB_reset((BB *)bbc);
- for (j = 0; j < gridsize * gridsize; ++j)
+ for (int j = 0; j < gridsize * gridsize; ++j)
BB_expand((BB *)bbc, CCG_elem_offset_co(key, grid, j));
BBC_update_centroid(bbc);
@@ -637,11 +619,8 @@ PBVH *BKE_pbvh_new(void)
void BKE_pbvh_free(PBVH *bvh)
{
- PBVHNode *node;
- int i;
-
- for (i = 0; i < bvh->totnode; ++i) {
- node = &bvh->nodes[i];
+ for (int i = 0; i < bvh->totnode; ++i) {
+ PBVHNode *node = &bvh->nodes[i];
if (node->flag & PBVH_Leaf) {
if (node->draw_buffers)
@@ -684,8 +663,7 @@ void BKE_pbvh_free(PBVH *bvh)
void BKE_pbvh_free_layer_disp(PBVH *bvh)
{
- int i;
- for (i = 0; i < bvh->totnode; ++i)
+ for (int i = 0; i < bvh->totnode; ++i)
BKE_pbvh_node_layer_disp_free(&bvh->nodes[i]);
}
@@ -699,7 +677,7 @@ static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BKE_pbvh_SearchCallback s
iter->stackspace = STACK_FIXED_DEPTH;
iter->stack[0].node = bvh->nodes;
- iter->stack[0].revisiting = 0;
+ iter->stack[0].revisiting = false;
iter->stacksize = 1;
}
@@ -709,7 +687,7 @@ static void pbvh_iter_end(PBVHIter *iter)
MEM_freeN(iter->stack);
}
-static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, int revisiting)
+static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, bool revisiting)
{
if (UNLIKELY(iter->stacksize == iter->stackspace)) {
iter->stackspace *= 2;
@@ -730,23 +708,20 @@ static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, int revisiting)
static PBVHNode *pbvh_iter_next(PBVHIter *iter)
{
- PBVHNode *node;
- int revisiting;
-
/* purpose here is to traverse tree, visiting child nodes before their
* parents, this order is necessary for e.g. computing bounding boxes */
while (iter->stacksize) {
/* pop node */
iter->stacksize--;
- node = iter->stack[iter->stacksize].node;
+ PBVHNode *node = iter->stack[iter->stacksize].node;
/* on a mesh with no faces this can happen
* can remove this check if we know meshes have at least 1 face */
if (node == NULL)
return NULL;
- revisiting = iter->stack[iter->stacksize].revisiting;
+ bool revisiting = iter->stack[iter->stacksize].revisiting;
/* revisiting node already checked */
if (revisiting)
@@ -761,11 +736,11 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter)
}
else {
/* come back later when children are done */
- pbvh_stack_push(iter, node, 1);
+ pbvh_stack_push(iter, node, true);
/* push two child nodes on the stack */
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, 0);
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, 0);
+ pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false);
+ pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false);
}
}
@@ -774,12 +749,10 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter)
static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
{
- PBVHNode *node;
-
while (iter->stacksize) {
/* pop node */
iter->stacksize--;
- node = iter->stack[iter->stacksize].node;
+ PBVHNode *node = iter->stack[iter->stacksize].node;
/* on a mesh with no faces this can happen
* can remove this check if we know meshes have at least 1 face */
@@ -792,8 +765,8 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
return node;
}
else {
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, 0);
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, 0);
+ pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false);
+ pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false);
}
}
@@ -957,7 +930,6 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
int totnode, float (*face_nors)[3])
{
float (*vnor)[3];
- int n;
if (bvh->type == PBVH_BMESH) {
BLI_assert(face_nors == NULL);
@@ -982,19 +954,19 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
* can only update vertices marked with ME_VERT_PBVH_UPDATE.
*/
+ int n;
#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
if ((node->flag & PBVH_UpdateNormals)) {
- int i, j, totface, *faces;
unsigned int mpoly_prev = UINT_MAX;
float fn[3];
- faces = node->prim_indices;
- totface = node->totprim;
+ const int *faces = node->prim_indices;
+ const int totface = node->totprim;
- for (i = 0; i < totface; ++i) {
+ for (int i = 0; i < totface; ++i) {
const MLoopTri *lt = &bvh->looptri[faces[i]];
const unsigned int vtri[3] = {
bvh->mloop[lt->tri[0]].v,
@@ -1014,7 +986,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
}
}
- for (j = 0; j < sides; ++j) {
+ for (int j = 0; j < sides; ++j) {
int v = vtri[j];
if (bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
@@ -1037,13 +1009,10 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
PBVHNode *node = nodes[n];
if (node->flag & PBVH_UpdateNormals) {
- const int *verts;
- int i, totvert;
+ const int *verts = node->vert_indices;
+ const int totvert = node->uniq_verts;
- verts = node->vert_indices;
- totvert = node->uniq_verts;
-
- for (i = 0; i < totvert; ++i) {
+ for (int i = 0; i < totvert; ++i) {
const int v = verts[i];
MVert *mvert = &bvh->verts[v];
@@ -1067,9 +1036,8 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
{
- int n;
-
/* update BB, redraw flag */
+ int n;
#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
@@ -1088,12 +1056,9 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
{
- PBVHNode *node;
- int n;
-
/* can't be done in parallel with OpenGL */
- for (n = 0; n < totnode; n++) {
- node = nodes[n];
+ for (int n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
if (node->flag & PBVH_RebuildDrawBuffers) {
GPU_free_pbvh_buffers(node->draw_buffers);
@@ -1116,8 +1081,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
break;
case PBVH_BMESH:
node->draw_buffers =
- GPU_build_bmesh_pbvh_buffers(bvh->flags &
- PBVH_DYNTOPO_SMOOTH_SHADING);
+ GPU_build_bmesh_pbvh_buffers(bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING);
break;
}
@@ -1163,13 +1127,10 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
static void pbvh_draw_BB(PBVH *bvh)
{
- PBVHNode *node;
- int a;
-
GPU_init_draw_pbvh_BB();
- for (a = 0; a < bvh->totnode; a++) {
- node = &bvh->nodes[a];
+ for (int a = 0; a < bvh->totnode; a++) {
+ PBVHNode *node = &bvh->nodes[a];
GPU_draw_pbvh_BB(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0));
}
@@ -1210,12 +1171,12 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
void BKE_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
{
- PBVHNode **nodes;
- int totnode;
-
if (!bvh->nodes)
return;
+ PBVHNode **nodes;
+ int totnode;
+
BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(flag),
&nodes, &totnode);
@@ -1251,24 +1212,18 @@ void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
copy_v3_v3(bb_max, bb.bmax);
}
-void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***r_gridfaces, int *r_totface)
+void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface)
{
- PBVHIter iter;
+ GSet *face_set = BLI_gset_ptr_new(__func__);
PBVHNode *node;
- GSetIterator gs_iter;
- GSet *face_set;
- void *face, **faces;
- unsigned i;
- int tot;
-
- face_set = BLI_gset_ptr_new(__func__);
+ PBVHIter iter;
pbvh_iter_begin(&iter, bvh, NULL, NULL);
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_UpdateNormals) {
- for (i = 0; i < node->totprim; ++i) {
- face = bvh->gridfaces[node->prim_indices[i]];
+ for (unsigned i = 0; i < node->totprim; ++i) {
+ void *face = bvh->gridfaces[node->prim_indices[i]];
if (!BLI_gset_haskey(face_set, face))
BLI_gset_insert(face_set, face);
}
@@ -1280,7 +1235,7 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***r_gridfaces, int *r
pbvh_iter_end(&iter);
- tot = BLI_gset_size(face_set);
+ const int tot = BLI_gset_size(face_set);
if (tot == 0) {
*r_totface = 0;
*r_gridfaces = NULL;
@@ -1288,8 +1243,10 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***r_gridfaces, int *r
return;
}
- faces = MEM_mallocN(sizeof(*faces) * tot, "PBVH Grid Faces");
+ void **faces = MEM_mallocN(sizeof(*faces) * tot, "PBVH Grid Faces");
+ GSetIterator gs_iter;
+ int i;
GSET_ITER_INDEX (gs_iter, face_set, i) {
faces[i] = BLI_gsetIterator_getKey(&gs_iter);
}
@@ -1589,12 +1546,11 @@ static bool pbvh_grids_node_raycast(
const float ray_start[3], const float ray_normal[3],
float *dist)
{
- int totgrid = node->totprim;
- int gridsize = bvh->gridkey.grid_size;
- int i, x, y;
+ const int totgrid = node->totprim;
+ const int gridsize = bvh->gridkey.grid_size;
bool hit = false;
- for (i = 0; i < totgrid; ++i) {
+ for (int i = 0; i < totgrid; ++i) {
CCGElem *grid = bvh->grids[node->prim_indices[i]];
BLI_bitmap *gh;
@@ -1603,8 +1559,8 @@ static bool pbvh_grids_node_raycast(
gh = bvh->grid_hidden[node->prim_indices[i]];
- for (y = 0; y < gridsize - 1; ++y) {
- for (x = 0; x < gridsize - 1; ++x) {
+ for (int y = 0; y < gridsize - 1; ++y) {
+ for (int x = 0; x < gridsize - 1; ++x) {
/* check if grid face is hidden */
if (gh) {
if (paint_is_grid_face_hidden(gh, gridsize, x, y))
@@ -1640,14 +1596,14 @@ static bool pbvh_grids_node_raycast(
}
bool BKE_pbvh_node_raycast(
- PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
+ PBVH *bvh, PBVHNode *node, float (*origco)[3], bool use_origco,
const float ray_start[3], const float ray_normal[3],
float *dist)
{
bool hit = false;
if (node->flag & PBVH_FullyHidden)
- return 0;
+ return false;
switch (bvh->type) {
case PBVH_FACES:
@@ -1713,9 +1669,6 @@ void BKE_pbvh_raycast_project_ray_root(
}
}
-
-//#include "GPU_glew.h"
-
typedef struct {
DMSetMaterial setMaterial;
bool wireframe;
@@ -1728,18 +1681,19 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
#if 0
/* XXX: Just some quick code to show leaf nodes in different colors */
- float col[3]; int i;
+ float col[3];
+ float spec[3] = {0.0f, 0.0f, 0.0f};
if (0) { //is_partial) {
col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6;
}
else {
srand((long long)node);
- for (i = 0; i < 3; ++i)
+ for (int i = 0; i < 3; ++i)
col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7;
}
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col);
+ GPU_basic_shader_colors(col, spec, 0, 1.0f);
glColor3f(1, 0, 0);
#endif
@@ -1768,10 +1722,9 @@ static PlaneAABBIsect test_planes_aabb(const float bb_min[3],
{
float vmin[3], vmax[3];
PlaneAABBIsect ret = ISECT_INSIDE;
- int i, axis;
- for (i = 0; i < 4; ++i) {
- for (axis = 0; axis < 3; ++axis) {
+ for (int i = 0; i < 4; ++i) {
+ for (int axis = 0; axis < 3; ++axis) {
if (planes[i][axis] > 0) {
vmin[axis] = bb_min[axis];
vmax[axis] = bb_max[axis];
@@ -1821,9 +1774,9 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
{
PBVHNodeDrawData draw_data = {setMaterial, wireframe, fast};
PBVHNode **nodes;
- int a, totnode;
+ int totnode;
- for (a = 0; a < bvh->totnode; a++)
+ for (int a = 0; a < bvh->totnode; a++)
pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]);
BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
@@ -1849,8 +1802,6 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces,
DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
{
- int a;
-
bvh->grids = grids;
bvh->gridfaces = gridfaces;
@@ -1858,7 +1809,7 @@ void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces,
bvh->grid_flag_mats = flagmats;
bvh->grid_hidden = grid_hidden;
- for (a = 0; a < bvh->totnode; ++a)
+ for (int a = 0; a < bvh->totnode; ++a)
BKE_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
}
}
@@ -1885,17 +1836,15 @@ void BKE_pbvh_node_layer_disp_free(PBVHNode *node)
float (*BKE_pbvh_get_vertCos(PBVH *pbvh))[3]
{
- int a;
float (*vertCos)[3] = NULL;
if (pbvh->verts) {
- float *co;
MVert *mvert = pbvh->verts;
vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BKE_pbvh_get_vertCoords");
- co = (float *)vertCos;
+ float *co = (float *)vertCos;
- for (a = 0; a < pbvh->totvert; a++, mvert++, co += 3) {
+ for (int a = 0; a < pbvh->totvert; a++, mvert++, co += 3) {
copy_v3_v3(co, mvert->co);
}
}
@@ -1905,8 +1854,6 @@ float (*BKE_pbvh_get_vertCos(PBVH *pbvh))[3]
void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
{
- int a;
-
if (!pbvh->deformed) {
if (pbvh->verts) {
/* if pbvh is not already deformed, verts/faces points to the */
@@ -1916,14 +1863,14 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
pbvh->verts = MEM_dupallocN(pbvh->verts);
pbvh->looptri = MEM_dupallocN(pbvh->looptri);
- pbvh->deformed = 1;
+ pbvh->deformed = true;
}
}
if (pbvh->verts) {
MVert *mvert = pbvh->verts;
/* copy new verts coords */
- for (a = 0; a < pbvh->totvert; ++a, ++mvert) {
+ for (int a = 0; a < pbvh->totvert; ++a, ++mvert) {
copy_v3_v3(mvert->co, vertCos[a]);
mvert->flag |= ME_VERT_PBVH_UPDATE;
}
@@ -1935,7 +1882,7 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
pbvh->looptri, pbvh->totprim,
NULL);
- for (a = 0; a < pbvh->totnode; ++a)
+ for (int a = 0; a < pbvh->totnode; ++a)
BKE_pbvh_node_mark_update(&pbvh->nodes[a]);
BKE_pbvh_update(pbvh, PBVH_UpdateBB, NULL);
@@ -1956,7 +1903,6 @@ PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
#pragma omp critical
{
-
index = node->proxy_count;
node->proxy_count++;
@@ -1977,9 +1923,7 @@ void BKE_pbvh_node_free_proxies(PBVHNode *node)
{
#pragma omp critical
{
- int p;
-
- for (p = 0; p < node->proxy_count; p++) {
+ for (int p = 0; p < node->proxy_count; p++) {
MEM_freeN(node->proxies[p].co);
node->proxies[p].co = NULL;
}
@@ -1993,12 +1937,11 @@ void BKE_pbvh_node_free_proxies(PBVHNode *node)
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
{
- PBVHNode **array = NULL, *node;
+ PBVHNode **array = NULL;
int tot = 0, space = 0;
- int n;
- for (n = 0; n < pbvh->totnode; n++) {
- node = pbvh->nodes + n;
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = pbvh->nodes + n;
if (node->proxy_count > 0) {
if (tot == space) {
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index ff4cae09437..88dc63d6cb2 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -87,17 +87,16 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index, const int cd_ver
GSET_ITER (gs_iter, n->bm_faces) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
- BMLoop *l_iter;
- BMLoop *l_first;
- BMVert *v;
/* Update ownership of faces */
BM_ELEM_CD_SET_INT(f, cd_face_node_offset, node_index);
- /* Update vertices */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ /* Update vertices */
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
+
do {
- v = l_iter->v;
+ BMVert *v = l_iter->v;
if (!BLI_gset_haskey(n->bm_unique_verts, v)) {
if (BM_ELEM_CD_GET_INT(v, cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
BLI_gset_add(n->bm_other_verts, v);
@@ -131,15 +130,9 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index, const int cd_ver
/* Recursively split the node if it exceeds the leaf_limit */
static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_index)
{
- GSet *empty, *other;
- GSetIterator gs_iter;
- PBVHNode *n, *c1, *c2;
- BB cb;
- float mid;
- int axis, children;
const int cd_vert_node_offset = bvh->cd_vert_node_offset;
const int cd_face_node_offset = bvh->cd_face_node_offset;
- n = &bvh->nodes[node_index];
+ PBVHNode *n = &bvh->nodes[node_index];
if (BLI_gset_size(n->bm_faces) <= bvh->leaf_limit) {
/* Node limit not exceeded */
@@ -148,7 +141,9 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
}
/* Calculate bounding box around primitive centroids */
+ BB cb;
BB_reset(&cb);
+ GSetIterator gs_iter;
GSET_ITER (gs_iter, n->bm_faces) {
const BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
const BBC *bbc = &bbc_array[BM_elem_index_get(f)];
@@ -157,11 +152,11 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
}
/* Find widest axis and its midpoint */
- axis = BB_widest_axis(&cb);
- mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f;
+ const int axis = BB_widest_axis(&cb);
+ const float mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f;
/* Add two new child nodes */
- children = bvh->totnode;
+ const int children = bvh->totnode;
n->children_offset = children;
pbvh_grow_nodes(bvh, bvh->totnode + 2);
@@ -169,8 +164,8 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
n = &bvh->nodes[node_index];
/* Initialize children */
- c1 = &bvh->nodes[children];
- c2 = &bvh->nodes[children + 1];
+ PBVHNode *c1 = &bvh->nodes[children],
+ *c2 = &bvh->nodes[children + 1];
c1->flag |= PBVH_Leaf;
c2->flag |= PBVH_Leaf;
c1->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_size(n->bm_faces) / 2);
@@ -188,7 +183,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
}
/* Enforce at least one primitive in each node */
- empty = NULL;
+ GSet *empty = NULL, *other;
if (BLI_gset_size(c1->bm_faces) == 0) {
empty = c1->bm_faces;
other = c2->bm_faces;
@@ -242,7 +237,6 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
n->flag &= ~PBVH_Leaf;
/* Recurse */
- c1 = c2 = NULL;
pbvh_bmesh_node_split(bvh, bbc_array, children);
pbvh_bmesh_node_split(bvh, bbc_array, children + 1);
@@ -259,30 +253,25 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
/* Recursively split the node if it exceeds the leaf_limit */
static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
{
- GSet *bm_faces;
- int bm_faces_size;
- GSetIterator gs_iter;
- BBC *bbc_array;
- unsigned int i;
-
- bm_faces = bvh->nodes[node_index].bm_faces;
- bm_faces_size = BLI_gset_size(bm_faces);
+ GSet *bm_faces = bvh->nodes[node_index].bm_faces;
+ const int bm_faces_size = BLI_gset_size(bm_faces);
if (bm_faces_size <= bvh->leaf_limit) {
/* Node limit not exceeded */
return false;
}
/* For each BMFace, store the AABB and AABB centroid */
- bbc_array = MEM_mallocN(sizeof(BBC) * bm_faces_size, "BBC");
+ BBC *bbc_array = MEM_mallocN(sizeof(BBC) * bm_faces_size, "BBC");
+ GSetIterator gs_iter;
+ int i;
GSET_ITER_INDEX (gs_iter, bm_faces, i) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
BBC *bbc = &bbc_array[i];
- BMLoop *l_iter;
- BMLoop *l_first;
BB_reset((BB *)bbc);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
do {
BB_expand((BB *)bbc, l_iter->v->co);
} while ((l_iter = l_iter->next) != l_first);
@@ -347,12 +336,11 @@ static BMVert *pbvh_bmesh_vert_create(
const int cd_vert_mask_offset)
{
PBVHNode *node = &bvh->nodes[node_index];
- BMVert *v;
BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode);
/* avoid initializing customdata because its quite involved */
- v = BM_vert_create(bvh->bm, co, NULL, BM_CREATE_SKIP_CD);
+ BMVert *v = BM_vert_create(bvh->bm, co, NULL, BM_CREATE_SKIP_CD);
CustomData_bmesh_set_default(&bvh->bm->vdata, &v->head.data);
/* This value is logged below */
@@ -374,13 +362,12 @@ static BMFace *pbvh_bmesh_face_create(
BMVert *v_tri[3], BMEdge *e_tri[3],
const BMFace *f_example)
{
- BMFace *f;
PBVHNode *node = &bvh->nodes[node_index];
/* ensure we never add existing face */
BLI_assert(BM_face_exists(v_tri, 3, NULL) == false);
- f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NO_DOUBLE);
+ BMFace *f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NO_DOUBLE);
f->head.hflag = f_example->head.hflag;
BLI_gset_insert(node->bm_faces, f);
@@ -442,14 +429,10 @@ static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v)
{
BMIter bm_iter;
BMFace *f;
- PBVHNode *current_node;
-
- current_node = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *current_node = pbvh_bmesh_node_lookup(bvh, v);
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- PBVHNode *f_node;
-
- f_node = pbvh_bmesh_node_lookup(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f);
if (f_node != current_node)
return f_node;
@@ -462,13 +445,10 @@ static void pbvh_bmesh_vert_ownership_transfer(
PBVH *bvh, PBVHNode *new_owner,
BMVert *v)
{
- PBVHNode *current_owner;
-
- current_owner = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *current_owner = pbvh_bmesh_node_lookup(bvh, v);
/* mark node for update */
current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
-
BLI_assert(current_owner != new_owner);
/* Remove current ownership */
@@ -486,21 +466,18 @@ static void pbvh_bmesh_vert_ownership_transfer(
static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
{
- PBVHNode *v_node;
- BMIter bm_iter;
- BMFace *f;
-
/* never match for first time */
int f_node_index_prev = DYNTOPO_NODE_NONE;
- v_node = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *v_node = pbvh_bmesh_node_lookup(bvh, v);
BLI_gset_remove(v_node->bm_unique_verts, v, NULL);
BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
/* Have to check each neighboring face's node */
+ BMIter bm_iter;
+ BMFace *f;
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
const int f_node_index = pbvh_bmesh_node_lookup_index(bvh, f);
- PBVHNode *f_node;
/* faces often share the same node,
* quick check to avoid redundant #BLI_gset_remove calls */
@@ -508,7 +485,7 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
continue;
f_node_index_prev = f_node_index;
- f_node = &bvh->nodes[f_node_index];
+ PBVHNode *f_node = &bvh->nodes[f_node_index];
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
/* Remove current ownership */
@@ -521,19 +498,14 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
{
- PBVHNode *f_node;
- BMVert *v;
-
- BMLoop *l_iter;
- BMLoop *l_first;
-
- f_node = pbvh_bmesh_node_lookup(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f);
/* Check if any of this face's vertices need to be removed
* from the node */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
do {
- v = l_iter->v;
+ BMVert *v = l_iter->v;
if (pbvh_bmesh_node_vert_use_count_is_equal(bvh, f_node, v, 1)) {
if (BLI_gset_haskey(f_node->bm_unique_verts, v)) {
/* Find a different node that uses 'v' */
@@ -630,12 +602,10 @@ typedef struct {
* (it's a requirement that edges enter and leave a clean tag state) */
static void pbvh_bmesh_edge_tag_verify(PBVH *bvh)
{
- int n;
-
- for (n = 0; n < bvh->totnode; n++) {
+ for (int n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
- GSetIterator gs_iter;
if (node->bm_faces) {
+ GSetIterator gs_iter;
GSET_ITER (gs_iter, node->bm_faces) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
BMEdge *e_tri[3];
@@ -668,21 +638,19 @@ static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
closest_on_tri_to_point_v3(c, q->center, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
/* Check if triangle intersects the sphere */
- return ((len_squared_v3v3(q->center, c) <= q->radius_squared));
+ return len_squared_v3v3(q->center, c) <= q->radius_squared;
}
/* Return true if the vertex mask is less than 1.0, false otherwise */
static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v)
{
- return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f);
+ return BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f;
}
static void edge_queue_insert(
EdgeQueueContext *eq_ctx, BMEdge *e,
float priority)
{
- BMVert **pair;
-
/* Don't let topology update affect fully masked vertices. This used to
* have a 50% mask cutoff, with the reasoning that you can't do a 50%
* topology update. But this gives an ugly border in the mesh. The mask
@@ -694,7 +662,7 @@ static void edge_queue_insert(
!(BM_elem_flag_test_bool(e->v1, BM_ELEM_HIDDEN) ||
BM_elem_flag_test_bool(e->v2, BM_ELEM_HIDDEN)))
{
- pair = BLI_mempool_alloc(eq_ctx->pool);
+ BMVert **pair = BLI_mempool_alloc(eq_ctx->pool);
pair[0] = e->v1;
pair[1] = e->v2;
BLI_heap_insert(eq_ctx->q->heap, priority, pair);
@@ -757,19 +725,15 @@ static void long_edge_queue_edge_add_recursive(
#define EVEN_GENERATION_SCALE 1.6f
const float len_sq_cmp = len_sq * EVEN_EDGELEN_THRESHOLD;
- float limit_len_sq;
- BMLoop *l_iter;
limit_len *= EVEN_GENERATION_SCALE;
- limit_len_sq = SQUARE(limit_len);
+ const float limit_len_sq = SQUARE(limit_len);
- l_iter = l_edge;
+ BMLoop *l_iter = l_edge;
do {
- float len_sq_other;
BMLoop *l_adjacent[2] = {l_iter->next, l_iter->prev};
- int i;
- for (i = 0; i < ARRAY_SIZE(l_adjacent); i++) {
- len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e);
+ for (int i = 0; i < ARRAY_SIZE(l_adjacent); i++) {
+ float len_sq_other = BM_edge_calc_length_squared(l_adjacent[i]->e);
if (len_sq_other > max_ff(len_sq_cmp, limit_len_sq)) {
// edge_queue_insert(eq_ctx, l_adjacent[i]->e, -len_sq_other);
long_edge_queue_edge_add_recursive(
@@ -813,24 +777,20 @@ static void long_edge_queue_face_add(
#endif
if (edge_queue_tri_in_sphere(eq_ctx->q, f)) {
- BMLoop *l_iter;
- BMLoop *l_first;
-
/* Check each edge of the face */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
do {
- {
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
- const float len_sq = BM_edge_calc_length_squared(l_iter->e);
- if (len_sq > eq_ctx->q->limit_len_squared) {
- long_edge_queue_edge_add_recursive(
- eq_ctx, l_iter->radial_next, l_iter,
- len_sq, eq_ctx->q->limit_len);
- }
+ const float len_sq = BM_edge_calc_length_squared(l_iter->e);
+ if (len_sq > eq_ctx->q->limit_len_squared) {
+ long_edge_queue_edge_add_recursive(
+ eq_ctx, l_iter->radial_next, l_iter,
+ len_sq, eq_ctx->q->limit_len);
+ }
#else
- long_edge_queue_edge_add(eq_ctx, l_iter->e);
+ long_edge_queue_edge_add(eq_ctx, l_iter->e);
#endif
- }
} while ((l_iter = l_iter->next) != l_first);
}
}
@@ -873,8 +833,6 @@ static void long_edge_queue_create(
PBVH *bvh, const float center[3], const float view_normal[3],
float radius)
{
- int n;
-
eq_ctx->q->heap = BLI_heap_new();
eq_ctx->q->center = center;
eq_ctx->q->radius_squared = radius * radius;
@@ -894,8 +852,7 @@ static void long_edge_queue_create(
pbvh_bmesh_edge_tag_verify(bvh);
#endif
-
- for (n = 0; n < bvh->totnode; n++) {
+ for (int n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
/* Check leaf nodes marked for topology update */
@@ -929,8 +886,6 @@ static void short_edge_queue_create(
PBVH *bvh, const float center[3], const float view_normal[3],
float radius)
{
- int n;
-
eq_ctx->q->heap = BLI_heap_new();
eq_ctx->q->center = center;
eq_ctx->q->radius_squared = radius * radius;
@@ -946,7 +901,7 @@ static void short_edge_queue_create(
UNUSED_VARS(view_normal);
#endif
- for (n = 0; n < bvh->totnode; n++) {
+ for (int n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
/* Check leaf nodes marked for topology update */
@@ -979,9 +934,7 @@ static void pbvh_bmesh_split_edge(
EdgeQueueContext *eq_ctx, PBVH *bvh,
BMEdge *e, BLI_Buffer *edge_loops)
{
- BMVert *v_new;
float co_mid[3], no_mid[3];
- int i, node_index;
/* Get all faces adjacent to the edge */
pbvh_bmesh_edge_loops(edge_loops, e);
@@ -991,8 +944,8 @@ static void pbvh_bmesh_split_edge(
mid_v3_v3v3(no_mid, e->v1->no, e->v2->no);
normalize_v3(no_mid);
- node_index = BM_ELEM_CD_GET_INT(e->v1, eq_ctx->cd_vert_node_offset);
- v_new = pbvh_bmesh_vert_create(bvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset);
+ int node_index = BM_ELEM_CD_GET_INT(e->v1, eq_ctx->cd_vert_node_offset);
+ BMVert *v_new = pbvh_bmesh_vert_create(bvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset);
/* update paint mask */
if (eq_ctx->cd_vert_mask_offset != -1) {
@@ -1004,17 +957,16 @@ static void pbvh_bmesh_split_edge(
}
/* For each face, add two new triangles and delete the original */
- for (i = 0; i < edge_loops->count; i++) {
+ for (int i = 0; i < edge_loops->count; i++) {
BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i);
BMFace *f_adj = l_adj->f;
BMFace *f_new;
BMVert *v_opp, *v1, *v2;
BMVert *v_tri[3];
BMEdge *e_tri[3];
- int ni;
BLI_assert(f_adj->len == 3);
- ni = BM_ELEM_CD_GET_INT(f_adj, eq_ctx->cd_face_node_offset);
+ int ni = BM_ELEM_CD_GET_INT(f_adj, eq_ctx->cd_face_node_offset);
/* Find the vertex not in the edge */
v_opp = l_adj->prev->v;
@@ -1153,11 +1105,7 @@ static void pbvh_bmesh_collapse_edge(
BLI_Buffer *deleted_faces,
EdgeQueueContext *eq_ctx)
{
- BMIter bm_iter;
- BMFace *f;
- BMLoop *l_adj;
BMVert *v_del, *v_conn;
- int i;
float mask_v1 = BM_ELEM_CD_GET_FLOAT(v1, eq_ctx->cd_vert_mask_offset);
/* one of the two vertices may be masked, select the correct one for deletion */
@@ -1174,6 +1122,7 @@ static void pbvh_bmesh_collapse_edge(
pbvh_bmesh_vert_remove(bvh, v_del);
/* Remove all faces adjacent to the edge */
+ BMLoop *l_adj;
while ((l_adj = e->l)) {
BMFace *f_adj = l_adj->f;
@@ -1192,16 +1141,17 @@ static void pbvh_bmesh_collapse_edge(
* really buy anything. */
BLI_buffer_empty(deleted_faces);
+ BMIter bm_iter;
+ BMFace *f;
+
BM_ITER_ELEM (f, &bm_iter, v_del, BM_FACES_OF_VERT) {
BMVert *v_tri[3];
BMFace *existing_face;
- PBVHNode *n;
- int ni;
/* Get vertices, replace use of v_del with v_conn */
// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3);
BM_face_as_array_vert_tri(f, v_tri);
- for (i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++) {
if (v_tri[i] == v_del) {
v_tri[i] = v_conn;
}
@@ -1217,8 +1167,8 @@ static void pbvh_bmesh_collapse_edge(
}
else {
BMEdge *e_tri[3];
- n = pbvh_bmesh_node_lookup(bvh, f);
- ni = n - bvh->nodes;
+ PBVHNode *n = pbvh_bmesh_node_lookup(bvh, f);
+ int ni = n - bvh->nodes;
bm_edges_from_tri(bvh->bm, v_tri, e_tri);
pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f);
@@ -1232,16 +1182,14 @@ static void pbvh_bmesh_collapse_edge(
}
/* Delete the tagged faces */
- for (i = 0; i < deleted_faces->count; i++) {
+ for (int i = 0; i < deleted_faces->count; i++) {
BMFace *f_del = BLI_buffer_at(deleted_faces, BMFace *, i);
- BMLoop *l_iter;
- BMVert *v_tri[3];
- BMEdge *e_tri[3];
- int j;
/* Get vertices and edges of face */
BLI_assert(f_del->len == 3);
- l_iter = BM_FACE_FIRST_LOOP(f_del);
+ BMLoop *l_iter = BM_FACE_FIRST_LOOP(f_del);
+ BMVert *v_tri[3];
+ BMEdge *e_tri[3];
v_tri[0] = l_iter->v; e_tri[0] = l_iter->e; l_iter = l_iter->next;
v_tri[1] = l_iter->v; e_tri[1] = l_iter->e; l_iter = l_iter->next;
v_tri[2] = l_iter->v; e_tri[2] = l_iter->e;
@@ -1252,14 +1200,14 @@ static void pbvh_bmesh_collapse_edge(
/* Check if any of the face's edges are now unused by any
* face, if so delete them */
- for (j = 0; j < 3; j++) {
+ for (int j = 0; j < 3; j++) {
if (BM_edge_is_wire(e_tri[j]))
BM_edge_kill(bvh->bm, e_tri[j]);
}
/* Check if any of the face's vertices are now unused, if so
* remove them from the PBVH */
- for (j = 0; j < 3; j++) {
+ for (int j = 0; j < 3; j++) {
if ((v_tri[j] != v_del) && (v_tri[j]->e == NULL)) {
BLI_gset_insert(deleted_verts, v_tri[j]);
pbvh_bmesh_vert_remove(bvh, v_tri[j]);
@@ -1291,17 +1239,13 @@ static bool pbvh_bmesh_collapse_short_edges(
PBVH *bvh,
BLI_Buffer *deleted_faces)
{
- float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
- GSet *deleted_verts;
+ const float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
bool any_collapsed = false;
-
- deleted_verts = BLI_gset_ptr_new("deleted_verts");
+ GSet *deleted_verts = BLI_gset_ptr_new("deleted_verts");
while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
BMVert *v1 = pair[0], *v2 = pair[1];
- BMEdge *e;
-
BLI_mempool_free(eq_ctx->pool, pair);
pair = NULL;
@@ -1313,6 +1257,7 @@ static bool pbvh_bmesh_collapse_short_edges(
}
/* Check that the edge still exists */
+ BMEdge *e;
if (!(e = BM_edge_exists(v1, v2))) {
continue;
}
@@ -1355,8 +1300,7 @@ bool pbvh_bmesh_node_raycast(
bool hit = false;
if (use_original && node->bm_tot_ortri) {
- int i;
- for (i = 0; i < node->bm_tot_ortri; i++) {
+ for (int i = 0; i < node->bm_tot_ortri; i++) {
const int *t = node->bm_ortri[i];
hit |= ray_face_intersection_tri(
ray_start, ray_normal,
@@ -1395,13 +1339,13 @@ bool BKE_pbvh_bmesh_node_raycast_detail(
const float ray_start[3], const float ray_normal[3],
float *dist, float *r_detail)
{
+ if (node->flag & PBVH_FullyHidden)
+ return 0;
+
GSetIterator gs_iter;
bool hit = false;
BMFace *f_hit = NULL;
- if (node->flag & PBVH_FullyHidden)
- return 0;
-
GSET_ITER (gs_iter, node->bm_faces) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
@@ -1425,12 +1369,11 @@ bool BKE_pbvh_bmesh_node_raycast_detail(
}
if (hit) {
- float len1, len2, len3;
BMVert *v_tri[3];
BM_face_as_array_vert_tri(f_hit, v_tri);
- len1 = len_squared_v3v3(v_tri[0]->co, v_tri[1]->co);
- len2 = len_squared_v3v3(v_tri[1]->co, v_tri[2]->co);
- len3 = len_squared_v3v3(v_tri[2]->co, v_tri[0]->co);
+ float len1 = len_squared_v3v3(v_tri[0]->co, v_tri[1]->co);
+ float len2 = len_squared_v3v3(v_tri[1]->co, v_tri[2]->co);
+ float len3 = len_squared_v3v3(v_tri[2]->co, v_tri[0]->co);
/* detail returned will be set to the maximum allowed size, so take max here */
*r_detail = sqrtf(max_fff(len1, len2, len3));
@@ -1442,9 +1385,7 @@ bool BKE_pbvh_bmesh_node_raycast_detail(
void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
{
- int n;
-
- for (n = 0; n < totnode; n++) {
+ for (int n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
if (node->flag & PBVH_UpdateNormals) {
@@ -1476,25 +1417,18 @@ typedef struct FastNodeBuildInfo {
* to a sub part of the arrays */
static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, FastNodeBuildInfo *node, MemArena *arena)
{
- BMFace *f;
- BB cb;
- BBC *bbc;
- float mid;
- int axis, i;
- int end;
FastNodeBuildInfo *child1, *child2;
- int num_child1, num_child2;
- BMFace *tmp;
if (node->totface <= bvh->leaf_limit) {
return;
}
/* Calculate bounding box around primitive centroids */
+ BB cb;
BB_reset(&cb);
- for (i = 0; i < node->totface; i++) {
- f = nodeinfo[i + node->start];
- bbc = &bbc_array[BM_elem_index_get(f)];
+ for (int i = 0; i < node->totface; i++) {
+ BMFace *f = nodeinfo[i + node->start];
+ BBC *bbc = &bbc_array[BM_elem_index_get(f)];
BB_expand(&cb, bbc->bcentroid);
}
@@ -1502,16 +1436,16 @@ static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC
/* initialize the children */
/* Find widest axis and its midpoint */
- axis = BB_widest_axis(&cb);
- mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f;
+ const int axis = BB_widest_axis(&cb);
+ const float mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f;
- num_child1 = 0, num_child2 = 0;
+ int num_child1 = 0, num_child2 = 0;
/* split vertices along the middle line */
- end = node->start + node->totface;
- for (i = node->start; i < end - num_child2; i++) {
- f = nodeinfo[i];
- bbc = &bbc_array[BM_elem_index_get(f)];
+ const int end = node->start + node->totface;
+ for (int i = node->start; i < end - num_child2; i++) {
+ BMFace *f = nodeinfo[i];
+ BBC *bbc = &bbc_array[BM_elem_index_get(f)];
if (bbc->bcentroid[axis] > mid) {
int i_iter = end - num_child2 - 1;
@@ -1531,7 +1465,7 @@ static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC
}
if (candidate != -1) {
- tmp = nodeinfo[i];
+ BMFace *tmp = nodeinfo[i];
nodeinfo[i] = nodeinfo[candidate];
nodeinfo[candidate] = tmp;
/* increase both counts */
@@ -1574,8 +1508,6 @@ static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC
pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child1, arena);
pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child2, arena);
-
- return;
}
static void pbvh_bmesh_create_nodes_fast_recursive(PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, FastNodeBuildInfo *node, int node_index)
@@ -1605,12 +1537,6 @@ static void pbvh_bmesh_create_nodes_fast_recursive(PBVH *bvh, BMFace **nodeinfo,
const int cd_face_node_offset = bvh->cd_face_node_offset;
bool has_visible = false;
- int i, end;
- BMFace *f;
- BMLoop *l_iter;
- BMLoop *l_first;
- BMVert *v;
- BBC *bbc;
n->flag = PBVH_Leaf;
n->bm_faces = BLI_gset_ptr_new_ex("bm_faces", node->totface);
@@ -1621,20 +1547,21 @@ static void pbvh_bmesh_create_nodes_fast_recursive(PBVH *bvh, BMFace **nodeinfo,
BB_reset(&n->vb);
- end = node->start + node->totface;
+ const int end = node->start + node->totface;
- for (i = node->start; i < end; i++) {
- f = nodeinfo[i];
- bbc = &bbc_array[BM_elem_index_get(f)];
+ for (int i = node->start; i < end; i++) {
+ BMFace *f = nodeinfo[i];
+ BBC *bbc = &bbc_array[BM_elem_index_get(f)];
/* Update ownership of faces */
BLI_gset_insert(n->bm_faces, f);
BM_ELEM_CD_SET_INT(f, cd_face_node_offset, node_index);
/* Update vertices */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
do {
- v = l_iter->v;
+ BMVert *v = l_iter->v;
if (!BLI_gset_haskey(n->bm_unique_verts, v)) {
if (BM_ELEM_CD_GET_INT(v, cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
BLI_gset_add(n->bm_other_verts, v);
@@ -1654,8 +1581,8 @@ static void pbvh_bmesh_create_nodes_fast_recursive(PBVH *bvh, BMFace **nodeinfo,
}
BLI_assert(n->vb.bmin[0] <= n->vb.bmax[0] &&
- n->vb.bmin[1] <= n->vb.bmax[1] &&
- n->vb.bmin[2] <= n->vb.bmax[2]);
+ n->vb.bmin[1] <= n->vb.bmax[1] &&
+ n->vb.bmin[2] <= n->vb.bmax[2]);
n->orig_vb = n->vb;
@@ -1675,16 +1602,6 @@ void BKE_pbvh_build_bmesh(
PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log,
const int cd_vert_node_offset, const int cd_face_node_offset)
{
- BMIter iter;
- BMFace *f;
- BMVert *v;
- int i;
- /* bounding box array of all faces, no need to recalculate every time */
- BBC *bbc_array;
- BMFace **nodeinfo;
- FastNodeBuildInfo rootnode = {0};
- MemArena *arena;
-
bvh->cd_vert_node_offset = cd_vert_node_offset;
bvh->cd_face_node_offset = cd_face_node_offset;
bvh->bm = bm;
@@ -1700,18 +1617,20 @@ void BKE_pbvh_build_bmesh(
if (smooth_shading)
bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
- /* calculate all bounding boxes once for all faces */
- bbc_array = MEM_mallocN(sizeof(BBC) * bm->totface, "BBC");
- nodeinfo = MEM_mallocN(sizeof(*nodeinfo) * bm->totface, "nodeinfo");
- arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "fast PBVH node storage");
+ /* bounding box array of all faces, no need to recalculate every time */
+ BBC *bbc_array = MEM_mallocN(sizeof(BBC) * bm->totface, "BBC");
+ BMFace **nodeinfo = MEM_mallocN(sizeof(*nodeinfo) * bm->totface, "nodeinfo");
+ MemArena *arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "fast PBVH node storage");
+ BMIter iter;
+ BMFace *f;
+ int i;
BM_ITER_MESH_INDEX(f, &iter, bm, BM_FACES_OF_MESH, i) {
BBC *bbc = &bbc_array[i];
- BMLoop *l_iter;
- BMLoop *l_first;
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
BB_reset((BB *)bbc);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
BB_expand((BB *)bbc, l_iter->v->co);
} while ((l_iter = l_iter->next) != l_first);
@@ -1723,6 +1642,7 @@ void BKE_pbvh_build_bmesh(
BM_ELEM_CD_SET_INT(f, cd_face_node_offset, DYNTOPO_NODE_NONE);
}
+ BMVert *v;
BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE);
}
@@ -1731,6 +1651,7 @@ void BKE_pbvh_build_bmesh(
bm->elem_index_dirty |= BM_FACE;
/* setup root node */
+ FastNodeBuildInfo rootnode = {0};
rootnode.totface = bm->totface;
/* start recursion, assign faces to nodes accordingly */
@@ -1764,7 +1685,6 @@ bool BKE_pbvh_bmesh_update_topology(
const int cd_face_node_offset = bvh->cd_face_node_offset;
bool modified = false;
- int n;
if (view_normal) {
BLI_assert(len_squared_v3(view_normal) != 0.0f);
@@ -1796,7 +1716,7 @@ bool BKE_pbvh_bmesh_update_topology(
}
/* Unmark nodes */
- for (n = 0; n < bvh->totnode; n++) {
+ for (int n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
if (node->flag & PBVH_Leaf &&
@@ -1832,23 +1752,21 @@ BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3])
* Skips triangles that are hidden. */
void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
{
- GSetIterator gs_iter;
- int i, totvert, tottri;
-
/* Skip if original coords/triangles are already saved */
if (node->bm_orco)
return;
- totvert = (BLI_gset_size(node->bm_unique_verts) +
- BLI_gset_size(node->bm_other_verts));
+ const int totvert = BLI_gset_size(node->bm_unique_verts) +
+ BLI_gset_size(node->bm_other_verts);
- tottri = BLI_gset_size(node->bm_faces);
+ const int tottri = BLI_gset_size(node->bm_faces);
node->bm_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, __func__);
node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, __func__);
/* Copy out the vertices and assign a temporary index */
- i = 0;
+ int i = 0;
+ GSetIterator gs_iter;
GSET_ITER (gs_iter, node->bm_unique_verts) {
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
copy_v3_v3(node->bm_orco[i], v->co);
@@ -1888,9 +1806,7 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
void BKE_pbvh_bmesh_after_stroke(PBVH *bvh)
{
- int i;
-
- for (i = 0; i < bvh->totnode; i++) {
+ for (int i = 0; i < bvh->totnode; i++) {
PBVHNode *n = &bvh->nodes[i];
if (n->flag & PBVH_Leaf) {
/* Free orco/ortri data */
@@ -1935,15 +1851,11 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node)
static void pbvh_bmesh_print(PBVH *bvh)
{
- GSetIterator gs_iter;
- int n;
- BMIter iter;
- BMFace *f;
- BMVert *v;
-
fprintf(stderr, "\npbvh=%p\n", bvh);
fprintf(stderr, "bm_face_to_node:\n");
+ BMIter iter;
+ BMFace *f;
BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
fprintf(stderr, " %d -> %d\n",
BM_elem_index_get(v),
@@ -1951,17 +1863,19 @@ static void pbvh_bmesh_print(PBVH *bvh)
}
fprintf(stderr, "bm_vert_to_node:\n");
+ BMVert *v;
BM_ITER_MESH(v, &iter, bvh->bm, BM_FACES_OF_MESH) {
fprintf(stderr, " %d -> %d\n",
BM_elem_index_get(v),
pbvh_bmesh_node_lookup_index(bvh, v));
}
- for (n = 0; n < bvh->totnode; n++) {
+ for (int n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
if (!(node->flag & PBVH_Leaf))
continue;
+ GSetIterator gs_iter;
fprintf(stderr, "node %d\n faces:\n", n);
GSET_ITER (gs_iter, node->bm_faces)
fprintf(stderr, " %d\n",
@@ -1979,9 +1893,8 @@ static void pbvh_bmesh_print(PBVH *bvh)
static void print_flag_factors(int flag)
{
- int i;
printf("flag=0x%x:\n", flag);
- for (i = 0; i < 32; i++) {
+ for (int i = 0; i < 32; i++) {
if (flag & (1 << i)) {
printf(" %d (1 << %d)\n", 1 << i, i);
}
@@ -1994,23 +1907,16 @@ static void print_flag_factors(int flag)
static void pbvh_bmesh_verify(PBVH *bvh)
{
- GSetIterator gs_iter;
- int i;
- BMIter iter;
- BMFace *f;
- BMVert *v;
-
- GSet *faces_all;
- GSet *verts_all;
-
-
/* build list of faces & verts to lookup */
- faces_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totface);
- verts_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totvert);
-
+ GSet *faces_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totface);
+ BMFace *f;
+ BMIter iter;
BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
BLI_gset_insert(faces_all, f);
}
+
+ GSet *verts_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totvert);
+ BMVert *v;
BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
BLI_gset_insert(verts_all, v);
@@ -2020,7 +1926,7 @@ static void pbvh_bmesh_verify(PBVH *bvh)
/* Check vert/face counts */
{
int totface = 0, totvert = 0;
- for (i = 0; i < bvh->totnode; i++) {
+ for (int i = 0; i < bvh->totnode; i++) {
PBVHNode *n = &bvh->nodes[i];
totface += n->bm_faces ? BLI_gset_size(n->bm_faces) : 0;
totvert += n->bm_unique_verts ? BLI_gset_size(n->bm_unique_verts) : 0;
@@ -2062,16 +1968,12 @@ static void pbvh_bmesh_verify(PBVH *bvh)
/* Check verts */
BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
- BMIter bm_iter;
- PBVHNode *n;
- bool found;
-
/* vertex isn't tracked */
if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
continue;
}
- n = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *n = pbvh_bmesh_node_lookup(bvh, v);
/* Check that the vert's node is a leaf */
BLI_assert(n->flag & PBVH_Leaf);
@@ -2084,6 +1986,8 @@ static void pbvh_bmesh_verify(PBVH *bvh)
/* Check that the vert's node also contains one of the vert's
* adjacent faces */
+ bool found = false;
+ BMIter bm_iter;
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
if (pbvh_bmesh_node_lookup(bvh, f) == n) {
found = true;
@@ -2095,13 +1999,12 @@ static void pbvh_bmesh_verify(PBVH *bvh)
#if 1
/* total freak stuff, check if node exists somewhere else */
/* Slow */
- for (i = 0; i < bvh->totnode; i++) {
+ for (int i = 0; i < bvh->totnode; i++) {
PBVHNode *n_other = &bvh->nodes[i];
if ((n != n_other) && (n_other->bm_unique_verts)) {
BLI_assert(!BLI_gset_haskey(n_other->bm_unique_verts, v));
}
}
-
#endif
}
@@ -2110,7 +2013,7 @@ static void pbvh_bmesh_verify(PBVH *bvh)
/* Slow */
BM_ITER_MESH (vi, &iter, bvh->bm, BM_VERTS_OF_MESH) {
bool has_unique = false;
- for (i = 0; i < bvh->totnode; i++) {
+ for (int i = 0; i < bvh->totnode; i++) {
PBVHNode *n = &bvh->nodes[i];
if ((n->bm_unique_verts != NULL) && BLI_gset_haskey(n->bm_unique_verts, vi))
has_unique = true;
@@ -2124,9 +2027,10 @@ static void pbvh_bmesh_verify(PBVH *bvh)
#endif
/* Check that node elements are recorded in the top level */
- for (i = 0; i < bvh->totnode; i++) {
+ for (int i = 0; i < bvh->totnode; i++) {
PBVHNode *n = &bvh->nodes[i];
if (n->flag & PBVH_Leaf) {
+ GSetIterator gs_iter;
GSET_ITER (gs_iter, n->bm_faces) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index a87935ae23b..7c420549a0d 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -91,6 +91,8 @@
# include AUD_SPECIAL_H
#endif
+#define USE_SCENE_RECURSIVE_HACK
+
static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seqbasep, float cfra, int chanshown);
static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, float cfra);
static void seq_free_animdata(Scene *scene, Sequence *seq);
@@ -1149,6 +1151,33 @@ const char *BKE_sequence_give_name(Sequence *seq)
return name;
}
+ListBase *BKE_sequence_seqbase_get(Sequence *seq, int *r_offset)
+{
+ ListBase *seqbase = NULL;
+
+ switch (seq->type) {
+ case SEQ_TYPE_META:
+ {
+ seqbase = &seq->seqbase;
+ *r_offset = seq->start;
+ break;
+ }
+ case SEQ_TYPE_SCENE:
+ {
+ if (seq->flag & SEQ_SCENE_STRIPS) {
+ Editing *ed = BKE_sequencer_editing_get(seq->scene, false);
+ if (ed) {
+ seqbase = &ed->seqbase;
+ *r_offset = seq->scene->r.sfra;
+ }
+ }
+ break;
+ }
+ }
+
+ return seqbase;
+}
+
/*********************** DO THE SEQUENCE *************************/
static void make_black_ibuf(ImBuf *ibuf)
@@ -3319,6 +3348,40 @@ finally:
return ibuf;
}
+/**
+ * Used for meta-strips & scenes with #SEQ_SCENE_STRIPS flag set.
+ */
+static ImBuf *do_render_strip_seqbase(
+ const SeqRenderData *context, Sequence *seq, float nr,
+ bool use_preprocess)
+{
+ ImBuf *meta_ibuf = NULL, *ibuf = NULL;
+ ListBase *seqbase = NULL;
+ int offset;
+
+ seqbase = BKE_sequence_seqbase_get(seq, &offset);
+
+ if (seqbase && !BLI_listbase_is_empty(seqbase)) {
+ meta_ibuf = seq_render_strip_stack(
+ context, seqbase,
+ /* scene strips don't have their start taken into account */
+ nr + offset, 0);
+ }
+
+ if (meta_ibuf) {
+ ibuf = meta_ibuf;
+ if (ibuf && use_preprocess) {
+ ImBuf *i = IMB_dupImBuf(ibuf);
+
+ IMB_freeImBuf(ibuf);
+
+ ibuf = i;
+ }
+ }
+
+ return ibuf;
+}
+
static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *seq, float cfra)
{
ImBuf *ibuf = NULL;
@@ -3329,22 +3392,38 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s
switch (type) {
case SEQ_TYPE_META:
{
- ImBuf *meta_ibuf = NULL;
-
- if (seq->seqbase.first)
- meta_ibuf = seq_render_strip_stack(context, &seq->seqbase, seq->start + nr, 0);
+ ibuf = do_render_strip_seqbase(context, seq, nr, use_preprocess);
+ break;
+ }
- if (meta_ibuf) {
- ibuf = meta_ibuf;
- if (ibuf && use_preprocess) {
- ImBuf *i = IMB_dupImBuf(ibuf);
+ case SEQ_TYPE_SCENE:
+ {
+ if (seq->flag & SEQ_SCENE_STRIPS) {
+ if (seq->scene && (context->scene != seq->scene)) {
+#ifdef USE_SCENE_RECURSIVE_HACK
+ /* weak recusrive check, same as T32017 */
+ if (seq->scene->id.flag & LIB_DOIT) {
+ break;
+ }
+ seq->scene->id.flag |= LIB_DOIT;
+#endif
- IMB_freeImBuf(ibuf);
+ ibuf = do_render_strip_seqbase(context, seq, nr, use_preprocess);
- ibuf = i;
+#ifdef USE_SCENE_RECURSIVE_HACK
+ seq->scene->id.flag &= ~LIB_DOIT;
+#endif
}
}
+ else {
+ /* scene can be NULL after deletions */
+ ibuf = seq_render_scene_strip(context, seq, nr, cfra);
+ /* Scene strips update all animation, so we need to restore original state.*/
+ BKE_animsys_evaluate_all_animation(context->bmain, context->scene, cfra);
+
+ copy_to_ibuf_still(context, seq, nr, ibuf);
+ }
break;
}
@@ -3395,18 +3474,6 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s
break;
}
- case SEQ_TYPE_SCENE:
- {
- /* scene can be NULL after deletions */
- ibuf = seq_render_scene_strip(context, seq, nr, cfra);
-
- /* Scene strips update all animation, so we need to restore original state.*/
- BKE_animsys_evaluate_all_animation(context->bmain, context->scene, cfra);
-
- copy_to_ibuf_still(context, seq, nr, ibuf);
- break;
- }
-
case SEQ_TYPE_MOVIECLIP:
{
ibuf = seq_render_movieclip_strip(context, seq, nr);
@@ -3731,6 +3798,10 @@ ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int cha
seqbasep = ed->seqbasep;
}
+#ifdef USE_SCENE_RECURSIVE_HACK
+ BKE_main_id_tag_idcode(context->bmain, ID_SCE, false);
+#endif
+
return seq_render_strip_stack(context, seqbasep, cfra, chanshown);
}
@@ -4348,7 +4419,7 @@ bool BKE_sequence_base_shuffle_ex(ListBase *seqbasep, Sequence *test, Scene *evi
test->machine += channel_delta;
BKE_sequence_calc(evil_scene, test);
while (BKE_sequence_test_overlap(seqbasep, test)) {
- if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine <= 1)) {
+ if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine < 1)) {
break;
}
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 86ffb541bf8..1c3ff3d3e02 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -81,7 +81,6 @@ variables on the UI for now
#include "BKE_scene.h"
#include "PIL_time.h"
-// #include "ONL_opennl.h" remove linking to ONL for now
/* callbacks for errors and interrupts and some goo */
static int (*SB_localInterruptCallBack)(void) = NULL;
@@ -1811,14 +1810,14 @@ static void dfdx_spring(int ia, int ic, int op, float dir[3], float L, float len
for (j=0;j<3;j++) {
delta_ij = (i==j ? (1.0f): (0.0f));
m=factor*(dir[i]*dir[j] + (1-L/len)*(delta_ij - dir[i]*dir[j]));
- nlMatrixAdd(ia+i, op+ic+j, m);
+ EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
}
}
else {
for (i=0;i<3;i++)
for (j=0;j<3;j++) {
m=factor*dir[i]*dir[j];
- nlMatrixAdd(ia+i, op+ic+j, m);
+ EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
}
}
}
@@ -1827,13 +1826,13 @@ static void dfdx_spring(int ia, int ic, int op, float dir[3], float L, float len
static void dfdx_goal(int ia, int ic, int op, float factor)
{
int i;
- for (i=0;i<3;i++) nlMatrixAdd(ia+i, op+ic+i, factor);
+ for (i=0;i<3;i++) EIG_linear_solver_matrix_add(ia+i, op+ic+i, factor);
}
static void dfdv_goal(int ia, int ic, float factor)
{
int i;
- for (i=0;i<3;i++) nlMatrixAdd(ia+i, ic+i, factor);
+ for (i=0;i<3;i++) EIG_linear_solver_matrix_add(ia+i, ic+i, factor);
}
*/
static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, float UNUSED(forcetime))
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 7ff292efd8a..53da38b2da8 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -74,9 +74,9 @@
#endif
#include "GPU_draw.h"
-#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_buffers.h"
+#include "GPU_shader.h"
#include "CCGSubSurf.h"
@@ -2810,8 +2810,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
CCG_key_top_level(&key, ss);
ccgdm_pbvh_update(ccgdm);
- if (setDrawOptions != NULL)
- {
+ if (setDrawOptions != NULL) {
const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
DMVertexAttribs attribs = {{{NULL}}};
int i;
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index a81fee2cdb7..9503da6e53e 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -116,14 +116,14 @@ BLI_INLINE bool BLI_ghashIterator_done(GHashIterator *ghi) { return !ghi
# define _gh_Entry void
#endif
-#define GHASH_ITER(gh_iter_, ghash_) \
- for (BLI_ghashIterator_init(&gh_iter_, ghash_); \
- BLI_ghashIterator_done(&gh_iter_) == false; \
+#define GHASH_ITER(gh_iter_, ghash_) \
+ for (BLI_ghashIterator_init(&gh_iter_, ghash_); \
+ BLI_ghashIterator_done(&gh_iter_) == false; \
BLI_ghashIterator_step(&gh_iter_))
-#define GHASH_ITER_INDEX(gh_iter_, ghash_, i_) \
- for (BLI_ghashIterator_init(&gh_iter_, ghash_), i_ = 0; \
- BLI_ghashIterator_done(&gh_iter_) == false; \
+#define GHASH_ITER_INDEX(gh_iter_, ghash_, i_) \
+ for (BLI_ghashIterator_init(&gh_iter_, ghash_), i_ = 0; \
+ BLI_ghashIterator_done(&gh_iter_) == false; \
BLI_ghashIterator_step(&gh_iter_), i_++)
/** \name Callbacks for GHash
@@ -249,14 +249,14 @@ BLI_INLINE void *BLI_gsetIterator_getKey(GSetIterator *gsi) { return BLI_ghashIt
BLI_INLINE void BLI_gsetIterator_step(GSetIterator *gsi) { BLI_ghashIterator_step((GHashIterator *)gsi); }
BLI_INLINE bool BLI_gsetIterator_done(GSetIterator *gsi) { return BLI_ghashIterator_done((GHashIterator *)gsi); }
-#define GSET_ITER(gs_iter_, gset_) \
- for (BLI_gsetIterator_init(&gs_iter_, gset_); \
- BLI_gsetIterator_done(&gs_iter_) == false; \
+#define GSET_ITER(gs_iter_, gset_) \
+ for (BLI_gsetIterator_init(&gs_iter_, gset_); \
+ BLI_gsetIterator_done(&gs_iter_) == false; \
BLI_gsetIterator_step(&gs_iter_))
-#define GSET_ITER_INDEX(gs_iter_, gset_, i_) \
- for (BLI_gsetIterator_init(&gs_iter_, gset_), i_ = 0; \
- BLI_gsetIterator_done(&gs_iter_) == false; \
+#define GSET_ITER_INDEX(gs_iter_, gset_, i_) \
+ for (BLI_gsetIterator_init(&gs_iter_, gset_), i_ = 0; \
+ BLI_gsetIterator_done(&gs_iter_) == false; \
BLI_gsetIterator_step(&gs_iter_), i_++)
diff --git a/source/blender/blenlib/BLI_kdtree.h b/source/blender/blenlib/BLI_kdtree.h
index d488dbce1fd..aa54e1c823c 100644
--- a/source/blender/blenlib/BLI_kdtree.h
+++ b/source/blender/blenlib/BLI_kdtree.h
@@ -58,6 +58,10 @@ int BLI_kdtree_find_nearest(
#define BLI_kdtree_range_search(tree, co, r_nearest, range) \
BLI_kdtree_range_search__normal(tree, co, NULL, r_nearest, range)
+int BLI_kdtree_find_nearest_cb(
+ const KDTree *tree, const float co[3],
+ int (*filter_cb)(void *user_data, int index, const float co[3], float dist_sq), void *user_data,
+ KDTreeNearest *r_nearest);
void BLI_kdtree_range_search_cb(
const KDTree *tree, const float co[3], float range,
bool (*search_cb)(void *user_data, int index, const float co[3], float dist_sq), void *user_data);
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h
index 67cb30e8d17..367f1bb9de5 100644
--- a/source/blender/blenlib/BLI_linklist.h
+++ b/source/blender/blenlib/BLI_linklist.h
@@ -58,8 +58,8 @@ typedef struct LinkNodePair {
LinkNode *list, *last_node;
} LinkNodePair;
-int BLI_linklist_count(LinkNode *list) ATTR_WARN_UNUSED_RESULT;
-int BLI_linklist_index(LinkNode *list, void *ptr) ATTR_WARN_UNUSED_RESULT;
+int BLI_linklist_count(const LinkNode *list) ATTR_WARN_UNUSED_RESULT;
+int BLI_linklist_index(const LinkNode *list, void *ptr) ATTR_WARN_UNUSED_RESULT;
LinkNode *BLI_linklist_find(LinkNode *list, int index) ATTR_WARN_UNUSED_RESULT;
@@ -91,5 +91,7 @@ LinkNode *BLI_linklist_sort_r(LinkNode *list, int (*cmp)(void *, const void *, c
#define BLI_linklist_prepend_alloca(listp, ptr) \
BLI_linklist_prepend_nlink(listp, ptr, alloca(sizeof(LinkNode)))
+#define BLI_linklist_append_alloca(list_pair, ptr) \
+ BLI_linklist_append_nlink(list_pair, ptr, alloca(sizeof(LinkNode)))
#endif /* __BLI_LINKLIST_H__ */
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
index c5f9be927d3..dd92dcec936 100644
--- a/source/blender/blenlib/BLI_linklist_stack.h
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -161,7 +161,7 @@
(_BLI_SMALLSTACK_CAST(var_src) ((_##var_src##_stack) ? \
(_BLI_SMALLSTACK_DEL_EX(var_src, var_dst), (_##var_dst##_free->link)) : NULL))
-#define BLI_SMALLSTACK_LAST(var) \
+#define BLI_SMALLSTACK_PEEK(var) \
(_BLI_SMALLSTACK_CAST(var) ((_##var##_stack) ? \
_##var##_stack->link : NULL))
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index d804b57ffe1..b0421c39707 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -244,6 +244,11 @@ bool isect_ray_tri_watertight_v3_simple(
const float v0[3], const float v1[3], const float v2[3],
float *r_lambda, float r_uv[2]);
+bool isect_ray_seg_v2(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3],
+ float *r_lambda, float *r_u);
+
/* point in polygon */
bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr, const bool use_holes);
bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr, const bool use_holes);
@@ -417,7 +422,8 @@ void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]);
MINLINE void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3]);
MINLINE float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE int axis_dominant_v3_single(const float vec[3]);
+MINLINE int axis_dominant_v3_single(const float vec[3]);
+MINLINE int axis_dominant_v3_ortho_single(const float vec[3]);
MINLINE int max_axis_v3(const float vec[3]);
MINLINE int min_axis_v3(const float vec[3]);
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 5900e391d3e..6fb983a622e 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -173,6 +173,10 @@ bool is_orthonormal_m4(float mat[4][4]);
bool is_uniform_scaled_m3(float mat[3][3]);
bool is_uniform_scaled_m4(float m[4][4]);
+/* Note: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix!
+ * Nowadays 'adjoint' usually refers to the conjugate transpose,
+ * which for real-valued matrices is simply the transpose.
+ */
void adjoint_m2_m2(float R[2][2], float A[2][2]);
void adjoint_m3_m3(float R[3][3], float A[3][3]);
void adjoint_m4_m4(float R[4][4], float A[4][4]);
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index 81c277cd956..45a6e0b02c1 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -112,10 +112,12 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
size_t BLI_task_pool_tasks_done(TaskPool *pool);
/* Parallel for routines */
-typedef void (*TaskParallelRangeFunc)(void *userdata, int iter);
+typedef void (*TaskParallelRangeFunc)(void *userdata, void *userdata_chunk, int iter);
void BLI_task_parallel_range_ex(
int start, int stop,
void *userdata,
+ void *userdata_chunk,
+ const size_t userdata_chunk_size,
TaskParallelRangeFunc func,
const int range_threshold,
const bool use_dynamic_scheduling);
diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h
index 8cf6f188e19..b421b7dbb90 100644
--- a/source/blender/blenlib/BLI_winstuff.h
+++ b/source/blender/blenlib/BLI_winstuff.h
@@ -90,7 +90,9 @@ extern "C" {
#endif
/* defines for using ISO C++ conformant names */
-#define snprintf _snprintf
+#if !defined(_MSC_VER) || _MSC_VER < 1900
+# define snprintf _snprintf
+#endif
#if defined(_MSC_VER) || (defined(FREE_WINDOWS) && !defined(FREE_WINDOWS64))
# define R_OK 4
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 0de614a5ca7..944ba60eb58 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -29,8 +29,8 @@ set(INC
../makesdna
../../../intern/guardedalloc
../../../intern/atomic
+ ../../../intern/eigen
../../../extern/wcwidth
- ../../../extern/Eigen3
)
set(INC_SYS
diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript
index 0e4b9bf4efd..5f92741fde2 100644
--- a/source/blender/blenlib/SConscript
+++ b/source/blender/blenlib/SConscript
@@ -34,9 +34,9 @@ cflags=''
incs = [
'.',
'#/extern/wcwidth',
- '#/extern/Eigen3',
'#/intern/guardedalloc',
'#/intern/atomic',
+ '#/intern/eigen',
'../makesdna',
env['BF_FREETYPE_INC'],
env['BF_ZLIB_INC'],
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 7e6dabdffef..29b07b37932 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -155,7 +155,7 @@ BLI_INLINE unsigned int ghash_entryhash(GHash *gh, const Entry *e)
}
/**
- * Get the bucket-hash for an already-computed full hash.
+ * Get the bucket-index for an already-computed full hash.
*/
BLI_INLINE unsigned int ghash_bucket_index(GHash *gh, const unsigned int hash)
{
@@ -175,7 +175,6 @@ static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets)
Entry **buckets_new;
const unsigned int nbuckets_old = gh->nbuckets;
unsigned int i;
- Entry *e;
BLI_assert((gh->nbuckets != nbuckets) || !gh->buckets);
// printf("%s: %d -> %d\n", __func__, nbuckets_old, nbuckets);
@@ -191,8 +190,7 @@ static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets)
if (buckets_old) {
if (nbuckets > nbuckets_old) {
for (i = 0; i < nbuckets_old; i++) {
- Entry *e_next;
- for (e = buckets_old[i]; e; e = e_next) {
+ for (Entry *e = buckets_old[i], *e_next; e; e = e_next) {
const unsigned hash = ghash_entryhash(gh, e);
const unsigned bucket_index = ghash_bucket_index(gh, hash);
e_next = e->next;
@@ -204,8 +202,7 @@ static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets)
else {
for (i = 0; i < nbuckets_old; i++) {
#ifdef GHASH_USE_MODULO_BUCKETS
- Entry *e_next;
- for (e = buckets_old[i]; e; e = e_next) {
+ for (Entry *e = buckets_old[i], *e_next; e; e = e_next) {
const unsigned hash = ghash_entryhash(gh, e);
const unsigned bucket_index = ghash_bucket_index(gh, hash);
e_next = e->next;
@@ -217,6 +214,7 @@ static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets)
* will go in same new bucket (i & new_mask)! */
const unsigned bucket_index = ghash_bucket_index(gh, i);
BLI_assert(!buckets_old[i] || (bucket_index == ghash_bucket_index(gh, ghash_entryhash(gh, buckets_old[i]))));
+ Entry *e;
for (e = buckets_old[i]; e && e->next; e = e->next);
if (e) {
e->next = buckets_new[bucket_index];
@@ -376,17 +374,16 @@ BLI_INLINE Entry *ghash_lookup_entry_ex(
/**
* Internal lookup function, returns previous entry of target one too.
- * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times.
+ * Takes bucket_index argument to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times.
* Useful when modifying buckets somehow (like removing an entry...).
*/
BLI_INLINE Entry *ghash_lookup_entry_prev_ex(
- GHash *gh, const void *key, Entry **r_e_prev, const unsigned int bucket_index)
+ GHash *gh, const void *key,
+ Entry **r_e_prev, const unsigned int bucket_index)
{
- Entry *e, *e_prev = NULL;
-
/* If we do not store GHash, not worth computing it for each entry here!
* Typically, comparison function will be quicker, and since it's needed in the end anyway... */
- for (e = gh->buckets[bucket_index]; e; e_prev = e, e = e->next) {
+ for (Entry *e_prev = NULL, *e = gh->buckets[bucket_index]; e; e_prev = e, e = e->next) {
if (UNLIKELY(gh->cmpfp(key, e->key) == false)) {
*r_e_prev = e_prev;
return e;
@@ -487,7 +484,8 @@ BLI_INLINE void ghash_insert(GHash *gh, void *key, void *val)
}
BLI_INLINE bool ghash_insert_safe(
- GHash *gh, void *key, void *val, const bool override, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+ GHash *gh, void *key, void *val, const bool override,
+ GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
const unsigned int hash = ghash_keyhash(gh, key);
const unsigned int bucket_index = ghash_bucket_index(gh, hash);
@@ -497,8 +495,12 @@ BLI_INLINE bool ghash_insert_safe(
if (e) {
if (override) {
- if (keyfreefp) keyfreefp(e->e.key);
- if (valfreefp) valfreefp(e->val);
+ if (keyfreefp) {
+ keyfreefp(e->e.key);
+ }
+ if (valfreefp) {
+ valfreefp(e->val);
+ }
e->e.key = key;
e->val = val;
}
@@ -510,7 +512,9 @@ BLI_INLINE bool ghash_insert_safe(
}
}
-BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, void *key, const bool override, GHashKeyFreeFP keyfreefp)
+BLI_INLINE bool ghash_insert_safe_keyonly(
+ GHash *gh, void *key, const bool override,
+ GHashKeyFreeFP keyfreefp)
{
const unsigned int hash = ghash_keyhash(gh, key);
const unsigned int bucket_index = ghash_bucket_index(gh, hash);
@@ -520,7 +524,9 @@ BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, void *key, const bool overr
if (e) {
if (override) {
- if (keyfreefp) keyfreefp(e->key);
+ if (keyfreefp) {
+ keyfreefp(e->key);
+ }
e->key = key;
}
return false;
@@ -535,7 +541,8 @@ BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, void *key, const bool overr
* Remove the entry and return it, caller must free from gh->entrypool.
*/
static Entry *ghash_remove_ex(
- GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
+ GHash *gh, const void *key,
+ GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
const unsigned int bucket_index)
{
Entry *e_prev;
@@ -544,11 +551,19 @@ static Entry *ghash_remove_ex(
BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET));
if (e) {
- if (keyfreefp) keyfreefp(e->key);
- if (valfreefp) valfreefp(((GHashEntry *)e)->val);
+ if (keyfreefp) {
+ keyfreefp(e->key);
+ }
+ if (valfreefp) {
+ valfreefp(((GHashEntry *)e)->val);
+ }
- if (e_prev) e_prev->next = e->next;
- else gh->buckets[bucket_index] = e->next;
+ if (e_prev) {
+ e_prev->next = e->next;
+ }
+ else {
+ gh->buckets[bucket_index] = e->next;
+ }
ghash_buckets_contract(gh, --gh->nentries, false, false);
}
@@ -559,7 +574,9 @@ static Entry *ghash_remove_ex(
/**
* Run free callbacks for freeing entries.
*/
-static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+static void ghash_free_cb(
+ GHash *gh,
+ GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
unsigned int i;
@@ -570,8 +587,12 @@ static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP va
Entry *e;
for (e = gh->buckets[i]; e; e = e->next) {
- if (keyfreefp) keyfreefp(e->key);
- if (valfreefp) valfreefp(((GHashEntry *)e)->val);
+ if (keyfreefp) {
+ keyfreefp(e->key);
+ }
+ if (valfreefp) {
+ valfreefp(((GHashEntry *)e)->val);
+ }
}
}
}
diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c
index fe822816be4..a81f9b28b83 100644
--- a/source/blender/blenlib/intern/BLI_kdtree.c
+++ b/source/blender/blenlib/intern/BLI_kdtree.c
@@ -291,6 +291,112 @@ int BLI_kdtree_find_nearest(
return min_node->index;
}
+
+/**
+ * A version of #BLI_kdtree_find_nearest which runs a callback
+ * to filter out values.
+ *
+ * \param filter_cb: Filter find results,
+ * Return codes: (1: accept, 0: skip, -1: immediate exit).
+ */
+int BLI_kdtree_find_nearest_cb(
+ const KDTree *tree, const float co[3],
+ int (*filter_cb)(void *user_data, int index, const float co[3], float dist_sq), void *user_data,
+ KDTreeNearest *r_nearest)
+{
+ const KDTreeNode *nodes = tree->nodes;
+ const KDTreeNode *min_node = NULL;
+
+ unsigned int *stack, defaultstack[KD_STACK_INIT];
+ float min_dist = FLT_MAX, cur_dist;
+ unsigned int totstack, cur = 0;
+
+#ifdef DEBUG
+ BLI_assert(tree->is_balanced == true);
+#endif
+
+ if (UNLIKELY(tree->root == KD_NODE_UNSET))
+ return -1;
+
+ stack = defaultstack;
+ totstack = KD_STACK_INIT;
+
+#define NODE_TEST_NEAREST(node) \
+{ \
+ const float dist_sq = len_squared_v3v3((node)->co, co); \
+ if (dist_sq < min_dist) { \
+ const int result = filter_cb(user_data, (node)->index, (node)->co, dist_sq); \
+ if (result == 1) { \
+ min_dist = dist_sq; \
+ min_node = node; \
+ } \
+ else if (result == 0) { \
+ /* pass */ \
+ } \
+ else { \
+ BLI_assert(result == -1); \
+ goto finally; \
+ } \
+ } \
+} ((void)0)
+
+ stack[cur++] = tree->root;
+
+ while (cur--) {
+ const KDTreeNode *node = &nodes[stack[cur]];
+
+ cur_dist = node->co[node->d] - co[node->d];
+
+ if (cur_dist < 0.0f) {
+ cur_dist = -cur_dist * cur_dist;
+
+ if (-cur_dist < min_dist) {
+ NODE_TEST_NEAREST(node);
+
+ if (node->left != KD_NODE_UNSET)
+ stack[cur++] = node->left;
+ }
+ if (node->right != KD_NODE_UNSET)
+ stack[cur++] = node->right;
+ }
+ else {
+ cur_dist = cur_dist * cur_dist;
+
+ if (cur_dist < min_dist) {
+ NODE_TEST_NEAREST(node);
+
+ if (node->right != KD_NODE_UNSET)
+ stack[cur++] = node->right;
+ }
+ if (node->left != KD_NODE_UNSET)
+ stack[cur++] = node->left;
+ }
+ if (UNLIKELY(cur + 3 > totstack)) {
+ stack = realloc_nodes(stack, &totstack, defaultstack != stack);
+ }
+ }
+
+#undef NODE_TEST_NEAREST
+
+
+finally:
+ if (stack != defaultstack)
+ MEM_freeN(stack);
+
+ if (min_node) {
+ if (r_nearest) {
+ r_nearest->index = min_node->index;
+ r_nearest->dist = sqrtf(min_dist);
+ copy_v3_v3(r_nearest->co, min_node->co);
+ }
+
+ return min_node->index;
+ }
+ else {
+ return -1;
+ }
+}
+
static void add_nearest(KDTreeNearest *ptn, unsigned int *found, unsigned int n, int index,
float dist, const float *co)
{
@@ -448,7 +554,6 @@ int BLI_kdtree_range_search__normal(
KDTreeNearest **r_nearest, float range)
{
const KDTreeNode *nodes = tree->nodes;
- const KDTreeNode *root;
unsigned int *stack, defaultstack[KD_STACK_INIT];
KDTreeNearest *foundstack = NULL;
float range_sq = range * range, dist_sq;
@@ -464,27 +569,7 @@ int BLI_kdtree_range_search__normal(
stack = defaultstack;
totstack = KD_STACK_INIT;
- root = &nodes[tree->root];
-
- if (co[root->d] + range < root->co[root->d]) {
- if (root->left != KD_NODE_UNSET)
- stack[cur++] = root->left;
- }
- else if (co[root->d] - range > root->co[root->d]) {
- if (root->right != KD_NODE_UNSET)
- stack[cur++] = root->right;
- }
- else {
- dist_sq = squared_distance(root->co, co, nor);
- if (dist_sq <= range_sq) {
- add_in_range(&foundstack, &totfoundstack, found++, root->index, dist_sq, root->co);
- }
-
- if (root->left != KD_NODE_UNSET)
- stack[cur++] = root->left;
- if (root->right != KD_NODE_UNSET)
- stack[cur++] = root->right;
- }
+ stack[cur++] = tree->root;
while (cur--) {
const KDTreeNode *node = &nodes[stack[cur]];
@@ -538,7 +623,7 @@ void BLI_kdtree_range_search_cb(
bool (*search_cb)(void *user_data, int index, const float co[3], float dist_sq), void *user_data)
{
const KDTreeNode *nodes = tree->nodes;
- const KDTreeNode *root;
+
unsigned int *stack, defaultstack[KD_STACK_INIT];
float range_sq = range * range, dist_sq;
unsigned int totstack, cur = 0;
@@ -553,29 +638,7 @@ void BLI_kdtree_range_search_cb(
stack = defaultstack;
totstack = KD_STACK_INIT;
- root = &nodes[tree->root];
-
- if (co[root->d] + range < root->co[root->d]) {
- if (root->left != KD_NODE_UNSET)
- stack[cur++] = root->left;
- }
- else if (co[root->d] - range > root->co[root->d]) {
- if (root->right != KD_NODE_UNSET)
- stack[cur++] = root->right;
- }
- else {
- dist_sq = len_squared_v3v3(root->co, co);
- if (dist_sq <= range_sq) {
- if (search_cb(user_data, root->index, root->co, dist_sq) == false) {
- goto finally;
- }
- }
-
- if (root->left != KD_NODE_UNSET)
- stack[cur++] = root->left;
- if (root->right != KD_NODE_UNSET)
- stack[cur++] = root->right;
- }
+ stack[cur++] = tree->root;
while (cur--) {
const KDTreeNode *node = &nodes[stack[cur]];
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index 1da39967945..1500e23d72e 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -41,7 +41,7 @@
#include "BLI_strict_flags.h"
-int BLI_linklist_count(LinkNode *list)
+int BLI_linklist_count(const LinkNode *list)
{
int len;
@@ -51,7 +51,7 @@ int BLI_linklist_count(LinkNode *list)
return len;
}
-int BLI_linklist_index(LinkNode *list, void *ptr)
+int BLI_linklist_index(const LinkNode *list, void *ptr)
{
int index;
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index cde4a8bf59d..d6eae348d52 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -88,9 +88,9 @@ struct EdgeHash {
* \{ */
/**
- * Get the hash for a key.
+ * Compute the hash and get the bucket-index.
*/
-BLI_INLINE unsigned int edgehash_keyhash(EdgeHash *eh, unsigned int v0, unsigned int v1)
+BLI_INLINE unsigned int edgehash_bucket_index(EdgeHash *eh, unsigned int v0, unsigned int v1)
{
BLI_assert(v0 < v1);
@@ -114,7 +114,6 @@ BLI_INLINE void edgehash_resize_buckets(EdgeHash *eh, const unsigned int nbucket
EdgeEntry **buckets_new;
const unsigned int nbuckets_old = eh->nbuckets;
unsigned int i;
- EdgeEntry *e;
BLI_assert(eh->nbuckets != nbuckets);
@@ -122,12 +121,11 @@ BLI_INLINE void edgehash_resize_buckets(EdgeHash *eh, const unsigned int nbucket
buckets_new = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets");
for (i = 0; i < nbuckets_old; i++) {
- EdgeEntry *e_next;
- for (e = buckets_old[i]; e; e = e_next) {
- const unsigned hash = edgehash_keyhash(eh, e->v0, e->v1);
+ for (EdgeEntry *e = buckets_old[i], *e_next; e; e = e_next) {
+ const unsigned bucket_index = edgehash_bucket_index(eh, e->v0, e->v1);
e_next = e->next;
- e->next = buckets_new[hash];
- buckets_new[hash] = e;
+ e->next = buckets_new[bucket_index];
+ buckets_new[bucket_index] = e;
}
}
@@ -147,14 +145,15 @@ BLI_INLINE void edgehash_buckets_reserve(EdgeHash *eh, const unsigned int nentri
/**
* Internal lookup function.
- * Takes a hash argument to avoid calling #edgehash_keyhash multiple times.
+ * Takes a \a bucket_index argument to avoid calling #edgehash_bucket_index multiple times.
*/
-BLI_INLINE EdgeEntry *edgehash_lookup_entry_ex(EdgeHash *eh, unsigned int v0, unsigned int v1,
- const unsigned int hash)
+BLI_INLINE EdgeEntry *edgehash_lookup_entry_ex(
+ EdgeHash *eh, unsigned int v0, unsigned int v1,
+ const unsigned int bucket_index)
{
EdgeEntry *e;
BLI_assert(v0 < v1);
- for (e = eh->buckets[hash]; e; e = e->next) {
+ for (e = eh->buckets[bucket_index]; e; e = e->next) {
if (UNLIKELY(v0 == e->v0 && v1 == e->v1)) {
return e;
}
@@ -163,14 +162,34 @@ BLI_INLINE EdgeEntry *edgehash_lookup_entry_ex(EdgeHash *eh, unsigned int v0, un
}
/**
+ * Internal lookup function, returns previous entry of target one too.
+ * Takes bucket_index argument to avoid calling #edgehash_bucket_index multiple times.
+ * Useful when modifying buckets somehow (like removing an entry...).
+ */
+BLI_INLINE EdgeEntry *edgehash_lookup_entry_prev_ex(
+ EdgeHash *eh, unsigned int v0, unsigned int v1,
+ EdgeEntry **r_e_prev, const unsigned int bucket_index)
+{
+ BLI_assert(v0 < v1);
+ for (EdgeEntry *e_prev = NULL, *e = eh->buckets[bucket_index]; e; e = e->next) {
+ if (UNLIKELY(v0 == e->v0 && v1 == e->v1)) {
+ *r_e_prev = e_prev;
+ return e;
+ }
+ }
+
+ *r_e_prev = NULL;
+ return NULL;
+}
+
+/**
* Internal lookup function. Only wraps #edgehash_lookup_entry_ex
*/
BLI_INLINE EdgeEntry *edgehash_lookup_entry(EdgeHash *eh, unsigned int v0, unsigned int v1)
{
- unsigned int hash;
- EDGE_ORD(v0, v1); /* ensure v0 is smaller */
- hash = edgehash_keyhash(eh, v0, v1);
- return edgehash_lookup_entry_ex(eh, v0, v1, hash);
+ EDGE_ORD(v0, v1);
+ const unsigned int bucket_index = edgehash_bucket_index(eh, v0, v1);
+ return edgehash_lookup_entry_ex(eh, v0, v1, bucket_index);
}
@@ -198,10 +217,11 @@ static EdgeHash *edgehash_new(const char *info,
/**
* Internal insert function.
- * Takes a hash argument to avoid calling #edgehash_keyhash multiple times.
+ * Takes a \a bucket_index argument to avoid calling #edgehash_bucket_index multiple times.
*/
-BLI_INLINE void edgehash_insert_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val,
- unsigned int hash)
+BLI_INLINE void edgehash_insert_ex(
+ EdgeHash *eh, unsigned int v0, unsigned int v1, void *val,
+ const unsigned int bucket_index)
{
EdgeEntry *e = BLI_mempool_alloc(eh->epool);
@@ -212,11 +232,11 @@ BLI_INLINE void edgehash_insert_ex(EdgeHash *eh, unsigned int v0, unsigned int v
BLI_assert(v0 < v1);
BLI_assert(v0 != v1);
- e->next = eh->buckets[hash];
+ e->next = eh->buckets[bucket_index];
e->v0 = v0;
e->v1 = v1;
e->val = val;
- eh->buckets[hash] = e;
+ eh->buckets[bucket_index] = e;
if (UNLIKELY(edgehash_test_expand_buckets(++eh->nentries, eh->nbuckets))) {
edgehash_resize_buckets(eh, _ehash_hashsizes[++eh->cursize]);
@@ -226,8 +246,9 @@ BLI_INLINE void edgehash_insert_ex(EdgeHash *eh, unsigned int v0, unsigned int v
/**
* Insert function that doesn't set the value (use for EdgeSet)
*/
-BLI_INLINE void edgehash_insert_ex_keyonly(EdgeHash *eh, unsigned int v0, unsigned int v1,
- unsigned int hash)
+BLI_INLINE void edgehash_insert_ex_keyonly(
+ EdgeHash *eh, unsigned int v0, unsigned int v1,
+ const unsigned int bucket_index)
{
EdgeEntry *e = BLI_mempool_alloc(eh->epool);
@@ -237,10 +258,10 @@ BLI_INLINE void edgehash_insert_ex_keyonly(EdgeHash *eh, unsigned int v0, unsign
BLI_assert(v0 < v1);
BLI_assert(v0 != v1);
- e->next = eh->buckets[hash];
+ e->next = eh->buckets[bucket_index];
e->v0 = v0;
e->v1 = v1;
- eh->buckets[hash] = e;
+ eh->buckets[bucket_index] = e;
if (UNLIKELY(edgehash_test_expand_buckets(++eh->nentries, eh->nbuckets))) {
edgehash_resize_buckets(eh, _ehash_hashsizes[++eh->cursize]);
@@ -252,7 +273,7 @@ BLI_INLINE void edgehash_insert_ex_keyonly(EdgeHash *eh, unsigned int v0, unsign
*/
BLI_INLINE void edgehash_insert_ex_keyonly_entry(
EdgeHash *eh, unsigned int v0, unsigned int v1,
- unsigned int hash,
+ const unsigned int bucket_index,
EdgeEntry *e)
{
BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0));
@@ -261,11 +282,11 @@ BLI_INLINE void edgehash_insert_ex_keyonly_entry(
BLI_assert(v0 < v1);
BLI_assert(v0 != v1);
- e->next = eh->buckets[hash];
+ e->next = eh->buckets[bucket_index];
e->v0 = v0;
e->v1 = v1;
/* intentionally leave value unset */
- eh->buckets[hash] = e;
+ eh->buckets[bucket_index] = e;
if (UNLIKELY(edgehash_test_expand_buckets(++eh->nentries, eh->nbuckets))) {
edgehash_resize_buckets(eh, _ehash_hashsizes[++eh->cursize]);
@@ -274,39 +295,43 @@ BLI_INLINE void edgehash_insert_ex_keyonly_entry(
BLI_INLINE void edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
{
- unsigned int hash;
- EDGE_ORD(v0, v1); /* ensure v0 is smaller */
- hash = edgehash_keyhash(eh, v0, v1);
- edgehash_insert_ex(eh, v0, v1, val, hash);
+ EDGE_ORD(v0, v1);
+ const unsigned int bucket_index = edgehash_bucket_index(eh, v0, v1);
+ edgehash_insert_ex(eh, v0, v1, val, bucket_index);
}
/**
* Remove the entry and return it, caller must free from eh->epool.
*/
-static EdgeEntry *edgehash_remove_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHashFreeFP valfreefp,
- unsigned int hash)
+BLI_INLINE EdgeEntry *edgehash_remove_ex(
+ EdgeHash *eh, unsigned int v0, unsigned int v1,
+ EdgeHashFreeFP valfreefp,
+ const unsigned int bucket_index)
{
- EdgeEntry *e;
- EdgeEntry *e_prev = NULL;
+ EdgeEntry *e_prev;
+ EdgeEntry *e = edgehash_lookup_entry_prev_ex(eh, v0, v1, &e_prev, bucket_index);
BLI_assert(v0 < v1);
- for (e = eh->buckets[hash]; e; e = e->next) {
- if (UNLIKELY(v0 == e->v0 && v1 == e->v1)) {
- EdgeEntry *e_next = e->next;
-
- if (valfreefp) valfreefp(e->val);
+ if (e) {
+ EdgeEntry *e_next = e->next;
- if (e_prev) e_prev->next = e_next;
- else eh->buckets[hash] = e_next;
+ if (valfreefp) {
+ valfreefp(e->val);
+ }
- eh->nentries--;
- return e;
+ if (e_prev) {
+ e_prev->next = e_next;
+ }
+ else {
+ eh->buckets[bucket_index] = e_next;
}
- e_prev = e;
+
+ eh->nentries--;
+ return e;
}
- return NULL;
+ return e;
}
/**
@@ -366,21 +391,18 @@ void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *v
*/
bool BLI_edgehash_reinsert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
{
- unsigned int hash;
- EdgeEntry *e;
-
IS_EDGEHASH_ASSERT(eh);
- EDGE_ORD(v0, v1); /* ensure v0 is smaller */
- hash = edgehash_keyhash(eh, v0, v1);
+ EDGE_ORD(v0, v1);
+ const unsigned int bucket_index = edgehash_bucket_index(eh, v0, v1);
- e = edgehash_lookup_entry_ex(eh, v0, v1, hash);
+ EdgeEntry *e = edgehash_lookup_entry_ex(eh, v0, v1, bucket_index);
if (e) {
e->val = val;
return false;
}
else {
- edgehash_insert_ex(eh, v0, v1, val, hash);
+ edgehash_insert_ex(eh, v0, v1, val, bucket_index);
return true;
}
}
@@ -412,18 +434,14 @@ void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1)
*/
bool BLI_edgehash_ensure_p(EdgeHash *eh, unsigned int v0, unsigned int v1, void ***r_val)
{
- unsigned int hash;
- EdgeEntry *e;
- bool haskey;
-
- EDGE_ORD(v0, v1); /* ensure v0 is smaller */
- hash = edgehash_keyhash(eh, v0, v1);
- e = edgehash_lookup_entry_ex(eh, v0, v1, hash);
- haskey = (e != NULL);
+ EDGE_ORD(v0, v1);
+ const unsigned int bucket_index = edgehash_bucket_index(eh, v0, v1);
+ EdgeEntry *e = edgehash_lookup_entry_ex(eh, v0, v1, bucket_index);
+ const bool haskey = (e != NULL);
if (!haskey) {
e = BLI_mempool_alloc(eh->epool);
- edgehash_insert_ex_keyonly_entry(eh, v0, v1, hash, e);
+ edgehash_insert_ex_keyonly_entry(eh, v0, v1, bucket_index, e);
}
*r_val = &e->val;
@@ -462,12 +480,9 @@ void *BLI_edgehash_lookup_default(EdgeHash *eh, unsigned int v0, unsigned int v1
*/
bool BLI_edgehash_remove(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHashFreeFP valfreefp)
{
- unsigned int hash;
- EdgeEntry *e;
-
- EDGE_ORD(v0, v1); /* ensure v0 is smaller */
- hash = edgehash_keyhash(eh, v0, v1);
- e = edgehash_remove_ex(eh, v0, v1, valfreefp, hash);
+ EDGE_ORD(v0, v1);
+ const unsigned int bucket_index = edgehash_bucket_index(eh, v0, v1);
+ EdgeEntry *e = edgehash_remove_ex(eh, v0, v1, valfreefp, bucket_index);
if (e) {
BLI_mempool_free(eh->epool, e);
return true;
@@ -487,12 +502,9 @@ bool BLI_edgehash_remove(EdgeHash *eh, unsigned int v0, unsigned int v1, EdgeHas
*/
void *BLI_edgehash_popkey(EdgeHash *eh, unsigned int v0, unsigned int v1)
{
- unsigned int hash;
- EdgeEntry *e;
-
- EDGE_ORD(v0, v1); /* ensure v0 is smaller */
- hash = edgehash_keyhash(eh, v0, v1);
- e = edgehash_remove_ex(eh, v0, v1, NULL, hash);
+ EDGE_ORD(v0, v1);
+ const unsigned int bucket_index = edgehash_bucket_index(eh, v0, v1);
+ EdgeEntry *e = edgehash_remove_ex(eh, v0, v1, NULL, bucket_index);
IS_EDGEHASH_ASSERT(eh);
if (e) {
void *val = e->val;
@@ -728,10 +740,9 @@ int BLI_edgeset_size(EdgeSet *es)
*/
void BLI_edgeset_insert(EdgeSet *es, unsigned int v0, unsigned int v1)
{
- unsigned int hash;
- EDGE_ORD(v0, v1); /* ensure v0 is smaller */
- hash = edgehash_keyhash((EdgeHash *)es, v0, v1);
- edgehash_insert_ex_keyonly((EdgeHash *)es, v0, v1, hash);
+ EDGE_ORD(v0, v1);
+ const unsigned int bucket_index = edgehash_bucket_index((EdgeHash *)es, v0, v1);
+ edgehash_insert_ex_keyonly((EdgeHash *)es, v0, v1, bucket_index);
}
/**
@@ -742,18 +753,15 @@ void BLI_edgeset_insert(EdgeSet *es, unsigned int v0, unsigned int v1)
*/
bool BLI_edgeset_add(EdgeSet *es, unsigned int v0, unsigned int v1)
{
- unsigned int hash;
- EdgeEntry *e;
-
- EDGE_ORD(v0, v1); /* ensure v0 is smaller */
- hash = edgehash_keyhash((EdgeHash *)es, v0, v1);
+ EDGE_ORD(v0, v1);
+ const unsigned int bucket_index = edgehash_bucket_index((EdgeHash *)es, v0, v1);
- e = edgehash_lookup_entry_ex((EdgeHash *)es, v0, v1, hash);
+ EdgeEntry *e = edgehash_lookup_entry_ex((EdgeHash *)es, v0, v1, bucket_index);
if (e) {
return false;
}
else {
- edgehash_insert_ex_keyonly((EdgeHash *)es, v0, v1, hash);
+ edgehash_insert_ex_keyonly((EdgeHash *)es, v0, v1, bucket_index);
return true;
}
}
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index f8bcbae00b0..5b809ab26cc 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -1495,6 +1495,51 @@ bool isect_ray_tri_threshold_v3(
}
#endif
+
+bool isect_ray_seg_v2(
+ const float p1[3], const float d[3],
+ const float v0[3], const float v1[3],
+ float *r_lambda, float *r_u)
+{
+ float v0_local[2], v1_local[2];
+ sub_v2_v2v2(v0_local, v0, p1);
+ sub_v2_v2v2(v1_local, v1, p1);
+
+ float s10[2];
+ float det;
+
+ sub_v2_v2v2(s10, v1_local, v0_local);
+
+ det = cross_v2v2(d, s10);
+ if (det != 0.0f) {
+ const float v = cross_v2v2(v0_local, v1_local);
+ float p[2] = {(d[0] * v) / det, (d[1] * v) / det};
+
+ const float t = (dot_v2v2(p, d) / dot_v2v2(d, d));
+ if ((t >= 0.0f) == 0) {
+ return false;
+ }
+
+ float h[2];
+ sub_v2_v2v2(h, v1_local, p);
+ const float u = (dot_v2v2(s10, h) / dot_v2v2(s10, s10));
+ if ((u >= 0.0f && u <= 1.0f) == 0) {
+ return false;
+ }
+
+ if (r_lambda) {
+ *r_lambda = t;
+ }
+ if (r_u) {
+ *r_u = u;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
/**
* Check if a point is behind all planes.
*/
@@ -2355,7 +2400,9 @@ static bool point_in_slice(const float p[3], const float v1[3], const float l1[3
sub_v3_v3v3(rp, p, v1);
h = dot_v3v3(q, rp) / dot_v3v3(q, q);
- return (h < 0.0f || h > 1.0f) ? false : true;
+ /* note: when 'h' is nan/-nan, this check returns false
+ * without explicit check - covering the degenerate case */
+ return (h >= 0.0f && h <= 1.0f);
}
#if 0
@@ -2399,22 +2446,15 @@ bool isect_point_tri_v3(const float p[3], const float v1[3], const float v2[3],
float r_vi[3])
{
if (isect_point_tri_prism_v3(p, v1, v2, v3)) {
- float no[3], n1[3], n2[3];
+ float plane[4];
+ float no[3];
/* Could use normal_tri_v3, but doesn't have to be unit-length */
- sub_v3_v3v3(n1, v1, v2);
- sub_v3_v3v3(n2, v2, v3);
- cross_v3_v3v3(no, n1, n2);
-
- if (LIKELY(len_squared_v3(no) != 0.0f)) {
- float plane[4];
- plane_from_point_normal_v3(plane, v1, no);
- closest_to_plane_v3(r_vi, plane, p);
- }
- else {
- /* degenerate */
- copy_v3_v3(r_vi, p);
- }
+ cross_tri_v3(no, v1, v2, v3);
+ BLI_assert(len_squared_v3(no) != 0.0f);
+
+ plane_from_point_normal_v3(plane, v1, no);
+ closest_to_plane_v3(r_vi, plane, p);
return true;
}
diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c
index 44b17681540..68a2e68db4f 100644
--- a/source/blender/blenlib/intern/math_geom_inline.c
+++ b/source/blender/blenlib/intern/math_geom_inline.c
@@ -199,6 +199,17 @@ MINLINE int axis_dominant_v3_single(const float vec[3])
((y > z) ? 1 : 2));
}
+/* the dominant axis of an orthogonal vector */
+MINLINE int axis_dominant_v3_ortho_single(const float vec[3])
+{
+ const float x = fabsf(vec[0]);
+ const float y = fabsf(vec[1]);
+ const float z = fabsf(vec[2]);
+ return ((x < y) ?
+ ((x < z) ? 0 : 2) :
+ ((y < z) ? 1 : 2));
+}
+
MINLINE int max_axis_v3(const float vec[3])
{
const float x = vec[0];
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 19d116928fd..52ff6fd3e8a 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -1569,6 +1569,7 @@ void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]
*
* See https://en.wikipedia.org/wiki/Polar_decomposition for more.
*/
+#ifndef MATH_STANDALONE
void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3])
{
/* From svd decomposition (M = WSV*), we have:
@@ -1586,7 +1587,7 @@ void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3])
mul_m3_m3m3(r_U, W, Vt);
mul_m3_series(r_P, V, S, Vt);
}
-
+#endif
void scale_m3_fl(float m[3][3], float scale)
{
@@ -1727,6 +1728,8 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa
loc_quat_size_to_mat4(out, floc, fquat, fsize);
}
+/* for builds without Eigen */
+#ifndef MATH_STANDALONE
/**
* A polar-decomposition-based interpolation between matrix A and matrix B.
*
@@ -1795,6 +1798,7 @@ void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
copy_m4_m3(R, R3);
copy_v3_v3(R[3], loc);
}
+#endif /* MATH_STANDALONE */
bool is_negative_m3(float mat[3][3])
{
diff --git a/source/blender/blenlib/intern/math_solvers.c b/source/blender/blenlib/intern/math_solvers.c
index d1dad9a6269..641e50c9bde 100644
--- a/source/blender/blenlib/intern/math_solvers.c
+++ b/source/blender/blenlib/intern/math_solvers.c
@@ -34,7 +34,7 @@
#include "BLI_strict_flags.h"
-#include "eigen3_capi.h"
+#include "eigen_capi.h"
/********************************** Eigen Solvers *********************************/
@@ -57,7 +57,7 @@ bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], float r_eigen_values[3
}
#endif
- return EG3_self_adjoint_eigen_solve(3, (const float *)m3, r_eigen_values, (float *)r_eigen_vectors);
+ return EIG_self_adjoint_eigen_solve(3, (const float *)m3, r_eigen_values, (float *)r_eigen_vectors);
}
/**
@@ -70,5 +70,5 @@ bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], float r_eigen_values[3
*/
void BLI_svd_m3(const float m3[3][3], float r_U[3][3], float r_S[3], float r_V[3][3])
{
- EG3_svd_square_matrix(3, (const float *)m3, (float *)r_U, (float *)r_S, (float *)r_V);
+ EIG_svd_square_matrix(3, (const float *)m3, (float *)r_U, (float *)r_S, (float *)r_V);
}
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 99e512475bb..fadfb64f1e1 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1761,7 +1761,7 @@ void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__r
}
/* inline BLI_add_slash */
- if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) {
+ if ((dirlen > 0) && !ELEM(dst[dirlen - 1], SEP, ALTSEP)) {
dst[dirlen++] = SEP;
dst[dirlen] = '\0';
}
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index 5803448a4c0..515da9cd95d 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -575,9 +575,15 @@ size_t BLI_task_pool_tasks_done(TaskPool *pool)
* - Chunk iterations to reduce number of spin locks.
*/
+/* Allows to avoid using malloc for userdata_chunk in tasks, when small enough. */
+#define MALLOCA(_size) ((_size) <= 8192) ? alloca((_size)) : MEM_mallocN((_size), __func__)
+#define MALLOCA_FREE(_mem, _size) if (((_mem) != NULL) && ((_size) > 8192)) MEM_freeN((_mem))
+
typedef struct ParallelRangeState {
int start, stop;
void *userdata;
+ void *userdata_chunk;
+ size_t userdata_chunk_size;
TaskParallelRangeFunc func;
int iter;
@@ -608,17 +614,45 @@ static void parallel_range_func(
{
ParallelRangeState * __restrict state = BLI_task_pool_userdata(pool);
int iter, count;
+
+ const bool use_userdata_chunk = (state->userdata_chunk_size != 0) && (state->userdata_chunk != NULL);
+ void *userdata_chunk = use_userdata_chunk ? MALLOCA(state->userdata_chunk_size) : NULL;
+
while (parallel_range_next_iter_get(state, &iter, &count)) {
int i;
+
+ if (use_userdata_chunk) {
+ memcpy(userdata_chunk, state->userdata_chunk, state->userdata_chunk_size);
+ }
+
for (i = 0; i < count; ++i) {
- state->func(state->userdata, iter + i);
+ state->func(state->userdata, userdata_chunk, iter + i);
}
}
+
+ MALLOCA_FREE(userdata_chunk, state->userdata_chunk_size);
}
+/**
+ * This function allows to parallelized for loops in a similar way to OpenMP's 'parallel for' statement.
+ *
+ * \param start First index to process.
+ * \param stop Index to stop looping (excluded).
+ * \param userdata Common userdata passed to all instances of \a func.
+ * \param userdata_chunk Optional, each instance of looping chunks will get a copy of this data
+ * (similar to OpenMP's firstprivate).
+ * \param userdata_chunk_size Memory size of \a userdata_chunk.
+ * \param func Callback function.
+ * \param range_threshold Minimum size of processed range to start using tasks
+ * (below this, loop is done in main thread only).
+ * \param use_dynamic_scheduling If \a true, the whole range is divided in a lot of small chunks (of size 32 currently),
+ * otherwise whole range is split in a few big chunks (num_threads * 2 chunks currently).
+ */
void BLI_task_parallel_range_ex(
int start, int stop,
void *userdata,
+ void *userdata_chunk,
+ const size_t userdata_chunk_size,
TaskParallelRangeFunc func,
const int range_threshold,
const bool use_dynamic_scheduling)
@@ -634,9 +668,19 @@ void BLI_task_parallel_range_ex(
* do everything from the main thread.
*/
if (stop - start < range_threshold) {
+ const bool use_userdata_chunk = (userdata_chunk_size != 0) && (userdata_chunk != NULL);
+ void *userdata_chunk_local = NULL;
+
+ if (use_userdata_chunk) {
+ userdata_chunk_local = MALLOCA(userdata_chunk_size);
+ memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size);
+ }
+
for (i = start; i < stop; ++i) {
- func(userdata, i);
+ func(userdata, userdata_chunk_local, i);
}
+
+ MALLOCA_FREE(userdata_chunk_local, userdata_chunk_size);
return;
}
@@ -654,6 +698,8 @@ void BLI_task_parallel_range_ex(
state.start = start;
state.stop = stop;
state.userdata = userdata;
+ state.userdata_chunk = userdata_chunk;
+ state.userdata_chunk_size = userdata_chunk_size;
state.func = func;
state.iter = start;
if (use_dynamic_scheduling) {
@@ -676,10 +722,18 @@ void BLI_task_parallel_range_ex(
BLI_spin_end(&state.lock);
}
+/**
+ * A simpler version of \a BLI_task_parallel_range_ex, which does not use \a use_dynamic_scheduling,
+ * has a \a range_threshold of 64, and does not handle 'firstprivate'-like \a userdata_chunk.
+ */
void BLI_task_parallel_range(
int start, int stop,
void *userdata,
TaskParallelRangeFunc func)
{
- BLI_task_parallel_range_ex(start, stop, userdata, func, 64, false);
+ BLI_task_parallel_range_ex(start, stop, userdata, NULL, 0, func, 64, false);
}
+
+#undef MALLOCA
+#undef MALLOCA_FREE
+
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9004a5f92f7..177055e7206 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -622,6 +622,7 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
/* Add library datablock itself to 'main' Main, since libraries are **never** linked data.
* Fixes bug where you could end with all ID_LI datablocks having the same name... */
lib = BKE_libblock_alloc(mainlist->first, ID_LI, "Lib");
+ lib->id.us = ID_FAKE_USERS(lib); /* Important, consistency with main ID reading code from read_libblock(). */
BLI_strncpy(lib->name, filepath, sizeof(lib->name));
BLI_strncpy(lib->filepath, name1, sizeof(lib->filepath));
@@ -1344,7 +1345,7 @@ bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, cha
while ((slash = (char *)BLI_last_slash(r_dir))) {
char tc = *slash;
*slash = '\0';
- if (BLO_has_bfile_extension(r_dir)) {
+ if (BLO_has_bfile_extension(r_dir) && BLI_is_file(r_dir)) {
break;
}
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 9456c286c6f..77a4aefb7ac 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -1386,7 +1386,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
SpaceClip *sclip = (SpaceClip *)sl;
if (sclip->around == 0) {
- sclip->around = V3D_CENTROID;
+ sclip->around = V3D_AROUND_CENTER_MEAN;
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index e6005da23e4..8a2045ddacf 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -921,7 +921,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
- {
+ if (!MAIN_VERSION_ATLEAST(main, 276, 3)) {
if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "CurveMapping", "mblur_shutter_curve")) {
Scene *scene;
for (scene = main->scene.first; scene != NULL; scene = scene->id.next) {
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 257768b0ac8..1afa98fd6f8 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../blentranslation
../makesdna
../../../intern/guardedalloc
+ ../../../intern/eigen
../../../extern/rangetree
)
@@ -112,6 +113,8 @@ set(SRC
intern/bmesh_operators_private.h
intern/bmesh_polygon.c
intern/bmesh_polygon.h
+ intern/bmesh_polygon_edgenet.c
+ intern/bmesh_polygon_edgenet.h
intern/bmesh_private.h
intern/bmesh_queries.c
intern/bmesh_queries.h
@@ -160,7 +163,7 @@ set(SRC
)
if(MSVC)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4101")
endif()
if(WITH_BULLET)
@@ -174,13 +177,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
-if(WITH_OPENNL)
- add_definitions(-DWITH_OPENNL)
- list(APPEND INC_SYS
- ../../../intern/opennl/extern
- )
-endif()
-
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript
index c53974be1a7..6bf4fdf7c78 100644
--- a/source/blender/bmesh/SConscript
+++ b/source/blender/bmesh/SConscript
@@ -40,9 +40,9 @@ incs = [
'../makesdna',
'../blenkernel',
'#/intern/guardedalloc',
+ '#/intern/eigen',
'#/extern/bullet2/src',
'#/extern/rangetree',
- '#/intern/opennl/extern'
]
defs = []
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index 78c814af86e..f29d280d071 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -244,6 +244,7 @@ extern "C" {
#include "intern/bmesh_mods.h"
#include "intern/bmesh_operators.h"
#include "intern/bmesh_polygon.h"
+#include "intern/bmesh_polygon_edgenet.h"
#include "intern/bmesh_queries.h"
#include "intern/bmesh_walkers.h"
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 57107ed4e37..4ffa0bda71a 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -276,8 +276,16 @@ enum {
#define BM_CHECK_TYPE_ELEM(ele) \
CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST, _BM_GENERIC_TYPE_ELEM_CONST)
+/* Assignment from a void* to a typed pointer is not allowed in C++,
+ * casting the LHS to void works fine though.
+ */
+#ifdef __cplusplus
+#define BM_CHECK_TYPE_ELEM_ASSIGN(ele) \
+ (BM_CHECK_TYPE_ELEM(ele)), *((void **)&ele)
+#else
#define BM_CHECK_TYPE_ELEM_ASSIGN(ele) \
(BM_CHECK_TYPE_ELEM(ele)), ele
+#endif
/* BMHeader->hflag (char) */
enum {
@@ -309,7 +317,11 @@ enum {
struct BPy_BMGeneric;
extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self);
-typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
+typedef bool (*BMElemFilterFunc)(const BMElem *, void *user_data);
+typedef bool (*BMVertFilterFunc)(const BMVert *, void *user_data);
+typedef bool (*BMEdgeFilterFunc)(const BMEdge *, void *user_data);
+typedef bool (*BMFaceFilterFunc)(const BMFace *, void *user_data);
+typedef bool (*BMLoopFilterFunc)(const BMLoop *, void *user_data);
/* defines */
#define BM_ELEM_CD_SET_INT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 7664108f348..3c2a85e9f52 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -116,7 +116,7 @@ BMFace *BM_face_create_quad_tri(
*/
void BM_face_copy_shared(
BMesh *bm, BMFace *f,
- BMElemFilterFunc filter_fn, void *user_data)
+ BMLoopFilterFunc filter_fn, void *user_data)
{
BMLoop *l_first;
BMLoop *l_iter;
@@ -149,7 +149,7 @@ void BM_face_copy_shared(
for (j = 0; j < 2; j++) {
BLI_assert(l_dst[j]->v == l_src[j]->v);
if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) {
- if ((filter_fn == NULL) || filter_fn((BMElem *)l_src[j], user_data)) {
+ if ((filter_fn == NULL) || filter_fn(l_src[j], user_data)) {
bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j]);
BM_ELEM_API_FLAG_ENABLE(l_dst[j], _FLAG_OVERLAP);
}
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index 29503679547..ce8b8dd8391 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -38,7 +38,7 @@ BMFace *BM_face_create_quad_tri(
void BM_face_copy_shared(
BMesh *bm, BMFace *f,
- BMElemFilterFunc filter_fn, void *user_data);
+ BMLoopFilterFunc filter_fn, void *user_data);
BMFace *BM_face_create_ngon(
BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 55a04767f51..7130d451ed7 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -823,6 +823,66 @@ void BM_face_kill(BMesh *bm, BMFace *f)
bm_kill_only_face(bm, f);
}
+
+/**
+ * A version of #BM_face_kill which removes edges and verts
+ * which have no remaining connected geometry.
+ */
+void BM_face_kill_loose(BMesh *bm, BMFace *f)
+{
+#ifdef USE_BMESH_HOLES
+ BMLoopList *ls, *ls_next;
+#endif
+
+ BM_CHECK_ELEMENT(f);
+
+#ifdef USE_BMESH_HOLES
+ for (ls = f->loops.first; ls; ls = ls_next)
+#else
+ if (f->l_first)
+#endif
+ {
+ BMLoop *l_iter, *l_next, *l_first;
+
+#ifdef USE_BMESH_HOLES
+ ls_next = ls->next;
+ l_iter = l_first = ls->first;
+#else
+ l_iter = l_first = f->l_first;
+#endif
+
+ do {
+ BMEdge *e;
+ l_next = l_iter->next;
+
+ e = l_iter->e;
+ bmesh_radial_loop_remove(l_iter, e);
+ bm_kill_only_loop(bm, l_iter);
+
+ if (e->l == NULL) {
+ BMVert *v1 = e->v1, *v2 = e->v2;
+
+ bmesh_disk_edge_remove(e, e->v1);
+ bmesh_disk_edge_remove(e, e->v2);
+ bm_kill_only_edge(bm, e);
+
+ if (v1->e == NULL) {
+ bm_kill_only_vert(bm, v1);
+ }
+ if (v2->e == NULL) {
+ bm_kill_only_vert(bm, v2);
+ }
+ }
+ } while ((l_iter = l_next) != l_first);
+
+#ifdef USE_BMESH_HOLES
+ BLI_mempool_free(bm->looplistpool, ls);
+#endif
+ }
+
+ bm_kill_only_face(bm, f);
+}
+
/**
* kills \a e and all faces that use it.
*/
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index a18d96824b7..08f916faf4f 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -58,6 +58,8 @@ BMFace *BM_face_create_verts(
void BM_face_edges_kill(BMesh *bm, BMFace *f);
void BM_face_verts_kill(BMesh *bm, BMFace *f);
+void BM_face_kill_loose(BMesh *bm, BMFace *f);
+
void BM_face_kill(BMesh *bm, BMFace *f);
void BM_edge_kill(BMesh *bm, BMEdge *e);
void BM_vert_kill(BMesh *bm, BMVert *v);
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index b157237c7d0..b9cdc4ccf66 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -94,8 +94,26 @@ extern const BMAllocTemplate bm_mesh_chunksize_default;
(bm)->totvert), (bm)->totedge, (bm)->totloop, (bm)->totface}
#define BMALLOC_TEMPLATE_FROM_ME(me) { (CHECK_TYPE_INLINE(me, Mesh *), \
(me)->totvert), (me)->totedge, (me)->totloop, (me)->totpoly}
-#define BMALLOC_TEMPLATE_FROM_DM(dm) { (CHECK_TYPE_INLINE(dm, DerivedMesh *), \
- (dm)->getNumVerts(dm)), (dm)->getNumEdges(dm), (dm)->getNumLoops(dm), (dm)->getNumPolys(dm)}
+
+#define _VA_BMALLOC_TEMPLATE_FROM_DM_1(dm) { \
+ (CHECK_TYPE_INLINE(dm, DerivedMesh *), \
+ (dm)->getNumVerts(dm)), \
+ (dm)->getNumEdges(dm), \
+ (dm)->getNumLoops(dm), \
+ (dm)->getNumPolys(dm), \
+ }
+#define _VA_BMALLOC_TEMPLATE_FROM_DM_2(dm_a, dm_b) { \
+ (CHECK_TYPE_INLINE(dm_a, DerivedMesh *), \
+ CHECK_TYPE_INLINE(dm_b, DerivedMesh *), \
+ (dm_a)->getNumVerts(dm_a)) + (dm_b)->getNumVerts(dm_b), \
+ (dm_a)->getNumEdges(dm_a) + (dm_b)->getNumEdges(dm_b), \
+ (dm_a)->getNumLoops(dm_a) + (dm_b)->getNumLoops(dm_b), \
+ (dm_a)->getNumPolys(dm_a) + (dm_b)->getNumPolys(dm_b), \
+ }
+
+#define BMALLOC_TEMPLATE_FROM_DM(...) VA_NARGS_CALL_OVERLOAD(_VA_BMALLOC_TEMPLATE_FROM_DM_, __VA_ARGS__)
+
+
enum {
BM_MESH_CREATE_USE_TOOLFLAGS = (1 << 0)
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index cde231b4494..84588d957de 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -29,22 +29,14 @@
#include "MEM_guardedalloc.h"
-
#include "BLI_math.h"
#include "BLI_array.h"
-#include "BLI_alloca.h"
-#include "BLI_stackdefines.h"
-#include "BLI_linklist_stack.h"
-#include "BLI_sort_utils.h"
#include "BKE_customdata.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
-// #define DEBUG_PRINT
-
-
/**
* \brief Dissolve Vert
*
@@ -425,549 +417,6 @@ BMFace *BM_face_split_n(
return f_new;
}
-
-/* -------------------------------------------------------------------- */
-/* Face Split Edge-Net */
-
-/** \name BM_face_split_edgenet and helper functions.
- *
- * \note Don't use #BM_edge_is_wire or #BM_edge_is_boundary
- * since we need to take flagged faces into account.
- * Also take care accessing e->l directly.
- *
- * \{ */
-
-/* Note: All these flags _must_ be cleared on exit */
-
-/* face is apart of the edge-net (including the original face we're splitting) */
-#define FACE_NET _FLAG_WALK
-/* edge is apart of the edge-net we're filling */
-#define EDGE_NET _FLAG_WALK
-/* tag verts we've visit */
-#define VERT_VISIT _FLAG_WALK
-
-struct VertOrder {
- float angle;
- BMVert *v;
-};
-
-static unsigned int bm_edge_flagged_radial_count(BMEdge *e)
-{
- unsigned int count = 0;
- BMLoop *l;
-
- if ((l = e->l)) {
- do {
- if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
- count++;
- }
- } while ((l = l->radial_next) != e->l);
- }
- return count;
-}
-
-static BMLoop *bm_edge_flagged_radial_first(BMEdge *e)
-{
- BMLoop *l;
-
- if ((l = e->l)) {
- do {
- if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
- return l;
- }
- } while ((l = l->radial_next) != e->l);
- }
- return NULL;
-}
-
-static bool bm_face_split_edgenet_find_loop_pair(
- BMVert *v_init, const float face_normal[3],
- BMEdge *e_pair[2])
-{
- /* Always find one boundary edge (to determine winding)
- * and one wire (if available), otherwise another boundary.
- */
- BMIter iter;
- BMEdge *e;
-
- /* detect winding */
- BMLoop *l_walk;
- bool swap;
-
- BLI_SMALLSTACK_DECLARE(edges_boundary, BMEdge *);
- BLI_SMALLSTACK_DECLARE(edges_wire, BMEdge *);
- int edges_boundary_len = 0;
- int edges_wire_len = 0;
-
- BM_ITER_ELEM (e, &iter, v_init, BM_EDGES_OF_VERT) {
- if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
- const unsigned int count = bm_edge_flagged_radial_count(e);
- if (count == 1) {
- BLI_SMALLSTACK_PUSH(edges_boundary, e);
- edges_boundary_len++;
- }
- else if (count == 0) {
- BLI_SMALLSTACK_PUSH(edges_wire, e);
- edges_wire_len++;
- }
- }
- }
-
- /* first edge should always be boundary */
- if (edges_boundary_len == 0) {
- return false;
- }
- e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary);
-
- /* attempt one boundary and one wire, or 2 boundary */
- if (edges_wire_len == 0) {
- if (edges_boundary_len >= 2) {
- e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary);
- }
- else {
- /* one boundary and no wire */
- return false;
- }
- }
- else {
- e_pair[1] = BLI_SMALLSTACK_POP(edges_wire);
-
- if (edges_wire_len > 1) {
- BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init);
- BMVert *v_next;
- float angle_best;
-
- v_next = BM_edge_other_vert(e_pair[1], v_init);
- angle_best = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
-
- while ((e = BLI_SMALLSTACK_POP(edges_wire))) {
- float angle_test;
- v_next = BM_edge_other_vert(e, v_init);
- angle_test = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
- if (angle_test < angle_best) {
- angle_best = angle_test;
- e_pair[1] = e;
- }
- }
- }
- }
-
-
- /* flip based on winding */
- l_walk = bm_edge_flagged_radial_first(e_pair[0]);
- swap = false;
- if (face_normal == l_walk->f->no) {
- swap = !swap;
- }
- if (l_walk->v != v_init) {
- swap = !swap;
- }
- if (swap) {
- SWAP(BMEdge *, e_pair[0], e_pair[1]);
- }
-
- return true;
-}
-
-static bool bm_face_split_edgenet_find_loop_walk(
- BMVert *v_init, const float face_normal[3],
- /* cache to avoid realloc every time */
- struct VertOrder *edge_order, const unsigned int edge_order_len,
- BMEdge *e_pair[2])
-{
- /* fast-path for the common case (avoid push-pop).
- * Also avoids tagging as visited since we know we
- * can't reach these verts some other way */
-#define USE_FASTPATH_NOFORK
-
- BMVert *v;
- BMVert *v_dst;
- bool found = false;
-
- struct VertOrder *eo;
- STACK_DECLARE(edge_order);
-
- /* store visited verts so we can clear the visit flag after execution */
- BLI_SMALLSTACK_DECLARE(vert_visit, BMVert *);
-
- /* likely this will stay very small
- * all verts pushed into this stack _must_ have their previous edges set! */
- BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
- BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
-
- STACK_INIT(edge_order, edge_order_len);
-
- /* start stepping */
- v = BM_edge_other_vert(e_pair[0], v_init);
- v->e = e_pair[0];
- BLI_SMALLSTACK_PUSH(vert_stack, v);
-
- v_dst = BM_edge_other_vert(e_pair[1], v_init);
-
-#ifdef DEBUG_PRINT
- printf("%s: vert (search) %d\n", __func__, BM_elem_index_get(v_init));
-#endif
-
- /* This loop will keep stepping over the best possible edge,
- * in most cases it finds the direct route to close the face.
- *
- * In cases where paths can't be closed,
- * alternatives are stored in the 'vert_stack'.
- */
- while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
- BMIter eiter;
- BMEdge *e_next;
-
-#ifdef USE_FASTPATH_NOFORK
-walk_nofork:
-#else
- BLI_SMALLSTACK_PUSH(vert_visit, v);
- BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
-#endif
-
- BLI_assert(STACK_SIZE(edge_order) == 0);
-
- /* check if we're done! */
- if (v == v_dst) {
- found = true;
- goto finally;
- }
-
- BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
- if ((v->e != e_next) &&
- (BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) &&
- (bm_edge_flagged_radial_count(e_next) < 2))
- {
- BMVert *v_next;
-
- v_next = BM_edge_other_vert(e_next, v);
-
-#ifdef DEBUG_PRINT
- /* indent and print */
- {
- BMVert *_v = v;
- do {
- printf(" ");
- } while ((_v = BM_edge_other_vert(_v->e, _v)) != v_init);
- printf("vert %d -> %d (add=%d)\n",
- BM_elem_index_get(v), BM_elem_index_get(v_next),
- BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT) == 0);
- }
-#endif
-
- if (!BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT)) {
- eo = STACK_PUSH_RET_PTR(edge_order);
- eo->v = v_next;
-
- v_next->e = e_next;
- }
- }
- }
-
-#ifdef USE_FASTPATH_NOFORK
- if (STACK_SIZE(edge_order) == 1) {
- eo = STACK_POP_PTR(edge_order);
- v = eo->v;
-
- goto walk_nofork;
- }
-#endif
-
- /* sort by angle if needed */
- if (STACK_SIZE(edge_order) > 1) {
- unsigned int j;
- BMVert *v_prev = BM_edge_other_vert(v->e, v);
-
- for (j = 0; j < STACK_SIZE(edge_order); j++) {
- edge_order[j].angle = angle_signed_on_axis_v3v3v3_v3(v_prev->co, v->co, edge_order[j].v->co, face_normal);
- }
- qsort(edge_order, STACK_SIZE(edge_order), sizeof(struct VertOrder), BLI_sortutil_cmp_float_reverse);
-
-#ifdef USE_FASTPATH_NOFORK
- /* only tag forks */
- BLI_SMALLSTACK_PUSH(vert_visit, v);
- BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
-#endif
- }
-
- while ((eo = STACK_POP_PTR(edge_order))) {
- BLI_SMALLSTACK_PUSH(vert_stack_next, eo->v);
- }
-
- if (!BLI_SMALLSTACK_IS_EMPTY(vert_stack_next)) {
- BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
- }
- }
-
-
-finally:
- /* clear flag for next execution */
- while ((v = BLI_SMALLSTACK_POP(vert_visit))) {
- BM_ELEM_API_FLAG_DISABLE(v, VERT_VISIT);
- }
-
- return found;
-
-#undef USE_FASTPATH_NOFORK
-}
-
-static bool bm_face_split_edgenet_find_loop(
- BMVert *v_init, const float face_normal[3],
- /* cache to avoid realloc every time */
- struct VertOrder *edge_order, const unsigned int edge_order_len,
- BMVert **r_face_verts, int *r_face_verts_len)
-{
- BMEdge *e_pair[2];
- BMVert *v;
-
- if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, e_pair)) {
- return false;
- }
-
- BLI_assert((bm_edge_flagged_radial_count(e_pair[0]) == 1) ||
- (bm_edge_flagged_radial_count(e_pair[1]) == 1));
-
- if (bm_face_split_edgenet_find_loop_walk(v_init, face_normal, edge_order, edge_order_len, e_pair)) {
- unsigned int i = 0;
-
- r_face_verts[i++] = v_init;
- v = BM_edge_other_vert(e_pair[1], v_init);
- do {
- r_face_verts[i++] = v;
- } while ((v = BM_edge_other_vert(v->e, v)) != v_init);
- *r_face_verts_len = i;
- return (i > 2) ? true : false;
- }
- else {
- return false;
- }
-}
-
-/**
- * Splits a face into many smaller faces defined by an edge-net.
- * handle customdata and degenerate cases.
- *
- * - isolated holes or unsupported face configurations, will be ignored.
- * - customdata calculations aren't efficient
- * (need to calculate weights for each vert).
- */
-bool BM_face_split_edgenet(
- BMesh *bm,
- BMFace *f, BMEdge **edge_net, const int edge_net_len,
- BMFace ***r_face_arr, int *r_face_arr_len)
-{
- /* re-use for new face verts */
- BMVert **face_verts;
- int face_verts_len;
-
- BMFace **face_arr = NULL;
- BLI_array_declare(face_arr);
-
- BMVert **vert_queue;
- STACK_DECLARE(vert_queue);
- int i;
-
- struct VertOrder *edge_order;
- const unsigned int edge_order_len = edge_net_len + 2;
-
- BMVert *v;
-
- BMLoop *l_iter, *l_first;
-
-
- if (!edge_net_len) {
- if (r_face_arr) {
- *r_face_arr = NULL;
- *r_face_arr_len = 0;
- }
- return false;
- }
-
- /* over-alloc (probably 2-4 is only used in most cases), for the biggest-fan */
- edge_order = BLI_array_alloca(edge_order, edge_order_len);
-
- /* use later */
- face_verts = BLI_array_alloca(face_verts, edge_net_len + f->len);
-
- vert_queue = BLI_array_alloca(vert_queue, edge_net_len + f->len);
- STACK_INIT(vert_queue, f->len + edge_net_len);
-
- BLI_assert(BM_ELEM_API_FLAG_TEST(f, FACE_NET) == 0);
- BM_ELEM_API_FLAG_ENABLE(f, FACE_NET);
-
-#ifdef DEBUG
- for (i = 0; i < edge_net_len; i++) {
- BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET) == 0);
- BLI_assert(BM_edge_in_face(edge_net[i], f) == false);
- }
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter->e, EDGE_NET) == 0);
- } while ((l_iter = l_iter->next) != l_first);
-#endif
-
-
- for (i = 0; i < edge_net_len; i++) {
- BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET);
- }
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET);
- } while ((l_iter = l_iter->next) != l_first);
-
-
- /* any vert can be used to begin with */
- STACK_PUSH(vert_queue, l_first->v);
-
- while ((v = STACK_POP(vert_queue))) {
- if (bm_face_split_edgenet_find_loop(v, f->no, edge_order, edge_order_len, face_verts, &face_verts_len)) {
- BMFace *f_new;
-
- f_new = BM_face_create_verts(bm, face_verts, face_verts_len, f, BM_CREATE_NOP, false);
-
- for (i = 0; i < edge_net_len; i++) {
- BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET));
- }
-
- if (f_new) {
- bool l_prev_is_boundary;
- BLI_array_append(face_arr, f_new);
- copy_v3_v3(f_new->no, f->no);
-
- BM_ELEM_API_FLAG_ENABLE(f_new, FACE_NET);
-
- /* add new verts to keep finding loops for
- * (verts between boundary and manifold edges) */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
- l_prev_is_boundary = (bm_edge_flagged_radial_count(l_iter->prev->e) == 1);
- do {
- bool l_iter_is_boundary = (bm_edge_flagged_radial_count(l_iter->e) == 1);
- if (l_prev_is_boundary != l_iter_is_boundary) {
- STACK_PUSH(vert_queue, l_iter->v);
- }
- l_prev_is_boundary = l_iter_is_boundary;
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- }
-
-
- if (CustomData_has_math(&bm->ldata)) {
- /* reuse VERT_VISIT here to tag vert's already interpolated */
- BMIter iter;
- BMLoop *l_other;
-
- /* see: #BM_loop_interp_from_face for similar logic */
- void **blocks = BLI_array_alloca(blocks, f->len);
- float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f->len);
- float *w = BLI_array_alloca(w, f->len);
- float axis_mat[3][3];
- float co[2];
-
- /* interior loops */
- axis_dominant_v3_to_m3(axis_mat, f->no);
-
-
- /* first simply copy from existing face */
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_ITER_ELEM (l_other, &iter, l_iter->v, BM_LOOPS_OF_VERT) {
- if ((l_other->f != f) && BM_ELEM_API_FLAG_TEST(l_other->f, FACE_NET)) {
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
- l_iter->head.data, &l_other->head.data);
- }
- }
- /* tag not to interpolate */
- BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_VISIT);
-
-
- mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
- blocks[i] = l_iter->head.data;
-
- } while (i++, (l_iter = l_iter->next) != l_first);
-
-
- for (i = 0; i < edge_net_len; i++) {
- BM_ITER_ELEM (v, &iter, edge_net[i], BM_VERTS_OF_EDGE) {
- if (!BM_ELEM_API_FLAG_TEST(v, VERT_VISIT)) {
- BMIter liter;
-
- BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
-
- /* interpolate this loop, then copy to the rest */
- l_first = NULL;
-
- BM_ITER_ELEM (l_iter, &liter, v, BM_LOOPS_OF_VERT) {
- if (BM_ELEM_API_FLAG_TEST(l_iter->f, FACE_NET)) {
- if (l_first == NULL) {
- mul_v2_m3v3(co, axis_mat, v->co);
- interp_weights_poly_v2(w, cos_2d, f->len, co);
- CustomData_bmesh_interp(
- &bm->ldata, (const void **)blocks,
- w, NULL, f->len, l_iter->head.data);
- l_first = l_iter;
- }
- else {
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
- l_first->head.data, &l_iter->head.data);
- }
- }
- }
- }
- }
- }
- }
-
-
-
- /* cleanup */
- for (i = 0; i < edge_net_len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edge_net[i], EDGE_NET);
- /* from interp only */
- BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_VISIT);
- BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_VISIT);
- }
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_ELEM_API_FLAG_DISABLE(l_iter->e, EDGE_NET);
- /* from interp only */
- BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT);
- } while ((l_iter = l_iter->next) != l_first);
-
- if (BLI_array_count(face_arr)) {
- bmesh_face_swap_data(f, face_arr[0]);
- BM_face_kill(bm, face_arr[0]);
- face_arr[0] = f;
- }
- else {
- BM_ELEM_API_FLAG_DISABLE(f, FACE_NET);
- }
-
- for (i = 0; i < BLI_array_count(face_arr); i++) {
- BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET);
- }
-
- if (r_face_arr) {
- *r_face_arr = face_arr;
- *r_face_arr_len = BLI_array_count(face_arr);
- }
- else {
- if (face_arr) {
- MEM_freeN(face_arr);
- }
- }
-
- return true;
-}
-
-#undef FACE_NET
-#undef VERT_VISIT
-#undef EDGE_NET
-
-/** \} */
-
-
/**
* \brief Vert Collapse Faces
*
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 142568e6e1a..2e557e3b606 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -27,14 +27,15 @@
* \ingroup bmesh
*/
-#include <stdio.h>
-
bool BM_vert_dissolve(BMesh *bm, BMVert *v);
bool BM_disk_dissolve(BMesh *bm, BMVert *v);
BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const bool do_del);
+
+/** see: bmesh_polygon_edgenet.h for #BM_face_split_edgenet */
+
BMFace *BM_face_split(
BMesh *bm, BMFace *f,
BMLoop *l_a, BMLoop *l_b,
@@ -47,11 +48,6 @@ BMFace *BM_face_split_n(
float cos[][3], int n,
BMLoop **r_l, BMEdge *example);
-bool BM_face_split_edgenet(
- BMesh *bm, BMFace *f,
- BMEdge **edge_net, const int edge_net_len,
- BMFace ***r_face_arr, int *r_face_arr_len);
-
BMEdge *BM_vert_collapse_faces(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
const bool do_del, const bool join_faces, const bool kill_degenerate_faces);
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index d92bdc6ea69..72a8dac534a 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -1567,6 +1567,7 @@ static BMOpDefine bmo_create_grid_def = {
{"y_segments", BMO_OP_SLOT_INT}, /* number of y segments */
{"size", BMO_OP_SLOT_FLT}, /* size of the grid */
{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
{{'\0'}},
},
/* slots_out */
@@ -1590,6 +1591,7 @@ static BMOpDefine bmo_create_uvsphere_def = {
{"v_segments", BMO_OP_SLOT_INT}, /* number of v segment */
{"diameter", BMO_OP_SLOT_FLT}, /* diameter */
{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
{{'\0'}},
},
/* slots_out */
@@ -1612,6 +1614,7 @@ static BMOpDefine bmo_create_icosphere_def = {
{{"subdivisions", BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */
{"diameter", BMO_OP_SLOT_FLT}, /* diameter */
{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
{{'\0'}},
},
/* slots_out */
@@ -1658,6 +1661,7 @@ static BMOpDefine bmo_create_cone_def = {
{"diameter2", BMO_OP_SLOT_FLT}, /* diameter of the opposite */
{"depth", BMO_OP_SLOT_FLT}, /* distance between ends */
{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
{{'\0'}},
},
/* slots_out */
@@ -1680,6 +1684,7 @@ static BMOpDefine bmo_create_circle_def = {
{"segments", BMO_OP_SLOT_INT},
{"diameter", BMO_OP_SLOT_FLT}, /* diameter of one end */
{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
{{'\0'}},
},
/* slots_out */
@@ -1701,6 +1706,7 @@ static BMOpDefine bmo_create_cube_def = {
/* slots_in */
{{"size", BMO_OP_SLOT_FLT}, /* size of the cube */
{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
{{'\0'}},
},
/* slots_out */
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index d9961e589da..0a4fb1d56a4 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -141,6 +141,14 @@ void BM_mesh_esubdivide(
const short use_only_quads,
const int seed);
+void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsigned int y_segments, const short oflag);
+void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag);
+void BM_mesh_calc_uvs_circle(BMesh *bm, float mat[4][4], const float radius, const short oflag);
+void BM_mesh_calc_uvs_cone(
+ BMesh *bm, float mat[4][4],
+ const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, const short oflag);
+void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag);
+
#include "intern/bmesh_operator_api_inline.h"
#endif /* __BMESH_OPERATORS_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index af0331d7771..8d8db799afa 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -150,10 +150,14 @@ static void bm_face_calc_poly_center_mean_vertex_cos(
/**
* For tools that insist on using triangles, ideally we would cache this data.
*
- * \param r_loops Store face loop pointers, (f->len)
- * \param r_index Store triangle triples, indices into \a r_loops, ((f->len - 2) * 3)
+ * \param use_fixed_quad: When true, always split quad along (0 -> 2) regardless of concave corners,
+ * (as done in #BM_mesh_calc_tessellation).
+ * \param r_loops: Store face loop pointers, (f->len)
+ * \param r_index: Store triangle triples, indices into \a r_loops, `((f->len - 2) * 3)`
*/
-void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3])
+void BM_face_calc_tessellation(
+ const BMFace *f, const bool use_fixed_quad,
+ BMLoop **r_loops, unsigned int (*r_index)[3])
{
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter;
@@ -167,7 +171,7 @@ void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (
r_index[0][1] = 1;
r_index[0][2] = 2;
}
- else if (f->len == 4) {
+ else if (f->len == 4 && use_fixed_quad) {
*r_loops++ = (l_iter = l_first);
*r_loops++ = (l_iter = l_iter->next);
*r_loops++ = (l_iter = l_iter->next);
@@ -202,6 +206,46 @@ void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (
}
/**
+ * Return a point inside the face.
+ */
+void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
+{
+ const BMLoop *l_tri[3];
+
+ if (f->len == 3) {
+ const BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ ARRAY_SET_ITEMS(l_tri, l, l->next, l->prev);
+ }
+ else {
+ /* tessellation here seems overkill when in many cases this will be the center,
+ * but without this we can't be sure the point is inside a concave face. */
+ const int tottri = f->len - 2;
+ BMLoop **loops = BLI_array_alloca(loops, f->len);
+ unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
+ int j;
+ int j_best = 0; /* use as fallback when unset */
+ float area_best = -1.0f;
+
+ BM_face_calc_tessellation(f, false, loops, index);
+
+ for (j = 0; j < tottri; j++) {
+ const float *p1 = loops[index[j][0]]->v->co;
+ const float *p2 = loops[index[j][1]]->v->co;
+ const float *p3 = loops[index[j][2]]->v->co;
+ const float area = area_squared_tri_v3(p1, p2, p3);
+ if (area > area_best) {
+ j_best = j;
+ area_best = area;
+ }
+ }
+
+ ARRAY_SET_ITEMS(l_tri, loops[index[j_best][0]], loops[index[j_best][1]], loops[index[j_best][2]]);
+ }
+
+ mid_v3_v3v3v3(r_co, l_tri[0]->v->co, l_tri[1]->v->co, l_tri[2]->v->co);
+}
+
+/**
* get the area of the face
*/
float BM_face_calc_area(const BMFace *f)
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index a1866bb010d..c84f4798ee4 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -34,7 +34,10 @@ struct Heap;
void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot);
-void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3]);
+void BM_face_calc_tessellation(
+ const BMFace *f, const bool use_fixed_quad,
+ BMLoop **r_loops, unsigned int (*r_index)[3]);
+void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]);
float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
float BM_face_calc_normal_vcos(
const BMesh *bm, const BMFace *f, float r_no[3],
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
new file mode 100644
index 00000000000..420fb26ca08
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -0,0 +1,1257 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/intern/bmesh_polygon_edgenet.c
+ * \ingroup bmesh
+ *
+ * This file contains functions for splitting faces into isolated regions,
+ * defined by connected edges.
+ */
+// #define DEBUG_PRINT
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_array.h"
+#include "BLI_alloca.h"
+#include "BLI_stackdefines.h"
+#include "BLI_linklist_stack.h"
+#include "BLI_sort.h"
+#include "BLI_sort_utils.h"
+#include "BLI_kdopbvh.h"
+
+#include "BKE_customdata.h"
+
+#include "bmesh.h"
+#include "intern/bmesh_private.h"
+
+/* -------------------------------------------------------------------- */
+/* Face Split Edge-Net */
+
+/** \name BM_face_split_edgenet and helper functions.
+ *
+ * \note Don't use #BM_edge_is_wire or #BM_edge_is_boundary
+ * since we need to take flagged faces into account.
+ * Also take care accessing e->l directly.
+ *
+ * \{ */
+
+/* Note: All these flags _must_ be cleared on exit */
+
+/* face is apart of the edge-net (including the original face we're splitting) */
+#define FACE_NET _FLAG_WALK
+/* edge is apart of the edge-net we're filling */
+#define EDGE_NET _FLAG_WALK
+/* tag verts we've visit */
+#define VERT_VISIT _FLAG_WALK
+
+struct VertOrder {
+ float angle;
+ BMVert *v;
+};
+
+static unsigned int bm_edge_flagged_radial_count(BMEdge *e)
+{
+ unsigned int count = 0;
+ BMLoop *l;
+
+ if ((l = e->l)) {
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
+ count++;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ return count;
+}
+
+static BMLoop *bm_edge_flagged_radial_first(BMEdge *e)
+{
+ BMLoop *l;
+
+ if ((l = e->l)) {
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
+ return l;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ return NULL;
+}
+
+static bool bm_face_split_edgenet_find_loop_pair(
+ BMVert *v_init, const float face_normal[3],
+ BMEdge *e_pair[2])
+{
+ /* Always find one boundary edge (to determine winding)
+ * and one wire (if available), otherwise another boundary.
+ */
+ BMIter iter;
+ BMEdge *e;
+
+ /* detect winding */
+ BMLoop *l_walk;
+ bool swap;
+
+ BLI_SMALLSTACK_DECLARE(edges_boundary, BMEdge *);
+ BLI_SMALLSTACK_DECLARE(edges_wire, BMEdge *);
+ int edges_boundary_len = 0;
+ int edges_wire_len = 0;
+
+ BM_ITER_ELEM (e, &iter, v_init, BM_EDGES_OF_VERT) {
+ if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
+ const unsigned int count = bm_edge_flagged_radial_count(e);
+ if (count == 1) {
+ BLI_SMALLSTACK_PUSH(edges_boundary, e);
+ edges_boundary_len++;
+ }
+ else if (count == 0) {
+ BLI_SMALLSTACK_PUSH(edges_wire, e);
+ edges_wire_len++;
+ }
+ }
+ }
+
+ /* first edge should always be boundary */
+ if (edges_boundary_len == 0) {
+ return false;
+ }
+ e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary);
+
+ /* attempt one boundary and one wire, or 2 boundary */
+ if (edges_wire_len == 0) {
+ if (edges_boundary_len >= 2) {
+ e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary);
+ }
+ else {
+ /* one boundary and no wire */
+ return false;
+ }
+ }
+ else {
+ e_pair[1] = BLI_SMALLSTACK_POP(edges_wire);
+
+ if (edges_wire_len > 1) {
+ BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init);
+ BMVert *v_next;
+ float angle_best;
+
+ v_next = BM_edge_other_vert(e_pair[1], v_init);
+ angle_best = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
+
+ while ((e = BLI_SMALLSTACK_POP(edges_wire))) {
+ float angle_test;
+ v_next = BM_edge_other_vert(e, v_init);
+ angle_test = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
+ if (angle_test < angle_best) {
+ angle_best = angle_test;
+ e_pair[1] = e;
+ }
+ }
+ }
+ }
+
+
+ /* flip based on winding */
+ l_walk = bm_edge_flagged_radial_first(e_pair[0]);
+ swap = false;
+ if (face_normal == l_walk->f->no) {
+ swap = !swap;
+ }
+ if (l_walk->v != v_init) {
+ swap = !swap;
+ }
+ if (swap) {
+ SWAP(BMEdge *, e_pair[0], e_pair[1]);
+ }
+
+ return true;
+}
+
+static bool bm_face_split_edgenet_find_loop_walk(
+ BMVert *v_init, const float face_normal[3],
+ /* cache to avoid realloc every time */
+ struct VertOrder *edge_order, const unsigned int edge_order_len,
+ BMEdge *e_pair[2])
+{
+ /* fast-path for the common case (avoid push-pop).
+ * Also avoids tagging as visited since we know we
+ * can't reach these verts some other way */
+#define USE_FASTPATH_NOFORK
+
+ BMVert *v;
+ BMVert *v_dst;
+ bool found = false;
+
+ struct VertOrder *eo;
+ STACK_DECLARE(edge_order);
+
+ /* store visited verts so we can clear the visit flag after execution */
+ BLI_SMALLSTACK_DECLARE(vert_visit, BMVert *);
+
+ /* likely this will stay very small
+ * all verts pushed into this stack _must_ have their previous edges set! */
+ BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
+ BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
+
+ STACK_INIT(edge_order, edge_order_len);
+
+ /* start stepping */
+ v = BM_edge_other_vert(e_pair[0], v_init);
+ v->e = e_pair[0];
+ BLI_SMALLSTACK_PUSH(vert_stack, v);
+
+ v_dst = BM_edge_other_vert(e_pair[1], v_init);
+
+#ifdef DEBUG_PRINT
+ printf("%s: vert (search) %d\n", __func__, BM_elem_index_get(v_init));
+#endif
+
+ /* This loop will keep stepping over the best possible edge,
+ * in most cases it finds the direct route to close the face.
+ *
+ * In cases where paths can't be closed,
+ * alternatives are stored in the 'vert_stack'.
+ */
+ while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
+ BMIter eiter;
+ BMEdge *e_next;
+
+#ifdef USE_FASTPATH_NOFORK
+walk_nofork:
+#else
+ BLI_SMALLSTACK_PUSH(vert_visit, v);
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+#endif
+
+ BLI_assert(STACK_SIZE(edge_order) == 0);
+
+ /* check if we're done! */
+ if (v == v_dst) {
+ found = true;
+ goto finally;
+ }
+
+ BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
+ if ((v->e != e_next) &&
+ (BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) &&
+ (bm_edge_flagged_radial_count(e_next) < 2))
+ {
+ BMVert *v_next;
+
+ v_next = BM_edge_other_vert(e_next, v);
+
+#ifdef DEBUG_PRINT
+ /* indent and print */
+ {
+ BMVert *_v = v;
+ do {
+ printf(" ");
+ } while ((_v = BM_edge_other_vert(_v->e, _v)) != v_init);
+ printf("vert %d -> %d (add=%d)\n",
+ BM_elem_index_get(v), BM_elem_index_get(v_next),
+ BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT) == 0);
+ }
+#endif
+
+ if (!BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT)) {
+ eo = STACK_PUSH_RET_PTR(edge_order);
+ eo->v = v_next;
+
+ v_next->e = e_next;
+ }
+ }
+ }
+
+#ifdef USE_FASTPATH_NOFORK
+ if (STACK_SIZE(edge_order) == 1) {
+ eo = STACK_POP_PTR(edge_order);
+ v = eo->v;
+
+ goto walk_nofork;
+ }
+#endif
+
+ /* sort by angle if needed */
+ if (STACK_SIZE(edge_order) > 1) {
+ unsigned int j;
+ BMVert *v_prev = BM_edge_other_vert(v->e, v);
+
+ for (j = 0; j < STACK_SIZE(edge_order); j++) {
+ edge_order[j].angle = angle_signed_on_axis_v3v3v3_v3(v_prev->co, v->co, edge_order[j].v->co, face_normal);
+ }
+ qsort(edge_order, STACK_SIZE(edge_order), sizeof(struct VertOrder), BLI_sortutil_cmp_float_reverse);
+
+#ifdef USE_FASTPATH_NOFORK
+ /* only tag forks */
+ BLI_SMALLSTACK_PUSH(vert_visit, v);
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+#endif
+ }
+
+ while ((eo = STACK_POP_PTR(edge_order))) {
+ BLI_SMALLSTACK_PUSH(vert_stack_next, eo->v);
+ }
+
+ if (!BLI_SMALLSTACK_IS_EMPTY(vert_stack_next)) {
+ BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
+ }
+ }
+
+
+finally:
+ /* clear flag for next execution */
+ while ((v = BLI_SMALLSTACK_POP(vert_visit))) {
+ BM_ELEM_API_FLAG_DISABLE(v, VERT_VISIT);
+ }
+
+ return found;
+
+#undef USE_FASTPATH_NOFORK
+}
+
+static bool bm_face_split_edgenet_find_loop(
+ BMVert *v_init, const float face_normal[3],
+ /* cache to avoid realloc every time */
+ struct VertOrder *edge_order, const unsigned int edge_order_len,
+ BMVert **r_face_verts, int *r_face_verts_len)
+{
+ BMEdge *e_pair[2];
+ BMVert *v;
+
+ if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, e_pair)) {
+ return false;
+ }
+
+ BLI_assert((bm_edge_flagged_radial_count(e_pair[0]) == 1) ||
+ (bm_edge_flagged_radial_count(e_pair[1]) == 1));
+
+ if (bm_face_split_edgenet_find_loop_walk(v_init, face_normal, edge_order, edge_order_len, e_pair)) {
+ unsigned int i = 0;
+
+ r_face_verts[i++] = v_init;
+ v = BM_edge_other_vert(e_pair[1], v_init);
+ do {
+ r_face_verts[i++] = v;
+ } while ((v = BM_edge_other_vert(v->e, v)) != v_init);
+ *r_face_verts_len = i;
+ return (i > 2) ? true : false;
+ }
+ else {
+ return false;
+ }
+}
+
+/**
+ * Splits a face into many smaller faces defined by an edge-net.
+ * handle customdata and degenerate cases.
+ *
+ * - isolated holes or unsupported face configurations, will be ignored.
+ * - customdata calculations aren't efficient
+ * (need to calculate weights for each vert).
+ */
+bool BM_face_split_edgenet(
+ BMesh *bm,
+ BMFace *f, BMEdge **edge_net, const int edge_net_len,
+ BMFace ***r_face_arr, int *r_face_arr_len)
+{
+ /* re-use for new face verts */
+ BMVert **face_verts;
+ int face_verts_len;
+
+ BMFace **face_arr = NULL;
+ BLI_array_declare(face_arr);
+
+ BMVert **vert_queue;
+ STACK_DECLARE(vert_queue);
+ int i;
+
+ struct VertOrder *edge_order;
+ const unsigned int edge_order_len = edge_net_len + 2;
+
+ BMVert *v;
+
+ BMLoop *l_iter, *l_first;
+
+
+ if (!edge_net_len) {
+ if (r_face_arr) {
+ *r_face_arr = NULL;
+ *r_face_arr_len = 0;
+ }
+ return false;
+ }
+
+ /* over-alloc (probably 2-4 is only used in most cases), for the biggest-fan */
+ edge_order = BLI_array_alloca(edge_order, edge_order_len);
+
+ /* use later */
+ face_verts = BLI_array_alloca(face_verts, edge_net_len + f->len);
+
+ vert_queue = BLI_array_alloca(vert_queue, edge_net_len + f->len);
+ STACK_INIT(vert_queue, f->len + edge_net_len);
+
+ BLI_assert(BM_ELEM_API_FLAG_TEST(f, FACE_NET) == 0);
+ BM_ELEM_API_FLAG_ENABLE(f, FACE_NET);
+
+#ifdef DEBUG
+ for (i = 0; i < edge_net_len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET) == 0);
+ BLI_assert(BM_edge_in_face(edge_net[i], f) == false);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter->e, EDGE_NET) == 0);
+ } while ((l_iter = l_iter->next) != l_first);
+#endif
+
+
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET);
+ } while ((l_iter = l_iter->next) != l_first);
+
+
+ /* any vert can be used to begin with */
+ STACK_PUSH(vert_queue, l_first->v);
+
+ while ((v = STACK_POP(vert_queue))) {
+ if (bm_face_split_edgenet_find_loop(v, f->no, edge_order, edge_order_len, face_verts, &face_verts_len)) {
+ BMFace *f_new;
+
+ f_new = BM_face_create_verts(bm, face_verts, face_verts_len, f, BM_CREATE_NOP, false);
+
+ for (i = 0; i < edge_net_len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET));
+ }
+
+ if (f_new) {
+ bool l_prev_is_boundary;
+ BLI_array_append(face_arr, f_new);
+ copy_v3_v3(f_new->no, f->no);
+
+ /* warning, normally don't do this,
+ * its needed for mesh intersection - which tracks face-sides based on selection */
+ f_new->head.hflag = f->head.hflag;
+ if (f->head.hflag & BM_ELEM_SELECT) {
+ bm->totfacesel++;
+ }
+
+ BM_ELEM_API_FLAG_ENABLE(f_new, FACE_NET);
+
+ /* add new verts to keep finding loops for
+ * (verts between boundary and manifold edges) */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
+ l_prev_is_boundary = (bm_edge_flagged_radial_count(l_iter->prev->e) == 1);
+ do {
+ bool l_iter_is_boundary = (bm_edge_flagged_radial_count(l_iter->e) == 1);
+ if (l_prev_is_boundary != l_iter_is_boundary) {
+ STACK_PUSH(vert_queue, l_iter->v);
+ }
+ l_prev_is_boundary = l_iter_is_boundary;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ }
+
+
+ if (CustomData_has_math(&bm->ldata)) {
+ /* reuse VERT_VISIT here to tag vert's already interpolated */
+ BMIter iter;
+ BMLoop *l_other;
+
+ /* see: #BM_loop_interp_from_face for similar logic */
+ void **blocks = BLI_array_alloca(blocks, f->len);
+ float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f->len);
+ float *w = BLI_array_alloca(w, f->len);
+ float axis_mat[3][3];
+ float co[2];
+
+ /* interior loops */
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+
+ /* first simply copy from existing face */
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ITER_ELEM (l_other, &iter, l_iter->v, BM_LOOPS_OF_VERT) {
+ if ((l_other->f != f) && BM_ELEM_API_FLAG_TEST(l_other->f, FACE_NET)) {
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
+ l_iter->head.data, &l_other->head.data);
+ }
+ }
+ /* tag not to interpolate */
+ BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_VISIT);
+
+
+ mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+ blocks[i] = l_iter->head.data;
+
+ } while (i++, (l_iter = l_iter->next) != l_first);
+
+
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ITER_ELEM (v, &iter, edge_net[i], BM_VERTS_OF_EDGE) {
+ if (!BM_ELEM_API_FLAG_TEST(v, VERT_VISIT)) {
+ BMIter liter;
+
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+
+ /* interpolate this loop, then copy to the rest */
+ l_first = NULL;
+
+ BM_ITER_ELEM (l_iter, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->f, FACE_NET)) {
+ if (l_first == NULL) {
+ mul_v2_m3v3(co, axis_mat, v->co);
+ interp_weights_poly_v2(w, cos_2d, f->len, co);
+ CustomData_bmesh_interp(
+ &bm->ldata, (const void **)blocks,
+ w, NULL, f->len, l_iter->head.data);
+ l_first = l_iter;
+ }
+ else {
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
+ l_first->head.data, &l_iter->head.data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+ /* cleanup */
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i], EDGE_NET);
+ /* from interp only */
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_VISIT);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_DISABLE(l_iter->e, EDGE_NET);
+ /* from interp only */
+ BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (BLI_array_count(face_arr)) {
+ bmesh_face_swap_data(f, face_arr[0]);
+ BM_face_kill(bm, face_arr[0]);
+ face_arr[0] = f;
+ }
+ else {
+ BM_ELEM_API_FLAG_DISABLE(f, FACE_NET);
+ }
+
+ for (i = 0; i < BLI_array_count(face_arr); i++) {
+ BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET);
+ }
+
+ if (r_face_arr) {
+ *r_face_arr = face_arr;
+ *r_face_arr_len = BLI_array_count(face_arr);
+ }
+ else {
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
+ }
+
+ return true;
+}
+
+#undef FACE_NET
+#undef VERT_VISIT
+#undef EDGE_NET
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Face Split Edge-Net Connect Islands */
+
+/** \name BM_face_split_edgenet_connect_islands and helper functions.
+ *
+ * Connect isolated mesh 'islands' so they form legal regions from which we can create faces.
+ *
+ * Intended to be used as a pre-processing step for #BM_face_split_edgenet.
+ *
+ * \warning Currently this risks running out of stack memory (#alloca),
+ * likely we'll pass in a memory arena (cleared each use) eventually.
+ *
+ * \{ */
+
+#define VERT_IS_VALID BM_ELEM_INTERNAL_TAG
+
+/* can be X or Y */
+#define SORT_AXIS 0
+
+BLI_INLINE bool edge_isect_verts_point_2d(
+ const BMEdge *e, const BMVert *v_a, const BMVert *v_b,
+ float r_isect[2])
+{
+ return ((isect_seg_seg_v2_point(v_a->co, v_b->co, e->v1->co, e->v2->co, r_isect) == 1) &&
+ ((e->v1 != v_a) && (e->v2 != v_a) && (e->v1 != v_b) && (e->v2 != v_b)));
+}
+
+/**
+ * Represents isolated edge-links,
+ * each island owns contiguous slices of the vert array.
+ * (edges remain in `edge_links`).
+ */
+struct EdgeGroupIsland {
+ LinkNode edge_links; /* keep first */
+ unsigned int vert_len, edge_len;
+
+ /* Set the following vars once we have >1 groups */
+
+ /* when when an edge in a previous group connects to this one,
+ * so theres no need to create one pointing back. */
+ unsigned int has_prev_edge : 1;
+
+ /* verts in the group which has the lowest & highest values,
+ * the lower vertex is connected to the first edge */
+ struct {
+ BMVert *min, *max;
+ /* used for sorting only */
+ float min_axis;
+ } vert_span;
+};
+
+static int group_min_cmp_fn(const void *p1, const void *p2)
+{
+ const struct EdgeGroupIsland *g1 = *(struct EdgeGroupIsland **)p1;
+ const struct EdgeGroupIsland *g2 = *(struct EdgeGroupIsland **)p2;
+ /* min->co[SORT_AXIS] hasn't been applied yet */
+ const float f1 = g1->vert_span.min_axis;
+ const float f2 = g2->vert_span.min_axis;
+
+ if (f1 < f2) return -1;
+ if (f1 > f2) return 1;
+ else return 0;
+}
+
+struct Edges_VertVert_BVHTreeTest {
+ float dist_orig;
+ BMEdge **edge_arr;
+
+ BMVert *v_origin;
+ BMVert *v_other;
+
+ const unsigned int *vert_range;
+};
+
+struct Edges_VertRay_BVHTreeTest {
+ BMEdge **edge_arr;
+
+ BMVert *v_origin;
+
+ const unsigned int *vert_range;
+};
+
+static void bvhtree_test_edges_isect_2d_vert_cb(
+ void *user_data, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit)
+{
+ struct Edges_VertVert_BVHTreeTest *data = user_data;
+ const BMEdge *e = data->edge_arr[index];
+ const int v1_index = BM_elem_index_get(e->v1);
+ float co_isect[2];
+
+ if (edge_isect_verts_point_2d(e, data->v_origin, data->v_other, co_isect)) {
+ const float t = line_point_factor_v2(co_isect, data->v_origin->co, data->v_other->co);
+ const float dist_new = data->dist_orig * t;
+ /* avoid float precision issues, possible this is greater */
+ if (LIKELY(dist_new < hit->dist)) {
+ /* v1/v2 will both be in the same group */
+ if (v1_index < (int)data->vert_range[0] ||
+ v1_index >= (int)data->vert_range[1])
+ {
+ hit->dist = dist_new;
+ hit->index = index;
+ }
+ }
+ }
+}
+
+static void bvhtree_test_edges_isect_2d_ray_cb(
+ void *user_data, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ struct Edges_VertRay_BVHTreeTest *data = user_data;
+ const BMEdge *e = data->edge_arr[index];
+
+ /* direction is normalized, so this will be the distance */
+ float dist_new;
+ if (isect_ray_seg_v2(data->v_origin->co, ray->direction, e->v1->co, e->v2->co, &dist_new, NULL)) {
+ /* avoid float precision issues, possible this is greater */
+ if (LIKELY(dist_new < hit->dist)) {
+ if (e->v1 != data->v_origin && e->v2 != data->v_origin) {
+ const int v1_index = BM_elem_index_get(e->v1);
+ /* v1/v2 will both be in the same group */
+ if (v1_index < (int)data->vert_range[0] ||
+ v1_index >= (int)data->vert_range[1])
+ {
+ hit->dist = dist_new;
+ hit->index = index;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Store values for:
+ * - #bm_face_split_edgenet_find_connection
+ * - #test_edges_isect_2d
+ * ... which don't change each call.
+ */
+struct EdgeGroup_FindConnection_Args {
+ BVHTree *bvhtree;
+ BMEdge **edge_arr;
+ unsigned int edge_arr_len;
+
+ BMEdge **edge_arr_new;
+ unsigned int edge_arr_new_len;
+
+ const unsigned int *vert_range;
+};
+
+static BMEdge *test_edges_isect_2d_vert(
+ const struct EdgeGroup_FindConnection_Args *args,
+ BMVert *v_origin, BMVert *v_other)
+{
+ int index;
+
+ BVHTreeRayHit hit = {0};
+ float dir[3];
+
+ sub_v2_v2v2(dir, v_other->co, v_origin->co);
+ dir[2] = 0.0f;
+ hit.index = -1;
+ hit.dist = normalize_v2(dir);
+
+ struct Edges_VertVert_BVHTreeTest user_data = {0};
+ user_data.dist_orig = hit.dist;
+ user_data.edge_arr = args->edge_arr;
+ user_data.v_origin = v_origin;
+ user_data.v_other = v_other;
+ user_data.vert_range = args->vert_range;
+
+ index = BLI_bvhtree_ray_cast_ex(
+ args->bvhtree, v_origin->co, dir, 0.0f, &hit,
+ bvhtree_test_edges_isect_2d_vert_cb, &user_data, 0);
+
+ BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL;
+
+ /* check existing connections (no spatial optimization here since we're continually adding). */
+ if (LIKELY(index == -1)) {
+ float t_best = 1.0f;
+ for (unsigned int i = 0; i < args->edge_arr_new_len; i++) {
+ float co_isect[2];
+ if (UNLIKELY(edge_isect_verts_point_2d(args->edge_arr_new[i], v_origin, v_other, co_isect))) {
+ const float t_test = line_point_factor_v2(co_isect, v_origin->co, v_other->co);
+ if (t_test < t_best) {
+ t_best = t_test;
+
+ e_hit = args->edge_arr_new[i];
+ }
+ }
+ }
+ }
+
+ return e_hit;
+}
+
+/**
+ * Similar to #test_edges_isect_2d_vert but we're casting into a direction,
+ * (not to a vertex)
+ */
+static BMEdge *test_edges_isect_2d_ray(
+ const struct EdgeGroup_FindConnection_Args *args,
+ BMVert *v_origin, const float dir[3])
+{
+ int index;
+ BVHTreeRayHit hit = {0};
+
+ BLI_ASSERT_UNIT_V2(dir);
+
+ hit.index = -1;
+ hit.dist = FLT_MAX;
+
+ struct Edges_VertRay_BVHTreeTest user_data = {0};
+ user_data.edge_arr = args->edge_arr;
+ user_data.v_origin = v_origin;
+ user_data.vert_range = args->vert_range;
+
+ index = BLI_bvhtree_ray_cast_ex(
+ args->bvhtree, v_origin->co, dir, 0.0f, &hit,
+ bvhtree_test_edges_isect_2d_ray_cb, &user_data, 0);
+
+ BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL;
+
+ /* check existing connections (no spatial optimization here since we're continually adding). */
+ if (LIKELY(index != -1)) {
+ for (unsigned int i = 0; i < args->edge_arr_new_len; i++) {
+ BMEdge *e = args->edge_arr_new[i];
+ float dist_new;
+ if (isect_ray_seg_v2(v_origin->co, dir, e->v1->co, e->v2->co, &dist_new, NULL)) {
+ if (e->v1 != v_origin && e->v2 != v_origin) {
+ /* avoid float precision issues, possible this is greater */
+ if (LIKELY(dist_new < hit.dist)) {
+ hit.dist = dist_new;
+
+ e_hit = args->edge_arr_new[i];
+ }
+ }
+ }
+ }
+ }
+
+ return e_hit;
+}
+
+static int bm_face_split_edgenet_find_connection(
+ const struct EdgeGroup_FindConnection_Args *args,
+ BMVert *v_origin,
+ /* false = negative, true = positive */
+ bool direction_sign)
+{
+ /**
+ * Method for finding connection is as follows:
+ *
+ * - Cast a ray along either the positive or negative directions.
+ * - Take the hit-edge, and cast rays to their vertices checking those rays don't intersect a closer edge.
+ * - Keep taking the hit-edge and testing its verts until a vertex is found which isn't blocked by an edge.
+ *
+ * \note It's possible none of the verts can be accessed (with self-intersecting lines).
+ * In that case theres no right answer (without subdividing edges),
+ * so return a fall-back vertex in that case.
+ */
+
+ const float dir[3] = {[SORT_AXIS] = direction_sign ? 1.0f : -1.0f};
+ BMEdge *e_hit = test_edges_isect_2d_ray(args, v_origin, dir);
+ BMVert *v_other = NULL;
+
+ if (e_hit) {
+ BMVert *v_other_fallback = NULL;
+
+ BLI_SMALLSTACK_DECLARE(vert_search, BMVert *);
+
+ /* ensure we never add verts multiple times (not all that likely - but possible) */
+ BLI_SMALLSTACK_DECLARE(vert_blacklist, BMVert *);
+
+ do {
+ BMVert *v_pair[2];
+ /* ensure the closest vertex is popped back off the stack first */
+ if (len_squared_v2v2(v_origin->co, e_hit->v1->co) >
+ len_squared_v2v2(v_origin->co, e_hit->v2->co))
+ {
+ ARRAY_SET_ITEMS(v_pair, e_hit->v1, e_hit->v2);
+ }
+ else {
+ ARRAY_SET_ITEMS(v_pair, e_hit->v2, e_hit->v1);
+ }
+
+ for (int j = 0; j < 2; j++) {
+ BMVert *v_iter = v_pair[j];
+ if (BM_elem_flag_test(v_iter, VERT_IS_VALID)) {
+ if (direction_sign ? (v_iter->co[SORT_AXIS] >= v_origin->co[SORT_AXIS]) :
+ (v_iter->co[SORT_AXIS] <= v_origin->co[SORT_AXIS]))
+ {
+ BLI_SMALLSTACK_PUSH(vert_search, v_iter);
+ BLI_SMALLSTACK_PUSH(vert_blacklist, v_iter);
+ BM_elem_flag_disable(v_iter, VERT_IS_VALID);
+ }
+ }
+ }
+ v_other_fallback = v_other;
+
+ } while ((v_other = BLI_SMALLSTACK_POP(vert_search)) &&
+ (e_hit = test_edges_isect_2d_vert(args, v_origin, v_other)));
+
+ if (v_other == NULL) {
+ printf("Using fallback\n");
+ v_other = v_other_fallback;
+ }
+
+ /* reset the blacklist flag, for future use */
+ BMVert *v;
+ while ((v = BLI_SMALLSTACK_POP(vert_blacklist))) {
+ BM_elem_flag_enable(v, VERT_IS_VALID);
+ }
+ }
+
+ /* if we reach this line, v_other is either the best vertex or its NULL */
+ return v_other ? BM_elem_index_get(v_other) : -1;
+}
+
+/**
+ * For when the edge-net has holes in it-this connects them.
+ *
+ * \param mem_arena: Avoids many small allocs & should be cleared after each use.
+ * take care since \a r_edge_net_new is stored in \a r_edge_net_new.
+ */
+bool BM_face_split_edgenet_connect_islands(
+ BMesh *bm,
+ BMFace *f, BMEdge **edge_net_init, const unsigned int edge_net_init_len,
+ MemArena *mem_arena,
+ BMEdge ***r_edge_net_new, unsigned int *r_edge_net_new_len)
+{
+ /* -------------------------------------------------------------------- */
+ /* This function has 2 main parts.
+ *
+ * - Check if there are any holes.
+ * - Connect the holes with edges (if any are found).
+ *
+ * Keep the first part fast since it will run very often for edge-nets that have no holes.
+ *
+ * \note Don't use the mem_arena unless he have holes to fill.
+ * (avoid thrashing the area when the initial check isn't so intensive on the stack).
+ */
+
+ const unsigned int edge_arr_len = (unsigned int)edge_net_init_len + (unsigned int)f->len;
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len);
+ bool ok = false;
+
+ memcpy(edge_arr, edge_net_init, sizeof(*edge_arr) * (size_t)edge_net_init_len);
+
+ /* _must_ clear on exit */
+#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
+#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
+
+ {
+ unsigned int i = edge_net_init_len;
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ edge_arr[i++] = l_iter->e;
+ } while ((l_iter = l_iter->next) != l_first);
+ BLI_assert(i == edge_arr_len);
+ }
+
+ for (unsigned int i = 0; i < edge_arr_len; i++) {
+ BM_elem_flag_enable(edge_arr[i], EDGE_NOT_IN_STACK);
+ BM_elem_flag_enable(edge_arr[i]->v1, VERT_NOT_IN_STACK);
+ BM_elem_flag_enable(edge_arr[i]->v2, VERT_NOT_IN_STACK);
+ }
+
+ unsigned int group_arr_len = 0;
+ LinkNode *group_head = NULL;
+ {
+ /* scan 'edge_arr' backwards so the outer face boundary is handled first
+ * (since its likely to be the largest) */
+ unsigned int edge_index = (edge_arr_len - 1);
+ unsigned int edge_in_group_tot = 0;
+
+ BLI_SMALLSTACK_DECLARE(vstack, BMVert *);
+
+ while (true) {
+ LinkNode *edge_links = NULL;
+ unsigned int unique_verts_in_group = 0, unique_edges_in_group = 0;
+
+ /* list of groups */
+ BLI_assert(BM_elem_flag_test(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK));
+ BLI_SMALLSTACK_PUSH(vstack, edge_arr[edge_index]->v1);
+ BM_elem_flag_disable(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK);
+
+ BMVert *v_iter;
+ while ((v_iter = BLI_SMALLSTACK_POP(vstack))) {
+ unique_verts_in_group++;
+
+ BMEdge *e_iter = v_iter->e;
+ do {
+ if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) {
+ BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK);
+ unique_edges_in_group++;
+
+ BLI_linklist_prepend_alloca(&edge_links, e_iter);
+
+ BMVert *v_other = BM_edge_other_vert(e_iter, v_iter);
+ if (BM_elem_flag_test(v_other, VERT_NOT_IN_STACK)) {
+ BLI_SMALLSTACK_PUSH(vstack, v_other);
+ BM_elem_flag_disable(v_other, VERT_NOT_IN_STACK);
+ }
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_iter)) != v_iter->e);
+ }
+
+ struct EdgeGroupIsland *g = alloca(sizeof(*g));
+ g->vert_len = unique_verts_in_group;
+ g->edge_len = unique_edges_in_group;
+ edge_in_group_tot += unique_edges_in_group;
+
+ BLI_linklist_prepend_nlink(&group_head, edge_links, (LinkNode *)g);
+
+ group_arr_len++;
+
+ if (edge_in_group_tot == edge_arr_len) {
+ break;
+ }
+
+ /* skip edges in the stack */
+ while (BM_elem_flag_test(edge_arr[edge_index], EDGE_NOT_IN_STACK) == false) {
+ BLI_assert(edge_index != 0);
+ edge_index--;
+ }
+ }
+ }
+
+ /* single group - no holes */
+ if (group_arr_len == 1) {
+ goto finally;
+ }
+
+
+ /* -------------------------------------------------------------------- */
+ /* Previous checks need to be kept fast, since they will run very often,
+ * now we know there are holes, so calculate a spatial lookup info and
+ * other per-group data.
+ */
+
+ float axis_mat[3][3];
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+#define VERT_IN_ARRAY BM_ELEM_INTERNAL_TAG
+
+ struct EdgeGroupIsland **group_arr = BLI_memarena_alloc(mem_arena, sizeof(*group_arr) * group_arr_len);
+ unsigned int vert_arr_len = 0;
+ /* sort groups by lowest value vertex */
+ {
+ /* fill 'groups_arr' in reverse order so the boundary face is first */
+ struct EdgeGroupIsland **group_arr_p = &group_arr[group_arr_len];
+
+ for (struct EdgeGroupIsland *g = (void *)group_head; g; g = (struct EdgeGroupIsland *)g->edge_links.next) {
+ LinkNode *edge_links = g->edge_links.link;
+
+ /* init with *any* different verts */
+ g->vert_span.min = ((BMEdge *)edge_links->link)->v1;
+ g->vert_span.max = ((BMEdge *)edge_links->link)->v2;
+ float min_axis = FLT_MAX;
+ float max_axis = -FLT_MAX;
+
+ do {
+ BMEdge *e = edge_links->link;
+ BLI_assert(e->head.htype == BM_EDGE);
+
+ for (int j = 0; j < 2; j++) {
+ BMVert *v_iter = (&e->v1)[j];
+ BLI_assert(v_iter->head.htype == BM_VERT);
+ /* ideally we could use 'v_iter->co[SORT_AXIS]' here,
+ * but we need to sort the groups before setting the vertex array order */
+#if SORT_AXIS == 0
+ const float axis_value = dot_m3_v3_row_x(axis_mat, v_iter->co);
+#else
+ const float axis_value = dot_m3_v3_row_y(axis_mat, v_iter->co);
+#endif
+
+ if (axis_value < min_axis) {
+ g->vert_span.min = v_iter;
+ min_axis = axis_value;
+ }
+ if (axis_value > max_axis ) {
+ g->vert_span.max = v_iter;
+ max_axis = axis_value;
+ }
+ }
+ } while ((edge_links = edge_links->next));
+
+ g->vert_span.min_axis = min_axis;
+
+ g->has_prev_edge = false;
+
+ vert_arr_len += g->vert_len;
+
+ *(--group_arr_p) = g;
+ }
+ }
+
+ qsort(group_arr, group_arr_len, sizeof(*group_arr), group_min_cmp_fn);
+
+ /* we don't know how many unique verts there are connecting the edges, so over-alloc */
+ BMVert **vert_arr = BLI_memarena_alloc(mem_arena, sizeof(*vert_arr) * vert_arr_len);
+ /* map vertex -> group index */
+ unsigned int *verts_group_table = BLI_memarena_alloc(mem_arena, sizeof(*verts_group_table) * vert_arr_len);
+
+ float (*vert_coords_backup)[3] = BLI_memarena_alloc(mem_arena, sizeof(*vert_coords_backup) * vert_arr_len);
+
+ {
+ /* relative location, for higher precision calculations */
+ const float f_co_ref[3] = {UNPACK3(BM_FACE_FIRST_LOOP(f)->v->co)};
+
+ int v_index = 0; /* global vert index */
+ for (unsigned int g_index = 0; g_index < group_arr_len; g_index++) {
+ LinkNode *edge_links = group_arr[g_index]->edge_links.link;
+ do {
+ BMEdge *e = edge_links->link;
+ for (int j = 0; j < 2; j++) {
+ BMVert *v_iter = (&e->v1)[j];
+ if (!BM_elem_flag_test(v_iter, VERT_IN_ARRAY)) {
+ BM_elem_flag_enable(v_iter, VERT_IN_ARRAY);
+
+ /* not nice, but alternatives arent much better :S */
+ {
+ copy_v3_v3(vert_coords_backup[v_index], v_iter->co);
+
+ /* for higher precision */
+ sub_v3_v3(v_iter->co, f_co_ref);
+
+ float co_2d[2];
+ mul_v2_m3v3(co_2d, axis_mat, v_iter->co);
+ v_iter->co[0] = co_2d[0];
+ v_iter->co[1] = co_2d[1];
+ v_iter->co[2] = 0.0f;
+ }
+
+ BM_elem_index_set(v_iter, v_index); /* set_dirty */
+
+ vert_arr[v_index] = v_iter;
+ verts_group_table[v_index] = g_index;
+ v_index++;
+ }
+ }
+ } while ((edge_links = edge_links->next));
+ }
+ }
+
+ bm->elem_index_dirty |= BM_VERT;
+
+ /* Now create bvh tree*/
+ BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 0.0f, 8, 8);
+ for (unsigned int i = 0; i < edge_arr_len; i++) {
+ const float e_cos[2][3] = {
+ {UNPACK2(edge_arr[i]->v1->co), 0.0f},
+ {UNPACK2(edge_arr[i]->v2->co), 0.0f},
+ };
+ BLI_bvhtree_insert(bvhtree, i, (const float *)e_cos, 2);
+ }
+ BLI_bvhtree_balance(bvhtree);
+
+ /* Create connections between groups */
+
+ /* may be an over-alloc, but not by much */
+ unsigned int edge_net_new_len = (unsigned int)edge_net_init_len + ((group_arr_len - 1) * 2);
+ BMEdge **edge_net_new = BLI_memarena_alloc(mem_arena, sizeof(*edge_net_new) * edge_net_new_len);
+ memcpy(edge_net_new, edge_net_init, sizeof(*edge_net_new) * (size_t)edge_net_init_len);
+
+ {
+ unsigned int edge_net_new_index = edge_net_init_len;
+ /* start-end of the verts in the current group */
+
+ unsigned int vert_range[2];
+
+ vert_range[0] = 0;
+ vert_range[1] = group_arr[0]->vert_len;
+
+ struct EdgeGroup_FindConnection_Args args = {
+ .bvhtree = bvhtree,
+
+ /* use the new edge array so we can scan edges which have been added */
+ .edge_arr = edge_arr,
+ .edge_arr_len = edge_arr_len,
+
+ /* we only want to check newly created edges */
+ .edge_arr_new = edge_net_new + edge_net_init_len,
+ .edge_arr_new_len = 0,
+
+ .vert_range = vert_range,
+ };
+
+ for (unsigned int g_index = 1; g_index < group_arr_len; g_index++) {
+ struct EdgeGroupIsland *g = group_arr[g_index];
+
+ /* the range of verts this group uses in 'verts_arr' (not uncluding the last index) */
+ vert_range[0] = vert_range[1];
+ vert_range[1] += g->vert_len;
+
+ if (g->has_prev_edge == false) {
+ BMVert *v_origin = g->vert_span.min;
+
+ const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, false);
+ // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len);
+
+ /* only for degenerate geometry */
+ if (index_other != -1) {
+ BMVert *v_end = vert_arr[index_other];
+
+ edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0);
+ edge_net_new_index++;
+ args.edge_arr_new_len++;
+ }
+ }
+
+ {
+ BMVert *v_origin = g->vert_span.max;
+
+ const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, true);
+ // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len);
+
+ /* only for degenerate geometry */
+ if (index_other != -1) {
+ BMVert *v_end = vert_arr[index_other];
+
+ edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0);
+ edge_net_new_index++;
+ args.edge_arr_new_len++;
+
+ /* tell the 'next' group it doesn't need to create its own back-link */
+ unsigned int g_index_other = verts_group_table[index_other];
+ group_arr[g_index_other]->has_prev_edge = true;
+ }
+ }
+
+ }
+ BLI_assert(edge_net_new_len >= edge_net_new_index);
+ edge_net_new_len = edge_net_new_index;
+ }
+
+ BLI_bvhtree_free(bvhtree);
+
+ *r_edge_net_new = edge_net_new;
+ *r_edge_net_new_len = edge_net_new_len;
+ ok = true;
+
+ for (unsigned int i = 0; i < vert_arr_len; i++) {
+ copy_v3_v3(vert_arr[i]->co, vert_coords_backup[i]);
+ }
+
+finally:
+ for (unsigned int i = 0; i < edge_arr_len; i++) {
+ BM_elem_flag_disable(edge_arr[i], EDGE_NOT_IN_STACK);
+ BM_elem_flag_disable(edge_arr[i]->v1, VERT_NOT_IN_STACK);
+ BM_elem_flag_disable(edge_arr[i]->v2, VERT_NOT_IN_STACK);
+ }
+
+#undef VERT_IN_ARRAY
+#undef VERT_NOT_IN_STACK
+#undef EDGE_NOT_IN_STACK
+
+ return ok;
+}
+
+#undef SORT_AXIS
+
+/** \} */
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.h b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
index 9f2039b4c6f..b6642319fe6 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.h
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
@@ -15,29 +15,26 @@
* 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) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file RAS_GLExtensionManager.h
- * \ingroup bgerastogl
- */
+#ifndef __BMESH_POLYGON_EDGENET_H__
+#define __BMESH_POLYGON_EDGENET_H__
-#ifndef __RAS_GLEXTENSIONMANAGER_H__
-#define __RAS_GLEXTENSIONMANAGER_H__
+/** \file blender/bmesh/intern/bmesh_polygon_edgenet.h
+ * \ingroup bmesh
+ */
-/** Note: this used to have a lot more code, but now extension handling
- * is done by GLEW, so it does mostly debug stuff */
+bool BM_face_split_edgenet(
+ BMesh *bm, BMFace *f,
+ BMEdge **edge_net, const int edge_net_len,
+ BMFace ***r_face_arr, int *r_face_arr_len);
-namespace bgl
-{
- void InitExtensions(bool debug);
-} /* namespace bgl */
+bool BM_face_split_edgenet_connect_islands(
+ BMesh *bm,
+ BMFace *f, BMEdge **edge_net_init, const unsigned int edge_net_init_len,
+ struct MemArena *arena,
+ BMEdge ***r_edge_net_new, unsigned int *r_edge_net_new_len)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 5, 6, 7);
-#endif /* __RAS_GLEXTENSIONMANAGER_H__ */
+#endif /* __BMESH_POLYGON_EDGENET_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 1a8ea1e3a0d..e7a93c6aad5 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -2299,7 +2299,7 @@ static void bm_mesh_calc_volume_face(const BMFace *f, float *r_vol)
unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
int j;
- BM_face_calc_tessellation(f, loops, index);
+ BM_face_calc_tessellation(f, false, loops, index);
for (j = 0; j < tottri; j++) {
const float *p1 = loops[index[j][0]]->v->co;
@@ -2339,8 +2339,7 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed)
* (or when hflag_test is set, the number of flagged faces).
* \param r_group_index index, length pairs into \a r_groups_array, size of return value
* int pairs: (array_start, array_length).
- * \param filter_fn Filter the edges or verts we step over (depends on \a htype_step)
- * as to which types we deal with.
+ * \param filter_fn Filter the edge-loops or vert-loops we step over (depends on \a htype_step).
* \param user_data Optional user data for \a filter_fn, can be NULL.
* \param hflag_test Optional flag to test faces,
* use to exclude faces from the calculation, 0 for all faces.
@@ -2350,7 +2349,7 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed)
*/
int BM_mesh_calc_face_groups(
BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
+ BMLoopFilterFunc filter_fn, void *user_data,
const char hflag_test, const char htype_step)
{
#ifdef DEBUG
@@ -2443,7 +2442,7 @@ int BM_mesh_calc_face_groups(
do {
BMLoop *l_radial_iter = l_iter->radial_next;
if ((l_radial_iter != l_iter) &&
- ((filter_fn == NULL) || filter_fn((BMElem *)l_iter->e, user_data)))
+ ((filter_fn == NULL) || filter_fn(l_iter, user_data)))
{
do {
BMFace *f_other = l_radial_iter->f;
@@ -2461,7 +2460,7 @@ int BM_mesh_calc_face_groups(
/* search for other faces */
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- if ((filter_fn == NULL) || filter_fn((BMElem *)l_iter->v, user_data)) {
+ if ((filter_fn == NULL) || filter_fn(l_iter, user_data)) {
BMLoop *l_other;
BM_ITER_ELEM (l_other, &liter, l_iter, BM_LOOPS_OF_LOOP) {
BMFace *f_other = l_other->f;
@@ -2508,7 +2507,7 @@ int BM_mesh_calc_face_groups(
*/
int BM_mesh_calc_edge_groups(
BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
+ BMVertFilterFunc filter_fn, void *user_data,
const char hflag_test)
{
#ifdef DEBUG
@@ -2597,7 +2596,7 @@ int BM_mesh_calc_edge_groups(
/* search for other edges */
BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
- if ((filter_fn == NULL) || filter_fn((BMElem *)v, user_data)) {
+ if ((filter_fn == NULL) || filter_fn(v, user_data)) {
BMEdge *e_other;
BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
if (BM_elem_flag_test(e_other, BM_ELEM_TAG) == false) {
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 2b18a5c8641..cfe291732de 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -175,12 +175,12 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATT
int BM_mesh_calc_face_groups(
BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
+ BMLoopFilterFunc filter_fn, void *user_data,
const char hflag_test, const char htype_step)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
int BM_mesh_calc_edge_groups(
BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
+ BMVertFilterFunc filter_fn, void *user_data,
const char hflag_test)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
index 85bca744d86..233ed746ed4 100644
--- a/source/blender/bmesh/operators/bmo_fill_attribute.c
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -53,9 +53,9 @@ static bool bm_loop_is_all_radial_tag(BMLoop *l)
/**
* Callback to run on source-loops for #BM_face_copy_shared
*/
-static bool bm_loop_is_face_untag(BMElem *ele, void *UNUSED(user_data))
+static bool bm_loop_is_face_untag(const BMLoop *l, void *UNUSED(user_data))
{
- return (BM_elem_flag_test(((BMLoop *)ele)->f, BM_ELEM_TAG) == 0);
+ return (BM_elem_flag_test(l->f, BM_ELEM_TAG) == 0);
}
/**
diff --git a/source/blender/bmesh/operators/bmo_normals.c b/source/blender/bmesh/operators/bmo_normals.c
index 1f50feb6d6d..6044960265b 100644
--- a/source/blender/bmesh/operators/bmo_normals.c
+++ b/source/blender/bmesh/operators/bmo_normals.c
@@ -41,9 +41,9 @@
#define FACE_FLIP (1 << 1)
#define FACE_TEMP (1 << 2)
-static bool bmo_recalc_normal_edge_filter_cb(BMElem *ele, void *UNUSED(user_data))
+static bool bmo_recalc_normal_loop_filter_cb(const BMLoop *l, void *UNUSED(user_data))
{
- return BM_edge_is_manifold((BMEdge *)ele);
+ return BM_edge_is_manifold(l->e);
}
/**
@@ -229,7 +229,7 @@ static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int f
do {
BMLoop *l_other = l_iter->radial_next;
- if ((l_other != l_iter) && bmo_recalc_normal_edge_filter_cb((BMElem *)l_iter->e, NULL)) {
+ if ((l_other != l_iter) && bmo_recalc_normal_loop_filter_cb(l_iter, NULL)) {
if (!BMO_elem_flag_test(bm, l_other->f, FACE_TEMP)) {
BMO_elem_flag_enable(bm, l_other->f, FACE_TEMP);
BMO_elem_flag_set(bm, l_other->f, FACE_FLIP, (l_other->v == l_iter->v) != flip_state);
@@ -264,9 +264,10 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op)
BMFace **faces_grp = MEM_mallocN(sizeof(*faces_grp) * bm->totface, __func__);
int (*group_index)[2];
- const int group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index,
- bmo_recalc_normal_edge_filter_cb, NULL,
- 0, BM_EDGE);
+ const int group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index,
+ bmo_recalc_normal_loop_filter_cb, NULL,
+ 0, BM_EDGE);
int i;
BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_FLAG);
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 2108a2c0589..33681c992a0 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -30,6 +30,10 @@
#include "BLI_math.h"
+#include "BKE_customdata.h"
+
+#include "DNA_meshdata_types.h"
+
#include "bmesh.h"
#include "intern/bmesh_operators_private.h"
@@ -235,6 +239,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
const unsigned int ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments"));
const float xtot_inv2 = 2.0f / (xtot - 1);
const float ytot_inv2 = 2.0f / (ytot - 1);
+ const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMVert **varr;
BMVert *vquad[4];
@@ -257,7 +262,9 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
for (x = 0; x < xtot; x++) {
vec[0] = ((x * xtot_inv2) - 1.0f) * dia;
mul_v3_m4v3(tvec, mat, vec);
- varr[i++] = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
+ varr[i] = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
+ BMO_elem_flag_enable(bm, varr[i], VERT_MARK);
+ i++;
}
}
@@ -265,17 +272,86 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
for (y = 1; y < ytot; y++) {
for (x = 1; x < xtot; x++) {
+ BMFace *f;
+
vquad[0] = varr[XY(x - 1, y - 1)];
vquad[1] = varr[XY(x, y - 1)];
vquad[2] = varr[XY(x, y)];
vquad[3] = varr[XY(x - 1, y)];
- BM_face_create_verts(bm, vquad, 4, NULL, BM_CREATE_NOP, true);
+ f = BM_face_create_verts(bm, vquad, 4, NULL, BM_CREATE_NOP, true);
+ if (calc_uvs) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
}
}
#undef XY
+ if (calc_uvs) {
+ BM_mesh_calc_uvs_grid(bm, xtot, ytot, FACE_MARK);
+ }
+}
+
+/**
+ * Fills first available UVmap with grid-like UVs for all faces OpFlag-ged by given flag.
+ *
+ * \param bm The BMesh to operate on
+ * \param x_segments The x-resolution of the grid
+ * \param y_segments The y-resolution of the grid
+ * \param oflag The flag to check faces with.
+ */
+void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsigned int y_segments, const short oflag)
+{
+ BMFace *f;
+ BMLoop *l;
+ BMIter iter, liter;
+
+ const float dx = 1.0f / (float)(x_segments - 1);
+ const float dy = 1.0f / (float)(y_segments - 1);
+ float x = 0.0f;
+ float y = 0.0f;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ int loop_index;
+
+ BLI_assert(cd_loop_uv_offset != -1);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_elem_flag_test(bm, f, oflag))
+ continue;
+
+ BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ switch (loop_index) {
+ case 0:
+ x += dx;
+ break;
+ case 1:
+ y += dy;
+ break;
+ case 2:
+ x -= dx;
+ break;
+ case 3:
+ y -= dy;
+ break;
+ default:
+ break;
+ }
+
+ luv->uv[0] = x;
+ luv->uv[1] = y;
+ }
+
+ x += dx;
+ if (x >= 1.0f) {
+ x = 0.0f;
+ y += dy;
+ }
+ }
}
void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
@@ -283,6 +359,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
const float dia = BMO_slot_float_get(op->slots_in, "diameter");
const int seg = BMO_slot_int_get(op->slots_in, "u_segments");
const int tot = BMO_slot_int_get(op->slots_in, "v_segments");
+ const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMOperator bmop, prevop;
BMVert *eve, *preveve;
@@ -358,6 +435,31 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, min_ff(len, len2) / 3.0f);
}
+ if (calc_uvs) {
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+
+ /* We cannot tag faces for UVs computing above, so we have to do it now, based on all its vertices
+ * being tagged. */
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bool valid = true;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) {
+ valid = false;
+ break;
+ }
+ }
+
+ if (valid) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
+ }
+
+ BM_mesh_calc_uvs_sphere(bm, FACE_MARK);
+ }
+
/* and now do imat */
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, eve, VERT_MARK)) {
@@ -373,6 +475,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
const float dia = BMO_slot_float_get(op->slots_in, "diameter");
const float dia_div = dia / 200.0f;
const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions");
+ const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMVert *eva[12];
BMVert *v;
@@ -431,6 +534,30 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
BMO_op_finish(bm, &bmop);
}
+ if (calc_uvs) {
+ BMFace *f;
+ BMIter fiter;
+
+ /* We cannot tag faces for UVs computing above, so we have to do it now, based on all its vertices
+ * being tagged. */
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bool valid = true;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) {
+ valid = false;
+ break;
+ }
+ }
+
+ if (valid) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
+ }
+
+ BM_mesh_calc_uvs_sphere(bm, FACE_MARK);
+ }
+
/* must transform after because of sphere subdivision */
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
@@ -441,6 +568,75 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
+static void bm_mesh_calc_uvs_sphere_face(BMFace *f, float mat_rot[3][3], const int cd_loop_uv_offset)
+{
+ float *uvs[4];
+ BMLoop *l;
+ BMIter iter;
+ float dx;
+ int loop_index, loop_index_max_x;
+
+ BLI_assert(f->len <= 4);
+
+ BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, loop_index) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ float vco[3];
+
+ mul_v3_m3v3(vco, mat_rot, l->v->co);
+ map_to_sphere(&luv->uv[0], &luv->uv[1], vco[0], vco[1], vco[2]);
+
+ uvs[loop_index] = luv->uv;
+ }
+
+ /* Fix awkwardly-wrapping UVs */
+ loop_index_max_x = 0;
+ for (loop_index = 1; loop_index < f->len; loop_index++) {
+ if (uvs[loop_index][0] > uvs[loop_index_max_x][0]) {
+ loop_index_max_x = loop_index;
+ }
+ }
+
+ for (loop_index = 0; loop_index < f->len; loop_index++) {
+ if (loop_index != loop_index_max_x) {
+ dx = uvs[loop_index_max_x][0] - uvs[loop_index][0];
+ if (dx > 0.5f) {
+ uvs[loop_index][0] += 1.0f;
+ }
+ }
+ }
+}
+
+/**
+ * Fills first available UVmap with spherical projected UVs for all faces OpFlag-ged by given flag.
+ *
+ * \param bm The BMesh to operate on
+ * \param oflag The flag to check faces with.
+ */
+void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag)
+{
+ BMFace *f;
+ BMIter iter;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ /* We apply a 'magic' rotationto vcos before mapping them to sphere,
+ * those values seem to give best results for both ico and uv sphere projections. */
+ float mat_rot[3][3];
+ const float axis[3] = {0.806f, 0.329f, 0.491f};
+ const float angle = DEG2RADF(120.0f);
+
+ axis_angle_to_mat3(mat_rot, axis, angle);
+
+ BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for giving us UVs */
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_elem_flag_test(bm, f, oflag))
+ continue;
+
+ bm_mesh_calc_uvs_sphere_face(f, mat_rot, cd_loop_uv_offset);
+ }
+}
+
void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
{
BMVert *eve;
@@ -498,6 +694,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
const int segs = BMO_slot_int_get(op->slots_in, "segments");
const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
+ const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL;
float vec[3], mat[4][4], phi, phid;
@@ -555,6 +752,10 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, f, FACE_NEW);
+
+ if (calc_uvs) {
+ BM_mesh_calc_uvs_circle(bm, mat, dia, FACE_NEW);
+ }
}
if (!cap_tris) {
@@ -564,9 +765,54 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
+/**
+ * Fills first available UVmap with 2D projected UVs for all faces OpFlag-ged by given flag.
+ *
+ * \param bm The BMesh to operate on.
+ * \param mat The transform matrix applied to the created circle.
+ * \param radius The size of the circle.
+ * \param oflag The flag to check faces with.
+ */
+void BM_mesh_calc_uvs_circle(BMesh *bm, float mat[4][4], const float radius, const short oflag)
+{
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ const float uv_scale = 0.5f / radius;
+ const float uv_center = 0.5f;
+
+ float inv_mat[4][4];
+
+ BLI_assert(cd_loop_uv_offset != -1); /* caller must ensure we have UVs already */
+
+ invert_m4_m4(inv_mat, mat);
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_elem_flag_test(bm, f, oflag))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ float uv_vco[3];
+ copy_v3_v3(uv_vco, l->v->co);
+ /* transform back into the unit circle flat on the Z-axis */
+ mul_m4_v3(inv_mat, uv_vco);
+
+ /* then just take those coords for UVs */
+ luv->uv[0] = uv_center + uv_scale * uv_vco[0];
+ luv->uv[1] = uv_center + uv_scale * uv_vco[1];
+ }
+ }
+}
+
void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
{
BMVert *v1, *v2, *lastv1 = NULL, *lastv2 = NULL, *cent1, *cent2, *firstv1, *firstv2;
+ BMFace *f;
float vec[3], mat[4][4], phi, phid;
float dia1 = BMO_slot_float_get(op->slots_in, "diameter1");
float dia2 = BMO_slot_float_get(op->slots_in, "diameter2");
@@ -574,6 +820,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
int segs = BMO_slot_int_get(op->slots_in, "segments");
const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
+ const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
int a;
if (!segs)
@@ -620,14 +867,23 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
if (a) {
if (cap_ends) {
- BMFace *f;
-
f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
BMO_elem_flag_enable(bm, f, FACE_NEW);
+
f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
- BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, BM_CREATE_NOP);
+
+ f = BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
}
else {
firstv1 = v1;
@@ -642,29 +898,149 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
return;
if (cap_ends) {
- BMFace *f;
-
f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
BMO_elem_flag_enable(bm, f, FACE_NEW);
+
f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
-
+
+ f = BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
+
+ if (calc_uvs) {
+ BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1, segs, cap_ends, FACE_MARK);
+ }
+
if (!cap_tris) {
BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
}
- BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, BM_CREATE_NOP);
-
BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
+/**
+ * Fills first available UVmap with cylinder/cone-like UVs for all faces OpFlag-ged by given flag.
+ *
+ * \param bm The BMesh to operate on.
+ * \param mat The transform matrix applied to the created cone/cylinder.
+ * \param radius_top The size of the top end of the cone/cylinder.
+ * \param radius_bottom The size of the bottom end of the cone/cylinder.
+ * \param segments The number of subdivisions in the sides of the cone/cylinder.
+ * \param cap_ends Whether the ends of the cone/cylinder are filled or not.
+ * \param oflag The flag to check faces with.
+ */
+void BM_mesh_calc_uvs_cone(
+ BMesh *bm, float mat[4][4],
+ const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, const short oflag)
+{
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ const float uv_width = 1.0f / (float)segments;
+ const float uv_height = cap_ends ? 0.5f : 1.0f;
+
+ /* Note that all this allows us to handle all cases (real cone, truncated cone, with or without ends capped)
+ * with a single common code. */
+ const float uv_center_y = cap_ends ? 0.25f : 0.5f;
+ const float uv_center_x_top = cap_ends ? 0.25f : 0.5f;
+ const float uv_center_x_bottom = cap_ends ? 0.75f : 0.5f;
+ const float uv_radius = cap_ends ? 0.24f : 0.5f;
+
+ /* Using the opposite's end uv_scale as fallback allows us to handle 'real cone' case. */
+ const float uv_scale_top = (radius_top != 0.0f) ? (uv_radius / radius_top) :
+ ((radius_bottom != 0.0f) ? (uv_radius / radius_bottom) : uv_radius);
+ const float uv_scale_bottom = (radius_bottom != 0.0f) ? (uv_radius / radius_bottom) :
+ uv_scale_top;
+
+ float local_up[3] = {0.0f, 0.0f, 1.0f};
+
+ float x, y;
+ float inv_mat[4][4];
+ int loop_index;
+
+ mul_mat3_m4_v3(mat, local_up); /* transform the upvector like we did the cone itself, without location. */
+ normalize_v3(local_up); /* remove global scaling... */
+
+ invert_m4_m4(inv_mat, mat);
+
+ BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for ensuring the mesh has UVs */
+
+ x = 0.0f;
+ y = 1.0f - uv_height;
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_elem_flag_test(bm, f, oflag))
+ continue;
+
+ if (f->len == 4 && radius_top && radius_bottom) {
+ /* side face - so unwrap it in a rectangle */
+ BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ switch (loop_index) {
+ case 0:
+ x += uv_width;
+ break;
+ case 1:
+ y += uv_height;
+ break;
+ case 2:
+ x -= uv_width;
+ break;
+ case 3:
+ y -= uv_height;
+ break;
+ default:
+ break;
+ }
+
+ luv->uv[0] = x;
+ luv->uv[1] = y;
+ }
+
+ x += uv_width;
+ }
+ else {
+ /* top or bottom face - so unwrap it by transforming back to a circle and using the X/Y coords */
+ BM_face_normal_update(f);
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ float uv_vco[3];
+
+ mul_v3_m4v3(uv_vco, inv_mat, l->v->co);
+
+ if (dot_v3v3(f->no, local_up) > 0.0f) { /* if this is a top face of the cone */
+ luv->uv[0] = uv_center_x_top + uv_vco[0] * uv_scale_top;
+ luv->uv[1] = uv_center_y + uv_vco[1] * uv_scale_top;
+ }
+ else {
+ luv->uv[0] = uv_center_x_bottom + uv_vco[0] * uv_scale_bottom;
+ luv->uv[1] = uv_center_y + uv_vco[1] * uv_scale_bottom;
+ }
+ }
+ }
+ }
+}
+
void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
{
BMVert *verts[8];
float mat[4][4];
float off = BMO_slot_float_get(op->slots_in, "size") / 2.0f;
+ const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
int i, x, y, z;
const char faces[6][4] = {
{1, 3, 2, 0},
@@ -693,6 +1069,7 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
}
for (i = 0; i < ARRAY_SIZE(faces); i++) {
+ BMFace *f;
BMVert *quad[4] = {
verts[faces[i][0]],
verts[faces[i][1]],
@@ -700,8 +1077,82 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
verts[faces[i][3]],
};
- BM_face_create_verts(bm, quad, 4, NULL, BM_CREATE_NOP, true);
+ f = BM_face_create_verts(bm, quad, 4, NULL, BM_CREATE_NOP, true);
+ if (calc_uvs) {
+ BMO_elem_flag_enable(bm, f, FACE_MARK);
+ }
+ }
+
+ if (calc_uvs) {
+ BM_mesh_calc_uvs_cube(bm, FACE_MARK);
}
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
+
+/**
+ * Fills first available UVmap with cube-like UVs for all faces OpFlag-ged by given flag.
+ *
+ * \note Expects tagged faces to be six quads...
+ *
+ * \param bm The BMesh to operate on.
+ * \param oflag The flag to check faces with.
+ */
+void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag)
+{
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+ const float width = 0.25f;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ float x = 0.375f;
+ float y = 0.0f;
+
+ int loop_index;
+
+ BLI_assert(cd_loop_uv_offset != -1); /* the caller can ensure that we have UVs */
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_elem_flag_test(bm, f, oflag)) {
+ continue;
+ }
+
+ BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ luv->uv[0] = x;
+ luv->uv[1] = y;
+
+ switch (loop_index) {
+ case 0:
+ x += width;
+ break;
+ case 1:
+ y += width;
+ break;
+ case 2:
+ x -= width;
+ break;
+ case 3:
+ y -= width;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (y >= 0.75f && x > 0.125f) {
+ x = 0.125f;
+ y = 0.5f;
+ }
+ else if (x <= 0.125f) {
+ x = 0.625f;
+ y = 0.5f;
+ }
+ else {
+ y += 0.25f;
+ }
+ }
+}
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 42373ad0ef0..5d9852d1c68 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -126,6 +126,21 @@ static void remdoubles_createface(BMesh *bm, BMFace *f, BMOpSlot *slot_targetmap
continue;
}
+ /* low level selection, not essential but means we can keep
+ * edge selection valid on auto-merge for example. */
+ if ((BM_elem_flag_test(l->e, BM_ELEM_SELECT) == true) &&
+ (BM_elem_flag_test(e_new, BM_ELEM_SELECT) == false))
+ {
+ BM_elem_flag_disable(l->e, BM_ELEM_SELECT);
+ BM_elem_flag_merge_into(e_new, e_new, l->e);
+ BM_elem_flag_enable(e_new, BM_ELEM_SELECT);
+ /* bm->totedgesel remains valid */
+ }
+ else {
+ BM_elem_flag_merge_into(e_new, e_new, l->e);
+ }
+
+
STACK_PUSH(edges, e_new);
STACK_PUSH(loops, l);
}
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index 624fbd93818..95ff3eb4858 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -28,18 +28,15 @@
#include "MEM_guardedalloc.h"
-
#include "BLI_math.h"
+#include "eigen_capi.h"
+
#include "bmesh.h"
#include "intern/bmesh_operators_private.h" /* own include */
-#ifdef WITH_OPENNL
-
-#include "ONL_opennl.h"
-
// #define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f /* UNUSED */
// #define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f /* UNUSED */
#define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8f
@@ -59,7 +56,7 @@ struct BLaplacianSystem {
/* Pointers to data*/
BMesh *bm;
BMOperator *op;
- NLContext *context;
+ LinearSolver *context;
/*Data*/
float min_area;
@@ -92,7 +89,7 @@ static void delete_laplacian_system(LaplacianSystem *sys)
delete_void_pointer(sys->vweights);
delete_void_pointer(sys->zerola);
if (sys->context) {
- nlDeleteContext(sys->context);
+ EIG_linear_solver_delete(sys->context);
}
sys->bm = NULL;
sys->op = NULL;
@@ -333,9 +330,9 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
w4 = w4 / 4.0f;
if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == 0) {
- nlMatrixAdd(sys->context, idv1, idv2, w2 * sys->vweights[idv1]);
- nlMatrixAdd(sys->context, idv1, idv3, w3 * sys->vweights[idv1]);
- nlMatrixAdd(sys->context, idv1, idv4, w4 * sys->vweights[idv1]);
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv2, w2 * sys->vweights[idv1]);
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv3, w3 * sys->vweights[idv1]);
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv4, w4 * sys->vweights[idv1]);
}
}
}
@@ -346,16 +343,16 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
/* Is ring if number of faces == number of edges around vertice*/
i = BM_elem_index_get(f);
if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) {
- nlMatrixAdd(sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]);
- nlMatrixAdd(sys->context, idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]);
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]);
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]);
}
if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == 0) {
- nlMatrixAdd(sys->context, idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]);
- nlMatrixAdd(sys->context, idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]);
+ EIG_linear_solver_matrix_add(sys->context, idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]);
+ EIG_linear_solver_matrix_add(sys->context, idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]);
}
if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == 0) {
- nlMatrixAdd(sys->context, idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]);
- nlMatrixAdd(sys->context, idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]);
+ EIG_linear_solver_matrix_add(sys->context, idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]);
+ EIG_linear_solver_matrix_add(sys->context, idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]);
}
}
}
@@ -368,8 +365,8 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
idv2 = BM_elem_index_get(e->v2);
if (sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) {
i = BM_elem_index_get(e);
- nlMatrixAdd(sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
- nlMatrixAdd(sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]);
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
+ EIG_linear_solver_matrix_add(sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]);
}
}
}
@@ -434,12 +431,12 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez
idv2 = BM_elem_index_get(e->v2);
vi1 = e->v1->co;
vi2 = e->v2->co;
- ve1[0] = nlGetVariable(sys->context, 0, idv1);
- ve1[1] = nlGetVariable(sys->context, 1, idv1);
- ve1[2] = nlGetVariable(sys->context, 2, idv1);
- ve2[0] = nlGetVariable(sys->context, 0, idv2);
- ve2[1] = nlGetVariable(sys->context, 1, idv2);
- ve2[2] = nlGetVariable(sys->context, 2, idv2);
+ ve1[0] = EIG_linear_solver_variable_get(sys->context, 0, idv1);
+ ve1[1] = EIG_linear_solver_variable_get(sys->context, 1, idv1);
+ ve1[2] = EIG_linear_solver_variable_get(sys->context, 2, idv1);
+ ve2[0] = EIG_linear_solver_variable_get(sys->context, 0, idv2);
+ ve2[1] = EIG_linear_solver_variable_get(sys->context, 1, idv2);
+ ve2[2] = EIG_linear_solver_variable_get(sys->context, 2, idv2);
leni = len_v3v3(vi1, vi2);
lene = len_v3v3(ve1, ve2);
if (lene > leni * SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE || lene < leni * SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE) {
@@ -455,13 +452,13 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez
m_vertex_id = BM_elem_index_get(v);
if (sys->zerola[m_vertex_id] == 0) {
if (usex) {
- v->co[0] = nlGetVariable(sys->context, 0, m_vertex_id);
+ v->co[0] = EIG_linear_solver_variable_get(sys->context, 0, m_vertex_id);
}
if (usey) {
- v->co[1] = nlGetVariable(sys->context, 1, m_vertex_id);
+ v->co[1] = EIG_linear_solver_variable_get(sys->context, 1, m_vertex_id);
}
if (usez) {
- v->co[2] = nlGetVariable(sys->context, 2, m_vertex_id);
+ v->co[2] = EIG_linear_solver_variable_get(sys->context, 2, m_vertex_id);
}
}
}
@@ -501,32 +498,24 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
preserve_volume = BMO_slot_bool_get(op->slots_in, "preserve_volume");
- sys->context = nlNewContext();
-
- nlSolverParameteri(sys->context, NL_NB_VARIABLES, bm->totvert);
- nlSolverParameteri(sys->context, NL_LEAST_SQUARES, NL_TRUE);
- nlSolverParameteri(sys->context, NL_NB_ROWS, bm->totvert);
- nlSolverParameteri(sys->context, NL_NB_RIGHT_HAND_SIDES, 3);
+ sys->context = EIG_linear_least_squares_solver_new(bm->totvert, bm->totvert, 3);
- nlBegin(sys->context, NL_SYSTEM);
for (i = 0; i < bm->totvert; i++) {
- nlLockVariable(sys->context, i);
+ EIG_linear_solver_variable_lock(sys->context, i);
}
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
m_vertex_id = BM_elem_index_get(v);
- nlUnlockVariable(sys->context, m_vertex_id);
- nlSetVariable(sys->context, 0, m_vertex_id, v->co[0]);
- nlSetVariable(sys->context, 1, m_vertex_id, v->co[1]);
- nlSetVariable(sys->context, 2, m_vertex_id, v->co[2]);
+ EIG_linear_solver_variable_set(sys->context, 0, m_vertex_id, v->co[0]);
+ EIG_linear_solver_variable_set(sys->context, 1, m_vertex_id, v->co[1]);
+ EIG_linear_solver_variable_set(sys->context, 2, m_vertex_id, v->co[2]);
}
- nlBegin(sys->context, NL_MATRIX);
init_laplacian_matrix(sys);
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
m_vertex_id = BM_elem_index_get(v);
- nlRightHandSideAdd(sys->context, 0, m_vertex_id, v->co[0]);
- nlRightHandSideAdd(sys->context, 1, m_vertex_id, v->co[1]);
- nlRightHandSideAdd(sys->context, 2, m_vertex_id, v->co[2]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, m_vertex_id, v->co[0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, m_vertex_id, v->co[1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, m_vertex_id, v->co[2]);
i = m_vertex_id;
if (sys->zerola[i] == 0) {
w = sys->vweights[i] * sys->ring_areas[i];
@@ -535,34 +524,22 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
sys->vlengths[i] = (w == 0.0f) ? 0.0f : -lambda_border * 2.0f / w;
if (!vert_is_boundary(v)) {
- nlMatrixAdd(sys->context, i, i, 1.0f + lambda_factor / (4.0f * sys->ring_areas[i]));
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + lambda_factor / (4.0f * sys->ring_areas[i]));
}
else {
- nlMatrixAdd(sys->context, i, i, 1.0f + lambda_border * 2.0f);
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + lambda_border * 2.0f);
}
}
else {
- nlMatrixAdd(sys->context, i, i, 1.0f);
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f);
}
}
fill_laplacian_matrix(sys);
- nlEnd(sys->context, NL_MATRIX);
- nlEnd(sys->context, NL_SYSTEM);
-
- if (nlSolve(sys->context, NL_TRUE) ) {
+ if (EIG_linear_solver_solve(sys->context) ) {
validate_solution(sys, usex, usey, usez, preserve_volume);
}
delete_laplacian_system(sys);
}
-#else /* WITH_OPENNL */
-
-#ifdef __GNUC__
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#endif
-
-void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) {}
-
-#endif /* WITH_OPENNL */
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index ddcbe34e8e1..0a5e5aba86b 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -242,6 +242,13 @@ static void bm_decim_build_edge_cost_single(
BLI_heap_remove(eheap, eheap_table[BM_elem_index_get(e)]);
}
+ if (UNLIKELY(vweights &&
+ ((vweights[BM_elem_index_get(e->v1)] == 0.0f) ||
+ (vweights[BM_elem_index_get(e->v2)] == 0.0f))))
+ {
+ goto clear;
+ }
+
/* check we can collapse, some edges we better not touch */
if (BM_edge_is_boundary(e)) {
if (e->l->f->len == 3) {
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 19cf2d29aff..80b1780758d 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -50,6 +50,7 @@
#endif
#include "BLI_kdopbvh.h"
+#include "BLI_buffer.h"
#include "bmesh.h"
#include "bmesh_intersect.h" /* own include */
@@ -70,12 +71,19 @@
#define USE_SEPARATE
/* remove verts created by intersecting triangles */
#define USE_DISSOLVE
+/* detect isolated holes and fill them */
+#define USE_NET_ISLAND_CONNECT
/* strict asserts that may fail in practice (handy for debugging cases which should succeed) */
// #define USE_PARANOID
/* use accelerated overlap check */
#define USE_BVH
+// #define USE_BOOLEAN_RAYCAST_DRAW
+
+#ifdef USE_BOOLEAN_RAYCAST_DRAW
+/* insert bl_debug_draw_quad_clear... here */
+#endif
static void tri_v3_scale(
float v1[3], float v2[3], float v3[3],
@@ -147,21 +155,20 @@ static bool ghash_insert_link(
GHash *gh, void *key, void *val, bool use_test,
MemArena *mem_arena)
{
+ void **ls_base_p;
struct LinkBase *ls_base;
LinkNode *ls;
- ls_base = BLI_ghash_lookup(gh, key);
-
- if (ls_base) {
- if (use_test && (BLI_linklist_index(ls_base->list, key) != -1)) {
- return false;
- }
- }
- else {
- ls_base = BLI_memarena_alloc(mem_arena, sizeof(*ls_base));
+ if (!BLI_ghash_ensure_p(gh, key, &ls_base_p)) {
+ ls_base = *ls_base_p = BLI_memarena_alloc(mem_arena, sizeof(*ls_base));
ls_base->list = NULL;
ls_base->list_len = 0;
- BLI_ghash_insert(gh, key, ls_base);
+ }
+ else {
+ ls_base = *ls_base_p;
+ if (use_test && (BLI_linklist_index(ls_base->list, val) != -1)) {
+ return false;
+ }
}
ls = BLI_memarena_alloc(mem_arena, sizeof(*ls));
@@ -231,12 +238,13 @@ static void face_edges_add(
#ifdef USE_NET
static void face_edges_split(
- BMesh *bm,
- BMFace *f,
- struct LinkBase *e_ls_base)
+ BMesh *bm, BMFace *f, struct LinkBase *e_ls_base,
+ bool use_island_connect,
+ MemArena *mem_arena_edgenet)
{
unsigned int i;
- BMEdge **edge_arr = BLI_array_alloca(edge_arr, e_ls_base->list_len);
+ unsigned int edge_arr_len = e_ls_base->list_len;
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len);
LinkNode *node;
BLI_assert(f->head.htype == BM_FACE);
@@ -249,7 +257,30 @@ static void face_edges_split(
printf("# %s: %d %u\n", __func__, BM_elem_index_get(f), e_ls_base->list_len);
#endif
- BM_face_split_edgenet(bm, f, edge_arr, (int)e_ls_base->list_len, NULL, NULL);
+#ifdef USE_NET_ISLAND_CONNECT
+ if (use_island_connect) {
+ unsigned int edge_arr_holes_len;
+ BMEdge **edge_arr_holes;
+ if (BM_face_split_edgenet_connect_islands(
+ bm, f,
+ edge_arr, edge_arr_len,
+ mem_arena_edgenet,
+ &edge_arr_holes, &edge_arr_holes_len))
+ {
+ /* newly created wire edges need to be tagged */
+ for (i = edge_arr_len; i < edge_arr_holes_len; i++) {
+ BM_elem_flag_enable(edge_arr_holes[i], BM_ELEM_TAG);
+ }
+
+ edge_arr_len = edge_arr_holes_len;
+ edge_arr = edge_arr_holes; /* owned by the arena */
+ }
+ }
+#else
+ UNUSED_VARS(use_island_connect, mem_arena_edgenet);
+#endif
+
+ BM_face_split_edgenet(bm, f, edge_arr, (int)edge_arr_len, NULL, NULL);
}
#endif
@@ -461,6 +492,35 @@ static BMVert *bm_isect_edge_tri(
return NULL;
}
+struct LoopFilterWrap {
+ int (*test_fn)(BMFace *f, void *user_data);
+ void *user_data;
+};
+
+static bool bm_loop_filter_fn(const BMLoop *l, void *user_data)
+{
+ if (BM_elem_flag_test(l->e, BM_ELEM_TAG)) {
+ return false;
+ }
+
+ if (l->radial_next != l) {
+ struct LoopFilterWrap *data = user_data;
+ BMLoop *l_iter = l->radial_next;
+ const int face_side = data->test_fn(l->f, data->user_data);
+ do {
+ const int face_side_other = data->test_fn(l_iter->f, data->user_data);
+ if (UNLIKELY(face_side_other == -1)) {
+ /* pass */
+ }
+ else if (face_side_other != face_side) {
+ return false;
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+ return true;
+ }
+ return false;
+}
+
/**
* Return true if we have any intersections.
*/
@@ -774,23 +834,146 @@ static void bm_isect_tri_tri(
}
}
+#ifdef USE_BVH
+
+struct RaycastData {
+ const float **looptris;
+ BLI_Buffer *z_buffer;
+};
+
+#ifdef USE_KDOPBVH_WATERTIGHT
+static const struct IsectRayPrecalc isect_precalc_x = {1, 2, 0, 0, 0, 1};
+#endif
+
+static void raycast_callback(void *userdata,
+ int index,
+ const BVHTreeRay *ray,
+ BVHTreeRayHit *UNUSED(hit))
+{
+ struct RaycastData *raycast_data = userdata;
+ const float **looptris = raycast_data->looptris;
+ const float *v0 = looptris[index * 3 + 0];
+ const float *v1 = looptris[index * 3 + 1];
+ const float *v2 = looptris[index * 3 + 2];
+ float dist;
+
+ if (
+#ifdef USE_KDOPBVH_WATERTIGHT
+ isect_ray_tri_watertight_v3(ray->origin, &isect_precalc_x, v0, v1, v2, &dist, NULL)
+#else
+ isect_ray_tri_epsilon_v3(ray->origin, ray->direction, v0, v1, v2, &dist, NULL, FLT_EPSILON)
+#endif
+ )
+ {
+ if (dist >= 0.0f) {
+#ifdef USE_DUMP
+ printf("%s:\n", __func__);
+ print_v3(" origin", ray->origin);
+ print_v3(" direction", ray->direction);
+ printf(" dist %f\n", dist);
+ print_v3(" v0", v0);
+ print_v3(" v1", v1);
+ print_v3(" v2", v2);
+#endif
+
+#ifdef USE_DUMP
+ printf("%s: Adding depth %f\n", __func__, depth);
+#endif
+ BLI_buffer_append(raycast_data->z_buffer, float, dist);
+ }
+ }
+}
+
+static int isect_bvhtree_point_v3(
+ BVHTree *tree,
+ const float **looptris,
+ const float co[3])
+{
+ BLI_buffer_declare_static(float, z_buffer, BLI_BUFFER_NOP, 64);
+
+ struct RaycastData raycast_data = {
+ looptris,
+ &z_buffer,
+ };
+ BVHTreeRayHit hit = {0};
+ float dir[3] = {1.0f, 0.0f, 0.0f};
+
+ /* Need to initialize hit even tho it's not used.
+ * This is to make it so kdotree believes we didn't intersect anything and
+ * keeps calling the intersect callback.
+ */
+ hit.index = -1;
+ hit.dist = FLT_MAX;
+
+ BLI_bvhtree_ray_cast(tree,
+ co, dir,
+ 0.0f,
+ &hit,
+ raycast_callback,
+ &raycast_data);
+
+#ifdef USE_DUMP
+ printf("%s: Total intersections: %d\n", __func__, raycast_data.num_isect);
+#endif
+
+ int num_isect;
+
+ if (z_buffer.count == 0) {
+ num_isect = 0;
+ }
+ else if (z_buffer.count == 1) {
+ num_isect = 1;
+ }
+ else {
+ /* 2 or more */
+ const float eps = FLT_EPSILON * 10;
+ num_isect = 1; /* always count first */
+
+ qsort(z_buffer.data, z_buffer.count, sizeof(float), BLI_sortutil_cmp_float);
+
+ const float *depth_arr = z_buffer.data;
+ float depth_last = depth_arr[0];
+
+ for (unsigned int i = 1; i < z_buffer.count; i++) {
+ if (depth_arr[i] - depth_last > eps) {
+ depth_last = depth_arr[i];
+ num_isect++;
+ }
+ }
+
+ BLI_buffer_free(&z_buffer);
+ }
+
+
+ // return (num_isect & 1) == 1;
+ return num_isect;
+}
+
+#endif /* USE_BVH */
+
/**
* Intersect tessellated faces
* leaving the resulting edges tagged.
*
* \param test_fn Return value: -1: skip, 0: tree_a, 1: tree_b (use_self == false)
+ * \param boolean_mode -1: no-boolean, 0: intersection... see #BMESH_ISECT_BOOLEAN_ISECT.
+ * \return true if the mesh is changed (intersections cut or faces removed from boolean).
*/
bool BM_mesh_intersect(
BMesh *bm,
struct BMLoop *(*looptris)[3], const int looptris_tot,
int (*test_fn)(BMFace *f, void *user_data), void *user_data,
- const bool use_self, const bool use_separate,
+ const bool use_self, const bool use_separate, const bool use_dissolve, const bool use_island_connect,
+ const int boolean_mode,
const float eps)
{
struct ISectState s;
bool has_isect;
const int totface_orig = bm->totface;
+ /* needed for boolean, since cutting up faces moves the loops within the face */
+ const float **looptri_coords = NULL;
+
#ifdef USE_BVH
BVHTree *tree_a, *tree_b;
unsigned int tree_overlap_tot;
@@ -799,6 +982,10 @@ bool BM_mesh_intersect(
int i_a, i_b;
#endif
+#ifdef USE_BOOLEAN_RAYCAST_DRAW
+ bl_debug_draw_quad_clear();
+#endif
+
s.bm = bm;
s.edgetri_cache = BLI_ghash_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
@@ -840,13 +1027,31 @@ bool BM_mesh_intersect(
0);
#ifdef USE_DISSOLVE
- BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
+ if (use_dissolve) {
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
+ }
+#else
+ UNUSED_VARS(use_dissolve);
#endif
#ifdef USE_DUMP
printf("data = [\n");
#endif
+ if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE) {
+ /* keep original geometrty for raycast callbacks */
+ float **cos;
+ int i, j;
+
+ cos = MEM_mallocN((size_t)looptris_tot * sizeof(*looptri_coords) * 3, __func__);
+ for (i = 0, j = 0; i < looptris_tot; i++) {
+ cos[j++] = looptris[i][0]->v->co;
+ cos[j++] = looptris[i][1]->v->co;
+ cos[j++] = looptris[i][2]->v->co;
+ }
+ looptri_coords = (const float **)cos;
+ }
+
#ifdef USE_BVH
{
int i;
@@ -908,9 +1113,13 @@ bool BM_mesh_intersect(
}
MEM_freeN(overlap);
}
- BLI_bvhtree_free(tree_a);
- if (tree_a != tree_b) {
- BLI_bvhtree_free(tree_b);
+
+ if (boolean_mode == BMESH_ISECT_BOOLEAN_NONE) {
+ /* no booleans, just free immediate */
+ BLI_bvhtree_free(tree_a);
+ if (tree_a != tree_b) {
+ BLI_bvhtree_free(tree_b);
+ }
}
#else
@@ -979,7 +1188,7 @@ bool BM_mesh_intersect(
}
#ifdef USE_DUMP
- printf("# SPLITTING EDGE: %d, %d\n", e_index, v_ls_base->list_len);
+ printf("# SPLITTING EDGE: %d, %d\n", BM_elem_index_get(e), v_ls_base->list_len);
#endif
/* intersect */
is_wire = BLI_gset_haskey(s.wire_edges, e);
@@ -999,7 +1208,8 @@ bool BM_mesh_intersect(
const float fac = line_point_factor_v3(vi->co, e->v1->co, e->v2->co);
if (BM_vert_in_edge(e, v_prev)) {
- v_prev = BM_edge_split(bm, e, v_prev, NULL, CLAMPIS(fac, 0.0f, 1.0f));
+ BMEdge *e_split;
+ v_prev = BM_edge_split(bm, e, v_prev, &e_split, CLAMPIS(fac, 0.0f, 1.0f));
BLI_assert(BM_vert_in_edge(e, v_end));
if (!BM_edge_exists(v_prev, vi) &&
@@ -1013,7 +1223,7 @@ bool BM_mesh_intersect(
}
v_prev = vi;
if (is_wire) {
- BLI_gset_insert(s.wire_edges, e);
+ BLI_gset_insert(s.wire_edges, e_split);
}
}
}
@@ -1025,7 +1235,7 @@ bool BM_mesh_intersect(
/* important to handle before edgenet */
#ifdef USE_DISSOLVE
- {
+ if (use_dissolve && (boolean_mode == BMESH_ISECT_BOOLEAN_NONE)) {
/* first pass */
BMVert *(*splice_ls)[2];
STACK_DECLARE(splice_ls);
@@ -1249,6 +1459,8 @@ bool BM_mesh_intersect(
GHashIterator gh_iter;
BMFace **faces;
+ MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
faces = bm->ftable;
GHASH_ITER (gh_iter, s.face_edges) {
@@ -1265,9 +1477,15 @@ bool BM_mesh_intersect(
BLI_assert(BM_elem_index_get(f) == f_index);
- face_edges_split(bm, f, e_ls_base);
+ face_edges_split(bm, f, e_ls_base, use_island_connect, mem_arena_edgenet);
+
+ BLI_memarena_clear(mem_arena_edgenet);
}
+
+ BLI_memarena_free(mem_arena_edgenet);
}
+#else
+ UNUSED_VARS(use_island_connect);
#endif /* USE_NET */
(void)totface_orig;
@@ -1284,10 +1502,168 @@ bool BM_mesh_intersect(
BM_mesh_edgesplit(bm, false, true, false);
}
+ else if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE) {
+ GSetIterator gs_iter;
+
+ /* no need to clear for boolean */
+
+ GSET_ITER (gs_iter, s.wire_edges) {
+ BMEdge *e = BLI_gsetIterator_getKey(&gs_iter);
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
#else
(void)use_separate;
#endif /* USE_SEPARATE */
+ if ((boolean_mode != BMESH_ISECT_BOOLEAN_NONE)) {
+ BVHTree *tree_pair[2] = {tree_a, tree_b};
+
+ /* group vars */
+ int *groups_array;
+ int (*group_index)[2];
+ int group_tot;
+ int i;
+ BMFace **ftable;
+
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+ ftable = bm->ftable;
+
+ /* wrap the face-test callback to make it into an edge-loop delimiter */
+ struct LoopFilterWrap user_data_wrap = {
+ .test_fn = test_fn,
+ .user_data = user_data,
+ };
+
+ groups_array = MEM_mallocN(sizeof(*groups_array) * (size_t)bm->totface, __func__);
+ group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index,
+ bm_loop_filter_fn, &user_data_wrap,
+ 0, BM_EDGE);
+
+#ifdef USE_DUMP
+ printf("%s: Total face-groups: %d\n", __func__, group_tot);
+#endif
+
+ /* Check if island is inside/outside */
+ for (i = 0; i < group_tot; i++) {
+ int fg = group_index[i][0];
+ int fg_end = group_index[i][1] + fg;
+ bool do_remove, do_flip;
+
+ {
+ /* for now assyme this is an OK face to test with (not degenerate!) */
+ BMFace *f = ftable[groups_array[fg]];
+ float co[3];
+ int hits;
+ int side = test_fn(f, user_data);
+
+ if (side == -1) {
+ continue;
+ }
+ BLI_assert(ELEM(side, 0, 1));
+ side = !side;
+
+ // BM_face_calc_center_mean(f, co);
+ BM_face_calc_point_in_face(f, co);
+
+ hits = isect_bvhtree_point_v3(tree_pair[side], looptri_coords, co);
+
+ switch (boolean_mode) {
+ case BMESH_ISECT_BOOLEAN_ISECT:
+ do_remove = ((hits & 1) != 1);
+ do_flip = false;
+ break;
+ case BMESH_ISECT_BOOLEAN_UNION:
+ do_remove = ((hits & 1) == 1);
+ do_flip = false;
+ break;
+ case BMESH_ISECT_BOOLEAN_DIFFERENCE:
+ do_remove = ((hits & 1) == 1) == side;
+ do_flip = (side == 0);
+ break;
+ }
+
+#ifdef USE_BOOLEAN_RAYCAST_DRAW
+ {
+ unsigned int colors[4] = {0x00000000, 0xffffffff, 0xff000000, 0x0000ff};
+ float co_other[3] = {UNPACK3(co)};
+ co_other[0] += 1000.0f;
+ bl_debug_color_set(colors[(hits & 1) == 1]);
+ bl_debug_draw_edge_add(co, co_other);
+ }
+#endif
+
+ }
+
+ if (do_remove) {
+ for (; fg != fg_end; fg++) {
+ /* postpone killing the face since we access below, mark instead */
+ // BM_face_kill_loose(bm, ftable[groups_array[fg]]);
+ ftable[groups_array[fg]]->mat_nr = -1;
+ }
+ }
+ else if (do_flip) {
+ for (; fg != fg_end; fg++) {
+ BM_face_normal_flip(bm, ftable[groups_array[fg]]);
+ }
+ }
+ }
+
+ MEM_freeN(groups_array);
+ MEM_freeN(group_index);
+
+#ifdef USE_DISSOLVE
+ /* We have dissolve code above, this is alternative logic,
+ * we need to do it after the boolean is executed. */
+ if (use_dissolve) {
+ LinkNode *node;
+ for (node = s.vert_dissolve; node; node = node->next) {
+ BMVert *v = node->link;
+ if (BM_vert_is_edge_pair(v)) {
+ /* we wont create degenerate faces from this */
+ bool ok = true;
+
+ /* would we create a 2-sided-face?
+ * if so, don't dissolve this since we may */
+ if (v->e->l) {
+ BMLoop *l_iter = v->e->l;
+ do {
+ if (l_iter->f->len == 3) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->radial_next) != v->e->l);
+ }
+
+ if (ok) {
+ BM_vert_collapse_edge(bm, v->e, v, true, false);
+ }
+ }
+ }
+ }
+#endif
+
+ {
+ int tot = bm->totface;
+ for (i = 0; i < tot; i++) {
+ if (ftable[i]->mat_nr == -1) {
+ BM_face_kill_loose(bm, ftable[i]);
+ }
+ }
+ }
+ }
+
+ if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE) {
+ MEM_freeN((void *)looptri_coords);
+
+ /* no booleans, just free immediate */
+ BLI_bvhtree_free(tree_a);
+ if (tree_a != tree_b) {
+ BLI_bvhtree_free(tree_b);
+ }
+ }
+
has_isect = (BLI_ghash_size(s.face_edges) != 0);
/* cleanup */
@@ -1299,5 +1675,5 @@ bool BM_mesh_intersect(
BLI_memarena_free(s.mem_arena);
- return has_isect;
+ return has_isect || (totface_orig != bm->totface);
}
diff --git a/source/blender/bmesh/tools/bmesh_intersect.h b/source/blender/bmesh/tools/bmesh_intersect.h
index af6e510a8f6..d0cc41654eb 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.h
+++ b/source/blender/bmesh/tools/bmesh_intersect.h
@@ -29,7 +29,16 @@ bool BM_mesh_intersect(
BMesh *bm,
struct BMLoop *(*looptris)[3], const int looptris_tot,
int (*test_fn)(BMFace *f, void *user_data), void *user_data,
- const bool use_self, const bool use_separate,
+ const bool use_self, const bool use_separate, const bool use_dissolve, const bool use_island_connect,
+ const int boolean_mode,
const float eps);
+enum {
+ BMESH_ISECT_BOOLEAN_NONE = -1,
+ /* aligned with BooleanModifierOp */
+ BMESH_ISECT_BOOLEAN_ISECT = 0,
+ BMESH_ISECT_BOOLEAN_UNION = 1,
+ BMESH_ISECT_BOOLEAN_DIFFERENCE = 2,
+};
+
#endif /* __BMESH_INTERSECT_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c
index 1c05b8ae5d4..bc9ab084467 100644
--- a/source/blender/bmesh/tools/bmesh_path.c
+++ b/source/blender/bmesh/tools/bmesh_path.c
@@ -316,10 +316,10 @@ static float facetag_cut_cost(BMFace *f_a, BMFace *f_b, BMEdge *e)
float ix_e[3], ix_f[3], f;
isect_line_line_v3(e->v1->co, e->v2->co, f_a_cent, f_b_cent, ix_e, ix_f);
f = line_point_factor_v3(ix_e, e->v1->co, e->v2->co);
- if (f < 0.0) {
+ if (f < 0.0f) {
copy_v3_v3(e_cent, e->v1->co);
}
- else if (f > 1.0) {
+ else if (f > 1.0f) {
copy_v3_v3(e_cent, e->v2->co);
}
else {
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index 7398126c97b..3ade7c3cb27 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -98,6 +98,7 @@ extern "C"
#include "BKE_material.h"
#include "BKE_object.h"
#include "BKE_scene.h"
+#include "BKE_appdir.h"
#include "ED_keyframing.h"
#ifdef WITH_BUILDINFO
@@ -153,6 +154,26 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {
}
+static COLLADABU::NativeString make_temp_filepath(const char *name, const char *extension)
+{
+ char tempfile[FILE_MAX];
+ const char *tempdir = BKE_tempdir_session();
+
+ if (name == NULL){
+ name = tmpnam(NULL);
+ }
+
+ BLI_make_file_string(NULL, tempfile, tempdir, name);
+
+ if (extension) {
+ BLI_ensure_extension(tempfile, FILE_MAX, extension);
+ }
+
+ COLLADABU::NativeString native_filename =
+ COLLADABU::NativeString(tempfile, COLLADABU::NativeString::ENCODING_UTF8);
+ return native_filename;
+}
+
// TODO: it would be better to instantiate animations rather than create a new one per object
// COLLADA allows this through multiple <channel>s in <animation>.
// For this to work, we need to know objects that use a certain action.
@@ -163,18 +184,17 @@ void DocumentExporter::exportCurrentScene(Scene *sce)
PropertyRNA *system; /* unused , *scale; */
clear_global_id_map();
-
- COLLADABU::NativeString native_filename =
- COLLADABU::NativeString(std::string(this->export_settings->filepath), COLLADABU::NativeString::ENCODING_UTF8);
- COLLADASW::StreamWriter sw(native_filename);
+
+ COLLADABU::NativeString native_filename = make_temp_filepath(NULL, ".dae");
+ COLLADASW::StreamWriter *writer = new COLLADASW::StreamWriter(native_filename);
fprintf(stdout, "Collada export: %s\n", this->export_settings->filepath);
// open <collada>
- sw.startDocument();
+ writer->startDocument();
// <asset>
- COLLADASW::Asset asset(&sw);
+ COLLADASW::Asset asset(writer);
RNA_id_pointer_create(&(sce->id), &sceneptr);
unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
@@ -241,41 +261,41 @@ void DocumentExporter::exportCurrentScene(Scene *sce)
LinkNode *export_set = this->export_settings->export_set;
// <library_cameras>
if (bc_has_object_type(export_set, OB_CAMERA)) {
- CamerasExporter ce(&sw, this->export_settings);
+ CamerasExporter ce(writer, this->export_settings);
ce.exportCameras(sce);
}
// <library_lights>
if (bc_has_object_type(export_set, OB_LAMP)) {
- LightsExporter le(&sw, this->export_settings);
+ LightsExporter le(writer, this->export_settings);
le.exportLights(sce);
}
// <library_images>
- ImagesExporter ie(&sw, this->export_settings);
+ ImagesExporter ie(writer, this->export_settings);
ie.exportImages(sce);
// <library_effects>
- EffectsExporter ee(&sw, this->export_settings);
+ EffectsExporter ee(writer, this->export_settings);
ee.exportEffects(sce);
// <library_materials>
- MaterialsExporter me(&sw, this->export_settings);
+ MaterialsExporter me(writer, this->export_settings);
me.exportMaterials(sce);
// <library_geometries>
if (bc_has_object_type(export_set, OB_MESH)) {
- GeometryExporter ge(&sw, this->export_settings);
+ GeometryExporter ge(writer, this->export_settings);
ge.exportGeom(sce);
}
// <library_animations>
- AnimationExporter ae(&sw, this->export_settings);
+ AnimationExporter ae(writer, this->export_settings);
bool has_animations = ae.exportAnimations(sce);
// <library_controllers>
- ArmatureExporter arm_exporter(&sw, this->export_settings);
- ControllerExporter controller_exporter(&sw , this->export_settings);
+ ArmatureExporter arm_exporter(writer, this->export_settings);
+ ControllerExporter controller_exporter(writer, this->export_settings);
if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys)
{
controller_exporter.export_controllers(sce);
@@ -283,7 +303,7 @@ void DocumentExporter::exportCurrentScene(Scene *sce)
// <library_visual_scenes>
- SceneExporter se(&sw, &arm_exporter, this->export_settings);
+ SceneExporter se(writer, &arm_exporter, this->export_settings);
if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
// channels adressing <matrix> objects is not (yet) supported
@@ -301,12 +321,16 @@ void DocumentExporter::exportCurrentScene(Scene *sce)
// <scene>
std::string scene_name(translate_id(id_name(sce)));
- COLLADASW::Scene scene(&sw, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING,
+ COLLADASW::Scene scene(writer, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING,
scene_name));
scene.add();
// close <Collada>
- sw.endDocument();
+ writer->endDocument();
+ delete writer;
+
+ // Finally move the created document into place
+ BLI_rename(native_filename.c_str(), this->export_settings->filepath);
}
diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp
index 2e60c2d3e42..97ac09d4abb 100644
--- a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp
+++ b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp
@@ -15,9 +15,9 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * Contributor(s): Jeroen Bakker
+ * Monique Dewanchand
+ * Sergey Sharybin
*/
#include "COM_AntiAliasOperation.h"
@@ -31,76 +31,122 @@ extern "C" {
}
+/* An implementation of the Scale3X edge-extrapolation algorithm.
+ *
+ * Code from GIMP plugin, based on code from Adam D. Moss (adam@gimp.org)
+ * licensed by the MIT license.
+ */
+static int extrapolate9(float *E0, float *E1, float *E2,
+ float *E3, float *E4, float *E5,
+ float *E6, float *E7, float *E8,
+ const float *A, const float *B, const float *C,
+ const float *D, const float *E, const float *F,
+ const float *G, const float *H, const float *I)
+{
+#define PEQ(X, Y) (fabsf(*X - *Y) < 1e-3f)
+#define PCPY(DST, SRC) do { *DST = *SRC; } while (0)
+ if ((!PEQ(B, H)) && (!PEQ(D, F))) {
+ if (PEQ(D, B)) PCPY(E0, D); else PCPY(E0, E);
+ if ((PEQ(D, B) && !PEQ(E, C)) || (PEQ(B, F) && !PEQ(E, A)))
+ PCPY(E1, B); else PCPY(E1, E);
+ if (PEQ(B, F)) PCPY(E2, F); else PCPY(E2, E);
+ if ((PEQ(D, B) && !PEQ(E, G)) || (PEQ(D, H) && !PEQ(E, A)))
+ PCPY(E3, D); else PCPY(E3, E);
+ PCPY(E4, E);
+ if ((PEQ(B, F) && !PEQ(E, I)) || (PEQ(H, F) && !PEQ(E, C)))
+ PCPY(E5, F); else PCPY(E5, E);
+ if (PEQ(D, H)) PCPY(E6, D); else PCPY(E6, E);
+ if ((PEQ(D, H) && !PEQ(E, I)) || (PEQ(H, F) && !PEQ(E, G)))
+ PCPY(E7, H); else PCPY(E7, E);
+ if (PEQ(H, F)) PCPY(E8, F); else PCPY(E8, E);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+#undef PEQ
+#undef PCPY
+}
+
AntiAliasOperation::AntiAliasOperation() : NodeOperation()
{
this->addInputSocket(COM_DT_VALUE);
this->addOutputSocket(COM_DT_VALUE);
this->m_valueReader = NULL;
- this->m_buffer = NULL;
this->setComplex(true);
}
+
void AntiAliasOperation::initExecution()
{
this->m_valueReader = this->getInputSocketReader(0);
- NodeOperation::initMutex();
}
-void AntiAliasOperation::executePixel(float output[4], int x, int y, void * /*data*/)
+void AntiAliasOperation::executePixel(float output[4],
+ int x, int y,
+ void *data)
{
- if (y < 0 || (unsigned int)y >= this->m_height || x < 0 || (unsigned int)x >= this->m_width) {
+ MemoryBuffer *input_buffer = (MemoryBuffer *)data;
+ const int buffer_width = input_buffer->getWidth(),
+ buffer_height = input_buffer->getHeight();
+ if (y < 0 || y >= buffer_height || x < 0 || x >= buffer_width) {
output[0] = 0.0f;
}
else {
- int offset = y * this->m_width + x;
- output[0] = this->m_buffer[offset] / 255.0f;
+ const float *buffer = input_buffer->getBuffer();
+ const float *row_curr = &buffer[y * buffer_width];
+ if (x == 0 || x == buffer_width - 1 ||
+ y == 0 || y == buffer_height - 1)
+ {
+ output[0] = row_curr[x];
+ return;
+ }
+ const float *row_prev = &buffer[(y - 1) * buffer_width],
+ *row_next = &buffer[(y + 1) * buffer_width];
+ float ninepix[9];
+ if (extrapolate9(&ninepix[0], &ninepix[1], &ninepix[2],
+ &ninepix[3], &ninepix[4], &ninepix[5],
+ &ninepix[6], &ninepix[7], &ninepix[8],
+ &row_prev[x - 1], &row_prev[x], &row_prev[x + 1],
+ &row_curr[x - 1], &row_curr[x], &row_curr[x + 1],
+ &row_next[x - 1], &row_next[x], &row_next[x + 1]))
+ {
+ /* Some rounding magic to so make weighting correct with the
+ * original coefficients.
+ */
+ unsigned char result = ((3 * ninepix[0] + 5 * ninepix[1] + 3 * ninepix[2] +
+ 5 * ninepix[3] + 6 * ninepix[4] + 5 * ninepix[5] +
+ 3 * ninepix[6] + 5 * ninepix[7] + 3 * ninepix[8]) * 255.0f +
+ 19.0f) / 38.0f;
+ output[0] = result / 255.0f;
+ }
+ else {
+ output[0] = row_curr[x];
+ }
}
-
}
void AntiAliasOperation::deinitExecution()
{
this->m_valueReader = NULL;
- if (this->m_buffer) {
- MEM_freeN(this->m_buffer);
- }
- NodeOperation::deinitMutex();
}
-bool AntiAliasOperation::determineDependingAreaOfInterest(rcti * /*input*/, ReadBufferOperation *readOperation, rcti *output)
+bool AntiAliasOperation::determineDependingAreaOfInterest(
+ rcti *input,
+ ReadBufferOperation *readOperation,
+ rcti *output)
{
rcti imageInput;
- if (this->m_buffer) {
- return false;
- }
- else {
- NodeOperation *operation = getInputOperation(0);
- imageInput.xmax = operation->getWidth();
- imageInput.xmin = 0;
- imageInput.ymax = operation->getHeight();
- imageInput.ymin = 0;
- if (operation->determineDependingAreaOfInterest(&imageInput, readOperation, output) ) {
- return true;
- }
- }
- return false;
+ NodeOperation *operation = getInputOperation(0);
+ imageInput.xmax = input->xmax + 1;
+ imageInput.xmin = input->xmin - 1;
+ imageInput.ymax = input->ymax + 1;
+ imageInput.ymin = input->ymin - 1;
+ return operation->determineDependingAreaOfInterest(&imageInput,
+ readOperation,
+ output);
}
void *AntiAliasOperation::initializeTileData(rcti *rect)
{
- if (this->m_buffer) { return this->m_buffer; }
- lockMutex();
- if (this->m_buffer == NULL) {
- MemoryBuffer *tile = (MemoryBuffer *)this->m_valueReader->initializeTileData(rect);
- int size = tile->getHeight() * tile->getWidth();
- float *input = tile->getBuffer();
- char *valuebuffer = (char *)MEM_mallocN(sizeof(char) * size, __func__);
- for (int i = 0; i < size; i++) {
- float in = input[i];
- valuebuffer[i] = FTOCHAR(in);
- }
- antialias_tagbuf(tile->getWidth(), tile->getHeight(), valuebuffer);
- this->m_buffer = valuebuffer;
- }
- unlockMutex();
- return this->m_buffer;
+ return getInputOperation(0)->initializeTileData(rect);
}
diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.h b/source/blender/compositor/operations/COM_AntiAliasOperation.h
index 385d59fec3c..996c7c2fe41 100644
--- a/source/blender/compositor/operations/COM_AntiAliasOperation.h
+++ b/source/blender/compositor/operations/COM_AntiAliasOperation.h
@@ -36,7 +36,6 @@ protected:
* @brief Cached reference to the reader
*/
SocketReader *m_valueReader;
- char *m_buffer;
public:
AntiAliasOperation();
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index 1ed70b3cd98..b213aca478f 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -28,6 +28,7 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/eigen
../../../../intern/glew-mx
)
@@ -68,13 +69,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
-if(WITH_OPENNL)
- add_definitions(-DWITH_OPENNL)
- list(APPEND INC_SYS
- ../../../../intern/opennl/extern
- )
-endif()
-
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_editor_armature "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/armature/SConscript b/source/blender/editors/armature/SConscript
index 9c3959ecb5b..850834d2cd4 100644
--- a/source/blender/editors/armature/SConscript
+++ b/source/blender/editors/armature/SConscript
@@ -31,9 +31,9 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
+ '#/intern/eigen',
env['BF_GLEW_INC'],
'#/intern/glew-mx',
- '#/intern/opennl/extern',
'../include',
'../../blenkernel',
'../../blenlib',
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 5a0e70dc5dd..94b7277ce8f 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -156,7 +156,7 @@ void ED_armature_origin_set(Scene *scene, Object *ob, float cursor[3], int cente
mul_m4_v3(ob->imat, cent);
}
else {
- if (around == V3D_CENTROID) {
+ if (around == V3D_AROUND_CENTER_MEAN) {
int total = 0;
zero_v3(cent);
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index ea1a94fbba6..c621d6f99c0 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -51,12 +51,10 @@
#include "ED_armature.h"
#include "ED_mesh.h"
+#include "eigen_capi.h"
#include "armature_intern.h"
-
-#ifdef WITH_OPENNL
-# include "meshlaplacian.h"
-#endif
+#include "meshlaplacian.h"
#if 0
#include "reeb.h"
@@ -401,12 +399,8 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
if (heat) {
const char *error = NULL;
-#ifdef WITH_OPENNL
heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
root, tip, selected, &error);
-#else
- error = "Built without OpenNL";
-#endif
if (error) {
BKE_report(reports, RPT_WARNING, error);
}
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index 9319ccf3b13..87d75aa8fad 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -982,7 +982,7 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
mvalf[0] = dd->mval[0];
mvalf[1] = dd->mval[1];
- peelObjectsContext(C, &sketch->depth_peels, mvalf, SNAP_ALL);
+ peelObjectsContext(C, mvalf, SNAP_ALL, &sketch->depth_peels);
if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) {
last_p = stk->points[stk->nb_points - 1].p;
@@ -1086,7 +1086,9 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
mval[1] = dd->mval[1];
/* try to snap to closer object */
- found = snapObjectsContext(C, mval, &dist_px, vec, no, SNAP_NOT_SELECTED);
+ found = snapObjectsContext(
+ C, mval, SNAP_NOT_SELECTED,
+ vec, no, &dist_px);
if (found == 1) {
pt->type = dd->type;
pt->mode = PT_SNAP;
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 3f27a58930d..ce87ffb3494 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -46,11 +46,9 @@
#include "ED_mesh.h"
#include "ED_armature.h"
-#include "meshlaplacian.h"
-
-#ifdef WITH_OPENNL
+#include "eigen_capi.h"
-#include "ONL_opennl.h"
+#include "meshlaplacian.h"
/* ************* XXX *************** */
static void waitcursor(int UNUSED(val)) {}
@@ -64,7 +62,7 @@ static void error(const char *str) { printf("error: %s\n", str); }
/************************** Laplacian System *****************************/
struct LaplacianSystem {
- NLContext *context; /* opennl context */
+ LinearSolver *context; /* linear solver */
int totvert, totface;
@@ -76,7 +74,7 @@ struct LaplacianSystem {
int areaweights; /* use area in cotangent weights? */
int storeweights; /* store cotangent weights in fweights */
- int nlbegun; /* nlBegin(NL_SYSTEM/NL_MATRIX) done */
+ bool variablesdone; /* variables set in linear system */
EdgeHash *edgehash; /* edge hash for construction */
@@ -182,18 +180,18 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int
t2 = cotangent_tri_weight_v3(v2, v3, v1) / laplacian_edge_count(sys->edgehash, i3, i1);
t3 = cotangent_tri_weight_v3(v3, v1, v2) / laplacian_edge_count(sys->edgehash, i1, i2);
- nlMatrixAdd(sys->context, i1, i1, (t2 + t3) * varea[i1]);
- nlMatrixAdd(sys->context, i2, i2, (t1 + t3) * varea[i2]);
- nlMatrixAdd(sys->context, i3, i3, (t1 + t2) * varea[i3]);
+ EIG_linear_solver_matrix_add(sys->context, i1, i1, (t2 + t3) * varea[i1]);
+ EIG_linear_solver_matrix_add(sys->context, i2, i2, (t1 + t3) * varea[i2]);
+ EIG_linear_solver_matrix_add(sys->context, i3, i3, (t1 + t2) * varea[i3]);
- nlMatrixAdd(sys->context, i1, i2, -t3 * varea[i1]);
- nlMatrixAdd(sys->context, i2, i1, -t3 * varea[i2]);
+ EIG_linear_solver_matrix_add(sys->context, i1, i2, -t3 * varea[i1]);
+ EIG_linear_solver_matrix_add(sys->context, i2, i1, -t3 * varea[i2]);
- nlMatrixAdd(sys->context, i2, i3, -t1 * varea[i2]);
- nlMatrixAdd(sys->context, i3, i2, -t1 * varea[i3]);
+ EIG_linear_solver_matrix_add(sys->context, i2, i3, -t1 * varea[i2]);
+ EIG_linear_solver_matrix_add(sys->context, i3, i2, -t1 * varea[i3]);
- nlMatrixAdd(sys->context, i3, i1, -t2 * varea[i3]);
- nlMatrixAdd(sys->context, i1, i3, -t2 * varea[i1]);
+ EIG_linear_solver_matrix_add(sys->context, i3, i1, -t2 * varea[i3]);
+ EIG_linear_solver_matrix_add(sys->context, i1, i3, -t2 * varea[i1]);
if (sys->storeweights) {
sys->fweights[f][0] = t1 * varea[i1];
@@ -218,11 +216,11 @@ static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totfac
sys->areaweights = 1;
sys->storeweights = 0;
- /* create opennl context */
- sys->context = nlNewContext();
- nlSolverParameteri(sys->context, NL_NB_VARIABLES, totvert);
+ /* create linear solver */
if (lsq)
- nlSolverParameteri(sys->context, NL_LEAST_SQUARES, NL_TRUE);
+ sys->context = EIG_linear_least_squares_solver_new(0, totvert, 1);
+ else
+ sys->context = EIG_linear_solver_new(0, totvert, 1);
return sys;
}
@@ -272,7 +270,7 @@ static void laplacian_system_construct_end(LaplacianSystem *sys)
/* for heat weighting */
if (sys->heat.H)
- nlMatrixAdd(sys->context, a, a, sys->heat.H[a]);
+ EIG_linear_solver_matrix_add(sys->context, a, a, sys->heat.H[a]);
}
if (sys->storeweights)
@@ -301,7 +299,7 @@ static void laplacian_system_delete(LaplacianSystem *sys)
if (sys->faces) MEM_freeN(sys->faces);
if (sys->fweights) MEM_freeN(sys->fweights);
- nlDeleteContext(sys->context);
+ EIG_linear_solver_delete(sys->context);
MEM_freeN(sys);
}
@@ -309,42 +307,37 @@ void laplacian_begin_solve(LaplacianSystem *sys, int index)
{
int a;
- if (!sys->nlbegun) {
- nlBegin(sys->context, NL_SYSTEM);
-
+ if (!sys->variablesdone) {
if (index >= 0) {
for (a = 0; a < sys->totvert; a++) {
if (sys->vpinned[a]) {
- nlSetVariable(sys->context, 0, a, sys->verts[a][index]);
- nlLockVariable(sys->context, a);
+ EIG_linear_solver_variable_set(sys->context, 0, a, sys->verts[a][index]);
+ EIG_linear_solver_variable_lock(sys->context, a);
}
}
}
- nlBegin(sys->context, NL_MATRIX);
- sys->nlbegun = 1;
+ sys->variablesdone = true;
}
}
void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value)
{
- nlRightHandSideAdd(sys->context, 0, v, value);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, v, value);
}
int laplacian_system_solve(LaplacianSystem *sys)
{
- nlEnd(sys->context, NL_MATRIX);
- nlEnd(sys->context, NL_SYSTEM);
- sys->nlbegun = 0;
+ sys->variablesdone = false;
- //nlPrintMatrix(sys->context, );
+ //EIG_linear_solver_print_matrix(sys->context, );
- return nlSolve(sys->context, NL_TRUE);
+ return EIG_linear_solver_solve(sys->context);
}
float laplacian_system_get_solution(LaplacianSystem *sys, int v)
{
- return nlGetVariable(sys->context, 0, v);
+ return EIG_linear_solver_variable_get(sys->context, 0, v);
}
/************************* Heat Bone Weighting ******************************/
@@ -1284,7 +1277,7 @@ static float meshdeform_boundary_total_weight(MeshDeformBind *mdb, int x, int y,
return totweight;
}
-static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, NLContext *context, int x, int y, int z)
+static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z)
{
MDefBoundIsect *isect;
float weight, totweight;
@@ -1294,7 +1287,7 @@ static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, NLContext *context,
if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
return;
- nlMatrixAdd(context, mdb->varidx[acenter], mdb->varidx[acenter], 1.0f);
+ EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[acenter], 1.0f);
totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
for (i = 1; i <= 6; i++) {
@@ -1305,12 +1298,12 @@ static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, NLContext *context,
isect = mdb->boundisect[acenter][i - 1];
if (!isect) {
weight = (1.0f / mdb->width[0]) / totweight;
- nlMatrixAdd(context, mdb->varidx[acenter], mdb->varidx[a], -weight);
+ EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[a], -weight);
}
}
}
-static void meshdeform_matrix_add_rhs(MeshDeformBind *mdb, NLContext *context, int x, int y, int z, int cagevert)
+static void meshdeform_matrix_add_rhs(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z, int cagevert)
{
MDefBoundIsect *isect;
float rhs, weight, totweight;
@@ -1331,7 +1324,7 @@ static void meshdeform_matrix_add_rhs(MeshDeformBind *mdb, NLContext *context, i
if (isect) {
weight = (1.0f / isect->len) / totweight;
rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
- nlRightHandSideAdd(context, 0, mdb->varidx[acenter], rhs);
+ EIG_linear_solver_right_hand_side_add(context, 0, mdb->varidx[acenter], rhs);
}
}
}
@@ -1386,7 +1379,7 @@ static void meshdeform_matrix_add_exterior_phi(MeshDeformBind *mdb, int x, int y
static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
{
- NLContext *context;
+ LinearSolver *context;
float vec[3], gridvec[3];
int a, b, x, y, z, totvar;
char message[256];
@@ -1403,15 +1396,8 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
progress_bar(0, "Starting mesh deform solve");
- /* setup opennl solver */
- context = nlNewContext();
-
- nlSolverParameteri(context, NL_NB_VARIABLES, totvar);
- nlSolverParameteri(context, NL_NB_ROWS, totvar);
- nlSolverParameteri(context, NL_NB_RIGHT_HAND_SIDES, 1);
-
- nlBegin(context, NL_SYSTEM);
- nlBegin(context, NL_MATRIX);
+ /* setup linear solver */
+ context = EIG_linear_solver_new(totvar, totvar, 1);
/* build matrix */
for (z = 0; z < mdb->size; z++)
@@ -1421,21 +1407,13 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
/* solve for each cage vert */
for (a = 0; a < mdb->totcagevert; a++) {
- if (a != 0) {
- nlBegin(context, NL_SYSTEM);
- nlBegin(context, NL_MATRIX);
- }
-
/* fill in right hand side and solve */
for (z = 0; z < mdb->size; z++)
for (y = 0; y < mdb->size; y++)
for (x = 0; x < mdb->size; x++)
meshdeform_matrix_add_rhs(mdb, context, x, y, z, a);
- nlEnd(context, NL_MATRIX);
- nlEnd(context, NL_SYSTEM);
-
- if (nlSolve(context, NL_TRUE)) {
+ if (EIG_linear_solver_solve(context)) {
for (z = 0; z < mdb->size; z++)
for (y = 0; y < mdb->size; y++)
for (x = 0; x < mdb->size; x++)
@@ -1448,7 +1426,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
for (b = 0; b < mdb->size3; b++) {
if (mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR)
- mdb->phi[b] = nlGetVariable(context, 0, mdb->varidx[b]);
+ mdb->phi[b] = EIG_linear_solver_variable_get(context, 0, mdb->varidx[b]);
mdb->totalphi[b] += mdb->phi[b];
}
@@ -1502,7 +1480,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
/* free */
MEM_freeN(mdb->varidx);
- nlDeleteContext(context);
+ EIG_linear_solver_delete(context);
}
static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierData *mmd, MeshDeformBind *mdb)
@@ -1655,7 +1633,9 @@ static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierDa
free_bvhtree_from_mesh(&mdb->bvhdata);
}
-void mesh_deform_bind(Scene *scene, MeshDeformModifierData *mmd, float *vertexcos, int totvert, float cagemat[4][4])
+void mesh_deform_bind(
+ Scene *scene, MeshDeformModifierData *mmd, DerivedMesh *cagedm,
+ float *vertexcos, int totvert, float cagemat[4][4])
{
MeshDeformBind mdb;
MVert *mvert;
@@ -1670,7 +1650,7 @@ void mesh_deform_bind(Scene *scene, MeshDeformModifierData *mmd, float *vertexco
mdb.vertexcos = MEM_callocN(sizeof(float) * 3 * totvert, "MeshDeformCos");
mdb.totvert = totvert;
- mdb.cagedm = mesh_create_derived_no_deform(scene, mmd->object, NULL, CD_MASK_BAREMESH);
+ mdb.cagedm = cagedm;
mdb.totcagevert = mdb.cagedm->getNumVerts(mdb.cagedm);
mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.totcagevert, "MeshDeformBindCos");
copy_m4_m4(mdb.cagemat, cagemat);
@@ -1695,7 +1675,6 @@ void mesh_deform_bind(Scene *scene, MeshDeformModifierData *mmd, float *vertexco
mul_m4_v3(mmd->object->obmat, mmd->bindcagecos + a * 3);
/* free */
- mdb.cagedm->release(mdb.cagedm);
MEM_freeN(mdb.vertexcos);
/* compact weights */
@@ -1704,14 +1683,3 @@ void mesh_deform_bind(Scene *scene, MeshDeformModifierData *mmd, float *vertexco
end_progress_bar();
waitcursor(0);
}
-
-#else /* WITH_OPENNL */
-
-#ifdef __GNUC__
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#endif
-
-void mesh_deform_bind(Scene *scene, MeshDeformModifierData *mmd, float *vertexcos, int totvert, float cagemat[4][4]) {}
-void *modifier_mdef_compact_influences_link_kludge = modifier_mdef_compact_influences;
-
-#endif /* WITH_OPENNL */
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index d53e5b857a0..a1c1f4f115e 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -2497,7 +2497,7 @@ int weightFromLoc(EditMesh *em, int axis)
return 1;
}
-static void addTriangle(NLContext *context, EditVert *v1, EditVert *v2, EditVert *v3, int e1, int e2, int e3)
+static void addTriangle(LinearSolver *context, EditVert *v1, EditVert *v2, EditVert *v3, int e1, int e2, int e3)
{
/* Angle opposite e1 */
float t1 = cotangent_tri_weight_v3(v1->co, v2->co, v3->co) / e2;
@@ -2512,23 +2512,23 @@ static void addTriangle(NLContext *context, EditVert *v1, EditVert *v2, EditVert
int i2 = indexData(v2);
int i3 = indexData(v3);
- nlMatrixAdd(context, i1, i1, t2 + t3);
- nlMatrixAdd(context, i2, i2, t1 + t3);
- nlMatrixAdd(context, i3, i3, t1 + t2);
+ EIG_linear_solver_matrix_add(context, i1, i1, t2 + t3);
+ EIG_linear_solver_matrix_add(context, i2, i2, t1 + t3);
+ EIG_linear_solver_matrix_add(context, i3, i3, t1 + t2);
- nlMatrixAdd(context, i1, i2, -t3);
- nlMatrixAdd(context, i2, i1, -t3);
+ EIG_linear_solver_matrix_add(context, i1, i2, -t3);
+ EIG_linear_solver_matrix_add(context, i2, i1, -t3);
- nlMatrixAdd(context, i2, i3, -t1);
- nlMatrixAdd(context, i3, i2, -t1);
+ EIG_linear_solver_matrix_add(context, i2, i3, -t1);
+ EIG_linear_solver_matrix_add(context, i3, i2, -t1);
- nlMatrixAdd(context, i3, i1, -t2);
- nlMatrixAdd(context, i1, i3, -t2);
+ EIG_linear_solver_matrix_add(context, i3, i1, -t2);
+ EIG_linear_solver_matrix_add(context, i1, i3, -t2);
}
int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges)
{
- NLContext *context;
+ LinearSolver *context;
NLboolean success;
EditVert *eve;
EditEdge *eed;
@@ -2542,14 +2542,10 @@ int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges)
totvert++;
}
- /* Solve with openNL */
+ /* Solve */
- context = nlNewContext();
+ context = EIG_linear_solver_new(, 0, totvert, 1);
- nlSolverParameteri(context, NL_NB_VARIABLES, totvert);
-
- nlBegin(context, NL_SYSTEM);
-
/* Find local extrema */
for (index = 0, eve = em->verts.first; eve; index++, eve = eve->next) {
if (eve->h == 0) {
@@ -2583,8 +2579,8 @@ int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges)
if (maximum || minimum) {
float w = weightData(eve);
eve->f1 = 0;
- nlSetVariable(context, 0, index, w);
- nlLockVariable(context, index);
+ EIG_linear_solver_variable_set(context, 0, index, w);
+ EIG_linear_solver_variable_lock(context, index);
}
else {
eve->f1 = 1;
@@ -2592,8 +2588,6 @@ int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges)
}
}
- nlBegin(context, NL_MATRIX);
-
/* Zero edge weight */
for (eed = em->edges.first; eed; eed = eed->next) {
eed->tmp.l = 0;
@@ -2625,23 +2619,19 @@ int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges)
}
}
- nlEnd(context, NL_MATRIX);
-
- nlEnd(context, NL_SYSTEM);
-
- success = nlSolve(context, NL_TRUE);
+ success = EIG_linear_solver_solve(context);
if (success) {
rval = 1;
for (index = 0, eve = em->verts.first; eve; index++, eve = eve->next) {
- weightSetData(eve, nlGetVariable(context, 0, index));
+ weightSetData(eve, EIG_linear_solver_variable_get(context, 0, index));
}
}
else {
rval = 0;
}
- nlDeleteContext(context);
+ EIG_linear_solver_delete(context);
return rval;
}
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index e2cf0c1ec14..22cb479e77d 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1352,7 +1352,11 @@ static int curve_split_exec(bContext *C, wmOperator *op)
adduplicateflagNurb(obedit, &newnurb, SELECT, true);
if (BLI_listbase_is_empty(&newnurb) == false) {
+ Curve *cu = obedit->data;
+ const int len_orig = BLI_listbase_count(editnurb);
+
curve_delete_segments(obedit, true);
+ cu->actnu -= len_orig - BLI_listbase_count(editnurb);
BLI_movelisttolist(editnurb, &newnurb);
if (ED_curve_updateAnimPaths(obedit->data))
@@ -1919,18 +1923,30 @@ bool ed_editnurb_extrude_flag(EditNurb *editnurb, const short flag)
return ok;
}
+static bool calc_duplicate_actvert(
+ const ListBase *editnurb, const ListBase *newnurb, Curve *cu,
+ int start, int end, int vert)
+{
+ if ((start <= cu->actvert) && (end > cu->actvert)) {
+ cu->actvert = vert;
+ cu->actnu = BLI_listbase_count(editnurb) + BLI_listbase_count(newnurb);
+ return true;
+ }
+ return false;
+}
+
static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
const short flag, const bool split)
{
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu = editnurb->last, *newnu;
+ Nurb *nu, *newnu;
BezTriple *bezt, *bezt1;
BPoint *bp, *bp1, *bp2, *bp3;
Curve *cu = (Curve *)obedit->data;
- int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv;
+ int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv, i;
char *usel;
- while (nu) {
+ for (i = 0, nu = editnurb->first; nu; i++, nu = nu->next) {
cyclicu = cyclicv = 0;
if (nu->type == CU_BEZIER) {
for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
@@ -1951,12 +1967,21 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
}
else {
if (enda == nu->pntsu - 1) newu += cyclicu;
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ starta, starta + diffa, cu->actvert - starta);
+ }
newnu = BKE_nurb_copy(nu, newu, 1);
- BLI_addtail(newnurb, newnu);
memcpy(newnu->bezt, &nu->bezt[starta], diffa * sizeof(BezTriple));
if (newu != diffa) {
memcpy(&newnu->bezt[diffa], nu->bezt, cyclicu * sizeof(BezTriple));
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ 0, cyclicu, newu - cyclicu + cu->actvert);
+ }
cyclicu = 0;
}
@@ -1965,19 +1990,28 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
select_beztriple(bezt1, SELECT, flag, HIDDEN);
}
+
+ BLI_addtail(newnurb, newnu);
}
}
}
if (cyclicu != 0) {
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ 0, cyclicu, cu->actvert);
+ }
+
newnu = BKE_nurb_copy(nu, cyclicu, 1);
- BLI_addtail(newnurb, newnu);
memcpy(newnu->bezt, nu->bezt, cyclicu * sizeof(BezTriple));
newnu->flagu &= ~CU_NURB_CYCLIC;
for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
select_beztriple(bezt1, SELECT, flag, HIDDEN);
}
+
+ BLI_addtail(newnurb, newnu);
}
}
else if (nu->pntsv == 1) { /* because UV Nurb has a different method for dupli */
@@ -1999,12 +2033,21 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
}
else {
if (enda == nu->pntsu - 1) newu += cyclicu;
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ starta, starta + diffa, cu->actvert - starta);
+ }
newnu = BKE_nurb_copy(nu, newu, 1);
- BLI_addtail(newnurb, newnu);
memcpy(newnu->bp, &nu->bp[starta], diffa * sizeof(BPoint));
if (newu != diffa) {
memcpy(&newnu->bp[diffa], nu->bp, cyclicu * sizeof(BPoint));
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ 0, cyclicu, newu - cyclicu + cu->actvert);
+ }
cyclicu = 0;
}
@@ -2013,19 +2056,28 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
select_bpoint(bp1, SELECT, flag, HIDDEN);
}
+
+ BLI_addtail(newnurb, newnu);
}
}
}
if (cyclicu != 0) {
+ if (i == cu->actnu) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ 0, cyclicu, cu->actvert);
+ }
+
newnu = BKE_nurb_copy(nu, cyclicu, 1);
- BLI_addtail(newnurb, newnu);
memcpy(newnu->bp, nu->bp, cyclicu * sizeof(BPoint));
newnu->flagu &= ~CU_NURB_CYCLIC;
for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
select_bpoint(bp1, SELECT, flag, HIDDEN);
}
+
+ BLI_addtail(newnurb, newnu);
}
}
else {
@@ -2101,6 +2153,28 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
memcpy(&newnu->bp[b * newnu->pntsu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint));
memcpy(&newnu->bp[b * newnu->pntsu + newu], &nu->bp[b * nu->pntsu], cyclicu * sizeof(BPoint));
}
+
+ if (cu->actnu == i) {
+ for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) {
+ starta = b * nu->pntsu + a;
+ if (calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ cu->actvert, starta,
+ cu->actvert % nu->pntsu + newu + b * newnu->pntsu))
+ {
+ /* actvert in cyclicu selection */
+ break;
+ }
+ else if (calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ starta, starta + newu,
+ cu->actvert - starta + b * newnu->pntsu))
+ {
+ /* actvert in 'current' iteration selection */
+ break;
+ }
+ }
+ }
cyclicu = cyclicv = 0;
}
else if ((a / nu->pntsu) + newv == nu->pntsv && cyclicv != 0) {
@@ -2108,6 +2182,14 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
newnu = BKE_nurb_copy(nu, newu, newv + cyclicv);
memcpy(newnu->bp, &nu->bp[a], newu * newv * sizeof(BPoint));
memcpy(&newnu->bp[newu * newv], nu->bp, newu * cyclicv * sizeof(BPoint));
+
+ /* check for actvert in cylicv selection */
+ if (cu->actnu == i) {
+ calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ cu->actvert, a,
+ (newu * newv) + cu->actvert);
+ }
cyclicu = cyclicv = 0;
}
else {
@@ -2116,6 +2198,20 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint));
}
}
+
+ /* general case if not handled by cyclicu or cyclicv */
+ if (cu->actnu == i) {
+ for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) {
+ starta = b * nu->pntsu + a;
+ if (calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ starta, starta + newu,
+ cu->actvert - (a / nu->pntsu * nu->pntsu + diffa + (starta % nu->pntsu))))
+ {
+ break;
+ }
+ }
+ }
BLI_addtail(newnurb, newnu);
if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
@@ -2132,6 +2228,20 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
for (b = 0; b < newv; b++) {
memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu], newu * sizeof(BPoint));
}
+
+ /* check for actvert in the unused cyclicuv selection */
+ if (cu->actnu == i) {
+ for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) {
+ starta = b * nu->pntsu;
+ if (calc_duplicate_actvert(
+ editnurb, newnurb, cu,
+ starta, starta + newu,
+ cu->actvert - (diffa + (starta % nu->pntsu))))
+ {
+ break;
+ }
+ }
+ }
BLI_addtail(newnurb, newnu);
if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
@@ -2145,12 +2255,9 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
}
}
}
- nu = nu->prev;
}
if (BLI_listbase_is_empty(newnurb) == false) {
- cu->actnu = cu->actvert = CU_ACT_NONE;
-
for (nu = newnurb->first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
if (split) {
@@ -4868,7 +4975,9 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const float mval[2] = {UNPACK2(event->mval)};
float no_dummy[3];
float dist_px_dummy;
- snapObjectsContext(C, mval, &dist_px_dummy, location, no_dummy, SNAP_NOT_OBEDIT);
+ snapObjectsContext(
+ C, mval, SNAP_NOT_OBEDIT,
+ location, no_dummy, &dist_px_dummy);
}
RNA_float_set_array(op->ptr, "location", location);
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index b904417cfcb..05b733d2564 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -90,12 +90,6 @@ void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments
void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments);
/**
- * Returns an integer value as obtained by glGetIntegerv.
- * The param must cause only one value to be gotten from GL.
- */
-int glaGetOneInteger(int param);
-
-/**
* Returns a float value as obtained by glGetFloatv.
* The param must cause only one value to be gotten from GL.
*/
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 7d7ee33bde4..15c68378b9a 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -42,6 +42,7 @@ struct bPoseChannel;
struct IDProperty;
struct ListBase;
struct MeshDeformModifierData;
+struct DerivedMesh;
struct Object;
struct ReportList;
struct Scene;
@@ -208,6 +209,7 @@ int BDR_drawSketchNames(struct ViewContext *vc);
/* meshlaplacian.c */
void mesh_deform_bind(struct Scene *scene,
struct MeshDeformModifierData *mmd,
+ struct DerivedMesh *cagedm,
float *vertexcos, int totvert, float cagemat[4][4]);
#ifdef __cplusplus
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 8e19ec839d8..c509aeb4ac2 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -196,7 +196,7 @@ void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEd
/* editface.c */
-void paintface_flush_flags(struct Object *ob);
+void paintface_flush_flags(struct Object *ob, short flag);
bool paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], bool extend, bool deselect, bool toggle);
int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, bool select, bool extend);
void paintface_deselect_all_visible(struct Object *ob, int action, bool flush_flags);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 9fd7ec32279..c9b7875aef0 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -137,6 +137,7 @@ float ED_object_new_primitive_matrix(
void ED_object_add_unit_props(struct wmOperatorType *ot);
void ED_object_add_generic_props(struct wmOperatorType *ot, bool do_editmode);
+void ED_object_add_mesh_props(struct wmOperatorType *ot);
bool ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, const char view_align_axis,
float loc[3], float rot[3],
bool *enter_editmode, unsigned int *layer, bool *is_view_aligned);
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index b0866a564e5..19bfb94e130 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -168,30 +168,53 @@ typedef struct DepthPeel {
struct ListBase;
-typedef enum SnapMode {
+typedef enum SnapSelect {
SNAP_ALL = 0,
SNAP_NOT_SELECTED = 1,
SNAP_NOT_OBEDIT = 2
-} SnapMode;
+} SnapSelect;
#define SNAP_MIN_DISTANCE 30
#define TRANSFORM_DIST_MAX_RAY (FLT_MAX / 2.0f)
-bool peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, const float mval[2], SnapMode mode);
-bool peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, const float mval[2], SnapMode mode);
-bool snapObjectsTransform(struct TransInfo *t, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode);
-bool snapObjectsContext(struct bContext *C, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode);
+bool peelObjectsTransForm(
+ struct TransInfo *t, const float mval[2], SnapSelect snap_select,
+ /* return args */
+ struct ListBase *r_depth_peels);
+bool peelObjectsContext(
+ struct bContext *C, const float mval[2], SnapSelect snap_select,
+ /* return args */
+ struct ListBase *r_depth_peels);
+bool snapObjectsTransform(
+ struct TransInfo *t, const float mval[2], SnapSelect snap_select,
+ /* return args */
+ float r_loc[3], float r_no[3], float *r_dist_px);
+bool snapObjectsContext(
+ struct bContext *C, const float mval[2], SnapSelect snap_select,
+ /* return args */
+ float r_loc[3], float r_no[3], float *r_dist_px);
/* taks args for all settings */
-bool snapObjectsEx(struct Scene *scene, struct Base *base_act, struct View3D *v3d, struct ARegion *ar, struct Object *obedit, short snap_mode,
- const float mval[2], float *r_dist_px,
- float r_loc[3], float r_no[3], float *r_ray_dist, SnapMode mode);
-bool snapObjectsRayEx(struct Scene *scene, struct Base *base_act, struct View3D *v3d, struct ARegion *ar, struct Object *obedit, short snap_mode,
- struct Object **r_ob, float r_obmat[4][4],
- const float ray_start[3], const float ray_normal[3], float *r_ray_dist,
- const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode);
-
-bool snapNodesTransform(struct TransInfo *t, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode);
-bool snapNodesContext(struct bContext *C, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode);
-
-#endif
-
+bool snapObjectsEx(
+ struct Scene *scene, struct View3D *v3d, struct ARegion *ar, struct Base *base_act, struct Object *obedit,
+ const float mval[2], SnapSelect snap_select, short snap_mode,
+ float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], float *r_dist_px);
+bool snapObjectsRayEx(
+ struct Scene *scene, struct View3D *v3d, struct ARegion *ar, struct Base *base_act, struct Object *obedit,
+ const float mval[2], SnapSelect snap_select, short snap_mode,
+ const float ray_start[3], const float ray_normal[3], float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
+ struct Object **r_ob, float r_obmat[4][4]);
+
+bool snapNodesTransform(
+ struct TransInfo *t, const int mval[2], SnapSelect snap_select,
+ /* return args */
+ float r_loc[2], float *r_dist_px, char *r_node_border);
+bool snapNodesContext(
+ struct bContext *C, const int mval[2], SnapSelect snap_select,
+ /* return args */
+ float r_loc[2], float *r_dist_px, char *r_node_border);
+
+#endif /* __ED_TRANSFORM_H__ */
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 496ce7f2c60..cb331554a8f 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -44,6 +44,8 @@ bool ED_editors_flush_edits(const struct bContext *C, bool for_render);
void ED_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
+void ED_OT_flush_edits(struct wmOperatorType *ot);
+
/* ************** Undo ************************ */
/* undo.c */
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 108fcdda613..d4b723b807f 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -39,9 +39,11 @@
/* Struct Declarations */
struct ID;
+struct IDProperty;
struct ListBase;
struct ARegion;
struct ScrArea;
+struct bScreen;
struct wmEvent;
struct wmWindow;
struct wmOperator;
@@ -657,7 +659,7 @@ uiBut *uiDefKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y
uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y, short width, short height, short *keypoin, short *modkeypoin, const char *tip);
uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, int x, int y, short width, short height, float a1, float a2, const char *tip);
-uiBut *uiDefSearchButO_ptr(uiBlock *block, struct wmOperatorType *ot, IDProperty *properties,
+uiBut *uiDefSearchButO_ptr(uiBlock *block, struct wmOperatorType *ot, struct IDProperty *properties,
void *arg, int retval, int icon, int maxlen, int x, int y,
short width, short height, float a1, float a2, const char *tip);
@@ -964,7 +966,7 @@ void uiItemIntO(uiLayout *layout, const char *name, int icon, const char *opname
void uiItemFloatO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, float value);
void uiItemStringO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, const char *value);
-PointerRNA uiItemFullO_ptr(uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, IDProperty *properties, int context, int flag);
+PointerRNA uiItemFullO_ptr(uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, struct IDProperty *properties, int context, int flag);
PointerRNA uiItemFullO(uiLayout *layout, const char *idname, const char *name, int icon, struct IDProperty *properties, int context, int flag);
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index cd68425cc33..dc843952229 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -200,8 +200,9 @@ enum {
TH_SEQ_EFFECT,
TH_SEQ_TRANSITION,
TH_SEQ_META,
+ TH_SEQ_TEXT,
TH_SEQ_PREVIEW,
-
+
TH_EDGE_SHARP,
TH_EDITMESH_ACTIVE,
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index e03273aa474..79a7f4fc57a 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1046,6 +1046,10 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
/* dopesheet filtering options... */
data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(but->rnaprop));
}
+ else if (RNA_struct_is_a(but->rnapoin.type, &RNA_FileSelectParams)) {
+ /* Filebrowser options... */
+ data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(but->rnaprop));
+ }
}
}
else if (GS(id->name) == ID_SCE) {
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index 89a44db5fa3..e9d601457b4 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -164,11 +164,16 @@ static void block_align_proximity_compute(ButAlign *butal, ButAlign *butal_other
if (delta < max_delta) {
/* We are only interested in neighbors that are at least as close as already found ones. */
if (delta <= butal->dists[side]) {
- if (delta < butal->dists[side]) {
- /* We found a closer neighbor.
+ {
+ /* We found an as close or closer neighbor.
* If both buttons are alignable, we set them as each other neighbors.
* Else, we have an unalignable one, we need to reset the others matching neighbor to NULL
- * if its 'proximity distance' is really lower with current one. */
+ * if its 'proximity distance' is really lower with current one.
+ *
+ * NOTE: We cannot only execute that piece of code in case we found a **closer** neighbor,
+ * due to the limited way we represent neighbors (buttons only know **one** neighbor
+ * on each side, when they can actually have several ones), it would prevent
+ * some buttons to be properly 'neighborly-initialized'. */
if (butal_can_align && butal_other_can_align) {
butal->neighbors[side] = butal_other;
butal_other->neighbors[side_opp] = butal;
@@ -181,6 +186,7 @@ static void block_align_proximity_compute(ButAlign *butal, ButAlign *butal_other
}
butal->dists[side] = butal_other->dists[side_opp] = delta;
}
+
if (butal_can_align && butal_other_can_align) {
const int side_s1 = SIDE1(side);
const int side_s2 = SIDE2(side);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 84767eae350..ae2e6744160 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -55,6 +55,9 @@
#include "BLF_api.h"
+#include "GPU_draw.h"
+#include "GPU_basic_shader.h"
+
#include "UI_interface.h"
/* own include */
@@ -1216,43 +1219,33 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
static GLuint displist = 0;
- int a, old[8];
- GLfloat diff[4], diffn[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- float vec0[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- float dir[4], size;
+ float diffuse[3] = {1.0f, 1.0f, 1.0f};
+ float size;
- /* store stuff */
- glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
-
/* backdrop */
glColor3ubv((unsigned char *)wcol->inner);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_draw_roundbox_gl_mode(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f);
/* sphere color */
- glMaterialfv(GL_FRONT, GL_DIFFUSE, diffn);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
- /* disable blender light */
- for (a = 0; a < 8; a++) {
- old[a] = glIsEnabled(GL_LIGHT0 + a);
- glDisable(GL_LIGHT0 + a);
- }
-
- /* own light */
- glEnable(GL_LIGHT7);
- glEnable(GL_LIGHTING);
-
- ui_but_v3_get(but, dir);
+ /* setup lights */
+ GPULightData light = {0};
+ light.type = GPU_LIGHT_SUN;
+ copy_v3_v3(light.diffuse, diffuse);
+ zero_v3(light.specular);
+ ui_but_v3_get(but, light.direction);
+
+ GPU_basic_shader_light_set(0, &light);
+ for (int a = 1; a < 8; a++)
+ GPU_basic_shader_light_set(a, NULL);
+
+ /* setup shader */
+ GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
- dir[3] = 0.0f; /* glLightfv needs 4 args, 0.0 is sun */
- glLightfv(GL_LIGHT7, GL_POSITION, dir);
- glLightfv(GL_LIGHT7, GL_DIFFUSE, diffn);
- glLightfv(GL_LIGHT7, GL_SPECULAR, vec0);
- glLightf(GL_LIGHT7, GL_CONSTANT_ATTENUATION, 1.0f);
- glLightf(GL_LIGHT7, GL_LINEAR_ATTENUATION, 0.0f);
-
/* transform to button */
glPushMatrix();
glTranslatef(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f);
@@ -1283,10 +1276,9 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
glCallList(displist);
/* restore */
- glDisable(GL_LIGHTING);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ GPU_default_lights();
glDisable(GL_CULL_FACE);
- glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
- glDisable(GL_LIGHT7);
/* AA circle */
glEnable(GL_BLEND);
@@ -1298,12 +1290,6 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
/* matrix after circle */
glPopMatrix();
-
- /* enable blender light */
- for (a = 0; a < 8; a++) {
- if (old[a])
- glEnable(GL_LIGHT0 + a);
- }
}
static void ui_draw_but_curve_grid(const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 561a59b57ef..9a85f5b508d 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2186,6 +2186,32 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
/* ******************* copy and paste ******************** */
+static void ui_but_copy_data_path(uiBut *but, const bool full_path)
+{
+ char *id_path;
+
+ if (but->rnapoin.id.data == NULL) {
+ return;
+ }
+
+ if (full_path) {
+ if (but->rnaprop) {
+ id_path = RNA_path_full_property_py_ex(&but->rnapoin, but->rnaprop, but->rnaindex, true);
+ }
+ else {
+ id_path = RNA_path_full_struct_py(&but->rnapoin);
+ }
+ }
+ else {
+ id_path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
+ }
+
+ if (id_path) {
+ WM_clipboard_text_set(id_path, false);
+ MEM_freeN(id_path);
+ }
+}
+
/* c = copy, v = paste */
static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, char mode)
{
@@ -6375,10 +6401,10 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
uiLayout *layout;
uiStyle *style = UI_style_get_dpi();
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
- kmi = WM_keymap_item_find_id(km, kmi_id);
-
+ kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km);
+ BLI_assert(kmi != NULL);
+
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
@@ -6482,9 +6508,10 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
wmKeyMap *km;
wmKeyMapItem *kmi;
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
- int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
-
- kmi = WM_keymap_item_find_id(km, kmi_id);
+
+ kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km);
+ BLI_assert(kmi != NULL);
+
WM_keymap_remove_item(km, kmi);
but_shortcut_name_func(C, but, 0);
@@ -6727,12 +6754,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int w = uiLayoutGetWidth(layout);
wmKeyMap *km;
- wmKeyMapItem *kmi = NULL;
/* We want to know if this op has a shortcut, be it hotkey or not. */
- int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, false, &km);
-
- if (kmi_id)
- kmi = WM_keymap_item_find_id(km, kmi_id);
+ wmKeyMapItem *kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, false, &km);
/* We do have a shortcut, but only keyboard ones are editbale that way... */
if (kmi) {
@@ -6840,6 +6863,12 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
}
+ /* special case, copy-data-path */
+ if ((event->type == CKEY) && event->shift) {
+ ui_but_copy_data_path(but, event->alt != 0);
+ return WM_UI_HANDLER_BREAK;
+ }
+
ui_but_copy_paste(C, but, data, (event->type == CKEY) ? 'c' : 'v');
return WM_UI_HANDLER_BREAK;
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 843b0d5f2dc..8e6558c74b8 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
#include "GPU_extensions.h"
+#include "GPU_basic_shader.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -626,7 +627,7 @@ static void init_internal_icons(void)
}
/* we only use a texture for cards with non-power of two */
- if (GPU_non_power_of_two_support()) {
+ if (GPU_full_non_power_of_two_support()) {
glGenTextures(1, &icongltex.id);
if (icongltex.id) {
@@ -639,12 +640,12 @@ static void init_internal_icons(void)
glBindTexture(GL_TEXTURE_2D, icongltex.id);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, b32buf->x, b32buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b32buf->rect);
- glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, b32buf->x, b32buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b32buf->rect);
+ glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
while (b16buf->x > 1) {
ImBuf *nbuf = IMB_onehalf(b16buf);
- glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
+ glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
level++;
IMB_freeImBuf(b16buf);
b16buf = nbuf;
@@ -1122,7 +1123,7 @@ static void icon_draw_texture(
y1 = iy * icongltex.invh;
y2 = (iy + ih) * icongltex.invh;
- glEnable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
/* sharper downscaling, has no effect when scale matches with a mip level */
@@ -1145,7 +1146,7 @@ static void icon_draw_texture(
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f);
glBindTexture(GL_TEXTURE_2D, 0);
- glDisable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
/* Drawing size for preview images */
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 5ee7556a042..8242d029b6a 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -1648,7 +1648,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* Secondary theme colors */
unsigned char theme_col_tab_outline[3];
- unsigned char theme_col_tab_divider[3]; /* line that divides tabs from the main area */
+ unsigned char theme_col_tab_divider[3]; /* line that divides tabs from the main region */
unsigned char theme_col_tab_highlight[3];
unsigned char theme_col_tab_highlight_inactive[3];
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 3a24625c36c..5fe6fd119aa 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -534,33 +534,18 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
if (but->rnapoin.id.data) {
/* this could get its own 'BUT_GET_...' type */
- PointerRNA *ptr = &but->rnapoin;
- PropertyRNA *prop = but->rnaprop;
- ID *id = ptr->id.data;
-
- char *id_path;
- char *data_path = NULL;
/* never fails */
- id_path = RNA_path_full_ID_py(id);
-
- if (ptr->data && prop) {
- data_path = RNA_path_from_ID_to_property(ptr, prop);
- }
+ char *id_path;
- if (data_path) {
- const char *data_delim = (data_path[0] == '[') ? "" : ".";
- BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]),
- "%s%s%s", /* no need to translate */
- id_path, data_delim, data_path);
- MEM_freeN(data_path);
+ if (but->rnaprop) {
+ id_path = RNA_path_full_property_py_ex(&but->rnapoin, but->rnaprop, but->rnaindex, true);
}
- else if (prop) {
- /* can't find the path. be explicit in our ignorance "..." */
- BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]),
- "%s ... %s", /* no need to translate */
- id_path, rna_prop.strinfo ? rna_prop.strinfo : RNA_property_identifier(prop));
+ else {
+ id_path = RNA_path_full_struct_py(&but->rnapoin);
}
+
+ BLI_strncat_utf8(data->lines[data->totline], id_path, sizeof(data->lines[0]));
MEM_freeN(id_path);
data->format[data->totline].style = UI_TIP_STYLE_MONO;
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 25a187c43ad..6ce29242cbb 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -410,6 +410,11 @@ void uiStyleInit(void)
BLF_unload_id(font->blf_id);
}
+ if (blf_mono_font != -1) {
+ BLF_unload_id(blf_mono_font);
+ blf_mono_font = -1;
+ }
+
font = U.uifonts.first;
/* default builtin */
@@ -498,14 +503,17 @@ void uiStyleInit(void)
}
/* reload */
- BLF_unload("monospace");
- blf_mono_font = -1;
blf_mono_font_render = -1;
#endif
/* XXX, this should be moved into a style, but for now best only load the monospaced font once. */
- if (blf_mono_font == -1)
+ BLI_assert(blf_mono_font == -1);
+ if (U.font_path_ui_mono[0]) {
+ blf_mono_font = BLF_load_unique(U.font_path_ui_mono);
+ }
+ if (blf_mono_font == -1) {
blf_mono_font = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size);
+ }
BLF_size(blf_mono_font, 12 * U.pixelsize, 72);
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 294aa6ce2ac..5fb1afac34f 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -492,6 +492,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->transition; break;
case TH_SEQ_META:
cp = ts->meta; break;
+ case TH_SEQ_TEXT:
+ cp = ts->text_strip; break;
case TH_SEQ_PREVIEW:
cp = ts->preview_back; break;
@@ -1062,6 +1064,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tseq.effect, 169, 84, 124, 255);
rgba_char_args_set(btheme->tseq.transition, 162, 95, 111, 255);
rgba_char_args_set(btheme->tseq.meta, 109, 145, 131, 255);
+ rgba_char_args_set(btheme->tseq.text_strip, 162, 151, 0, 255);
rgba_char_args_set(btheme->tseq.preview_back, 0, 0, 0, 255);
rgba_char_args_set(btheme->tseq.grid, 64, 64, 64, 255);
@@ -2668,6 +2671,13 @@ void init_userdef_do_versions(void)
}
}
+ if (!USER_VERSION_ATLEAST(276, 3)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_set(btheme->tseq.text_strip, 162, 151, 0, 255);
+ }
+ }
+
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 0017cd3c2ae..e5b4e661773 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -53,11 +53,13 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "GPU_buffers.h"
+
/* own include */
/* copy the face flags, most importantly selection from the mesh to the final derived mesh,
* use in object mode when selecting faces (while painting) */
-void paintface_flush_flags(Object *ob)
+void paintface_flush_flags(Object *ob, short flag)
{
Mesh *me = BKE_mesh_from_object(ob);
DerivedMesh *dm = ob->derivedFinal;
@@ -66,6 +68,8 @@ void paintface_flush_flags(Object *ob)
int totpoly;
int i;
+ BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0);
+
if (me == NULL)
return;
@@ -73,7 +77,9 @@ void paintface_flush_flags(Object *ob)
/* we could call this directly in all areas that change selection,
* since this could become slow for realtime updates (circle-select for eg) */
- BKE_mesh_flush_select_from_polys(me);
+ if (flag & SELECT) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
if (dm == NULL)
return;
@@ -90,9 +96,15 @@ void paintface_flush_flags(Object *ob)
/* Copy flags onto the final derived poly from the original mesh poly */
mp_orig = me->mpoly + index_array[i];
polys[i].flag = mp_orig->flag;
+
}
}
}
+
+ if (flag & ME_HIDE) {
+ /* draw-object caches hidden faces, force re-generation T46867 */
+ GPU_drawobject_free(dm);
+ }
}
void paintface_hide(Object *ob, const bool unselected)
@@ -122,7 +134,7 @@ void paintface_hide(Object *ob, const bool unselected)
BKE_mesh_flush_hidden_from_polys(me);
- paintface_flush_flags(ob);
+ paintface_flush_flags(ob, SELECT | ME_HIDE);
}
@@ -147,7 +159,7 @@ void paintface_reveal(Object *ob)
BKE_mesh_flush_hidden_from_polys(me);
- paintface_flush_flags(ob);
+ paintface_flush_flags(ob, SELECT | ME_HIDE);
}
/* Set tface seams based on edge data, uses hash table to find seam edges. */
@@ -241,7 +253,7 @@ void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const b
select_linked_tfaces_with_seams(me, index, select);
- paintface_flush_flags(ob);
+ paintface_flush_flags(ob, SELECT);
}
void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags)
@@ -287,7 +299,7 @@ void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags)
}
if (flush_flags) {
- paintface_flush_flags(ob);
+ paintface_flush_flags(ob, SELECT);
}
}
@@ -376,7 +388,7 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b
/* image window redraw */
- paintface_flush_flags(ob);
+ paintface_flush_flags(ob, SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
return true;
@@ -454,7 +466,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten
glReadBuffer(GL_BACK);
#endif
- paintface_flush_flags(vc->obact);
+ paintface_flush_flags(vc->obact, SELECT);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index e073a255f73..2a9f9c830f4 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -29,6 +29,7 @@
* \ingroup edmesh
*/
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -49,6 +50,7 @@
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_object.h"
+#include "ED_uvedit.h"
#include "mesh_intern.h" /* own include */
@@ -105,16 +107,21 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
bool enter_editmode;
bool was_editmode;
unsigned int layer;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Plane"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
- "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4",
- 1, 1, RNA_float_get(op->ptr, "radius"), mat))
+ "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4 calc_uvs=%b",
+ 1, 1, RNA_float_get(op->ptr, "radius"), mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
@@ -139,6 +146,7 @@ void MESH_OT_primitive_plane_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ED_object_add_unit_props(ot);
+ ED_object_add_mesh_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -150,16 +158,21 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
bool enter_editmode;
bool was_editmode;
unsigned int layer;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cube"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
- "create_cube matrix=%m4 size=%f",
- mat, RNA_float_get(op->ptr, "radius") * 2.0f))
+ "create_cube matrix=%m4 size=%f calc_uvs=%b",
+ mat, RNA_float_get(op->ptr, "radius") * 2.0f, calc_uvs))
{
return OPERATOR_CANCELLED;
}
@@ -185,6 +198,7 @@ void MESH_OT_primitive_cube_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ED_object_add_unit_props(ot);
+ ED_object_add_mesh_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -203,6 +217,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
int cap_end, cap_tri;
unsigned int layer;
bool was_editmode;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
cap_end = RNA_enum_get(op->ptr, "fill_type");
cap_tri = (cap_end == 2);
@@ -212,11 +227,15 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Circle"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
- "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b matrix=%m4",
+ "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius"),
- cap_end, cap_tri, mat))
+ cap_end, cap_tri, mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
@@ -245,6 +264,7 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot)
ED_object_add_unit_props(ot);
RNA_def_enum(ot->srna, "fill_type", fill_type_items, 0, "Fill Type", "");
+ ED_object_add_mesh_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -259,20 +279,25 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
const bool cap_end = (end_fill_type != 0);
const bool cap_tri = (end_fill_type == 2);
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cylinder"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
- "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4",
+ "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "vertices"),
RNA_float_get(op->ptr, "radius"),
RNA_float_get(op->ptr, "radius"),
cap_end, cap_tri,
- RNA_float_get(op->ptr, "depth"), mat))
+ RNA_float_get(op->ptr, "depth"), mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
@@ -284,8 +309,6 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Add Cylinder";
ot->description = "Construct a cylinder mesh";
@@ -301,10 +324,10 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
/* props */
RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
ED_object_add_unit_props(ot);
- prop = RNA_def_float(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_float_distance(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Cap Fill Type", "");
+ ED_object_add_mesh_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -319,17 +342,22 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
const bool cap_end = (end_fill_type != 0);
const bool cap_tri = (end_fill_type == 2);
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cone"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
- "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4",
+ "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1"),
- RNA_float_get(op->ptr, "radius2"), cap_end, cap_tri, RNA_float_get(op->ptr, "depth"), mat))
+ RNA_float_get(op->ptr, "radius2"), cap_end, cap_tri, RNA_float_get(op->ptr, "depth"), mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
@@ -341,8 +369,6 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
void MESH_OT_primitive_cone_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Add Cone";
ot->description = "Construct a conic mesh";
@@ -357,14 +383,12 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot)
/* props */
RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
- prop = RNA_def_float(ot->srna, "radius1", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 1", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_float_distance(ot->srna, "radius1", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 1", "", 0.001, 100.00);
+ RNA_def_float_distance(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.001, 100.00);
+ RNA_def_float_distance(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Base Fill Type", "");
+ ED_object_add_mesh_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -376,18 +400,23 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
bool enter_editmode;
bool was_editmode;
unsigned int layer;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Grid"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
- "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4",
+ "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "x_subdivisions"),
RNA_int_get(op->ptr, "y_subdivisions"),
- RNA_float_get(op->ptr, "radius"), mat))
+ RNA_float_get(op->ptr, "radius"), mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
@@ -418,6 +447,7 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot)
RNA_def_int(ot->srna, "y_subdivisions", 10, 2, MESH_ADD_VERTS_MAXI, "Y Subdivisions", "", 2, 1000);
ED_object_add_unit_props(ot);
+ ED_object_add_mesh_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -479,17 +509,22 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
bool enter_editmode;
bool was_editmode;
unsigned int layer;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Sphere"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
- "create_uvsphere u_segments=%i v_segments=%i diameter=%f matrix=%m4",
+ "create_uvsphere u_segments=%i v_segments=%i diameter=%f matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "segments"), RNA_int_get(op->ptr, "ring_count"),
- RNA_float_get(op->ptr, "size"), mat))
+ RNA_float_get(op->ptr, "size"), mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
@@ -501,8 +536,6 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Add UV Sphere";
ot->description = "Construct a UV sphere mesh";
@@ -518,9 +551,9 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
/* props */
RNA_def_int(ot->srna, "segments", 32, 3, MESH_ADD_VERTS_MAXI / 100, "Segments", "", 3, 500);
RNA_def_int(ot->srna, "ring_count", 16, 3, MESH_ADD_VERTS_MAXI / 100, "Rings", "", 3, 500);
- prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_float_distance(ot->srna, "size", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
+ ED_object_add_mesh_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -532,17 +565,22 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
bool enter_editmode;
bool was_editmode;
unsigned int layer;
+ const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Icosphere"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
+ if (calc_uvs) {
+ ED_mesh_uv_texture_ensure(obedit->data, NULL);
+ }
+
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
- "create_icosphere subdivisions=%i diameter=%f matrix=%m4",
+ "create_icosphere subdivisions=%i diameter=%f matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "subdivisions"),
- RNA_float_get(op->ptr, "size"), mat))
+ RNA_float_get(op->ptr, "size"), mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
@@ -554,8 +592,6 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Add Ico Sphere";
ot->description = "Construct an Icosphere mesh";
@@ -570,8 +606,8 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
/* props */
RNA_def_int(ot->srna, "subdivisions", 2, 1, 10, "Subdivisions", "", 1, 8);
- prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001f, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_float_distance(ot->srna, "size", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001f, 100.00);
+ ED_object_add_mesh_props(ot);
ED_object_add_generic_props(ot, true);
}
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index ce6856321d2..f001eadd9cd 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -259,7 +259,7 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
opdata = op->customdata;
/* initialize mouse values */
- if (!calculateTransformCenter(C, V3D_CENTROID, center_3d, opdata->mcenter)) {
+ if (!calculateTransformCenter(C, V3D_AROUND_CENTER_MEAN, center_3d, opdata->mcenter)) {
/* in this case the tool will likely do nothing,
* ideally this will never happen and should be checked for above */
opdata->mcenter[0] = opdata->mcenter[1] = 0;
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index a020fed0835..161159d0be0 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -326,7 +326,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 1e12f, "Offset", "", 0.0f, 100.0f);
+ RNA_def_float_distance(ot->srna, "offset", 2.0f, 0.0f, 1e12f, "Offset", "", 0.0f, 100.0f);
RNA_def_int(ot->srna, "steps", 10, 0, 1000000, "Steps", "", 0, 180);
}
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index c037b0c6b0f..937547c99ef 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -280,7 +280,7 @@ static int edbm_inset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
opdata = op->customdata;
/* initialize mouse values */
- if (!calculateTransformCenter(C, V3D_CENTROID, center_3d, opdata->mcenter)) {
+ if (!calculateTransformCenter(C, V3D_AROUND_CENTER_MEAN, center_3d, opdata->mcenter)) {
/* in this case the tool will likely do nothing,
* ideally this will never happen and should be checked for above */
opdata->mcenter[0] = opdata->mcenter[1] = 0;
@@ -507,10 +507,10 @@ void MESH_OT_inset(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry");
RNA_def_boolean(ot->srna, "use_edge_rail", false, "Edge Rail", "Inset the region along existing edges");
- prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, 1e12f, "Thickness", "", 0.0f, 10.0f);
+ prop = RNA_def_float_distance(ot->srna, "thickness", 0.01f, 0.0f, 1e12f, "Thickness", "", 0.0f, 10.0f);
/* use 1 rather then 10 for max else dragging the button moves too far */
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
- prop = RNA_def_float(ot->srna, "depth", 0.0f, -1e12f, 1e12f, "Depth", "", -10.0f, 10.0f);
+ prop = RNA_def_float_distance(ot->srna, "depth", 0.0f, -1e12f, 1e12f, "Depth", "", -10.0f, 10.0f);
RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.01, 4);
RNA_def_boolean(ot->srna, "use_outset", false, "Outset", "Outset rather than inset");
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index e2e4638254b..fcba1e5ec72 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -49,10 +49,6 @@
#include "tools/bmesh_intersect.h"
-
-/* -------------------------------------------------------------------- */
-/* Cut intersections into geometry */
-
/**
* Compare selected with its self.
*/
@@ -75,6 +71,23 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
return -1;
}
else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+/**
+ * A flipped version of #bm_face_isect_pair
+ * use for boolean 'difference', which depends on order.
+ */
+static int bm_face_isect_pair_swap(BMFace *f, void *UNUSED(user_data))
+{
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return -1;
+ }
+ else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
return 0;
}
else {
@@ -82,19 +95,41 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
}
}
+/**
+ * Use for intersect and boolean.
+ */
+static void edbm_intersect_select(BMEditMesh *em)
+{
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+
+ if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
+ }
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+
+}
+
+/* -------------------------------------------------------------------- */
+/* Cut intersections into geometry */
+
+/** \name Simple Intersect (self-intersect)
+ * \{
+ */
+
enum {
ISECT_SEL = 0,
ISECT_SEL_UNSEL = 1,
};
-static EnumPropertyItem isect_mode_items[] = {
- {ISECT_SEL, "SELECT", 0, "Self Intersect",
- "Self intersect selected faces"},
- {ISECT_SEL_UNSEL, "SELECT_UNSELECT", 0, "Selected/Unselected",
- "Intersect selected with unselected faces"},
- {0, NULL, 0, NULL, NULL}
-};
-
static int edbm_intersect_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -123,26 +158,13 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
bm,
em->looptris, em->tottri,
test_fn, NULL,
- use_self, use_separate,
+ use_self, use_separate, true, true,
+ -1,
eps);
if (has_isect) {
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
-
- if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
- BMIter iter;
- BMEdge *e;
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BM_edge_select_set(bm, e, true);
- }
- }
- }
-
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
+ edbm_intersect_select(em);
}
else {
BKE_report(op->reports, RPT_WARNING, "No intersections found");
@@ -153,6 +175,14 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
void MESH_OT_intersect(struct wmOperatorType *ot)
{
+ static EnumPropertyItem isect_mode_items[] = {
+ {ISECT_SEL, "SELECT", 0, "Self Intersect",
+ "Self intersect selected faces"},
+ {ISECT_SEL_UNSEL, "SELECT_UNSELECT", 0, "Selected/Unselected",
+ "Intersect selected with unselected faces"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
/* identifiers */
ot->name = "Intersect";
ot->description = "Cut an intersection into faces";
@@ -165,16 +195,89 @@ void MESH_OT_intersect(struct wmOperatorType *ot)
/* props */
RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", "");
RNA_def_boolean(ot->srna, "use_separate", true, "Separate", "");
- RNA_def_float(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
+ RNA_def_float_distance(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Face Split by Edges */
+/* Boolean (a kind of intersect) */
+
+/** \name Boolean Intersect
+ *
+ * \note internally this is nearly exactly the same as 'MESH_OT_intersect',
+ * however from a user perspective they are quite different, so expose as different tools.
+ *
+ * \{
+ */
+
+static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ const int boolean_operation = RNA_enum_get(op->ptr, "operation");
+ bool use_swap = RNA_boolean_get(op->ptr, "use_swap");
+ const float eps = RNA_float_get(op->ptr, "threshold");
+ int (*test_fn)(BMFace *, void *);
+ bool has_isect;
+
+ test_fn = use_swap ? bm_face_isect_pair_swap : bm_face_isect_pair;
+
+ has_isect = BM_mesh_intersect(
+ bm,
+ em->looptris, em->tottri,
+ test_fn, NULL,
+ false, false, true, true,
+ boolean_operation,
+ eps);
+
+
+ if (has_isect) {
+ edbm_intersect_select(em);
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "No intersections found");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_intersect_boolean(struct wmOperatorType *ot)
+{
+ static EnumPropertyItem isect_boolean_operation_items[] = {
+ {BMESH_ISECT_BOOLEAN_ISECT, "INTERSECT", 0, "Intersect", ""},
+ {BMESH_ISECT_BOOLEAN_UNION, "UNION", 0, "Union", ""},
+ {BMESH_ISECT_BOOLEAN_DIFFERENCE, "DIFFERENCE", 0, "Difference", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Boolean Intersect";
+ ot->description = "Cut solid geometry from selected to unselected";
+ ot->idname = "MESH_OT_intersect_boolean";
+
+ /* api callbacks */
+ ot->exec = edbm_intersect_boolean_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* props */
+ RNA_def_enum(ot->srna, "operation", isect_boolean_operation_items, BMESH_ISECT_BOOLEAN_DIFFERENCE, "Boolean", "");
+ RNA_def_boolean(ot->srna, "use_swap", false, "Swap", "Use with difference intersection to swap which side is kept");
+ RNA_def_float_distance(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+/* -------------------------------------------------------------------- */
+/* Face Split by Edges */
/** \name Face/Edge Split
* \{ */
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index baf1fa8ed4d..818526ab772 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -3341,43 +3341,6 @@ void MESH_OT_knife_tool(wmOperatorType *ot)
/* Knife tool as a utility function
* that can be used for internal slicing operations */
-/**
- * Return a point inside the face.
- *
- * tessellation here seems way overkill,
- * but without this its very hard to know of a point is inside the face
- */
-static void edbm_mesh_knife_face_point(BMFace *f, float r_cent[3])
-{
- const int tottri = f->len - 2;
- BMLoop **loops = BLI_array_alloca(loops, f->len);
- unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
- int j;
- int j_best = 0; /* use as fallback when unset */
- float area_best = -1.0f;
-
- BM_face_calc_tessellation(f, loops, index);
-
- for (j = 0; j < tottri; j++) {
- const float *p1 = loops[index[j][0]]->v->co;
- const float *p2 = loops[index[j][1]]->v->co;
- const float *p3 = loops[index[j][2]]->v->co;
- float area;
-
- area = area_squared_tri_v3(p1, p2, p3);
- if (area > area_best) {
- j_best = j;
- area_best = area;
- }
- }
-
- mid_v3_v3v3v3(
- r_cent,
- loops[index[j_best][0]]->v->co,
- loops[index[j_best][1]]->v->co,
- loops[index[j_best][2]]->v->co);
-}
-
static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
{
LinkNode *p = polys;
@@ -3495,7 +3458,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
BMIter fiter;
BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
float cent[3], cent_ss[2];
- edbm_mesh_knife_face_point(f, cent);
+ BM_face_calc_point_in_face(f, cent);
knife_project_v2(kcd, cent, cent_ss);
if (edbm_mesh_knife_point_isect(polys, cent_ss)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
@@ -3531,7 +3494,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
if (found) {
float cent[3], cent_ss[2];
- edbm_mesh_knife_face_point(f, cent);
+ BM_face_calc_point_in_face(f, cent);
knife_project_v2(kcd, cent, cent_ss);
if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, &mats, (BMElem *)f)) &&
edbm_mesh_knife_point_isect(polys, cent_ss))
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 23deffe5b0d..d6933aa88d8 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -1259,7 +1259,7 @@ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
while ((f = *(faces++))) {
BM_face_select_set(bm, f, true);
}
- MEM_freeN(faces);
+ MEM_freeN(link->data);
MEM_freeN(link);
changed = true;
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 3cd3b7ec86e..b240836b153 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -306,7 +306,10 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
float mval[2], co_proj[3], no_dummy[3];
float dist_px_dummy;
if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- if (snapObjectsContext(C, mval, &dist_px_dummy, co_proj, no_dummy, SNAP_NOT_OBEDIT)) {
+ if (snapObjectsContext(
+ C, mval, SNAP_NOT_OBEDIT,
+ co_proj, no_dummy, &dist_px_dummy))
+ {
mul_v3_m4v3(eve->co, obedit->imat, co_proj);
}
}
@@ -2357,8 +2360,8 @@ void MESH_OT_remove_doubles(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "threshold", 1e-4f, 1e-6f, 50.0f, "Merge Distance",
- "Minimum distance between elements to merge", 1e-5f, 10.0f);
+ RNA_def_float_distance(ot->srna, "threshold", 1e-4f, 1e-6f, 50.0f, "Merge Distance",
+ "Minimum distance between elements to merge", 1e-5f, 10.0f);
RNA_def_boolean(ot->srna, "use_unselected", false, "Unselected", "Merge selected to other unselected vertices");
}
@@ -2608,7 +2611,7 @@ void MESH_OT_solidify(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_float(ot->srna, "thickness", 0.01f, -1e4f, 1e4f, "Thickness", "", -10.0f, 10.0f);
+ prop = RNA_def_float_distance(ot->srna, "thickness", 0.01f, -1e4f, 1e4f, "Thickness", "", -10.0f, 10.0f);
RNA_def_property_ui_range(prop, -10.0, 10.0, 0.1, 4);
}
@@ -3783,7 +3786,6 @@ static int edbm_poke_face_exec(bContext *C, wmOperator *op)
void MESH_OT_poke(wmOperatorType *ot)
{
-
static EnumPropertyItem poke_center_modes[] = {
{BMOP_POKE_MEAN_WEIGHTED, "MEAN_WEIGHTED", 0, "Weighted Mean", "Weighted Mean Face Center"},
{BMOP_POKE_MEAN, "MEAN", 0, "Mean", "Mean Face Center"},
@@ -3803,7 +3805,7 @@ void MESH_OT_poke(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "offset", 0.0f, -1e3f, 1e3f, "Poke Offset", "Poke Offset", -1.0f, 1.0f);
+ RNA_def_float_distance(ot->srna, "offset", 0.0f, -1e3f, 1e3f, "Poke Offset", "Poke Offset", -1.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry");
RNA_def_enum(ot->srna, "center_mode", poke_center_modes, BMOP_POKE_MEAN_WEIGHTED,
"Poke Center", "Poke Face Center Calculation");
@@ -4255,8 +4257,8 @@ void MESH_OT_dissolve_degenerate(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "threshold", 1e-4f, 1e-6f, 50.0f, "Merge Distance",
- "Minimum distance between elements to merge", 1e-5f, 10.0f);
+ RNA_def_float_distance(ot->srna, "threshold", 1e-4f, 1e-6f, 50.0f, "Merge Distance",
+ "Minimum distance between elements to merge", 1e-5f, 10.0f);
}
@@ -5252,10 +5254,10 @@ void MESH_OT_wireframe(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_even_offset", true, "Offset Even", "Scale the offset to give more even thickness");
RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry");
RNA_def_boolean(ot->srna, "use_replace", true, "Replace", "Remove original faces");
- prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, 1e4f, "Thickness", "", 0.0f, 10.0f);
+ prop = RNA_def_float_distance(ot->srna, "thickness", 0.01f, 0.0f, 1e4f, "Thickness", "", 0.0f, 10.0f);
/* use 1 rather then 10 for max else dragging the button moves too far */
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
- RNA_def_float(ot->srna, "offset", 0.01f, 0.0f, 1e4f, "Offset", "", 0.0f, 10.0f);
+ RNA_def_float_distance(ot->srna, "offset", 0.01f, 0.0f, 1e4f, "Offset", "", 0.0f, 10.0f);
RNA_def_boolean(ot->srna, "use_crease", false, "Crease", "Crease hub edges for improved subsurf");
prop = RNA_def_float(ot->srna, "crease_weight", 0.01f, 0.0f, 1e3f, "Crease weight", "", 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2);
@@ -5587,7 +5589,7 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "direction", rna_enum_symmetrize_direction_items,
BMO_SYMMETRIZE_NEGATIVE_X,
"Direction", "Which sides to copy from and to");
- RNA_def_float(ot->srna, "threshold", 0.05f, 0.0f, 10.0f, "Threshold", "", 1e-4f, 1.0f);
+ RNA_def_float_distance(ot->srna, "threshold", 0.05f, 0.0f, 10.0f, "Threshold", "", 1e-4f, 1.0f);
RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_center", true, "Center", "Snap mid verts to the axis center");
}
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 148398fca5c..4a9be4978b1 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -382,7 +382,7 @@ void EDBM_mesh_make(ToolSettings *ts, Object *ob)
/**
* \warning This can invalidate the #DerivedMesh cache of other objects (for linked duplicates).
- * Most callers should run #DAG_id_tag_update on \a ob, see: T46738.
+ * Most callers should run #DAG_id_tag_update on \a ob->data, see: T46738, T46913
*/
void EDBM_mesh_load(Object *ob)
{
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index c56465f570a..3b018eadb2d 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -109,6 +109,7 @@ void MESH_OT_inset(struct wmOperatorType *ot);
/* *** editmesh_intersect.c *** */
void MESH_OT_intersect(struct wmOperatorType *ot);
+void MESH_OT_intersect_boolean(struct wmOperatorType *ot);
void MESH_OT_face_split_by_edges(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 9718e63f012..e24dfa3d123 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -179,6 +179,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_inset);
WM_operatortype_append(MESH_OT_offset_edge_loops);
WM_operatortype_append(MESH_OT_intersect);
+ WM_operatortype_append(MESH_OT_intersect_boolean);
WM_operatortype_append(MESH_OT_face_split_by_edges);
WM_operatortype_append(MESH_OT_poke);
WM_operatortype_append(MESH_OT_wireframe);
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 31497f69d71..f05414fbfa6 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -665,6 +665,11 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
/* ************* undo for MetaBalls ************* */
+typedef struct UndoMBall {
+ ListBase editelems;
+ int lastelem_index;
+} UndoMBall;
+
/* free all MetaElems from ListBase */
static void freeMetaElemlist(ListBase *lb)
{
@@ -678,58 +683,61 @@ static void freeMetaElemlist(ListBase *lb)
}
-static void undoMball_to_editMball(void *lbu, void *lbe, void *UNUSED(obe))
+static void undoMball_to_editMball(void *umb_v, void *mb_v, void *UNUSED(obdata))
{
- ListBase *lb = lbu;
- ListBase *editelems = lbe;
- MetaElem *ml, *newml;
-
- freeMetaElemlist(editelems);
+ MetaBall *mb = mb_v;
+ UndoMBall *umb = umb_v;
+
+ freeMetaElemlist(mb->editelems);
+ mb->lastelem = NULL;
/* copy 'undo' MetaElems to 'edit' MetaElems */
- ml = lb->first;
- while (ml) {
- newml = MEM_dupallocN(ml);
- BLI_addtail(editelems, newml);
- ml = ml->next;
+ int index = 0;
+ for (MetaElem *ml_undo = umb->editelems.first; ml_undo; ml_undo = ml_undo->next, index += 1) {
+ MetaElem *ml_edit = MEM_dupallocN(ml_undo);
+ BLI_addtail(mb->editelems, ml_edit);
+ if (index == umb->lastelem_index) {
+ mb->lastelem = ml_edit;
+ }
}
}
-static void *editMball_to_undoMball(void *lbe, void *UNUSED(obe))
+static void *editMball_to_undoMball(void *mb_v, void *UNUSED(obdata))
{
- ListBase *editelems = lbe;
- ListBase *lb;
- MetaElem *ml, *newml;
+ MetaBall *mb = mb_v;
+ UndoMBall *umb;
/* allocate memory for undo ListBase */
- lb = MEM_callocN(sizeof(ListBase), "listbase undo");
+ umb = MEM_callocN(sizeof(UndoMBall), __func__);
+ umb->lastelem_index = -1;
/* copy contents of current ListBase to the undo ListBase */
- ml = editelems->first;
- while (ml) {
- newml = MEM_dupallocN(ml);
- BLI_addtail(lb, newml);
- ml = ml->next;
+ int index = 0;
+ for (MetaElem *ml_edit = mb->editelems->first; ml_edit; ml_edit = ml_edit->next, index += 1) {
+ MetaElem *ml_undo = MEM_dupallocN(ml_edit);
+ BLI_addtail(&umb->editelems, ml_undo);
+ if (ml_edit == mb->lastelem) {
+ umb->lastelem_index = index;
+ }
}
- return lb;
+ return umb;
}
/* free undo ListBase of MetaElems */
-static void free_undoMball(void *lbv)
+static void free_undoMball(void *umb_v)
{
- ListBase *lb = lbv;
+ UndoMBall *umb = umb_v;
- freeMetaElemlist(lb);
- MEM_freeN(lb);
+ freeMetaElemlist(&umb->editelems);
+ MEM_freeN(umb);
}
-static ListBase *metaball_get_editelems(Object *ob)
+static MetaBall *metaball_get_obdata(Object *ob)
{
if (ob && ob->type == OB_MBALL) {
- struct MetaBall *mb = (struct MetaBall *)ob->data;
- return mb->editelems;
+ return ob->data;
}
return NULL;
}
@@ -738,7 +746,7 @@ static ListBase *metaball_get_editelems(Object *ob)
static void *get_data(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
- return metaball_get_editelems(obedit);
+ return metaball_get_obdata(obedit);
}
/* this is undo system for MetaBalls */
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 7ef6638e753..7650be941d4 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -261,10 +261,7 @@ static void view_align_update(struct Main *UNUSED(main), struct Scene *UNUSED(sc
void ED_object_add_unit_props(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_float_distance(ot->srna, "radius", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
}
void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
@@ -293,6 +290,11 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+void ED_object_add_mesh_props(wmOperatorType *ot)
+{
+ RNA_def_boolean(ot->srna, "calc_uvs", false, "Generate UVs", "Generate a default UV map");
+}
+
bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view_align_axis,
float loc[3], float rot[3],
bool *enter_editmode, unsigned int *layer, bool *is_view_aligned)
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 6a1220bbbaa..492b6724f93 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -318,7 +318,7 @@ static bool object_hook_index_array(Scene *scene, Object *obedit,
EDBM_mesh_load(obedit);
EDBM_mesh_make(scene->toolsettings, obedit);
- DAG_id_tag_update(&obedit->id, 0);
+ DAG_id_tag_update(obedit->data, 0);
em = me->edit_btmesh;
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index c638714a951..a1f59166c81 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -138,6 +138,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
EDBM_mesh_load(obedit);
EDBM_mesh_make(scene->toolsettings, obedit);
+ DAG_id_tag_update(obedit->data, 0);
+
em = me->edit_btmesh;
EDBM_mesh_normals_update(em);
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index ac1f13ee59c..8f00c0eb467 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -718,7 +718,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
mul_m4_v3(obedit->imat, cent);
}
else {
- if (around == V3D_CENTROID) {
+ if (around == V3D_AROUND_CENTER_MEAN) {
if (em->bm->totvert) {
const float total_div = 1.0f / (float)em->bm->totvert;
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
@@ -825,9 +825,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
Mesh *me = ob->data;
if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (centermode == ORIGIN_TO_CENTER_OF_MASS) { BKE_mesh_center_centroid(me, cent); }
- else if (around == V3D_CENTROID) { BKE_mesh_center_median(me, cent); }
- else { BKE_mesh_center_bounds(me, cent); }
+ else if (centermode == ORIGIN_TO_CENTER_OF_MASS) { BKE_mesh_center_centroid(me, cent); }
+ else if (around == V3D_AROUND_CENTER_MEAN) { BKE_mesh_center_median(me, cent); }
+ else { BKE_mesh_center_bounds(me, cent); }
negate_v3_v3(cent_neg, cent);
BKE_mesh_translate(me, cent_neg, 1);
@@ -839,9 +839,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (around == V3D_CENTROID) { BKE_curve_center_median(cu, cent); }
- else { BKE_curve_center_bounds(cu, cent); }
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
+ else if (around == V3D_AROUND_CENTER_MEAN) { BKE_curve_center_median(cu, cent); }
+ else { BKE_curve_center_bounds(cu, cent); }
/* don't allow Z change if curve is 2D */
if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D))
@@ -921,9 +921,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_MBALL) {
MetaBall *mb = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (around == V3D_CENTROID) { BKE_mball_center_median(mb, cent); }
- else { BKE_mball_center_bounds(mb, cent); }
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
+ else if (around == V3D_AROUND_CENTER_MEAN) { BKE_mball_center_median(mb, cent); }
+ else { BKE_mball_center_bounds(mb, cent); }
negate_v3_v3(cent_neg, cent);
BKE_mball_translate(mb, cent_neg);
@@ -942,9 +942,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_LATTICE) {
Lattice *lt = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (around == V3D_CENTROID) { BKE_lattice_center_median(lt, cent); }
- else { BKE_lattice_center_bounds(lt, cent); }
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
+ else if (around == V3D_AROUND_CENTER_MEAN) { BKE_lattice_center_median(lt, cent); }
+ else { BKE_lattice_center_bounds(lt, cent); }
negate_v3_v3(cent_neg, cent);
BKE_lattice_translate(lt, cent_neg, 1);
@@ -1044,8 +1044,8 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
};
static EnumPropertyItem prop_set_bounds_types[] = {
- {V3D_CENTROID, "MEDIAN", 0, "Median Center", ""},
- {V3D_CENTER, "BOUNDS", 0, "Bounds Center", ""},
+ {V3D_AROUND_CENTER_MEAN, "MEDIAN", 0, "Median Center", ""},
+ {V3D_AROUND_CENTER_BOUNDS, "BOUNDS", 0, "Bounds Center", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1064,5 +1064,5 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
- RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_CENTROID, "Center", "");
+ RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEAN, "Center", "");
}
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index f44374b1d7b..a7038ac53cc 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -311,7 +311,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
- BKE_image_backup_render(scene, ima);
+ BKE_image_backup_render(scene, ima, true);
/* cleanup sequencer caches before starting user triggered render.
* otherwise, invalidated cache entries can make their way into
@@ -956,7 +956,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* get a render result image, and make sure it is empty */
ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
- BKE_image_backup_render(rj->scene, ima);
+ BKE_image_backup_render(rj->scene, ima, true);
rj->image = ima;
/* setup new render */
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 2e9ccc520d9..5268afae270 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -69,9 +69,9 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_compositing.h"
+#include "GPU_framebuffer.h"
#include "render_intern.h"
@@ -559,7 +559,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
/* create image and image user */
oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
BKE_image_signal(oglrender->ima, NULL, IMA_SIGNAL_FREE);
- BKE_image_backup_render(oglrender->scene, oglrender->ima);
+ BKE_image_backup_render(oglrender->scene, oglrender->ima, true);
oglrender->iuser.scene = scene;
oglrender->iuser.ok = 1;
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index fd65d81baad..91eea6f8248 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -45,10 +45,11 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
-
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
+#include "GPU_basic_shader.h"
+
#include "UI_interface.h"
#ifndef GL_CLAMP_TO_EDGE
@@ -136,7 +137,7 @@ const GLubyte stipple_diag_stripes_neg[128] = {
const GLubyte stipple_checker_8px[128] = {
255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
- 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
+ 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
@@ -179,32 +180,20 @@ void fdrawbezier(float vec[4][3])
void fdrawline(float x1, float y1, float x2, float y2)
{
- float v[2];
-
- glBegin(GL_LINE_STRIP);
- v[0] = x1; v[1] = y1;
- glVertex2fv(v);
- v[0] = x2; v[1] = y2;
- glVertex2fv(v);
+ glBegin(GL_LINES);
+ glVertex2f(x1, y1);
+ glVertex2f(x2, y2);
glEnd();
}
void fdrawbox(float x1, float y1, float x2, float y2)
{
- float v[2];
+ glBegin(GL_LINE_LOOP);
- glBegin(GL_LINE_STRIP);
-
- v[0] = x1; v[1] = y1;
- glVertex2fv(v);
- v[0] = x1; v[1] = y2;
- glVertex2fv(v);
- v[0] = x2; v[1] = y2;
- glVertex2fv(v);
- v[0] = x2; v[1] = y1;
- glVertex2fv(v);
- v[0] = x1; v[1] = y1;
- glVertex2fv(v);
+ glVertex2f(x1, y1);
+ glVertex2f(x1, y2);
+ glVertex2f(x2, y2);
+ glVertex2f(x2, y1);
glEnd();
}
@@ -225,13 +214,9 @@ void fdrawcheckerboard(float x1, float y1, float x2, float y2)
void sdrawline(int x1, int y1, int x2, int y2)
{
- int v[2];
-
- glBegin(GL_LINE_STRIP);
- v[0] = x1; v[1] = y1;
- glVertex2iv(v);
- v[0] = x2; v[1] = y2;
- glVertex2iv(v);
+ glBegin(GL_LINES);
+ glVertex2i(x1, y1);
+ glVertex2i(x2, y2);
glEnd();
}
@@ -247,13 +232,9 @@ void sdrawline(int x1, int y1, int x2, int y2)
static void sdrawtripoints(int x1, int y1, int x2, int y2)
{
- int v[2];
- v[0] = x1; v[1] = y1;
- glVertex2iv(v);
- v[0] = x1; v[1] = y2;
- glVertex2iv(v);
- v[0] = x2; v[1] = y1;
- glVertex2iv(v);
+ glVertex2i(x1, y1);
+ glVertex2i(x1, y2);
+ glVertex2i(x2, y1);
}
void sdrawtri(int x1, int y1, int x2, int y2)
@@ -273,20 +254,12 @@ void sdrawtrifill(int x1, int y1, int x2, int y2)
void sdrawbox(int x1, int y1, int x2, int y2)
{
- int v[2];
-
- glBegin(GL_LINE_STRIP);
+ glBegin(GL_LINE_LOOP);
- v[0] = x1; v[1] = y1;
- glVertex2iv(v);
- v[0] = x1; v[1] = y2;
- glVertex2iv(v);
- v[0] = x2; v[1] = y2;
- glVertex2iv(v);
- v[0] = x2; v[1] = y1;
- glVertex2iv(v);
- v[0] = x1; v[1] = y1;
- glVertex2iv(v);
+ glVertex2i(x1, y1);
+ glVertex2i(x1, y2);
+ glVertex2i(x2, y2);
+ glVertex2i(x2, y1);
glEnd();
}
@@ -436,13 +409,6 @@ void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments
glEnd();
}
-int glaGetOneInteger(int param)
-{
- GLint i;
- glGetIntegerv(param, &i);
- return i;
-}
-
float glaGetOneFloat(int param)
{
GLfloat v;
@@ -474,7 +440,6 @@ static int get_cached_work_texture(int *r_w, int *r_h)
static int tex_h = 256;
if (texid == -1) {
- GLint ltexid = glaGetOneInteger(GL_TEXTURE_2D);
unsigned char *tbuf;
glGenTextures(1, (GLuint *)&texid);
@@ -488,7 +453,7 @@ static int get_cached_work_texture(int *r_w, int *r_h)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tbuf);
MEM_freeN(tbuf);
- glBindTexture(GL_TEXTURE_2D, ltexid);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
*r_w = tex_w;
@@ -501,8 +466,6 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
unsigned char *uc_rect = (unsigned char *) rect;
const float *f_rect = (float *)rect;
float xzoom = glaGetOneFloat(GL_ZOOM_X), yzoom = glaGetOneFloat(GL_ZOOM_Y);
- int ltexid = glaGetOneInteger(GL_TEXTURE_2D);
- int lrowlength = glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
int subpart_x, subpart_y, tex_w, tex_h;
int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
int texid = get_cached_work_texture(&tex_w, &tex_h);
@@ -511,7 +474,6 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
/* Specify the color outside this function, and tex will modulate it.
* This is useful for changing alpha without using glPixelTransferf()
*/
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
glBindTexture(GL_TEXTURE_2D, texid);
@@ -520,9 +482,10 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
-#ifdef __APPLE__
+#if defined(__APPLE__) && 0
+ /* [merwin] disable this workaround and see if anyone is affected. If not scrap it! Also at end of this function */
/* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */
- glPixelZoom(1.f, 1.f);
+ glPixelZoom(1.0f, 1.0f);
#endif
/* setup seamless 2=on, 0=off */
@@ -600,7 +563,7 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
}
- glEnable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glBegin(GL_QUADS);
glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
@@ -614,15 +577,14 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
glEnd();
- glDisable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
}
- glBindTexture(GL_TEXTURE_2D, ltexid);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, lrowlength);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-#ifdef __APPLE__
+#if defined(__APPLE__) && 0
/* workaround for os x 10.5/10.6 driver bug (above) */
glPixelZoom(xzoom, yzoom);
#endif
@@ -676,8 +638,6 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
draw_h = min_ii(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom));
if (draw_w > 0 && draw_h > 0) {
- int old_row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH);
-
/* Don't use safe RasterPos (slower) if we can avoid it. */
if (rast_x >= 0 && rast_y >= 0) {
glRasterPos2f(rast_x, rast_y);
@@ -708,7 +668,7 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
}
}
- glPixelStorei(GL_UNPACK_ROW_LENGTH, old_row_length);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
}
@@ -1096,7 +1056,6 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
}
if (ok) {
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f(1.0, 1.0, 1.0, 1.0);
if (ibuf->rect_float) {
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index f8dda23bc9b..7806038b313 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -4231,6 +4231,8 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(ED_OT_undo_push);
WM_operatortype_append(ED_OT_redo);
WM_operatortype_append(ED_OT_undo_history);
+
+ WM_operatortype_append(ED_OT_flush_edits);
}
@@ -4302,14 +4304,13 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "SCREEN_OT_area_options", RIGHTMOUSE, KM_PRESS, 0, 0);
-
- WM_keymap_add_item(keymap, "SCREEN_OT_header", F9KEY, KM_PRESS, KM_ALT, 0);
-
+
/* Header Editing ------------------------------------------------ */
keymap = WM_keymap_find(keyconf, "Header", 0, 0);
-
+
+ WM_keymap_add_item(keymap, "SCREEN_OT_header", F9KEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_header_toolbox", RIGHTMOUSE, KM_PRESS, 0, 0);
-
+
/* Screen General ------------------------------------------------ */
keymap = WM_keymap_find(keyconf, "Screen", 0, 0);
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 1a12ec3e6bc..f57255aff61 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -59,6 +59,8 @@
#include "ED_view3d.h"
+#include "GPU_basic_shader.h"
+
#include "UI_resources.h"
#include "paint_intern.h"
@@ -149,7 +151,6 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
int size;
int j;
int refresh;
- GLenum format = col ? GL_RGBA : GL_ALPHA;
OverlayControlFlags invalid = (primary) ? (overlay_flags & PAINT_INVALID_OVERLAY_TEXTURE_PRIMARY) :
(overlay_flags & PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY);
@@ -321,8 +322,11 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
glBindTexture(GL_TEXTURE_2D, target->overlay_texture);
if (refresh) {
+ GLenum format = col ? GL_RGBA : GL_ALPHA;
+ GLenum internalformat = col ? GL_RGBA8 : GL_ALPHA8;
+
if (!init || (target->old_col != col)) {
- glTexImage2D(GL_TEXTURE_2D, 0, format, size, size, 0, format, GL_UNSIGNED_BYTE, buffer);
+ glTexImage2D(GL_TEXTURE_2D, 0, internalformat, size, size, 0, format, GL_UNSIGNED_BYTE, buffer);
}
else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, format, GL_UNSIGNED_BYTE, buffer);
@@ -334,9 +338,8 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
target->old_col = col;
}
- glEnable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -448,7 +451,7 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
if (refresh) {
if (!init) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
}
else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
@@ -458,9 +461,8 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
MEM_freeN(buffer);
}
- glEnable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -534,8 +536,7 @@ static bool sculpt_get_brush_geometry(
mouse[0] = x;
mouse[1] = y;
- if (vc->obact->sculpt && vc->obact->sculpt->pbvh)
- {
+ if (vc->obact->sculpt && vc->obact->sculpt->pbvh) {
if (!ups->stroke_active) {
hit = sculpt_stroke_get_location(C, location, mouse);
}
@@ -796,6 +797,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
}
glPopAttrib();
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 5d0b34a2e0c..b6f4600ab88 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -83,7 +83,7 @@ static SpaceLink *action_new(const bContext *C)
ar->alignment = RGN_ALIGN_BOTTOM;
/* channel list region */
- ar = MEM_callocN(sizeof(ARegion), "channel area for action");
+ ar = MEM_callocN(sizeof(ARegion), "channel region for action");
BLI_addtail(&saction->regionbase, ar);
ar->regiontype = RGN_TYPE_CHANNELS;
ar->alignment = RGN_ALIGN_LEFT;
@@ -92,8 +92,8 @@ static SpaceLink *action_new(const bContext *C)
ar->v2d.scroll = V2D_SCROLL_BOTTOM;
ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for action");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for action");
BLI_addtail(&saction->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -149,7 +149,7 @@ static SpaceLink *action_duplicate(SpaceLink *sl)
/* add handlers, stuff you only do once or on area/region changes */
-static void action_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void action_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -160,7 +160,7 @@ static void action_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void action_main_area_draw(const bContext *C, ARegion *ar)
+static void action_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceAction *saction = CTX_wm_space_action(C);
@@ -218,7 +218,7 @@ static void action_main_area_draw(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
+static void action_channel_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -232,7 +232,7 @@ static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void action_channel_area_draw(const bContext *C, ARegion *ar)
+static void action_channel_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
bAnimContext ac;
@@ -257,17 +257,17 @@ static void action_channel_area_draw(const bContext *C, ARegion *ar)
/* add handlers, stuff you only do once or on area/region changes */
-static void action_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void action_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void action_header_area_draw(const bContext *C, ARegion *ar)
+static void action_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void action_channel_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -306,7 +306,7 @@ static void action_channel_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
}
}
-static void action_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -457,7 +457,7 @@ static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
}
}
-static void action_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
// SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
@@ -543,9 +543,9 @@ void ED_spacetype_action(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = action_main_area_init;
- art->draw = action_main_area_draw;
- art->listener = action_main_area_listener;
+ art->init = action_main_region_init;
+ art->draw = action_main_region_draw;
+ art->listener = action_main_region_listener;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -556,9 +556,9 @@ void ED_spacetype_action(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->init = action_header_area_init;
- art->draw = action_header_area_draw;
- art->listener = action_header_area_listener;
+ art->init = action_header_region_init;
+ art->draw = action_header_region_draw;
+ art->listener = action_header_region_listener;
BLI_addhead(&st->regiontypes, art);
@@ -568,9 +568,9 @@ void ED_spacetype_action(void)
art->prefsizex = 200;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
- art->init = action_channel_area_init;
- art->draw = action_channel_area_draw;
- art->listener = action_channel_area_listener;
+ art->init = action_channel_region_init;
+ art->draw = action_channel_region_draw;
+ art->listener = action_channel_region_listener;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index e28ad686d2a..126a27c36cb 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -66,15 +66,15 @@ static SpaceLink *buttons_new(const bContext *UNUSED(C))
ar->alignment = RGN_ALIGN_TOP;
#if 0
- /* context area */
- ar = MEM_callocN(sizeof(ARegion), "context area for buts");
+ /* context region */
+ ar = MEM_callocN(sizeof(ARegion), "context region for buts");
BLI_addtail(&sbuts->regionbase, ar);
ar->regiontype = RGN_TYPE_CHANNELS;
ar->alignment = RGN_ALIGN_TOP;
#endif
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for buts");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for buts");
BLI_addtail(&sbuts->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -123,7 +123,7 @@ static SpaceLink *buttons_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void buttons_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void buttons_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -133,7 +133,7 @@ static void buttons_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void buttons_main_area_draw(const bContext *C, ARegion *ar)
+static void buttons_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceButs *sbuts = CTX_wm_space_buts(C);
@@ -189,12 +189,12 @@ static void buttons_keymap(struct wmKeyConfig *keyconf)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void buttons_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void buttons_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void buttons_header_area_draw(const bContext *C, ARegion *ar)
+static void buttons_header_region_draw(const bContext *C, ARegion *ar)
{
SpaceButs *sbuts = CTX_wm_space_buts(C);
@@ -410,8 +410,8 @@ void ED_spacetype_buttons(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = buttons_main_area_init;
- art->draw = buttons_main_area_draw;
+ art->init = buttons_main_region_init;
+ art->draw = buttons_main_region_draw;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -423,8 +423,8 @@ void ED_spacetype_buttons(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->init = buttons_header_area_init;
- art->draw = buttons_header_area_draw;
+ art->init = buttons_header_region_init;
+ art->draw = buttons_header_region_draw;
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index ba5bf7449d2..e00ebc14ee0 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -58,6 +58,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_basic_shader.h"
+
#include "WM_types.h"
#include "UI_interface.h"
@@ -1063,7 +1065,7 @@ static void draw_plane_marker_image(Scene *scene,
}
if (display_buffer) {
- GLuint texid, last_texid;
+ GLuint texid;
float frame_corners[4][2] = {{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
@@ -1083,11 +1085,9 @@ static void draw_plane_marker_image(Scene *scene,
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity);
- last_texid = glaGetOneInteger(GL_TEXTURE_2D);
- glEnable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glGenTextures(1, (GLuint *)&texid);
glBindTexture(GL_TEXTURE_2D, texid);
@@ -1110,8 +1110,8 @@ static void draw_plane_marker_image(Scene *scene,
glPopMatrix();
- glBindTexture(GL_TEXTURE_2D, last_texid);
- glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
if (transparent) {
glDisable(GL_BLEND);
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index c1db31a26db..7a66599655f 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -1534,7 +1534,7 @@ static int clip_set_2d_cursor_exec(bContext *C, wmOperator *op)
bool show_cursor = false;
show_cursor |= sclip->mode == SC_MODE_MASKEDIT;
- show_cursor |= sclip->around == V3D_CURSOR;
+ show_cursor |= sclip->around == V3D_AROUND_CURSOR;
if (!show_cursor) {
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index f119fe23c12..e1d4e4fabc5 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -250,7 +250,7 @@ static SpaceLink *clip_new(const bContext *C)
sc->zoom = 1.0f;
sc->path_length = 20;
sc->scopes.track_preview_height = 120;
- sc->around = V3D_LOCAL;
+ sc->around = V3D_AROUND_LOCAL_ORIGINS;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for clip");
@@ -296,8 +296,8 @@ static SpaceLink *clip_new(const bContext *C)
BLI_addtail(&sc->regionbase, ar);
init_preview_region(C, ar);
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for clip");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for clip");
BLI_addtail(&sc->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -1132,7 +1132,7 @@ static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void clip_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void clip_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -1150,7 +1150,7 @@ static void clip_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void clip_main_area_draw(const bContext *C, ARegion *ar)
+static void clip_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceClip *sc = CTX_wm_space_clip(C);
@@ -1213,7 +1213,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
}
show_cursor |= sc->mode == SC_MODE_MASKEDIT;
- show_cursor |= sc->around == V3D_CURSOR;
+ show_cursor |= sc->around == V3D_AROUND_CURSOR;
if (show_cursor) {
glPushMatrix();
@@ -1241,7 +1241,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
}
}
-static void clip_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void clip_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -1256,7 +1256,7 @@ static void clip_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AR
/****************** preview region ******************/
-static void clip_preview_area_init(wmWindowManager *wm, ARegion *ar)
+static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -1273,7 +1273,7 @@ static void clip_preview_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void graph_area_draw(const bContext *C, ARegion *ar)
+static void graph_region_draw(const bContext *C, ARegion *ar)
{
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
@@ -1304,7 +1304,7 @@ static void graph_area_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
}
-static void dopesheet_area_draw(const bContext *C, ARegion *ar)
+static void dopesheet_region_draw(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
SpaceClip *sc = CTX_wm_space_clip(C);
@@ -1342,23 +1342,23 @@ static void dopesheet_area_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
}
-static void clip_preview_area_draw(const bContext *C, ARegion *ar)
+static void clip_preview_region_draw(const bContext *C, ARegion *ar)
{
SpaceClip *sc = CTX_wm_space_clip(C);
if (sc->view == SC_VIEW_GRAPH)
- graph_area_draw(C, ar);
+ graph_region_draw(C, ar);
else if (sc->view == SC_VIEW_DOPESHEET)
- dopesheet_area_draw(C, ar);
+ dopesheet_region_draw(C, ar);
}
-static void clip_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void clip_preview_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
{
}
/****************** channels region ******************/
-static void clip_channels_area_init(wmWindowManager *wm, ARegion *ar)
+static void clip_channels_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -1371,7 +1371,7 @@ static void clip_channels_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void clip_channels_area_draw(const bContext *C, ARegion *ar)
+static void clip_channels_region_draw(const bContext *C, ARegion *ar)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -1393,24 +1393,24 @@ static void clip_channels_area_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
}
-static void clip_channels_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void clip_channels_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
{
}
/****************** header region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void clip_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void clip_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void clip_header_area_draw(const bContext *C, ARegion *ar)
+static void clip_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void clip_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void clip_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -1433,7 +1433,7 @@ static void clip_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
/****************** tools region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void clip_tools_area_init(wmWindowManager *wm, ARegion *ar)
+static void clip_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -1443,14 +1443,14 @@ static void clip_tools_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void clip_tools_area_draw(const bContext *C, ARegion *ar)
+static void clip_tools_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
/****************** tool properties region ******************/
-static void clip_props_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void clip_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -1476,7 +1476,7 @@ static void clip_props_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), A
/****************** properties region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void clip_properties_area_init(wmWindowManager *wm, ARegion *ar)
+static void clip_properties_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -1486,7 +1486,7 @@ static void clip_properties_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void clip_properties_area_draw(const bContext *C, ARegion *ar)
+static void clip_properties_region_draw(const bContext *C, ARegion *ar)
{
SpaceClip *sc = CTX_wm_space_clip(C);
@@ -1495,7 +1495,7 @@ static void clip_properties_area_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void clip_properties_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void clip_properties_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -1535,9 +1535,9 @@ void ED_spacetype_clip(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype clip region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = clip_main_area_init;
- art->draw = clip_main_area_draw;
- art->listener = clip_main_area_listener;
+ art->init = clip_main_region_init;
+ art->draw = clip_main_region_draw;
+ art->listener = clip_main_region_listener;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_GPENCIL;
BLI_addhead(&st->regiontypes, art);
@@ -1546,9 +1546,9 @@ void ED_spacetype_clip(void)
art = MEM_callocN(sizeof(ARegionType), "spacetype clip region preview");
art->regionid = RGN_TYPE_PREVIEW;
art->prefsizey = 240;
- art->init = clip_preview_area_init;
- art->draw = clip_preview_area_draw;
- art->listener = clip_preview_area_listener;
+ art->init = clip_preview_region_init;
+ art->draw = clip_preview_region_draw;
+ art->listener = clip_preview_region_listener;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
BLI_addhead(&st->regiontypes, art);
@@ -1558,9 +1558,9 @@ void ED_spacetype_clip(void)
art->regionid = RGN_TYPE_UI;
art->prefsizex = UI_COMPACT_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
- art->init = clip_properties_area_init;
- art->draw = clip_properties_area_draw;
- art->listener = clip_properties_area_listener;
+ art->init = clip_properties_region_init;
+ art->draw = clip_properties_region_draw;
+ art->listener = clip_properties_region_listener;
BLI_addhead(&st->regiontypes, art);
ED_clip_buttons_register(art);
@@ -1569,9 +1569,9 @@ void ED_spacetype_clip(void)
art->regionid = RGN_TYPE_TOOLS;
art->prefsizex = UI_COMPACT_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
- art->listener = clip_props_area_listener;
- art->init = clip_tools_area_init;
- art->draw = clip_tools_area_draw;
+ art->listener = clip_props_region_listener;
+ art->init = clip_tools_region_init;
+ art->draw = clip_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
@@ -1581,9 +1581,9 @@ void ED_spacetype_clip(void)
art->prefsizex = 0;
art->prefsizey = 120;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
- art->listener = clip_props_area_listener;
- art->init = clip_tools_area_init;
- art->draw = clip_tools_area_draw;
+ art->listener = clip_props_region_listener;
+ art->init = clip_tools_region_init;
+ art->draw = clip_tools_region_draw;
ED_clip_tool_props_register(art);
BLI_addhead(&st->regiontypes, art);
@@ -1594,9 +1594,9 @@ void ED_spacetype_clip(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->init = clip_header_area_init;
- art->draw = clip_header_area_draw;
- art->listener = clip_header_area_listener;
+ art->init = clip_header_region_init;
+ art->draw = clip_header_region_draw;
+ art->listener = clip_header_region_listener;
BLI_addhead(&st->regiontypes, art);
@@ -1607,9 +1607,9 @@ void ED_spacetype_clip(void)
art->regionid = RGN_TYPE_CHANNELS;
art->prefsizex = UI_COMPACT_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
- art->listener = clip_channels_area_listener;
- art->init = clip_channels_area_init;
- art->draw = clip_channels_area_draw;
+ art->listener = clip_channels_region_listener;
+ art->init = clip_channels_region_init;
+ art->draw = clip_channels_region_draw;
BLI_addhead(&st->regiontypes, art);
}
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index d206ce4699e..6396b390ca0 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -68,21 +68,6 @@ static void console_line_color(unsigned char fg[3], int type)
}
}
-typedef struct ConsoleDrawContext {
- int cwidth;
- int lheight;
- int console_width;
- int ymin, ymax;
-#if 0 /* used by textview, may use later */
- int winx;
- int *xy; // [2]
- int *sel; // [2]
- int *pos_pick; /* bottom of view == 0, top of file == combine chars, end of line is lower then start. */
- int *mval; // [2]
- int draw;
-#endif
-} ConsoleDrawContext;
-
void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_dummy)
{
/* fake the edit line being in the scroll buffer */
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index a592f35f629..cf235d0fc02 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -74,8 +74,8 @@ static SpaceLink *console_new(const bContext *UNUSED(C))
ar->alignment = RGN_ALIGN_BOTTOM;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for text");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for text");
BLI_addtail(&sconsole->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -129,7 +129,7 @@ static SpaceLink *console_duplicate(SpaceLink *sl)
/* add handlers, stuff you only do once or on area/region changes */
-static void console_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void console_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
ListBase *lb;
@@ -219,7 +219,7 @@ static void console_dropboxes(void)
/* ************* end drop *********** */
-static void console_main_area_draw(const bContext *C, ARegion *ar)
+static void console_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceConsole *sc = CTX_wm_space_console(C);
@@ -362,17 +362,17 @@ static void console_keymap(struct wmKeyConfig *keyconf)
/****************** header region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void console_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void console_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void console_header_area_draw(const bContext *C, ARegion *ar)
+static void console_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void console_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void console_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
// SpaceInfo *sinfo = sa->spacedata.first;
@@ -408,10 +408,10 @@ void ED_spacetype_console(void)
art->regionid = RGN_TYPE_WINDOW;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
- art->init = console_main_area_init;
- art->draw = console_main_area_draw;
+ art->init = console_main_region_init;
+ art->draw = console_main_region_draw;
art->cursor = console_cursor;
- art->listener = console_main_area_listener;
+ art->listener = console_main_region_listener;
@@ -423,8 +423,8 @@ void ED_spacetype_console(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->init = console_header_area_init;
- art->draw = console_header_area_draw;
+ art->init = console_header_region_init;
+ art->draw = console_header_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 7f405e8ad16..85d92d07222 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -2444,6 +2444,7 @@ static void filelist_readjob_do(
bool is_lib = do_lib;
char *subdir;
+ char rel_subdir[FILE_MAX_LIBEXTRA];
int recursion_level;
bool skip_currpar;
@@ -2454,6 +2455,14 @@ static void filelist_readjob_do(
BLI_stack_discard(todo_dirs);
+ /* ARRRG! We have to be very careful *not to use* common BLI_path_util helpers over entry->relpath itself
+ * (nor any path containing it), since it may actually be a datablock name inside .blend file,
+ * which can have slashes and backslashes! See T46827.
+ * Note that in the end, this means we 'cache' valid relative subdir once here, this is actually better. */
+ BLI_strncpy(rel_subdir, subdir, sizeof(rel_subdir));
+ BLI_cleanup_dir(root, rel_subdir);
+ BLI_path_rel(rel_subdir, root);
+
if (do_lib) {
nbr_entries = filelist_readjob_list_lib(subdir, &entries, skip_currpar);
}
@@ -2463,8 +2472,7 @@ static void filelist_readjob_do(
}
for (entry = entries.first; entry; entry = entry->next) {
- BLI_join_dirfile(dir, sizeof(dir), subdir, entry->relpath);
- BLI_cleanup_file(root, dir);
+ BLI_join_dirfile(dir, sizeof(dir), rel_subdir, entry->relpath);
/* Generate our entry uuid. Abusing uuid as an uint32, shall be more than enough here,
* things would crash way before we overflow that counter!
@@ -2473,10 +2481,9 @@ static void filelist_readjob_do(
* remain consistent about threading! */
*((uint32_t *)entry->uuid) = atomic_add_uint32((uint32_t *)filelist->filelist_intern.curr_uuid, 1);
- BLI_path_rel(dir, root);
/* Only thing we change in direntry here, so we need to free it first. */
MEM_freeN(entry->relpath);
- entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//' added by BLI_path_rel */
+ entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//' added by BLI_path_rel to rel_subdir */
entry->name = BLI_strdup(fileentry_uiname(root, entry->relpath, entry->typeflag, dir));
/* Here we decide whether current filedirentry is to be listed too, or not. */
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 3202164edbd..e77f545fbc0 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -82,25 +82,25 @@ static SpaceLink *file_new(const bContext *UNUSED(C))
ar->alignment = RGN_ALIGN_TOP;
/* Tools region */
- ar = MEM_callocN(sizeof(ARegion), "tools area for file");
+ ar = MEM_callocN(sizeof(ARegion), "tools region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOLS;
ar->alignment = RGN_ALIGN_LEFT;
/* Tool props (aka operator) region */
- ar = MEM_callocN(sizeof(ARegion), "tool props area for file");
+ ar = MEM_callocN(sizeof(ARegion), "tool props region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOL_PROPS;
ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
/* ui list region */
- ar = MEM_callocN(sizeof(ARegion), "ui area for file");
+ ar = MEM_callocN(sizeof(ARegion), "ui region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_UI;
ar->alignment = RGN_ALIGN_TOP;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for file");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
@@ -281,7 +281,7 @@ static void file_refresh(const bContext *C, ScrArea *sa)
sfile->layout->dirty = true;
}
- /* Might be called with NULL sa, see file_main_area_draw() below. */
+ /* Might be called with NULL sa, see file_main_region_draw() below. */
if (sa && BKE_area_find_region_type(sa, RGN_TYPE_TOOLS) == NULL) {
/* Create TOOLS/TOOL_PROPS regions. */
file_tools_region(sa);
@@ -319,7 +319,7 @@ static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void file_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void file_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -333,7 +333,7 @@ static void file_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void file_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void file_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -350,7 +350,7 @@ static void file_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AR
}
}
-static void file_main_area_draw(const bContext *C, ARegion *ar)
+static void file_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -435,7 +435,6 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_bookmark_cleanup);
WM_operatortype_append(FILE_OT_bookmark_move);
WM_operatortype_append(FILE_OT_reset_recent);
- WM_operatortype_append(FILE_OT_hidedot);
WM_operatortype_append(FILE_OT_filenum);
WM_operatortype_append(FILE_OT_directory_new);
WM_operatortype_append(FILE_OT_delete);
@@ -448,24 +447,36 @@ static void file_operatortypes(void)
static void file_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMapItem *kmi;
- /* keys for all areas */
+ /* keys for all regions */
wmKeyMap *keymap = WM_keymap_find(keyconf, "File Browser", SPACE_FILE, 0);
- WM_keymap_add_item(keymap, "FILE_OT_bookmark_toggle", TKEY, KM_PRESS, 0, 0);
+
+ /* More common 'fliebrowser-like navigation' shortcuts. */
+ WM_keymap_add_item(keymap, "FILE_OT_parent", UPARROWKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_previous", LEFTARROWKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_next", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_refresh", RKEY, KM_PRESS, 0, 0);
+
WM_keymap_add_item(keymap, "FILE_OT_parent", PKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "FILE_OT_bookmark_add", BKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "FILE_OT_hidedot", HKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_previous", BACKSPACEKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_next", BACKSPACEKEY, KM_PRESS, KM_SHIFT, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", HKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.params.show_hidden");
WM_keymap_add_item(keymap, "FILE_OT_directory_new", IKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_delete", DELKEY, KM_PRESS, 0, 0);
+
WM_keymap_verify_item(keymap, "FILE_OT_smoothscroll", TIMER1, KM_ANY, KM_ANY, 0);
- /* keys for main area */
+ WM_keymap_add_item(keymap, "FILE_OT_bookmark_toggle", TKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "FILE_OT_bookmark_add", BKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* keys for main region */
keymap = WM_keymap_find(keyconf, "File Browser Main", SPACE_FILE, 0);
kmi = WM_keymap_add_item(keymap, "FILE_OT_execute", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
RNA_boolean_set(kmi->ptr, "need_active", true);
+ WM_keymap_add_item(keymap, "FILE_OT_refresh", PADPERIOD, KM_PRESS, 0, 0);
+
/* left mouse selects and opens */
WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, 0, 0);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0);
@@ -533,7 +544,6 @@ static void file_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "FILE_OT_next", BUTTON5MOUSE, KM_CLICK, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "FILE_OT_refresh", PADPERIOD, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_select_border", BKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_select_border", EVT_TWEAK_L, KM_ANY, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
@@ -552,7 +562,7 @@ static void file_keymap(struct wmKeyConfig *keyconf)
RNA_int_set(kmi->ptr, "increment", -100);
- /* keys for button area (top) */
+ /* keys for button region (top) */
keymap = WM_keymap_find(keyconf, "File Browser Buttons", SPACE_FILE, 0);
kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, 0, 0);
RNA_int_set(kmi->ptr, "increment", 1);
@@ -569,7 +579,7 @@ static void file_keymap(struct wmKeyConfig *keyconf)
}
-static void file_tools_area_init(wmWindowManager *wm, ARegion *ar)
+static void file_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -581,12 +591,12 @@ static void file_tools_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void file_tools_area_draw(const bContext *C, ARegion *ar)
+static void file_tools_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
-static void file_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void file_tools_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
{
#if 0
/* context changes */
@@ -597,7 +607,7 @@ static void file_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), A
}
/* add handlers, stuff you only do once or on area/region changes */
-static void file_header_area_init(wmWindowManager *wm, ARegion *ar)
+static void file_header_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -607,13 +617,13 @@ static void file_header_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void file_header_area_draw(const bContext *C, ARegion *ar)
+static void file_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void file_ui_area_init(wmWindowManager *wm, ARegion *ar)
+static void file_ui_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -627,7 +637,7 @@ static void file_ui_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void file_ui_area_draw(const bContext *C, ARegion *ar)
+static void file_ui_region_draw(const bContext *C, ARegion *ar)
{
float col[3];
/* clear */
@@ -648,7 +658,7 @@ static void file_ui_area_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
}
-static void file_ui_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void file_ui_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -709,9 +719,9 @@ void ED_spacetype_file(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = file_main_area_init;
- art->draw = file_main_area_draw;
- art->listener = file_main_area_listener;
+ art->init = file_main_region_init;
+ art->draw = file_main_region_draw;
+ art->listener = file_main_region_listener;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
BLI_addhead(&st->regiontypes, art);
@@ -720,9 +730,9 @@ void ED_spacetype_file(void)
art->regionid = RGN_TYPE_HEADER;
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->init = file_header_area_init;
- art->draw = file_header_area_draw;
- // art->listener = file_header_area_listener;
+ art->init = file_header_region_init;
+ art->draw = file_header_region_draw;
+ // art->listener = file_header_region_listener;
BLI_addhead(&st->regiontypes, art);
/* regions: ui */
@@ -730,9 +740,9 @@ void ED_spacetype_file(void)
art->regionid = RGN_TYPE_UI;
art->prefsizey = 60;
art->keymapflag = ED_KEYMAP_UI;
- art->listener = file_ui_area_listener;
- art->init = file_ui_area_init;
- art->draw = file_ui_area_draw;
+ art->listener = file_ui_region_listener;
+ art->init = file_ui_region_init;
+ art->draw = file_ui_region_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: channels (directories) */
@@ -741,9 +751,9 @@ void ED_spacetype_file(void)
art->prefsizex = 240;
art->prefsizey = 60;
art->keymapflag = ED_KEYMAP_UI;
- art->listener = file_tools_area_listener;
- art->init = file_tools_area_init;
- art->draw = file_tools_area_draw;
+ art->listener = file_tools_region_listener;
+ art->init = file_tools_region_init;
+ art->draw = file_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: tool properties */
@@ -752,9 +762,9 @@ void ED_spacetype_file(void)
art->prefsizex = 0;
art->prefsizey = 360;
art->keymapflag = ED_KEYMAP_UI;
- art->listener = file_tools_area_listener;
- art->init = file_tools_area_init;
- art->draw = file_tools_area_draw;
+ art->listener = file_tools_region_listener;
+ art->init = file_tools_region_init;
+ art->draw = file_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
file_panels_register(art);
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 91e11ac4b1e..51865ebcf90 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -964,7 +964,7 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
glDisable(GL_BLEND);
}
-/* This is called twice from space_graph.c -> graph_main_area_draw()
+/* This is called twice from space_graph.c -> graph_main_region_draw()
* Unselected then selected F-Curves are drawn so that they do not occlude each other.
*/
void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid *grid, short sel)
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 200523f591d..9f3bfe6b533 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -119,7 +119,7 @@ static SpaceLink *graph_new(const bContext *C)
ar->alignment = RGN_ALIGN_BOTTOM;
/* channels */
- ar = MEM_callocN(sizeof(ARegion), "channels area for graphedit");
+ ar = MEM_callocN(sizeof(ARegion), "channels region for graphedit");
BLI_addtail(&sipo->regionbase, ar);
ar->regiontype = RGN_TYPE_CHANNELS;
@@ -128,15 +128,15 @@ static SpaceLink *graph_new(const bContext *C)
ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
/* ui buttons */
- ar = MEM_callocN(sizeof(ARegion), "buttons area for graphedit");
+ ar = MEM_callocN(sizeof(ARegion), "buttons region for graphedit");
BLI_addtail(&sipo->regionbase, ar);
ar->regiontype = RGN_TYPE_UI;
ar->alignment = RGN_ALIGN_RIGHT;
ar->flag = RGN_FLAG_HIDDEN;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for graphedit");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for graphedit");
BLI_addtail(&sipo->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -208,7 +208,7 @@ static SpaceLink *graph_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void graph_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void graph_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -221,7 +221,7 @@ static void graph_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void graph_main_area_draw(const bContext *C, ARegion *ar)
+static void graph_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceIpo *sipo = CTX_wm_space_graph(C);
@@ -340,7 +340,7 @@ static void graph_main_area_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
}
-static void graph_channel_area_init(wmWindowManager *wm, ARegion *ar)
+static void graph_channel_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -359,7 +359,7 @@ static void graph_channel_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void graph_channel_area_draw(const bContext *C, ARegion *ar)
+static void graph_channel_region_draw(const bContext *C, ARegion *ar)
{
bAnimContext ac;
View2D *v2d = &ar->v2d;
@@ -388,18 +388,18 @@ static void graph_channel_area_draw(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void graph_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void graph_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void graph_header_area_draw(const bContext *C, ARegion *ar)
+static void graph_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void graph_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -409,7 +409,7 @@ static void graph_buttons_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void graph_buttons_area_draw(const bContext *C, ARegion *ar)
+static void graph_buttons_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
@@ -659,8 +659,8 @@ void ED_spacetype_ipo(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = graph_main_area_init;
- art->draw = graph_main_area_draw;
+ art->init = graph_main_region_init;
+ art->draw = graph_main_region_draw;
art->listener = graph_region_listener;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
@@ -672,8 +672,8 @@ void ED_spacetype_ipo(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
art->listener = graph_region_listener;
- art->init = graph_header_area_init;
- art->draw = graph_header_area_draw;
+ art->init = graph_header_region_init;
+ art->draw = graph_header_region_draw;
BLI_addhead(&st->regiontypes, art);
@@ -683,8 +683,8 @@ void ED_spacetype_ipo(void)
art->prefsizex = 200 + V2D_SCROLL_WIDTH; /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
art->listener = graph_region_listener;
- art->init = graph_channel_area_init;
- art->draw = graph_channel_area_draw;
+ art->init = graph_channel_region_init;
+ art->draw = graph_channel_region_draw;
BLI_addhead(&st->regiontypes, art);
@@ -694,8 +694,8 @@ void ED_spacetype_ipo(void)
art->prefsizex = 200;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = graph_region_listener;
- art->init = graph_buttons_area_init;
- art->draw = graph_buttons_area_draw;
+ art->init = graph_buttons_region_init;
+ art->draw = graph_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 80d6858ea86..ffd801d2146 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -150,7 +150,7 @@ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
/* 0: disable preview
* otherwise refresh preview
*
- * XXX if you put this back, also check XXX in image_main_area_draw() */
+ * XXX if you put this back, also check XXX in image_main_region_draw() */
* /
void image_preview_event(int event)
{
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 35a53afa550..d36ab5e10e2 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -816,7 +816,7 @@ static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scen
}
}
-/* draw main image area */
+/* draw main image region */
void draw_image_main(const bContext *C, ARegion *ar)
{
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 6eaad302180..3b57d17f9f3 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -54,7 +54,7 @@ void draw_image_grease_pencil(struct bContext *C, bool onlyv2d);
void draw_image_sample_line(struct SpaceImage *sima);
/* image_ops.c */
-int space_image_main_area_poll(struct bContext *C);
+int space_image_main_region_poll(struct bContext *C);
void IMAGE_OT_view_all(struct wmOperatorType *ot);
void IMAGE_OT_view_pan(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 9a4a3b24e24..1d11e7c6287 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -230,7 +230,7 @@ static int space_image_poll(bContext *C)
}
#endif
-int space_image_main_area_poll(bContext *C)
+int space_image_main_region_poll(bContext *C)
{
SpaceImage *sima = CTX_wm_space_image(C);
/* XXX ARegion *ar = CTX_wm_region(C); */
@@ -270,7 +270,7 @@ static int image_sample_poll(bContext *C)
return false;
}
- return space_image_main_area_poll(C);
+ return space_image_main_region_poll(C);
}
else {
return false;
@@ -401,7 +401,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot)
ot->invoke = image_view_pan_invoke;
ot->modal = image_view_pan_modal;
ot->cancel = image_view_pan_cancel;
- ot->poll = space_image_main_area_poll;
+ ot->poll = space_image_main_region_poll;
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
@@ -617,7 +617,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
ot->invoke = image_view_zoom_invoke;
ot->modal = image_view_zoom_modal;
ot->cancel = image_view_zoom_cancel;
- ot->poll = space_image_main_area_poll;
+ ot->poll = space_image_main_region_poll;
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
@@ -672,7 +672,7 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot)
/* api callbacks */
ot->invoke = image_view_ndof_invoke;
- ot->poll = space_image_main_area_poll;
+ ot->poll = space_image_main_region_poll;
/* flags */
ot->flag = OPTYPE_LOCK_BYPASS;
@@ -744,7 +744,7 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_view_all_exec;
- ot->poll = space_image_main_area_poll;
+ ot->poll = space_image_main_region_poll;
/* flags */
ot->flag = OPTYPE_LOCK_BYPASS;
@@ -808,7 +808,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
static int image_view_selected_poll(bContext *C)
{
- return (space_image_main_area_poll(C) && (ED_operator_uvedit(C) || ED_operator_mask(C)));
+ return (space_image_main_region_poll(C) && (ED_operator_uvedit(C) || ED_operator_mask(C)));
}
void IMAGE_OT_view_selected(wmOperatorType *ot)
@@ -863,7 +863,7 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
/* api callbacks */
ot->invoke = image_view_zoom_in_invoke;
ot->exec = image_view_zoom_in_exec;
- ot->poll = space_image_main_area_poll;
+ ot->poll = space_image_main_region_poll;
/* flags */
ot->flag = OPTYPE_LOCK_BYPASS;
@@ -912,7 +912,7 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
/* api callbacks */
ot->invoke = image_view_zoom_out_invoke;
ot->exec = image_view_zoom_out_exec;
- ot->poll = space_image_main_area_poll;
+ ot->poll = space_image_main_region_poll;
/* flags */
ot->flag = OPTYPE_LOCK_BYPASS;
@@ -959,7 +959,7 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_view_zoom_ratio_exec;
- ot->poll = space_image_main_area_poll;
+ ot->poll = space_image_main_region_poll;
/* flags */
ot->flag = OPTYPE_LOCK_BYPASS;
@@ -3079,7 +3079,7 @@ void IMAGE_OT_sample_line(wmOperatorType *ot)
ot->invoke = image_sample_line_invoke;
ot->modal = WM_gesture_straightline_modal;
ot->exec = image_sample_line_exec;
- ot->poll = space_image_main_area_poll;
+ ot->poll = space_image_main_region_poll;
ot->cancel = WM_gesture_straightline_cancel;
/* flags */
@@ -3322,7 +3322,7 @@ static int change_frame_poll(bContext *C)
if (G.is_rendering)
return 0;
- return space_image_main_area_poll(C);
+ return space_image_main_region_poll(C);
}
static void change_frame_apply(bContext *C, wmOperator *op)
@@ -3455,7 +3455,7 @@ void IMAGE_OT_read_renderlayers(wmOperatorType *ot)
ot->idname = "IMAGE_OT_read_renderlayers";
ot->description = "Read all the current scene's render layers from cache, as needed";
- ot->poll = space_image_main_area_poll;
+ ot->poll = space_image_main_region_poll;
ot->exec = image_read_renderlayers_exec;
/* flags */
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 97e3390f142..93c446ab3cb 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -582,7 +582,7 @@ static int image_context(const bContext *C, const char *member, bContextDataResu
/************************** main region ***************************/
/* sets up the fields of the View2D from zoom and offset */
-static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar)
+static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar)
{
Image *ima = ED_space_image(sima);
float x1, y1, w, h;
@@ -635,7 +635,7 @@ static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void image_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void image_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -670,7 +670,7 @@ static void image_main_area_init(wmWindowManager *wm, ARegion *ar)
}
-static void image_main_area_draw(const bContext *C, ARegion *ar)
+static void image_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceImage *sima = CTX_wm_space_image(C);
@@ -704,7 +704,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
sima->iuser.scene = scene;
/* we set view2d from own zoom and offset each time */
- image_main_area_set_view2d(sima, ar);
+ image_main_region_set_view2d(sima, ar);
/* we draw image in pixelspace */
draw_image_main(C, ar);
@@ -793,7 +793,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
#endif
}
-static void image_main_area_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, wmNotifier *wmn)
+static void image_main_region_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -821,7 +821,7 @@ static void image_main_area_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion *
/* *********************** buttons region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void image_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+static void image_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -832,12 +832,12 @@ static void image_buttons_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void image_buttons_area_draw(const bContext *C, ARegion *ar)
+static void image_buttons_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
-static void image_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void image_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -873,7 +873,7 @@ static void image_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
/* *********************** scopes region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void image_tools_area_init(wmWindowManager *wm, ARegion *ar)
+static void image_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -884,7 +884,7 @@ static void image_tools_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void image_tools_area_draw(const bContext *C, ARegion *ar)
+static void image_tools_region_draw(const bContext *C, ARegion *ar)
{
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
@@ -910,7 +910,7 @@ static void image_tools_area_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void image_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void image_tools_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -946,17 +946,17 @@ static void image_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
/************************* header region **************************/
/* add handlers, stuff you only do once or on area/region changes */
-static void image_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void image_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void image_header_area_draw(const bContext *C, ARegion *ar)
+static void image_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void image_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void image_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -1005,9 +1005,9 @@ void ED_spacetype_image(void)
art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
art->regionid = RGN_TYPE_WINDOW;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
- art->init = image_main_area_init;
- art->draw = image_main_area_draw;
- art->listener = image_main_area_listener;
+ art->init = image_main_region_init;
+ art->draw = image_main_region_draw;
+ art->listener = image_main_region_listener;
BLI_addhead(&st->regiontypes, art);
@@ -1016,9 +1016,9 @@ void ED_spacetype_image(void)
art->regionid = RGN_TYPE_UI;
art->prefsizex = 220; // XXX
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = image_buttons_area_listener;
- art->init = image_buttons_area_init;
- art->draw = image_buttons_area_draw;
+ art->listener = image_buttons_region_listener;
+ art->init = image_buttons_region_init;
+ art->draw = image_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
ED_uvedit_buttons_register(art);
@@ -1029,9 +1029,9 @@ void ED_spacetype_image(void)
art->regionid = RGN_TYPE_TOOLS;
art->prefsizex = 220; // XXX
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = image_tools_area_listener;
- art->init = image_tools_area_init;
- art->draw = image_tools_area_draw;
+ art->listener = image_tools_region_listener;
+ art->init = image_tools_region_init;
+ art->draw = image_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: header */
@@ -1039,9 +1039,9 @@ void ED_spacetype_image(void)
art->regionid = RGN_TYPE_HEADER;
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->listener = image_header_area_listener;
- art->init = image_header_area_init;
- art->draw = image_header_area_draw;
+ art->listener = image_header_region_listener;
+ art->init = image_header_region_init;
+ art->draw = image_header_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index aeab87e6cb5..21777fd8afa 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -77,8 +77,8 @@ static SpaceLink *info_new(const bContext *UNUSED(C))
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_BOTTOM;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for info");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for info");
BLI_addtail(&sinfo->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -123,7 +123,7 @@ static SpaceLink *info_duplicate(SpaceLink *sl)
/* add handlers, stuff you only do once or on area/region changes */
-static void info_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void info_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -145,7 +145,7 @@ static void info_textview_update_rect(const bContext *C, ARegion *ar)
UI_view2d_totRect_set(v2d, ar->winx - 1, info_textview_height(sinfo, ar, CTX_wm_reports(C)));
}
-static void info_main_area_draw(const bContext *C, ARegion *ar)
+static void info_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceInfo *sinfo = CTX_wm_space_info(C);
@@ -226,17 +226,17 @@ static void info_keymap(struct wmKeyConfig *keyconf)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void info_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void info_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void info_header_area_draw(const bContext *C, ARegion *ar)
+static void info_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void info_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void info_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
// SpaceInfo *sinfo = sa->spacedata.first;
@@ -329,9 +329,9 @@ void ED_spacetype_info(void)
art->regionid = RGN_TYPE_WINDOW;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
- art->init = info_main_area_init;
- art->draw = info_main_area_draw;
- art->listener = info_main_area_listener;
+ art->init = info_main_region_init;
+ art->draw = info_main_region_draw;
+ art->listener = info_main_region_listener;
BLI_addhead(&st->regiontypes, art);
@@ -342,8 +342,8 @@ void ED_spacetype_info(void)
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
art->listener = info_header_listener;
- art->init = info_header_area_init;
- art->draw = info_header_area_draw;
+ art->init = info_header_region_init;
+ art->draw = info_header_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index ebce13389c9..c801a736e31 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -45,13 +45,14 @@
#include "textview.h"
-static void console_font_begin(TextViewContext *sc)
+static void console_font_begin(const int font_id, const int lheight)
{
/* 0.875 is based on: 16 pixels lines get 14 pixel text */
- BLF_size(blf_mono_font, 0.875 * sc->lheight, 72);
+ BLF_size(font_id, 0.875 * lheight, 72);
}
typedef struct ConsoleDrawContext {
+ int font_id;
int cwidth;
int lheight;
int lofs; /* text vertical offset */
@@ -123,7 +124,6 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
int tot_lines; /* total number of lines for wrapping */
int *offsets; /* offsets of line beginnings for wrapping */
int y_next;
- const int mono = blf_mono_font;
str_len = console_wrap_offsets(str, str_len, cdc->console_width, &tot_lines, &offsets);
y_next = cdc->xy[1] + cdc->lheight * tot_lines;
@@ -189,8 +189,8 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
glColor3ubv(fg);
/* last part needs no clipping */
- BLF_position(mono, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
- BLF_draw_mono(mono, s, len, cdc->cwidth);
+ BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
+ BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
console_step_sel(cdc, -initial_offset);
@@ -205,8 +205,8 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
len = offsets[i] - offsets[i - 1];
s = str + offsets[i - 1];
- BLF_position(mono, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
- BLF_draw_mono(mono, s, len, cdc->cwidth);
+ BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
+ BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
console_step_sel(cdc, len);
@@ -236,8 +236,8 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
glColor3ubv(fg);
- BLF_position(mono, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
- BLF_draw_mono(mono, str, str_len, cdc->cwidth);
+ BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
+ BLF_draw_mono(cdc->font_id, str, str_len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
int isel[2];
@@ -272,9 +272,9 @@ int textview_draw(TextViewContext *tvc, const int draw, int mval[2], void **mous
int xy[2], y_prev;
int sel[2] = {-1, -1}; /* defaults disabled */
unsigned char fg[3], bg[3];
- const int mono = blf_mono_font;
+ const int font_id = blf_mono_font;
- console_font_begin(tvc);
+ console_font_begin(font_id, tvc->lheight);
xy[0] = x_orig; xy[1] = y_orig;
@@ -285,10 +285,11 @@ int textview_draw(TextViewContext *tvc, const int draw, int mval[2], void **mous
*pos_pick = 0;
/* constants for the sequencer context */
- cdc.cwidth = (int)BLF_fixed_width(mono);
+ cdc.font_id = font_id;
+ cdc.cwidth = (int)BLF_fixed_width(font_id);
assert(cdc.cwidth > 0);
cdc.lheight = tvc->lheight;
- cdc.lofs = -BLF_descender(mono);
+ cdc.lofs = -BLF_descender(font_id);
/* note, scroll bar must be already subtracted () */
cdc.console_width = (tvc->winx - (CONSOLE_DRAW_MARGIN * 2)) / cdc.cwidth;
/* avoid divide by zero on small windows */
diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c
index 34a5fee88eb..243a522011b 100644
--- a/source/blender/editors/space_logic/space_logic.c
+++ b/source/blender/editors/space_logic/space_logic.c
@@ -113,8 +113,8 @@ static SpaceLink *logic_new(const bContext *C)
ar->regiontype= RGN_TYPE_UI;
ar->alignment= RGN_ALIGN_RIGHT;
- /* main area */
- ar= MEM_callocN(sizeof(ARegion), "main area for logic");
+ /* main region */
+ ar= MEM_callocN(sizeof(ARegion), "main region for logic");
BLI_addtail(&slogic->regionbase, ar);
ar->regiontype= RGN_TYPE_WINDOW;
@@ -230,7 +230,7 @@ static int logic_context(const bContext *UNUSED(C), const char *UNUSED(member),
/* add handlers, stuff you only do once or on area/region changes */
-static void logic_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void logic_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -241,7 +241,7 @@ static void logic_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void logic_main_area_draw(const bContext *C, ARegion *ar)
+static void logic_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
// SpaceLogic *slogic= CTX_wm_space_logic(C);
@@ -270,7 +270,7 @@ static void logic_main_area_draw(const bContext *C, ARegion *ar)
/* *********************** buttons region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void logic_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+static void logic_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -280,7 +280,7 @@ static void logic_buttons_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void logic_buttons_area_draw(const bContext *C, ARegion *ar)
+static void logic_buttons_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
@@ -288,12 +288,12 @@ static void logic_buttons_area_draw(const bContext *C, ARegion *ar)
/************************* header region **************************/
/* add handlers, stuff you only do once or on area/region changes */
-static void logic_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void logic_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void logic_header_area_draw(const bContext *C, ARegion *ar)
+static void logic_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
@@ -322,8 +322,8 @@ void ED_spacetype_logic(void)
art = MEM_callocN(sizeof(ARegionType), "spacetype logic region");
art->regionid = RGN_TYPE_WINDOW;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES | ED_KEYMAP_VIEW2D;
- art->init = logic_main_area_init;
- art->draw = logic_main_area_draw;
+ art->init = logic_main_region_init;
+ art->draw = logic_main_region_draw;
art->listener = logic_listener;
BLI_addhead(&st->regiontypes, art);
@@ -334,8 +334,8 @@ void ED_spacetype_logic(void)
art->prefsizex= 220; // XXX
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = logic_listener;
- art->init = logic_buttons_area_init;
- art->draw = logic_buttons_area_draw;
+ art->init = logic_buttons_region_init;
+ art->draw = logic_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: header */
@@ -343,8 +343,8 @@ void ED_spacetype_logic(void)
art->regionid = RGN_TYPE_HEADER;
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->init = logic_header_area_init;
- art->draw = logic_header_area_draw;
+ art->init = logic_header_region_init;
+ art->draw = logic_header_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index a0ea12b8aa0..9e73e03a664 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -268,7 +268,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
{
AnimData *adt = BKE_animdata_from_id(ale->id);
- /* button area... */
+ /* button region... */
if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
if (nlaedit_is_tweakmode_on(ac) == 0) {
/* 'push-down' action - only usable when not in TweakMode */
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 9fc7b5d6f8f..e2b36c5b5ae 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -125,15 +125,15 @@ static SpaceLink *nla_new(const bContext *C)
ar->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
/* ui buttons */
- ar = MEM_callocN(sizeof(ARegion), "buttons area for nla");
+ ar = MEM_callocN(sizeof(ARegion), "buttons region for nla");
BLI_addtail(&snla->regionbase, ar);
ar->regiontype = RGN_TYPE_UI;
ar->alignment = RGN_ALIGN_RIGHT;
ar->flag = RGN_FLAG_HIDDEN;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for nla");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for nla");
BLI_addtail(&snla->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -200,7 +200,7 @@ static SpaceLink *nla_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void nla_channel_area_init(wmWindowManager *wm, ARegion *ar)
+static void nla_channel_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -222,7 +222,7 @@ static void nla_channel_area_init(wmWindowManager *wm, ARegion *ar)
}
/* draw entirely, view changes should be handled here */
-static void nla_channel_area_draw(const bContext *C, ARegion *ar)
+static void nla_channel_region_draw(const bContext *C, ARegion *ar)
{
bAnimContext ac;
View2D *v2d = &ar->v2d;
@@ -250,7 +250,7 @@ static void nla_channel_area_draw(const bContext *C, ARegion *ar)
/* add handlers, stuff you only do once or on area/region changes */
-static void nla_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void nla_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -263,7 +263,7 @@ static void nla_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void nla_main_area_draw(const bContext *C, ARegion *ar)
+static void nla_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceNla *snla = CTX_wm_space_nla(C);
@@ -326,18 +326,18 @@ static void nla_main_area_draw(const bContext *C, ARegion *ar)
/* add handlers, stuff you only do once or on area/region changes */
-static void nla_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void nla_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void nla_header_area_draw(const bContext *C, ARegion *ar)
+static void nla_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void nla_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+static void nla_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -347,7 +347,7 @@ static void nla_buttons_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void nla_buttons_area_draw(const bContext *C, ARegion *ar)
+static void nla_buttons_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
@@ -385,7 +385,7 @@ static void nla_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegio
}
-static void nla_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -430,7 +430,7 @@ static void nla_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARe
}
}
-static void nla_channel_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void nla_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -521,9 +521,9 @@ void ED_spacetype_nla(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = nla_main_area_init;
- art->draw = nla_main_area_draw;
- art->listener = nla_main_area_listener;
+ art->init = nla_main_region_init;
+ art->draw = nla_main_region_draw;
+ art->listener = nla_main_region_listener;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -534,8 +534,8 @@ void ED_spacetype_nla(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->init = nla_header_area_init;
- art->draw = nla_header_area_draw;
+ art->init = nla_header_region_init;
+ art->draw = nla_header_region_draw;
BLI_addhead(&st->regiontypes, art);
@@ -545,9 +545,9 @@ void ED_spacetype_nla(void)
art->prefsizex = 200;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
- art->init = nla_channel_area_init;
- art->draw = nla_channel_area_draw;
- art->listener = nla_channel_area_listener;
+ art->init = nla_channel_region_init;
+ art->draw = nla_channel_region_draw;
+ art->listener = nla_channel_region_listener;
BLI_addhead(&st->regiontypes, art);
@@ -557,8 +557,8 @@ void ED_spacetype_nla(void)
art->prefsizex = 200;
art->keymapflag = ED_KEYMAP_UI;
art->listener = nla_region_listener;
- art->init = nla_buttons_area_init;
- art->draw = nla_buttons_area_draw;
+ art->init = nla_buttons_region_init;
+ art->draw = nla_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 413cdc208dd..a312888fc44 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -277,7 +277,7 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene
G.is_break = false;
#endif
- BKE_image_backup_render(scene, BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"));
+ BKE_image_backup_render(scene, BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), false);
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene_owner, "Compositing",
WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS, WM_JOB_TYPE_COMPOSITE);
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 96f0e69ca71..7788173a8ee 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -233,7 +233,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_properties", NKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_toolbar", TKEY, KM_PRESS, 0, 0);
- /* Main Area only ----------------- */
+ /* Main Region only ----------------- */
keymap = WM_keymap_find(keyconf, "Node Editor", SPACE_NODE, 0);
/* mouse select in nodes used to be both keys, but perhaps this should be reduced?
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 8a808b2ae9d..0852b6164d3 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -29,8 +29,6 @@
* \ingroup spnode
*/
-#include <ctype.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_node_types.h"
@@ -420,7 +418,6 @@ static void node_link_update_header(bContext *C, bNodeLinkDrag *UNUSED(nldrag))
#undef HEADER_LENGTH
}
-/* update link_count fields to avoid repeated link counting */
static int node_count_links(bNodeTree *ntree, bNodeSocket *sock)
{
bNodeLink *link;
@@ -434,64 +431,13 @@ static int node_count_links(bNodeTree *ntree, bNodeSocket *sock)
return count;
}
-/* test if two sockets are interchangeable
- * XXX this could be made into a tree-type callback for flexibility
- */
-static bool node_link_socket_match(bNodeSocket *a, bNodeSocket *b)
-{
- /* tests if alphabetic prefix matches
- * this allows for imperfect matches, such as numeric suffixes,
- * like Color1/Color2
- */
- int prefix_len = 0;
- char *ca = a->name, *cb = b->name;
- for (; *ca != '\0' && *cb != '\0'; ++ca, ++cb) {
- /* end of common prefix? */
- if (*ca != *cb) {
- /* prefix delimited by non-alphabetic char */
- if (isalpha(*ca) || isalpha(*cb))
- return false;
- break;
- }
- ++prefix_len;
- }
- return prefix_len > 0;
-}
-
-/* find an eligible socket for linking */
-static bNodeSocket *node_find_linkable_socket(bNodeTree *ntree, bNode *node, bNodeSocket *cur, bool use_swap)
-{
- int cur_link_count = node_count_links(ntree, cur);
- if (cur_link_count <= cur->limit) {
- /* current socket is fine, use it */
- return cur;
- }
- else if (use_swap) {
- /* link swapping: try to find a free slot with a matching name */
-
- bNodeSocket *first = cur->in_out == SOCK_IN ? node->inputs.first : node->outputs.first;
- bNodeSocket *sock;
-
- sock = cur->next ? cur->next : first; /* wrap around the list end */
- while (sock != cur) {
- if (!nodeSocketIsHidden(sock) && node_link_socket_match(sock, cur)) {
- int link_count = node_count_links(ntree, sock);
- /* take +1 into account since we would add a new link */
- if (link_count + 1 <= sock->limit)
- return sock; /* found a valid free socket we can swap to */
- }
-
- sock = sock->next ? sock->next : first; /* wrap around the list end */
- }
- }
- return NULL;
-}
-
-static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link, bool use_swap)
+static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link)
{
bNodeTree *ntree = snode->edittree;
bNodeSocket *from = link->fromsock, *to = link->tosock;
bNodeLink *tlink, *tlink_next;
+ int to_count = node_count_links(ntree, to);
+ int from_count = node_count_links(ntree, from);
for (tlink = ntree->links.first; tlink; tlink = tlink_next) {
tlink_next = tlink->next;
@@ -499,28 +445,18 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link, bool use_
continue;
if (tlink && tlink->fromsock == from) {
- bNodeSocket *new_from = node_find_linkable_socket(ntree, tlink->fromnode, from, use_swap);
- if (new_from && new_from != from) {
- /* redirect existing link */
- tlink->fromsock = new_from;
- }
- else if (!new_from) {
- /* no possible replacement, remove tlink */
+ if (from_count > from->limit) {
nodeRemLink(ntree, tlink);
tlink = NULL;
+ --from_count;
}
}
if (tlink && tlink->tosock == to) {
- bNodeSocket *new_to = node_find_linkable_socket(ntree, tlink->tonode, to, use_swap);
- if (new_to && new_to != to) {
- /* redirect existing link */
- tlink->tosock = new_to;
- }
- else if (!new_to) {
- /* no possible replacement, remove tlink */
+ if (to_count > to->limit) {
nodeRemLink(ntree, tlink);
tlink = NULL;
+ --to_count;
}
}
}
@@ -533,10 +469,20 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
bNodeLinkDrag *nldrag = op->customdata;
LinkData *linkdata;
+ /* avoid updates while applying links */
+ ntree->is_updating = true;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
bNodeLink *link = linkdata->data;
if (apply_links && link->tosock && link->fromsock) {
+ /* before actually adding the link,
+ * let nodes perform special link insertion handling
+ */
+ if (link->fromnode->typeinfo->insert_link)
+ link->fromnode->typeinfo->insert_link(ntree, link->fromnode, link);
+ if (link->tonode->typeinfo->insert_link)
+ link->tonode->typeinfo->insert_link(ntree, link->tonode, link);
+
/* add link to the node tree */
BLI_addtail(&ntree->links, link);
@@ -546,11 +492,12 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
link->tonode->update |= NODE_UPDATE;
/* we might need to remove a link */
- node_remove_extra_links(snode, link, true);
+ node_remove_extra_links(snode, link);
}
else
nodeRemLink(ntree, link);
}
+ ntree->is_updating = false;
ntreeUpdateTree(CTX_data_main(C), ntree);
snode_notify(C, snode);
@@ -1746,7 +1693,7 @@ void ED_node_link_insert(ScrArea *sa)
link->tonode = select;
link->tosock = best_input;
- node_remove_extra_links(snode, link, false);
+ node_remove_extra_links(snode, link);
link->flag &= ~NODE_LINKFLAG_HILITE;
nodeAddLink(snode->edittree, select, best_output, node, sockto);
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index b9b925f1829..df484724fc5 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -333,8 +333,8 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
ar->flag = RGN_FLAG_HIDDEN;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for node");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for node");
BLI_addtail(&snode->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -586,7 +586,7 @@ static SpaceLink *node_duplicate(SpaceLink *sl)
/* add handlers, stuff you only do once or on area/region changes */
-static void node_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -596,13 +596,13 @@ static void node_buttons_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void node_buttons_area_draw(const bContext *C, ARegion *ar)
+static void node_buttons_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
/* add handlers, stuff you only do once or on area/region changes */
-static void node_toolbar_area_init(wmWindowManager *wm, ARegion *ar)
+static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -612,7 +612,7 @@ static void node_toolbar_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void node_toolbar_area_draw(const bContext *C, ARegion *ar)
+static void node_toolbar_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
@@ -634,8 +634,8 @@ static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
}
-/* Initialize main area, setting handlers. */
-static void node_main_area_init(wmWindowManager *wm, ARegion *ar)
+/* Initialize main region, setting handlers. */
+static void node_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
ListBase *lb;
@@ -655,7 +655,7 @@ static void node_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_dropbox_handler(&ar->handlers, lb);
}
-static void node_main_area_draw(const bContext *C, ARegion *ar)
+static void node_main_region_draw(const bContext *C, ARegion *ar)
{
drawnodespace(C, ar);
}
@@ -722,12 +722,12 @@ static void node_dropboxes(void)
/* add handlers, stuff you only do once or on area/region changes */
-static void node_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void node_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void node_header_area_draw(const bContext *C, ARegion *ar)
+static void node_header_region_draw(const bContext *C, ARegion *ar)
{
/* find and set the context */
snode_set_context(C);
@@ -735,7 +735,7 @@ static void node_header_area_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-/* used for header + main area */
+/* used for header + main region */
static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
@@ -844,8 +844,8 @@ void ED_spacetype_node(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = node_main_area_init;
- art->draw = node_main_area_draw;
+ art->init = node_main_region_init;
+ art->draw = node_main_region_draw;
art->listener = node_region_listener;
art->cursor = node_cursor;
art->event_cursor = true;
@@ -859,8 +859,8 @@ void ED_spacetype_node(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
art->listener = node_region_listener;
- art->init = node_header_area_init;
- art->draw = node_header_area_draw;
+ art->init = node_header_region_init;
+ art->draw = node_header_region_draw;
BLI_addhead(&st->regiontypes, art);
@@ -870,8 +870,8 @@ void ED_spacetype_node(void)
art->prefsizex = 180; // XXX
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = node_region_listener;
- art->init = node_buttons_area_init;
- art->draw = node_buttons_area_draw;
+ art->init = node_buttons_region_init;
+ art->draw = node_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
node_buttons_register(art);
@@ -883,8 +883,8 @@ void ED_spacetype_node(void)
art->prefsizey = 50; /* XXX */
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = node_region_listener;
- art->init = node_toolbar_area_init;
- art->draw = node_toolbar_area_draw;
+ art->init = node_toolbar_region_init;
+ art->draw = node_toolbar_region_draw;
BLI_addhead(&st->regiontypes, art);
node_toolbar_register(art);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index fd1eb129c51..14f397f61fe 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -434,6 +434,7 @@ static void restrictbutton_gr_restrict_view(bContext *C, void *poin, void *poin2
{
restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_VIEW);
WM_event_add_notifier(C, NC_GROUP, NULL);
+ DAG_id_type_tag(CTX_data_main(C), ID_OB);
}
static void restrictbutton_gr_restrict_select(bContext *C, void *poin, void *poin2)
{
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 6d420674f3e..46974a6e911 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -290,6 +290,103 @@ void OUTLINER_OT_item_rename(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
}
+/* Library delete --------------------------------------------------- */
+
+static void lib_delete(bContext *C, TreeElement *te, TreeStoreElem *tselem, ReportList *reports)
+{
+ Library *lib = (Library *)tselem->id;
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a;
+
+ BLI_assert(te->idcode == ID_LI && lib != NULL);
+ UNUSED_VARS_NDEBUG(te);
+
+ /* We simply set all ID from given lib (including lib itself) to zero user count.
+ * It is not possible to do a proper cleanup without a save/reload in current master. */
+ a = set_listbasepointers(CTX_data_main(C), lbarray);
+ while (a--) {
+ ListBase *lb = lbarray[a];
+ ID *id;
+
+ for (id = lb->first; id; id = id->next) {
+ if (id->lib == lib) {
+ id_fake_user_clear(id);
+ id->us = 0;
+ }
+ }
+ }
+
+ BKE_reportf(reports, RPT_WARNING,
+ "Please save and reload .blend file to complete deletion of '%s' library",
+ ((Library *)tselem->id)->filepath);
+}
+
+void lib_delete_cb(
+ bContext *C, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem)
+{
+ lib_delete(C, te, tselem, CTX_wm_reports(C));
+}
+
+static int outliner_lib_delete_invoke_do(bContext *C, ReportList *reports, TreeElement *te, const float mval[2])
+{
+ if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (te->idcode == ID_LI && tselem->id) {
+ if (((Library *)tselem->id)->parent) {
+ BKE_reportf(reports, RPT_ERROR_INVALID_INPUT,
+ "Cannot delete indirectly linked library '%s'", ((Library *)tselem->id)->filepath);
+ return OPERATOR_CANCELLED;
+ }
+
+ lib_delete(C, te, tselem, reports);
+ return OPERATOR_FINISHED;
+ }
+ }
+ else {
+ for (te = te->subtree.first; te; te = te->next) {
+ int ret;
+ if ((ret = outliner_lib_delete_invoke_do(C, reports, te, mval))) {
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int outliner_lib_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te;
+ float fmval[2];
+
+ BLI_assert(ar && soops);
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+
+ for (te = soops->tree.first; te; te = te->next) {
+ int ret;
+
+ if ((ret = outliner_lib_delete_invoke_do(C, op->reports, te, fmval))) {
+ return ret;
+ }
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void OUTLINER_OT_lib_delete(wmOperatorType *ot)
+{
+ ot->name = "Delete Library";
+ ot->idname = "OUTLINER_OT_lib_delete";
+ ot->description = "Delete the library under cursor (needs a save/reload)";
+
+ ot->invoke = outliner_lib_delete_invoke;
+ ot->poll = ED_operator_outliner_active;
+}
+
/* ************************************************************** */
/* Setting Toggling Operators */
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index f10e6be2fa9..262aa9b6209 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -176,6 +176,10 @@ void group_toggle_renderability_cb(struct bContext *C, struct Scene *scene, Tree
void item_rename_cb(struct bContext *C, struct Scene *scene, TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem);
+void lib_delete_cb(
+ struct bContext *C, struct Scene *scene, struct TreeElement *te,
+ struct TreeStoreElem *tsep, struct TreeStoreElem *tselem);
+
TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children);
/* ...................................................... */
@@ -183,6 +187,8 @@ void OUTLINER_OT_item_activate(struct wmOperatorType *ot);
void OUTLINER_OT_item_openclose(struct wmOperatorType *ot);
void OUTLINER_OT_item_rename(struct wmOperatorType *ot);
+void OUTLINER_OT_lib_delete(struct wmOperatorType *ot);
+
void OUTLINER_OT_show_one_level(struct wmOperatorType *ot);
void OUTLINER_OT_show_active(struct wmOperatorType *ot);
void OUTLINER_OT_show_hierarchy(struct wmOperatorType *ot);
@@ -218,6 +224,7 @@ void OUTLINER_OT_operation(struct wmOperatorType *ot);
void OUTLINER_OT_scene_operation(struct wmOperatorType *ot);
void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
void OUTLINER_OT_group_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_lib_operation(struct wmOperatorType *ot);
void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
void OUTLINER_OT_data_operation(struct wmOperatorType *ot);
void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 839d44df25d..9710c3fc36b 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -47,10 +47,12 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_select_border);
WM_operatortype_append(OUTLINER_OT_item_openclose);
WM_operatortype_append(OUTLINER_OT_item_rename);
+ WM_operatortype_append(OUTLINER_OT_lib_delete);
WM_operatortype_append(OUTLINER_OT_operation);
WM_operatortype_append(OUTLINER_OT_scene_operation);
WM_operatortype_append(OUTLINER_OT_object_operation);
WM_operatortype_append(OUTLINER_OT_group_operation);
+ WM_operatortype_append(OUTLINER_OT_lib_operation);
WM_operatortype_append(OUTLINER_OT_id_operation);
WM_operatortype_append(OUTLINER_OT_data_operation);
WM_operatortype_append(OUTLINER_OT_animdata_operation);
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 02511917b29..84f8c629c5d 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -315,7 +315,7 @@ static eOLDrawState tree_element_active_texture(
/*tselem = TREESTORE(te);*/ /*UNUSED*/
- /* find buttons area (note, this is undefined really still, needs recode in blender) */
+ /* find buttons region (note, this is undefined really still, needs recode in blender) */
/* XXX removed finding sbuts */
/* where is texture linked to? */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 313a75f373a..e4471acc2c8 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -119,6 +119,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
case ID_MA: case ID_TE: case ID_IP: case ID_IM:
case ID_SO: case ID_KE: case ID_WO: case ID_AC:
case ID_NLA: case ID_TXT: case ID_GR: case ID_LS:
+ case ID_LI:
if (*idlevel == 0) *idlevel = idcode;
else if (*idlevel != idcode) *idlevel = -1;
break;
@@ -846,7 +847,7 @@ enum {
OL_OP_TOGVIS,
OL_OP_TOGSEL,
OL_OP_TOGREN,
- OL_OP_RENAME
+ OL_OP_RENAME,
};
static EnumPropertyItem prop_object_op_types[] = {
@@ -1246,6 +1247,88 @@ void OUTLINER_OT_id_operation(wmOperatorType *ot)
/* **************************************** */
+typedef enum eOutlinerLibOpTypes {
+ OL_LIB_INVALID = 0,
+
+ OL_LIB_RENAME,
+ OL_LIB_DELETE,
+} eOutlinerLibOpTypes;
+
+static EnumPropertyItem outliner_lib_op_type_items[] = {
+ {OL_LIB_RENAME, "RENAME", 0, "Rename", ""},
+ {OL_LIB_DELETE, "DELETE", 0, "Delete", "Delete this library and all its item from Blender (needs a save/reload)"},
+ {0, NULL, 0, NULL, NULL}
+
+};
+
+static int outliner_lib_operation_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutlinerIdOpTypes event;
+
+ /* check for invalid states */
+ if (soops == NULL)
+ return OPERATOR_CANCELLED;
+
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ event = RNA_enum_get(op->ptr, "type");
+
+ switch (event) {
+ case OL_LIB_RENAME:
+ {
+ /* rename */
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, item_rename_cb);
+
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+ ED_undo_push(C, "Rename");
+ break;
+ }
+ case OL_LIB_DELETE:
+ {
+ /* delete */
+ outliner_do_libdata_operation(C, scene, soops, &soops->tree, lib_delete_cb);
+
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+ /* Note: no undo possible here really, not 100% sure why...
+ * Probably because of library optimizations in undo/redo process? */
+ /* ED_undo_push(C, "Rename"); */
+ break;
+ }
+ default:
+ /* invalid - unhandled */
+ break;
+ }
+
+ /* wrong notifier still... */
+ WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
+
+ /* XXX: this is just so that outliner is always up to date */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void OUTLINER_OT_lib_operation(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Outliner Library Operation";
+ ot->idname = "OUTLINER_OT_lib_operation";
+ ot->description = "";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_lib_operation_exec;
+ ot->poll = ED_operator_outliner_active;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", outliner_lib_op_type_items, 0, "Library Operation", "");
+}
+
+/* **************************************** */
+
static void outliner_do_id_set_operation(SpaceOops *soops, int type, ListBase *lb, ID *newid,
void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *, ID *))
{
@@ -1703,10 +1786,17 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S
BKE_report(reports, RPT_WARNING, "Mixed selection");
}
else {
- if (idlevel == ID_GR)
- WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
- else
- WM_operator_name_call(C, "OUTLINER_OT_id_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ switch (idlevel) {
+ case ID_GR:
+ WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ case ID_LI:
+ WM_operator_name_call(C, "OUTLINER_OT_lib_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ default:
+ WM_operator_name_call(C, "OUTLINER_OT_id_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ break;
+ }
}
}
else if (datalevel) {
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 7b1ec174a6b..1dd66366e5d 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -62,7 +62,7 @@
#include "outliner_intern.h"
-static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void outliner_main_region_init(wmWindowManager *wm, ARegion *ar)
{
ListBase *lb;
wmKeyMap *keymap;
@@ -266,7 +266,7 @@ static void outliner_dropboxes(void)
WM_dropbox_add(lb, "OUTLINER_OT_group_link", outliner_group_link_poll, outliner_group_link_copy);
}
-static void outliner_main_area_draw(const bContext *C, ARegion *ar)
+static void outliner_main_region_draw(const bContext *C, ARegion *ar)
{
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
@@ -287,12 +287,12 @@ static void outliner_main_area_draw(const bContext *C, ARegion *ar)
}
-static void outliner_main_area_free(ARegion *UNUSED(ar))
+static void outliner_main_region_free(ARegion *UNUSED(ar))
{
}
-static void outliner_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void outliner_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -399,21 +399,21 @@ static void outliner_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
/* ************************ header outliner area region *********************** */
/* add handlers, stuff you only do once or on area/region changes */
-static void outliner_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void outliner_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void outliner_header_area_draw(const bContext *C, ARegion *ar)
+static void outliner_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void outliner_header_area_free(ARegion *UNUSED(ar))
+static void outliner_header_region_free(ARegion *UNUSED(ar))
{
}
-static void outliner_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void outliner_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -445,8 +445,8 @@ static SpaceLink *outliner_new(const bContext *UNUSED(C))
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_BOTTOM;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for outliner");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for outliner");
BLI_addtail(&soutliner->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -508,10 +508,10 @@ void ED_spacetype_outliner(void)
art->regionid = RGN_TYPE_WINDOW;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
- art->init = outliner_main_area_init;
- art->draw = outliner_main_area_draw;
- art->free = outliner_main_area_free;
- art->listener = outliner_main_area_listener;
+ art->init = outliner_main_region_init;
+ art->draw = outliner_main_region_draw;
+ art->free = outliner_main_region_free;
+ art->listener = outliner_main_region_listener;
BLI_addhead(&st->regiontypes, art);
/* regions: header */
@@ -520,10 +520,10 @@ void ED_spacetype_outliner(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->init = outliner_header_area_init;
- art->draw = outliner_header_area_draw;
- art->free = outliner_header_area_free;
- art->listener = outliner_header_area_listener;
+ art->init = outliner_header_region_init;
+ art->draw = outliner_header_region_draw;
+ art->free = outliner_header_region_free;
+ art->listener = outliner_header_region_listener;
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c
index 759dcd3d0a4..4228635ccd6 100644
--- a/source/blender/editors/space_script/space_script.c
+++ b/source/blender/editors/space_script/space_script.c
@@ -78,8 +78,8 @@ static SpaceLink *script_new(const bContext *UNUSED(C))
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_BOTTOM;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for script");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for script");
BLI_addtail(&sscript->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -125,7 +125,7 @@ static SpaceLink *script_duplicate(SpaceLink *sl)
/* add handlers, stuff you only do once or on area/region changes */
-static void script_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void script_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -136,7 +136,7 @@ static void script_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void script_main_area_draw(const bContext *C, ARegion *ar)
+static void script_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceScript *sscript = (SpaceScript *)CTX_wm_space_data(C);
@@ -166,17 +166,17 @@ static void script_main_area_draw(const bContext *C, ARegion *ar)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void script_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void script_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void script_header_area_draw(const bContext *C, ARegion *ar)
+static void script_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void script_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void script_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
{
/* context changes */
// XXX - Todo, need the ScriptSpace accessible to get the python script to run.
@@ -202,9 +202,9 @@ void ED_spacetype_script(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype script region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = script_main_area_init;
- art->draw = script_main_area_draw;
- art->listener = script_main_area_listener;
+ art->init = script_main_region_init;
+ art->draw = script_main_region_draw;
+ art->listener = script_main_region_listener;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_UI | ED_KEYMAP_FRAMES; // XXX need to further test this ED_KEYMAP_UI is needed for button interaction
BLI_addhead(&st->regiontypes, art);
@@ -215,8 +215,8 @@ void ED_spacetype_script(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->init = script_header_area_init;
- art->draw = script_header_area_draw;
+ art->init = script_header_region_init;
+ art->draw = script_header_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 2ae7cdd4f98..deb0a3f6d03 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -58,6 +58,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_basic_shader.h"
+
#include "ED_anim_api.h"
#include "ED_gpencil.h"
#include "ED_markers.h"
@@ -177,7 +179,11 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
blendcol[0] = blendcol[1] = blendcol[2] = 128;
if (seq->flag & SEQ_MUTE) UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20);
break;
-
+
+ case SEQ_TYPE_TEXT:
+ UI_GetThemeColor3ubv(TH_SEQ_TEXT, col);
+ break;
+
default:
col[0] = 10; col[1] = 255; col[2] = 40;
break;
@@ -301,6 +307,20 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
int chan_range = 0;
float draw_range = y2 - y1;
float draw_height;
+ ListBase *seqbase;
+ int offset;
+
+ seqbase = BKE_sequence_seqbase_get(seqm, &offset);
+ if (!seqbase || BLI_listbase_is_empty(seqbase)) {
+ return;
+ }
+
+ if (seqm->type == SEQ_TYPE_SCENE) {
+ offset = seqm->start - offset;
+ }
+ else {
+ offset = 0;
+ }
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -308,7 +328,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
if (seqm->flag & SEQ_MUTE)
drawmeta_stipple(1);
- for (seq = seqm->seqbase.first; seq; seq = seq->next) {
+ for (seq = seqbase->first; seq; seq = seq->next) {
chan_min = min_ii(chan_min, seq->machine);
chan_max = max_ii(chan_max, seq->machine);
}
@@ -318,11 +338,14 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
col[3] = 196; /* alpha, used for all meta children */
- for (seq = seqm->seqbase.first; seq; seq = seq->next) {
- if ((seq->startdisp > x2 || seq->enddisp < x1) == 0) {
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ const int startdisp = seq->startdisp + offset;
+ const int enddisp = seq->enddisp + offset;
+
+ if ((startdisp > x2 || enddisp < x1) == 0) {
float y_chan = (seq->machine - chan_min) / (float)(chan_range) * draw_range;
- float x1_chan = seq->startdisp;
- float x2_chan = seq->enddisp;
+ float x1_chan = startdisp;
+ float x2_chan = enddisp;
float y1_chan, y2_chan;
if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
@@ -830,7 +853,9 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
glDisable(GL_LINE_STIPPLE);
}
- if (seq->type == SEQ_TYPE_META) {
+ if ((seq->type == SEQ_TYPE_META) ||
+ ((seq->type == SEQ_TYPE_SCENE) && (seq->flag & SEQ_SCENE_STRIPS)))
+ {
drawmeta_contents(scene, seq, x1, y1, x2, y2);
}
@@ -1074,7 +1099,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
float viewrect[2];
float col[3];
GLuint texid;
- GLuint last_texid;
void *display_buffer;
void *cache_handle = NULL;
const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
@@ -1270,11 +1294,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
}
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f(1.0, 1.0, 1.0, 1.0);
- last_texid = glaGetOneInteger(GL_TEXTURE_2D);
- glEnable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glGenTextures(1, (GLuint *)&texid);
glBindTexture(GL_TEXTURE_2D, texid);
@@ -1348,8 +1370,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
glEnd();
- glBindTexture(GL_TEXTURE_2D, last_texid);
- glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
glDisable(GL_BLEND);
glDeleteTextures(1, &texid);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 70adaa2f3a6..fd8b1165719 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -2517,7 +2517,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
#if 1
BKE_sequence_tx_set_final_left(ms->parseq, ms->disp_range[0]);
BKE_sequence_tx_set_final_right(ms->parseq, ms->disp_range[1]);
- BKE_sequence_single_fix(seq);
+ BKE_sequence_single_fix(ms->parseq);
BKE_sequence_calc(scene, ms->parseq);
#else
if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq))
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 5b3061bd513..fce40f8ca59 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -136,9 +136,9 @@ static SpaceLink *sequencer_new(const bContext *C)
ar->alignment = RGN_ALIGN_RIGHT;
ar->flag = RGN_FLAG_HIDDEN;
- /* preview area */
+ /* preview region */
/* NOTE: if you change values here, also change them in sequencer_init_preview_region */
- ar = MEM_callocN(sizeof(ARegion), "preview area for sequencer");
+ ar = MEM_callocN(sizeof(ARegion), "preview region for sequencer");
BLI_addtail(&sseq->regionbase, ar);
ar->regiontype = RGN_TYPE_PREVIEW;
ar->alignment = RGN_ALIGN_TOP;
@@ -160,8 +160,8 @@ static SpaceLink *sequencer_new(const bContext *C)
ar->v2d.keeptot = V2D_KEEPTOT_FREE;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for sequencer");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for sequencer");
BLI_addtail(&sseq->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -283,7 +283,7 @@ static void sequencer_refresh(const bContext *C, ScrArea *sa)
/* Get available height (without DPI correction). */
const float height = (sa->winy - ED_area_headersize()) / UI_DPI_FAC;
- /* We reuse hidden area's size, allows to find same layout as before if we just switch
+ /* We reuse hidden region's size, allows to find same layout as before if we just switch
* between one 'full window' view and the combined one. This gets lost if we switch to both
* 'full window' views before, though... Better than nothing. */
if (ar_main->flag & RGN_FLAG_HIDDEN) {
@@ -457,7 +457,7 @@ static int sequencer_context(const bContext *C, const char *member, bContextData
/* *********************** sequencer (main) region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void sequencer_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
ListBase *lb;
@@ -482,13 +482,13 @@ static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_dropbox_handler(&ar->handlers, lb);
}
-static void sequencer_main_area_draw(const bContext *C, ARegion *ar)
+static void sequencer_main_region_draw(const bContext *C, ARegion *ar)
{
/* NLE - strip editing timeline interface */
draw_timeline_seq(C, ar);
}
-static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void sequencer_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -528,18 +528,18 @@ static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
/* *********************** header region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void sequencer_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void sequencer_header_area_draw(const bContext *C, ARegion *ar)
+static void sequencer_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
/* *********************** preview region ************************ */
-static void sequencer_preview_area_init(wmWindowManager *wm, ARegion *ar)
+static void sequencer_preview_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -558,7 +558,7 @@ static void sequencer_preview_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
+static void sequencer_preview_region_draw(const bContext *C, ARegion *ar)
{
ScrArea *sa = CTX_wm_area(C);
SpaceSeq *sseq = sa->spacedata.first;
@@ -594,7 +594,7 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
}
}
-static void sequencer_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void sequencer_preview_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -645,7 +645,7 @@ static void sequencer_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
/* *********************** buttons region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -655,12 +655,12 @@ static void sequencer_buttons_area_init(wmWindowManager *wm, ARegion *ar)
ED_region_panels_init(wm, ar);
}
-static void sequencer_buttons_area_draw(const bContext *C, ARegion *ar)
+static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
-static void sequencer_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void sequencer_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -712,9 +712,9 @@ void ED_spacetype_sequencer(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = sequencer_main_area_init;
- art->draw = sequencer_main_area_draw;
- art->listener = sequencer_main_area_listener;
+ art->init = sequencer_main_region_init;
+ art->draw = sequencer_main_region_draw;
+ art->listener = sequencer_main_region_listener;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
BLI_addhead(&st->regiontypes, art);
@@ -722,9 +722,9 @@ void ED_spacetype_sequencer(void)
/* preview */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_PREVIEW;
- art->init = sequencer_preview_area_init;
- art->draw = sequencer_preview_area_draw;
- art->listener = sequencer_preview_area_listener;
+ art->init = sequencer_preview_region_init;
+ art->draw = sequencer_preview_region_draw;
+ art->listener = sequencer_preview_region_listener;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
BLI_addhead(&st->regiontypes, art);
@@ -733,9 +733,9 @@ void ED_spacetype_sequencer(void)
art->regionid = RGN_TYPE_UI;
art->prefsizex = 220; // XXX
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = sequencer_buttons_area_listener;
- art->init = sequencer_buttons_area_init;
- art->draw = sequencer_buttons_area_draw;
+ art->listener = sequencer_buttons_region_listener;
+ art->init = sequencer_buttons_region_init;
+ art->draw = sequencer_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
sequencer_buttons_register(art);
@@ -746,9 +746,9 @@ void ED_spacetype_sequencer(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->init = sequencer_header_area_init;
- art->draw = sequencer_header_area_draw;
- art->listener = sequencer_main_area_listener;
+ art->init = sequencer_header_region_init;
+ art->draw = sequencer_header_region_draw;
+ art->listener = sequencer_main_region_listener;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index ff53d306e69..87270bace9a 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -80,8 +80,8 @@ static SpaceLink *text_new(const bContext *UNUSED(C))
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_BOTTOM;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for text");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for text");
BLI_addtail(&stext->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -404,7 +404,7 @@ static int text_context(const bContext *C, const char *member, bContextDataResul
/********************* main region ********************/
/* add handlers, stuff you only do once or on area/region changes */
-static void text_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void text_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
ListBase *lb;
@@ -423,7 +423,7 @@ static void text_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_dropbox_handler(&ar->handlers, lb);
}
-static void text_main_area_draw(const bContext *C, ARegion *ar)
+static void text_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceText *st = CTX_wm_space_text(C);
@@ -511,12 +511,12 @@ static void text_dropboxes(void)
/****************** header region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void text_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void text_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void text_header_area_draw(const bContext *C, ARegion *ar)
+static void text_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
@@ -524,7 +524,7 @@ static void text_header_area_draw(const bContext *C, ARegion *ar)
/****************** properties region ******************/
/* add handlers, stuff you only do once or on area/region changes */
-static void text_properties_area_init(wmWindowManager *wm, ARegion *ar)
+static void text_properties_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -537,7 +537,7 @@ static void text_properties_area_init(wmWindowManager *wm, ARegion *ar)
}
-static void text_properties_area_draw(const bContext *C, ARegion *ar)
+static void text_properties_region_draw(const bContext *C, ARegion *ar)
{
SpaceText *st = CTX_wm_space_text(C);
@@ -578,8 +578,8 @@ void ED_spacetype_text(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = text_main_area_init;
- art->draw = text_main_area_draw;
+ art->init = text_main_region_init;
+ art->draw = text_main_region_draw;
art->cursor = text_cursor;
art->event_cursor = true;
@@ -591,8 +591,8 @@ void ED_spacetype_text(void)
art->prefsizex = UI_COMPACT_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI;
- art->init = text_properties_area_init;
- art->draw = text_properties_area_draw;
+ art->init = text_properties_region_init;
+ art->draw = text_properties_region_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: header */
@@ -601,8 +601,8 @@ void ED_spacetype_text(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->init = text_header_area_init;
- art->draw = text_header_area_draw;
+ art->init = text_header_region_init;
+ art->draw = text_header_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 9bcaf04e520..16087921ab6 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -57,45 +57,56 @@
#include "text_format.h"
/******************** text font drawing ******************/
-// XXX, fixme
-#define mono blf_mono_font
-static void text_font_begin(SpaceText *st)
+typedef struct TextDrawContext {
+ int font_id;
+ int cwidth;
+ int lheight_dpi;
+} TextDrawContext;
+
+static void text_draw_context_init(const SpaceText *st, TextDrawContext *tdc)
+{
+ tdc->font_id = blf_mono_font;
+ tdc->cwidth = 0;
+ tdc->lheight_dpi = st->lheight_dpi;
+}
+
+static void text_font_begin(const TextDrawContext *tdc)
{
- BLF_size(mono, st->lheight_dpi, 72);
+ BLF_size(tdc->font_id, tdc->lheight_dpi, 72);
}
-static void text_font_end(SpaceText *UNUSED(st))
+static void text_font_end(const TextDrawContext *UNUSED(tdc))
{
}
-static int text_font_draw(SpaceText *st, int x, int y, const char *str)
+static int text_font_draw(const TextDrawContext *tdc, int x, int y, const char *str)
{
int columns;
- BLF_position(mono, x, y, 0);
- columns = BLF_draw_mono(mono, str, BLF_DRAW_STR_DUMMY_MAX, st->cwidth);
+ BLF_position(tdc->font_id, x, y, 0);
+ columns = BLF_draw_mono(tdc->font_id, str, BLF_DRAW_STR_DUMMY_MAX, tdc->cwidth);
- return st->cwidth * columns;
+ return tdc->cwidth * columns;
}
-static int text_font_draw_character(SpaceText *st, int x, int y, char c)
+static int text_font_draw_character(const TextDrawContext *tdc, int x, int y, char c)
{
- BLF_position(mono, x, y, 0);
- BLF_draw(mono, &c, 1);
+ BLF_position(tdc->font_id, x, y, 0);
+ BLF_draw(tdc->font_id, &c, 1);
- return st->cwidth;
+ return tdc->cwidth;
}
-static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c)
+static int text_font_draw_character_utf8(const TextDrawContext *tdc, int x, int y, const char *c)
{
int columns;
const size_t len = BLI_str_utf8_size_safe(c);
- BLF_position(mono, x, y, 0);
- columns = BLF_draw_mono(mono, c, len, st->cwidth);
+ BLF_position(tdc->font_id, x, y, 0);
+ columns = BLF_draw_mono(tdc->font_id, c, len, tdc->cwidth);
- return st->cwidth * columns;
+ return tdc->cwidth * columns;
}
#if 0
@@ -174,7 +185,7 @@ static void format_draw_color(char formatchar)
*
*/
-int wrap_width(SpaceText *st, ARegion *ar)
+int wrap_width(const SpaceText *st, ARegion *ar)
{
int winx = ar->winx - TXT_SCROLL_WIDTH;
int x, max;
@@ -185,7 +196,7 @@ int wrap_width(SpaceText *st, ARegion *ar)
}
/* Sets (offl, offc) for transforming (line, curs) to its wrapped position */
-void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
+void wrap_offset(const SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
{
Text *text;
TextLine *linep;
@@ -280,7 +291,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *
}
/* cursin - mem, offc - view */
-void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
+void wrap_offset_in_line(const SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
{
int i, j, start, end, chars, max, chop;
char ch;
@@ -342,7 +353,7 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi
}
}
-int text_get_char_pos(SpaceText *st, const char *line, int cur)
+int text_get_char_pos(const SpaceText *st, const char *line, int cur)
{
int a = 0, i;
@@ -373,7 +384,9 @@ static const char *txt_utf8_forward_columns(const char *str, int columns, int *p
return p;
}
-static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w, const char *format, int skip)
+static int text_draw_wrapped(
+ const SpaceText *st, const TextDrawContext *tdc,
+ const char *str, int x, int y, int w, const char *format, int skip)
{
const bool use_syntax = (st->showsyntax && format);
FlattenString fs;
@@ -418,7 +431,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
if (use_syntax) {
if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
}
- x += text_font_draw_character_utf8(st, x, y, str + ma);
+ x += text_font_draw_character_utf8(tdc, x, y, str + ma);
fpos++;
}
y -= st->lheight_dpi + TXT_LINE_SPACING;
@@ -442,7 +455,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
}
- x += text_font_draw_character_utf8(st, x, y, str + ma);
+ x += text_font_draw_character_utf8(tdc, x, y, str + ma);
}
flatten_string_free(&fs);
@@ -450,7 +463,9 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
return lines;
}
-static void text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int x, int y, const char *format)
+static void text_draw(
+ const SpaceText *st, const TextDrawContext *tdc,
+ char *str, int cshift, int maxwidth, int x, int y, const char *format)
{
const bool use_syntax = (st->showsyntax && format);
FlattenString fs;
@@ -483,7 +498,7 @@ static void text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int x,
return; /* String is shorter than shift or ends with a padding */
}
- x += st->cwidth * padding;
+ x += tdc->cwidth * padding;
if (use_syntax) {
int a, str_shift = 0;
@@ -491,12 +506,12 @@ static void text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int x,
for (a = 0; a < amount; a++) {
if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]);
- x += text_font_draw_character_utf8(st, x, y, in + str_shift);
+ x += text_font_draw_character_utf8(tdc, x, y, in + str_shift);
str_shift += BLI_str_utf8_size_safe(in + str_shift);
}
}
else {
- text_font_draw(st, x, y, in);
+ text_font_draw(tdc, x, y, in);
}
flatten_string_free(&fs);
@@ -696,14 +711,14 @@ void text_free_caches(SpaceText *st)
/************************ word-wrap utilities *****************************/
/* cache should be updated in caller */
-static int text_get_visible_lines_no(SpaceText *st, int lineno)
+static int text_get_visible_lines_no(const SpaceText *st, int lineno)
{
- DrawCache *drawcache = (DrawCache *)st->drawcache;
+ const DrawCache *drawcache = st->drawcache;
return drawcache->line_height[lineno];
}
-int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str)
+int text_get_visible_lines(const SpaceText *st, ARegion *ar, const char *str)
{
int i, j, start, end, max, lines, chars;
char ch;
@@ -742,7 +757,7 @@ int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str)
return lines;
}
-int text_get_span_wrap(SpaceText *st, ARegion *ar, TextLine *from, TextLine *to)
+int text_get_span_wrap(const SpaceText *st, ARegion *ar, TextLine *from, TextLine *to)
{
if (st->wordwrap) {
int ret = 0;
@@ -767,7 +782,7 @@ int text_get_total_lines(SpaceText *st, ARegion *ar)
DrawCache *drawcache;
text_update_drawcache(st, ar);
- drawcache = (DrawCache *)st->drawcache;
+ drawcache = st->drawcache;
return drawcache->total_lines;
}
@@ -785,7 +800,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
pix_available = ar->winy - pix_top_margin - pix_bottom_margin;
ltexth = text_get_total_lines(st, ar);
blank_lines = st->viewlines / 2;
-
+
/* nicer code: use scroll rect for entire bar */
back->xmin = ar->winx - (V2D_SCROLL_WIDTH + 1);
back->xmax = ar->winx;
@@ -887,7 +902,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
CLAMP(st->txtscroll.ymax, pix_bottom_margin, ar->winy - pix_top_margin);
}
-static void draw_textscroll(SpaceText *st, rcti *scroll, rcti *back)
+static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
{
bTheme *btheme = UI_GetTheme();
uiWidgetColors wcol = btheme->tui.wcol_scroll;
@@ -911,8 +926,9 @@ static void draw_textscroll(SpaceText *st, rcti *scroll, rcti *back)
/*********************** draw documentation *******************************/
-static void draw_documentation(SpaceText *st, ARegion *ar)
+static void draw_documentation(const SpaceText *st, ARegion *ar)
{
+ TextDrawContext tdc = {0};
TextLine *tmp;
char *docs, buf[DOC_WIDTH + 1], *p;
int i, br, lines;
@@ -925,6 +941,8 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
if (!docs) return;
+ text_draw_context_init(st, &tdc);
+
/* Count the visible lines to the cursor */
for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
if (l < 0) return;
@@ -974,7 +992,7 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
buf[i] = '\0';
if (lines >= 0) {
y -= st->lheight_dpi;
- text_draw(st, buf, 0, 0, x + 4, y - 3, NULL);
+ text_draw(st, &tdc, buf, 0, 0, x + 4, y - 3, NULL);
}
i = 0; br = DOC_WIDTH; lines++;
}
@@ -983,7 +1001,7 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
buf[br] = '\0';
if (lines >= 0) {
y -= st->lheight_dpi;
- text_draw(st, buf, 0, 0, x + 4, y - 3, NULL);
+ text_draw(st, &tdc, buf, 0, 0, x + 4, y - 3, NULL);
}
p -= i - br - 1; /* Rewind pointer to last break */
i = 0; br = DOC_WIDTH; lines++;
@@ -999,7 +1017,7 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
/*********************** draw suggestion list *******************************/
-static void draw_suggestion_list(SpaceText *st, ARegion *ar)
+static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc, ARegion *ar)
{
SuggItem *item, *first, *last, *sel;
char str[SUGG_LIST_WIDTH * BLI_UTF8_MAX + 1];
@@ -1064,7 +1082,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
}
format_draw_color(item->type);
- text_draw(st, str, 0, 0, x + margin_x, y - 1, NULL);
+ text_draw(st, tdc, str, 0, 0, x + margin_x, y - 1, NULL);
if (item == last) break;
}
@@ -1191,7 +1209,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
/******************* draw matching brackets *********************/
-static void draw_brackets(SpaceText *st, ARegion *ar)
+static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegion *ar)
{
TextLine *startl, *endl, *linep;
Text *text = st->text;
@@ -1299,8 +1317,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
if (viewc >= 0) {
viewl = txt_get_span(text->lines.first, startl) - st->top + offl;
- text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
- text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ text_font_draw_character(tdc, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ text_font_draw_character(tdc, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
}
/* draw closing bracket */
@@ -1311,15 +1329,16 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
if (viewc >= 0) {
viewl = txt_get_span(text->lines.first, endl) - st->top + offl;
- text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
- text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ text_font_draw_character(tdc, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ text_font_draw_character(tdc, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
}
}
-/*********************** main area drawing *************************/
+/*********************** main region drawing *************************/
void draw_text_main(SpaceText *st, ARegion *ar)
{
+ TextDrawContext tdc = {0};
Text *text = st->text;
TextFormatType *tft;
TextLine *tmp;
@@ -1328,8 +1347,6 @@ void draw_text_main(SpaceText *st, ARegion *ar)
int i, x, y, winx, linecount = 0, lineno = 0;
int wraplinecount = 0, wrap_skip = 0;
int margin_column_x;
- /* don't draw lines below this */
- const int clip_min_y = -(int)(st->lheight_dpi - 1);
/* if no text, nothing to do */
if (!text)
@@ -1337,8 +1354,14 @@ void draw_text_main(SpaceText *st, ARegion *ar)
/* dpi controlled line height and font size */
st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
+
+ /* don't draw lines below this */
+ const int clip_min_y = -(int)(st->lheight_dpi - 1);
+
st->viewlines = (st->lheight_dpi) ? (int)(ar->winy - clip_min_y) / (st->lheight_dpi + TXT_LINE_SPACING) : 0;
+ text_draw_context_init(st, &tdc);
+
text_update_drawcache(st, ar);
/* make sure all the positional pointers exist */
@@ -1377,9 +1400,11 @@ void draw_text_main(SpaceText *st, ARegion *ar)
lineno++;
}
- text_font_begin(st);
- st->cwidth = BLF_fixed_width(mono);
- st->cwidth = MAX2(st->cwidth, (char)1);
+
+ text_font_begin(&tdc);
+
+ tdc.cwidth = max_ii((int)BLF_fixed_width(tdc.font_id), 1);
+ st->cwidth = tdc.cwidth;
/* draw line numbers background */
if (st->showlinenrs) {
@@ -1414,19 +1439,19 @@ void draw_text_main(SpaceText *st, ARegion *ar)
BLI_snprintf(linenr, sizeof(linenr), "%*d", st->linenrs_tot, i + linecount + 1);
/* itoa(i + linecount + 1, linenr, 10); */ /* not ansi-c :/ */
- text_font_draw(st, TXT_OFFSET - 7, y, linenr);
+ text_font_draw(&tdc, TXT_OFFSET - 7, y, linenr);
UI_ThemeColor(TH_TEXT);
}
if (st->wordwrap) {
/* draw word wrapped text */
- int lines = text_draw_wrapped(st, tmp->line, x, y, winx - x, tmp->format, wrap_skip);
+ int lines = text_draw_wrapped(st, &tdc, tmp->line, x, y, winx - x, tmp->format, wrap_skip);
y -= lines * (st->lheight_dpi + TXT_LINE_SPACING);
}
else {
/* draw unwrapped text */
- text_draw(st, tmp->line, st->left, ar->winx / st->cwidth, x, y, tmp->format);
+ text_draw(st, &tdc, tmp->line, st->left, ar->winx / st->cwidth, x, y, tmp->format);
y -= st->lheight_dpi + TXT_LINE_SPACING;
}
@@ -1450,22 +1475,26 @@ void draw_text_main(SpaceText *st, ARegion *ar)
}
/* draw other stuff */
- draw_brackets(st, ar);
+ draw_brackets(st, &tdc, ar);
draw_textscroll(st, &scroll, &back);
draw_documentation(st, ar);
- draw_suggestion_list(st, ar);
+ draw_suggestion_list(st, &tdc, ar);
- text_font_end(st);
+ text_font_end(&tdc);
}
/************************** update ***************************/
void text_update_character_width(SpaceText *st)
{
- text_font_begin(st);
- st->cwidth = BLF_fixed_width(mono);
+ TextDrawContext tdc = {0};
+
+ text_draw_context_init(st, &tdc);
+
+ text_font_begin(&tdc);
+ st->cwidth = BLF_fixed_width(tdc.font_id);
st->cwidth = MAX2(st->cwidth, (char)1);
- text_font_end(st);
+ text_font_end(&tdc);
}
/* Moves the view to the cursor location,
diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c
index b29c6420d60..0133122c5a3 100644
--- a/source/blender/editors/space_text/text_format.c
+++ b/source/blender/editors/space_text/text_format.c
@@ -73,7 +73,7 @@ static void flatten_string_append(FlattenString *fs, const char *c, int accum, i
fs->pos += len;
}
-int flatten_string(SpaceText *st, FlattenString *fs, const char *in)
+int flatten_string(const SpaceText *st, FlattenString *fs, const char *in)
{
int r, i, total = 0;
diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index daed3b3e447..b901ec83a9c 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -54,7 +54,7 @@ enum {
#define FMT_CONT_ALL \
(FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C)
-int flatten_string(struct SpaceText *st, FlattenString *fs, const char *in);
+int flatten_string(const struct SpaceText *st, FlattenString *fs, const char *in);
void flatten_string_free(FlattenString *fs);
int flatten_string_strlen(FlattenString *fs, const char *str);
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index 7ae2617f375..3129c1bfc85 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -65,10 +65,10 @@ void text_update_cursor_moved(struct bContext *C);
#define TOOL_SUGG_LIST 0x01
#define TOOL_DOCUMENT 0x02
-int wrap_width(struct SpaceText *st, struct ARegion *ar);
-void wrap_offset(struct SpaceText *st, struct ARegion *ar, struct TextLine *linein, int cursin, int *offl, int *offc);
-void wrap_offset_in_line(struct SpaceText *st, struct ARegion *ar, struct TextLine *linep, int cursin, int *offl, int *offc);
-int text_get_char_pos(struct SpaceText *st, const char *line, int cur);
+int wrap_width(const struct SpaceText *st, struct ARegion *ar);
+void wrap_offset(const struct SpaceText *st, struct ARegion *ar, struct TextLine *linein, int cursin, int *offl, int *offc);
+void wrap_offset_in_line(const struct SpaceText *st, struct ARegion *ar, struct TextLine *linep, int cursin, int *offl, int *offc);
+int text_get_char_pos(const struct SpaceText *st, const char *line, int cur);
void text_drawcache_tag_update(struct SpaceText *st, int full);
void text_free_caches(struct SpaceText *st);
@@ -76,8 +76,8 @@ void text_free_caches(struct SpaceText *st);
int text_do_suggest_select(struct SpaceText *st, struct ARegion *ar);
void text_pop_suggest_list(void);
-int text_get_visible_lines(struct SpaceText *st, struct ARegion *ar, const char *str);
-int text_get_span_wrap(struct SpaceText *st, struct ARegion *ar, struct TextLine *from, struct TextLine *to);
+int text_get_visible_lines(const struct SpaceText *st, struct ARegion *ar, const char *str);
+int text_get_span_wrap(const struct SpaceText *st, struct ARegion *ar, struct TextLine *from, struct TextLine *to);
int text_get_total_lines(struct SpaceText *st, struct ARegion *ar);
/* text_ops.c */
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 003dbd55edd..4c64c52ba2b 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -487,7 +487,7 @@ static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
/* ---------------- */
/* add handlers, stuff you only do once or on area/region changes */
-static void time_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void time_main_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -498,7 +498,7 @@ static void time_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void time_main_area_draw(const bContext *C, ARegion *ar)
+static void time_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
Scene *scene = CTX_data_scene(C);
@@ -557,7 +557,7 @@ static void time_main_area_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
}
-static void time_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void time_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -588,17 +588,17 @@ static void time_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AR
/* ************************ header time area region *********************** */
/* add handlers, stuff you only do once or on area/region changes */
-static void time_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void time_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void time_header_area_draw(const bContext *C, ARegion *ar)
+static void time_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void time_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void time_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -651,8 +651,8 @@ static SpaceLink *time_new(const bContext *C)
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_BOTTOM;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for time");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for time");
BLI_addtail(&stime->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -739,9 +739,9 @@ void ED_spacetype_time(void)
art->regionid = RGN_TYPE_WINDOW;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
- art->init = time_main_area_init;
- art->draw = time_main_area_draw;
- art->listener = time_main_area_listener;
+ art->init = time_main_region_init;
+ art->draw = time_main_region_draw;
+ art->listener = time_main_region_listener;
art->keymap = time_keymap;
BLI_addhead(&st->regiontypes, art);
@@ -751,9 +751,9 @@ void ED_spacetype_time(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->init = time_header_area_init;
- art->draw = time_header_area_draw;
- art->listener = time_header_area_listener;
+ art->init = time_header_region_init;
+ art->draw = time_header_region_draw;
+ art->listener = time_header_region_listener;
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index b5a6821d147..aeba4a86f3e 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -66,8 +66,8 @@ static SpaceLink *userpref_new(const bContext *UNUSED(C))
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_BOTTOM;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for userpref");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for userpref");
BLI_addtail(&spref->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -101,7 +101,7 @@ static SpaceLink *userpref_duplicate(SpaceLink *sl)
/* add handlers, stuff you only do once or on area/region changes */
-static void userpref_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void userpref_main_region_init(wmWindowManager *wm, ARegion *ar)
{
/* do not use here, the properties changed in userprefs do a system-wide refresh, then scroller jumps back */
/* ar->v2d.flag &= ~V2D_IS_INITIALISED; */
@@ -111,7 +111,7 @@ static void userpref_main_area_init(wmWindowManager *wm, ARegion *ar)
ED_region_panels_init(wm, ar);
}
-static void userpref_main_area_draw(const bContext *C, ARegion *ar)
+static void userpref_main_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
@@ -126,17 +126,17 @@ static void userpref_keymap(struct wmKeyConfig *UNUSED(keyconf))
}
/* add handlers, stuff you only do once or on area/region changes */
-static void userpref_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void userpref_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
{
ED_region_header_init(ar);
}
-static void userpref_header_area_draw(const bContext *C, ARegion *ar)
+static void userpref_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void userpref_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void userpref_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
{
/* context changes */
}
@@ -171,9 +171,9 @@ void ED_spacetype_userpref(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype userpref region");
art->regionid = RGN_TYPE_WINDOW;
- art->init = userpref_main_area_init;
- art->draw = userpref_main_area_draw;
- art->listener = userpref_main_area_listener;
+ art->init = userpref_main_region_init;
+ art->draw = userpref_main_region_draw;
+ art->listener = userpref_main_region_listener;
art->keymapflag = ED_KEYMAP_UI;
BLI_addhead(&st->regiontypes, art);
@@ -184,8 +184,8 @@ void ED_spacetype_userpref(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
art->listener = userpref_header_listener;
- art->init = userpref_header_area_init;
- art->draw = userpref_header_area_draw;
+ art->init = userpref_header_region_init;
+ art->draw = userpref_header_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index f7698b0e9f3..2ff3dcdda29 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -61,6 +61,7 @@
#include "ED_armature.h"
#include "ED_keyframes_draw.h"
+#include "GPU_basic_shader.h"
#include "UI_resources.h"
@@ -884,8 +885,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
if (dt == OB_SOLID) {
/* set up solid drawing */
- glEnable(GL_COLOR_MATERIAL);
- glEnable(GL_LIGHTING);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
gluQuadricDrawStyle(qobj, GLU_FILL);
glShadeModel(GL_SMOOTH);
@@ -967,8 +967,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
/* restore */
if (dt == OB_SOLID) {
glShadeModel(GL_FLAT);
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
glPopMatrix();
@@ -1166,8 +1165,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
/* set up solid drawing */
if (dt > OB_WIRE) {
- glEnable(GL_COLOR_MATERIAL);
- glEnable(GL_LIGHTING);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
if (armflag & ARM_POSEMODE)
set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
@@ -1177,8 +1175,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
/* disable solid drawing */
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LIGHTING);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
else {
/* wire */
@@ -1297,8 +1294,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
/* set up solid drawing */
if (dt > OB_WIRE) {
- glEnable(GL_COLOR_MATERIAL);
- glEnable(GL_LIGHTING);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
UI_ThemeColor(TH_BONE_SOLID);
}
@@ -1352,8 +1348,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
/* disable solid drawing */
if (dt > OB_WIRE) {
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LIGHTING);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
}
@@ -2602,13 +2597,20 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (v3d->flag2 & V3D_RENDER_OVERRIDE)
return true;
-
- if (dt > OB_WIRE && !ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
+
+ if (dt > OB_WIRE) {
/* we use color for solid lighting */
- const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); /* only for lighting... */
+ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
+ const float diffuse[3] = {0.64f, 0.64f, 0.64f};
+ const float specular[3] = {0.5f, 0.5f, 0.5f};
+ GPU_basic_shader_colors(diffuse, specular, 35, 1.0f);
+ }
+ else {
+ const float diffuse[3] = {1.0f, 1.0f, 1.0f};
+ const float specular[3] = {1.0f, 1.0f, 1.0f};
+ GPU_basic_shader_colors(diffuse, specular, 35, 1.0f);
+ glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); /* only for lighting... */
+ }
}
/* arm->flag is being used to detect mode... */
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 9fac4ca2265..5c8c1a42389 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -60,9 +60,10 @@
#include "UI_resources.h"
-#include "GPU_extensions.h"
#include "GPU_draw.h"
#include "GPU_material.h"
+#include "GPU_basic_shader.h"
+#include "GPU_shader.h"
#include "RE_engine.h"
@@ -179,7 +180,6 @@ void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm, bool d
data.edge_flags = get_tface_mesh_marked_edge_info(me, draw_select_edges);
glEnable(GL_DEPTH_TEST);
- glDisable(GL_LIGHTING);
ED_view3d_polygon_offset(rv3d, 1.0);
/* Draw (Hidden) Edges */
@@ -231,10 +231,11 @@ static struct TextureDrawState {
int is_lit, is_tex;
int color_profile;
bool use_backface_culling;
+ bool two_sided_lighting;
unsigned char obcol[4];
bool is_texpaint;
bool texpaint_material; /* use material slots for texture painting */
-} Gtexdraw = {NULL, NULL, NULL, false, 0, 0, 0, false, {0, 0, 0, 0}, false, false};
+} Gtexdraw = {NULL, NULL, NULL, false, 0, 0, 0, false, false, {0, 0, 0, 0}, false, false};
static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material *ma, struct TextureDrawState gtexdraw)
{
@@ -370,24 +371,26 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material
if (c_badtex) lit = 0;
if (lit != c_lit || ma != c_ma) {
if (lit) {
- float spec[4];
- if (!ma) ma = give_current_material_or_def(NULL, 0); /* default material */
-
- spec[0] = ma->spec * ma->specr;
- spec[1] = ma->spec * ma->specg;
- spec[2] = ma->spec * ma->specb;
- spec[3] = 1.0;
-
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(ma->har, 0, 128));
- glEnable(GL_LIGHTING);
- glEnable(GL_COLOR_MATERIAL);
+ int options = GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR;
+
+ if (gtexdraw.two_sided_lighting)
+ options |= GPU_SHADER_TWO_SIDED;
+ if (c_textured && !c_badtex)
+ options |= GPU_SHADER_TEXTURE_2D;
+
+ if (!ma)
+ ma = give_current_material_or_def(NULL, 0); /* default material */
+
+ float specular[3];
+ mul_v3_v3fl(specular, &ma->specr, ma->spec);
+
+ GPU_basic_shader_colors(NULL, specular, ma->har, 0.0f);
+ GPU_basic_shader_bind(options);
}
else {
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
+
c_lit = lit;
c_ma = ma;
}
@@ -488,12 +491,12 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene);
Gtexdraw.use_game_mat = (RE_engines_find(scene->r.engine)->flag & RE_GAME) != 0;
Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0;
+ Gtexdraw.two_sided_lighting = (me->flag & ME_TWOSIDED);
memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
set_draw_settings_cached(1, NULL, NULL, Gtexdraw);
glShadeModel(GL_SMOOTH);
glCullFace(GL_BACK);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
}
static void draw_textured_end(void)
@@ -526,7 +529,7 @@ static void draw_textured_end(void)
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
/* XXX, bad patch - GPU_default_lights() calls
* glLightfv(GL_POSITION, ...) which
@@ -815,7 +818,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
/* TEXFACE */
if (glsl) {
- GPU_enable_material(matnr + 1, &gattribs);
+ GPU_object_material_bind(matnr + 1, &gattribs);
for (i = 0; i < gattribs.totlayer; i++) {
if (gattribs.layer[i].type == CD_MTFACE) {
@@ -967,7 +970,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
}
else if (draw_flags & DRAW_FACE_SELECT) {
if (ob->mode & OB_MODE_WEIGHT_PAINT)
- dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions_facemask, GPU_enable_material, NULL, me,
+ dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions_facemask, GPU_object_material_bind, NULL, me,
DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH | DM_DRAW_SKIP_HIDDEN);
else {
drawTFace_userData userData;
@@ -1016,6 +1019,8 @@ typedef struct TexMatCallback {
Object *ob;
Mesh *me;
DerivedMesh *dm;
+ bool shadeless;
+ bool two_sided_lighting;
} TexMatCallback;
static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *attribs)
@@ -1024,7 +1029,7 @@ static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *at
* that the GLSL code will give different result depending on the drawtype,
* in texture draw mode it will output the active texture node, in material
* draw mode it will show the full material. */
- GPU_enable_material(mat_nr, attribs);
+ GPU_object_material_bind(mat_nr, attribs);
}
static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
@@ -1035,31 +1040,21 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
Image *ima;
ImageUser *iuser;
bNode *node;
- int texture_set = 0;
/* draw image texture if we find one */
if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) {
/* get openl texture */
int mipmap = 1;
int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap, false) : 0;
- float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
if (bindcode) {
NodeTexBase *texbase = node->storage;
/* disable existing material */
- GPU_disable_material();
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
+ GPU_object_material_unbind();
/* bind texture */
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_COLOR_MATERIAL);
- glEnable(GL_TEXTURE_2D);
-
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
- glColor3f(1.0f, 1.0f, 1.0f);
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(texbase->tex_mapping.mat);
@@ -1073,21 +1068,36 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
gattribs->layer[0].gltexco = 1;
gattribs->totlayer = 1;
- texture_set = 1;
+ /* bind material */
+ float diffuse[3] = {1.0f, 1.0f, 1.0f};
+
+ int options = GPU_SHADER_TEXTURE_2D;
+ if (!data->shadeless)
+ options |= GPU_SHADER_LIGHTING;
+ if (data->two_sided_lighting)
+ options |= GPU_SHADER_TWO_SIDED;
+
+ GPU_basic_shader_colors(diffuse, NULL, 0, 0.0f);
+ GPU_basic_shader_bind(options);
+
+ return;
}
}
- if (!texture_set) {
+ /* disable texture material */
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+
+ if (data->shadeless) {
+ glColor3f(1.0f, 1.0f, 1.0f);
+ memset(gattribs, 0, sizeof(*gattribs));
+ }
+ else {
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
- /* disable texture */
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_COLOR_MATERIAL);
-
- /* draw single color */
- GPU_enable_material(mat_nr, attribs);
+ /* enable solid material */
+ GPU_object_material_bind(mat_nr, attribs);
}
}
@@ -1138,61 +1148,50 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
else glFrontFace(GL_CCW);
- if ((v3d->flag2 & V3D_SHADELESS_TEX) &&
- ((v3d->drawtype == OB_TEXTURE) || (ob->mode & OB_MODE_TEXTURE_PAINT)))
- {
- glColor3f(1.0f, 1.0f, 1.0f);
- }
- else {
- glEnable(GL_LIGHTING);
- }
-
- {
- Mesh *me = ob->data;
- TexMatCallback data = {scene, ob, me, dm};
- bool (*set_face_cb)(void *, int);
- bool glsl, picking = (G.f & G_PICKSEL) != 0;
-
- /* face hiding callback depending on mode */
- if (ob == scene->obedit)
- set_face_cb = tex_mat_set_face_editmesh_cb;
- else if (draw_flags & DRAW_FACE_SELECT)
- set_face_cb = tex_mat_set_face_mesh_cb;
- else
- set_face_cb = NULL;
-
- /* test if we can use glsl */
- glsl = (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support() && !picking;
+ Mesh *me = ob->data;
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ bool shadeless = ((v3d->flag2 & V3D_SHADELESS_TEX) &&
+ ((v3d->drawtype == OB_TEXTURE) || (ob->mode & OB_MODE_TEXTURE_PAINT)));
+ bool two_sided_lighting = (me->flag & ME_TWOSIDED) != 0;
- if (glsl || picking) {
- /* draw glsl or solid */
- dm->drawMappedFacesMat(dm,
- tex_mat_set_material_cb,
- set_face_cb, &data);
- }
- else {
- float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ TexMatCallback data = {scene, ob, me, dm, shadeless, two_sided_lighting};
+ bool (*set_face_cb)(void *, int);
+ bool picking = (G.f & G_PICKSEL) != 0;
+
+ /* face hiding callback depending on mode */
+ if (ob == scene->obedit)
+ set_face_cb = tex_mat_set_face_editmesh_cb;
+ else if (draw_flags & DRAW_FACE_SELECT)
+ set_face_cb = tex_mat_set_face_mesh_cb;
+ else
+ set_face_cb = NULL;
- /* draw textured */
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
+ /* test if we can use glsl */
+ bool glsl = (v3d->drawtype == OB_MATERIAL) && !picking;
- dm->drawMappedFacesMat(dm,
- tex_mat_set_texture_cb,
- set_face_cb, &data);
- }
+ GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
- GPU_end_object_materials();
+ if (glsl || picking) {
+ /* draw glsl or solid */
+ dm->drawMappedFacesMat(dm,
+ tex_mat_set_material_cb,
+ set_face_cb, &data);
}
+ else {
+ /* draw textured */
+ dm->drawMappedFacesMat(dm,
+ tex_mat_set_texture_cb,
+ set_face_cb, &data);
+ }
+
+ GPU_end_object_materials();
/* reset opengl state */
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_LIGHTING);
+ GPU_end_object_materials();
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+
glBindTexture(GL_TEXTURE_2D, 0);
+
glFrontFace(GL_CCW);
glMatrixMode(GL_TEXTURE);
@@ -1209,38 +1208,29 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
/* Vertex Paint and Weight Paint */
static void draw_mesh_paint_light_begin(void)
{
- const float spec[4] = {0.47f, 0.47f, 0.47f, 0.47f};
-
- GPU_enable_material(0, NULL);
-
- /* but set default spec */
- glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
-
- /* diffuse */
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_LIGHTING);
- glEnable(GL_COLOR_MATERIAL);
+ /* get material diffuse color from vertex colors but set default spec */
+ const float specular[3] = {0.47f, 0.47f, 0.47f};
+ GPU_basic_shader_colors(NULL, specular, 35, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
}
+
static void draw_mesh_paint_light_end(void)
{
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LIGHTING);
-
- GPU_disable_material();
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
void draw_mesh_paint_weight_faces(DerivedMesh *dm, const bool use_light,
void *facemask_cb, void *user_data)
{
- DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_enable_material : NULL;
+ DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_object_material_bind : NULL;
+ int flags = DM_DRAW_USE_COLORS;
if (use_light) {
draw_mesh_paint_light_begin();
+ flags |= DM_DRAW_NEED_NORMALS;
}
- dm->drawMappedFaces(dm, (DMSetDrawOptions)facemask_cb, setMaterial, NULL, user_data,
- DM_DRAW_USE_COLORS);
+ dm->drawMappedFaces(dm, (DMSetDrawOptions)facemask_cb, setMaterial, NULL, user_data, flags);
if (use_light) {
draw_mesh_paint_light_end();
@@ -1251,18 +1241,21 @@ void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light,
void *facemask_cb, void *user_data,
const Mesh *me)
{
- DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_enable_material : NULL;
+ DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_object_material_bind : NULL;
+ int flags = 0;
if (use_light) {
draw_mesh_paint_light_begin();
+ flags |= DM_DRAW_NEED_NORMALS;
}
if (me->mloopcol) {
- dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, DM_DRAW_USE_COLORS);
+ dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data,
+ DM_DRAW_USE_COLORS | flags);
}
else {
glColor3f(1.0f, 1.0f, 1.0f);
- dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, 0);
+ dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, flags);
}
if (use_light) {
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index c697b22d57b..e03f81742b7 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -87,8 +87,9 @@
#include "BIF_glutil.h"
#include "GPU_draw.h"
-#include "GPU_extensions.h"
#include "GPU_select.h"
+#include "GPU_basic_shader.h"
+#include "GPU_shader.h"
#include "ED_mesh.h"
#include "ED_particle.h"
@@ -289,8 +290,6 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
{
- if (!GPU_glsl_support())
- return false;
if (G.f & G_PICKSEL)
return false;
if (!check_object_draw_texture(scene, v3d, dt))
@@ -1694,8 +1693,6 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
v3d->bundle_size / 0.05f / camera_size[2]);
if (v3d->drawtype == OB_WIRE) {
- glDisable(GL_LIGHTING);
-
if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) {
glColor3ubv(ob_wire_col);
@@ -1706,8 +1703,6 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
}
drawaxes(0.05f, v3d->bundle_drawtype);
-
- glEnable(GL_LIGHTING);
}
else if (v3d->drawtype > OB_WIRE) {
if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
@@ -1718,13 +1713,11 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
}
glLineWidth(2.0f);
- glDisable(GL_LIGHTING);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
draw_bundle_sphere();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glEnable(GL_LIGHTING);
glLineWidth(1.0f);
}
@@ -1736,8 +1729,6 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
draw_bundle_sphere();
}
else {
- glDisable(GL_LIGHTING);
-
if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (selected) {
glColor3ubv(ob_wire_col);
@@ -1749,8 +1740,6 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
}
drawaxes(0.05f, v3d->bundle_drawtype);
-
- glEnable(GL_LIGHTING);
}
}
@@ -1778,7 +1767,6 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
MovieReconstructedCamera *camera = reconstruction->cameras;
int a = 0;
- glDisable(GL_LIGHTING);
UI_ThemeColor(TH_CAMERA_PATH);
glLineWidth(2.0f);
@@ -1789,7 +1777,6 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
glEnd();
glLineWidth(1.0f);
- glEnable(GL_LIGHTING);
}
}
}
@@ -1813,9 +1800,9 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d,
if (v3d->flag2 & V3D_RENDER_OVERRIDE)
return;
- glEnable(GL_LIGHTING);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_COLOR_MATERIAL);
+ GPU_basic_shader_colors(NULL, NULL, 0, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
+
glShadeModel(GL_SMOOTH);
tracking_object = tracking->objects.first;
@@ -1828,8 +1815,7 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d,
/* restore */
glShadeModel(GL_FLAT);
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LIGHTING);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
glColor3ubv(ob_wire_col);
@@ -2137,7 +2123,6 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
asp, shift, &drawsize, vec);
- glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
/* camera frame */
@@ -3799,16 +3784,16 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
/* use the cageDM since it always overlaps the editmesh faces */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
cageDM->drawMappedFaces(cageDM, draw_em_fancy__setFaceOpts,
- GPU_enable_material, NULL, me->edit_btmesh, DM_DRAW_SKIP_HIDDEN);
+ GPU_object_material_bind, NULL, me->edit_btmesh, DM_DRAW_SKIP_HIDDEN | DM_DRAW_NEED_NORMALS);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
else if (check_object_draw_texture(scene, v3d, dt)) {
if (draw_glsl_material(scene, ob, v3d, dt)) {
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
+ finalDM->drawMappedFacesGLSL(finalDM, GPU_object_material_bind,
draw_em_fancy__setGLSLFaceOpts, em);
- GPU_disable_material();
+ GPU_object_material_unbind();
glFrontFace(GL_CCW);
}
@@ -3817,17 +3802,12 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
}
}
else {
- /* 3 floats for position,
- * 3 for normal and times two because the faces may actually be quads instead of triangles */
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
-
- glEnable(GL_LIGHTING);
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, me->edit_btmesh, DM_DRAW_SKIP_HIDDEN);
+ finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_object_material_bind, NULL, me->edit_btmesh, DM_DRAW_SKIP_HIDDEN | DM_DRAW_NEED_NORMALS);
glFrontFace(GL_CCW);
- glDisable(GL_LIGHTING);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
+
+ GPU_object_material_unbind();
}
/* Setup for drawing wire over, disable zbuffer
@@ -3987,7 +3967,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
if (dt > OB_WIRE) {
glDepthMask(1);
ED_view3d_polygon_offset(rv3d, 0.0);
- GPU_disable_material();
+ GPU_object_material_unbind();
}
#if 0 /* currently not needed */
else if (use_occlude_wire) {
@@ -4006,13 +3986,13 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
glDepthMask(0);
- /* if transparent, we cannot draw the edges for solid select... edges have no material info.
- * drawFacesSolid() doesn't draw the transparent faces */
+ /* if transparent, we cannot draw the edges for solid select... edges
+ * have no material info. GPU_object_material_visible will skip the
+ * transparent faces */
if (ob->dtx & OB_DRAWTRANSP) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
+ dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_visible);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- GPU_disable_material();
}
else {
dm->drawEdges(dm, 0, 1);
@@ -4122,18 +4102,18 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
}
- GPU_enable_material(1, &gattribs);
+ GPU_object_material_bind(1, &gattribs);
dm->drawFacesSolid(dm, fpl, fast, NULL);
draw_loose = false;
}
else
- dm->drawFacesGLSL(dm, GPU_enable_material);
+ dm->drawFacesGLSL(dm, GPU_object_material_bind);
#if 0 /* XXX */
if (BKE_bproperty_object_get(ob, "Text"))
draw_mesh_text(ob, 1);
#endif
- GPU_disable_material();
+ GPU_object_material_unbind();
glFrontFace(GL_CCW);
@@ -4157,10 +4137,11 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (draw_flags & DRAW_MODIFIERS_PREVIEW) {
/* for object selection draws no shade */
if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) {
- dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
+ dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
+ GPU_object_material_unbind();
}
else {
- const float spec[4] = {0.47f, 0.47f, 0.47f, 0.47f};
+ const float specular[3] = {0.47f, 0.47f, 0.47f};
/* draw outline */
if ((v3d->flag & V3D_SELECT_OUTLINE) &&
@@ -4175,21 +4156,13 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
/* materials arent compatible with vertex colors */
GPU_end_object_materials();
- GPU_enable_material(0, NULL);
-
- /* set default spec */
- glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
- /* diffuse */
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_LIGHTING);
- glEnable(GL_COLOR_MATERIAL);
+ /* set default specular */
+ GPU_basic_shader_colors(NULL, specular, 35, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- dm->drawMappedFaces(dm, NULL, NULL, NULL, NULL, DM_DRAW_USE_COLORS);
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LIGHTING);
+ dm->drawMappedFaces(dm, NULL, NULL, NULL, NULL, DM_DRAW_USE_COLORS | DM_DRAW_NEED_NORMALS);
- GPU_disable_material();
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
}
else {
@@ -4204,9 +4177,6 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
draw_mesh_object_outline(v3d, ob, dm);
}
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
-
- glEnable(GL_LIGHTING);
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
if (ob->sculpt && (p = BKE_paint_get_active(scene))) {
@@ -4222,17 +4192,14 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
}
- dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
+ dm->drawFacesSolid(dm, fpl, fast, GPU_object_material_bind);
}
else
- dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
-
- GPU_disable_material();
+ dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
glFrontFace(GL_CCW);
- glDisable(GL_LIGHTING);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
+ GPU_object_material_unbind();
if (!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
@@ -4536,7 +4503,6 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
if (lb == NULL) return;
- glEnable(GL_LIGHTING);
glEnableClientState(GL_VERTEX_ARRAY);
if (ob->type == OB_MBALL) { /* mball always smooth shaded */
@@ -4553,8 +4519,6 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
if (ob->type == OB_SURF) {
int nr;
- glDisable(GL_LIGHTING);
-
if ((dflag & DRAW_CONSTCOLOR) == 0)
glColor3ubv(ob_wire_col);
@@ -4565,16 +4529,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
for (nr = dl->nr; nr; nr--, data += 3)
glVertex3fv(data);
glEnd();
-
- glEnable(GL_LIGHTING);
}
break;
case DL_POLY:
if (ob->type == OB_SURF) {
int nr;
- glDisable(GL_LIGHTING);
-
/* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
//glVertexPointer(3, GL_FLOAT, 0, dl->verts);
//glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
@@ -4583,14 +4543,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
for (nr = dl->nr; nr; nr--, data += 3)
glVertex3fv(data);
glEnd();
-
- glEnable(GL_LIGHTING);
}
break;
case DL_SURF:
if (dl->index) {
- GPU_enable_material(dl->col + 1, (use_glsl) ? &gattribs : NULL);
+ GPU_object_material_bind(dl->col + 1, (use_glsl) ? &gattribs : NULL);
if (dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
else glShadeModel(GL_FLAT);
@@ -4604,7 +4562,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
break;
case DL_INDEX3:
- GPU_enable_material(dl->col + 1, (use_glsl) ? &gattribs : NULL);
+ GPU_object_material_bind(dl->col + 1, (use_glsl) ? &gattribs : NULL);
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
@@ -4624,7 +4582,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
break;
case DL_INDEX4:
- GPU_enable_material(dl->col + 1, (use_glsl) ? &gattribs : NULL);
+ GPU_object_material_bind(dl->col + 1, (use_glsl) ? &gattribs : NULL);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
@@ -4639,8 +4597,9 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
glDisableClientState(GL_VERTEX_ARRAY);
glShadeModel(GL_FLAT);
- glDisable(GL_LIGHTING);
glFrontFace(GL_CCW);
+
+ GPU_object_material_unbind();
}
static void drawCurveDMWired(Object *ob)
@@ -4667,13 +4626,10 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d,
int glsl = draw_glsl_material(scene, ob, v3d, dt);
GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
- if (!glsl) {
- glEnable(GL_LIGHTING);
- dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
- glDisable(GL_LIGHTING);
- }
+ if (!glsl)
+ dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
else
- dm->drawFacesGLSL(dm, GPU_enable_material);
+ dm->drawFacesGLSL(dm, GPU_object_material_bind);
GPU_end_object_materials();
}
@@ -5505,19 +5461,10 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glEnableClientState(GL_COLOR_ARRAY);
}
- glEnable(GL_LIGHTING);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_COLOR_MATERIAL);
- }
-#if 0
- else {
- glDisableClientState(GL_NORMAL_ARRAY);
-
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LIGHTING);
- UI_ThemeColor(TH_WIRE);
+ // XXX test
+ GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
}
-#endif
if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
totpart = 0;
@@ -5548,8 +5495,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (part->draw & PART_DRAW_GUIDE_HAIRS) {
DerivedMesh *hair_dm = psys->hair_out_dm;
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
@@ -5593,8 +5538,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glEnd();
}
- glEnable(GL_LIGHTING);
- glEnable(GL_COLOR_MATERIAL);
glEnableClientState(GL_NORMAL_ARRAY);
if ((dflag & DRAW_CONSTCOLOR) == 0)
if (part->draw_col == PART_DRAW_COL_MAT)
@@ -5609,8 +5552,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
int *res = clmd->hair_grid_res;
int i;
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
@@ -5665,8 +5606,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glEnd();
glDisable(GL_BLEND);
- glEnable(GL_LIGHTING);
- glEnable(GL_COLOR_MATERIAL);
glEnableClientState(GL_NORMAL_ARRAY);
if ((dflag & DRAW_CONSTCOLOR) == 0)
if (part->draw_col == PART_DRAW_COL_MAT)
@@ -5697,7 +5636,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (1) { //ob_dt > OB_WIRE) {
if (part->draw_col == PART_DRAW_COL_MAT)
glDisableClientState(GL_COLOR_ARRAY);
- glDisable(GL_COLOR_MATERIAL);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
if (cdata2) {
@@ -5758,11 +5697,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (pdd->ndata && ob_dt > OB_WIRE) {
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, pdd->ndata);
- glEnable(GL_LIGHTING);
- }
- else {
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisable(GL_LIGHTING);
+ GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
}
if ((dflag & DRAW_CONSTCOLOR) == 0) {
@@ -5794,7 +5730,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
/* 7. */
- glDisable(GL_LIGHTING);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
@@ -5869,14 +5805,10 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_SMOOTH);
- if (pset->brushtype == PE_BRUSH_WEIGHT) {
+ if (pset->brushtype == PE_BRUSH_WEIGHT)
glLineWidth(2.0f);
- glDisable(GL_LIGHTING);
- }
cache = edit->pathcache;
for (i = 0, point = edit->points; i < totpoint; i++, point++) {
@@ -5989,8 +5921,6 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
}
glDisable(GL_BLEND);
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
@@ -7939,11 +7869,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
draw_bounding_volume(ob, ob->boundtype);
}
else {
- if (dt > OB_WIRE)
- GPU_enable_material(0, NULL); /* we use default material */
empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, false);
- if (dt > OB_WIRE)
- GPU_disable_material();
}
}
break;
@@ -8113,13 +8039,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
sds->tex = NULL;
GPU_create_smoke(smd, 0);
- draw_smoke_volume(sds, ob, p0, p1, sds->res, viewnormal);
+ draw_smoke_volume(sds, ob, p0, p1, viewnormal);
GPU_free_smoke(smd);
}
else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
sds->tex = NULL;
GPU_create_smoke(smd, 1);
- draw_smoke_volume(sds, ob, p0, p1, sds->res_wt, viewnormal);
+ draw_smoke_volume(sds, ob, p0, p1, viewnormal);
GPU_free_smoke(smd);
}
@@ -8542,7 +8468,7 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
DM_update_materials(dm, ob);
- dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, DM_DRAW_SKIP_HIDDEN);
+ dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_object_material_bind, NULL, me, DM_DRAW_SKIP_HIDDEN);
bbs_obmode_mesh_verts(ob, dm, 1);
bm_vertoffs = me->totvert + 1;
@@ -8668,23 +8594,17 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
glsl = draw_glsl_material(scene, ob, v3d, dt);
GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
}
- else {
- glEnable(GL_COLOR_MATERIAL);
- UI_ThemeColor(TH_BONE_SOLID);
- glDisable(GL_COLOR_MATERIAL);
- }
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- glEnable(GL_LIGHTING);
if (dm) {
- dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
+ dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
GPU_end_object_materials();
}
else if (edm)
- edm->drawMappedFaces(edm, NULL, GPU_enable_material, NULL, NULL, 0);
-
- glDisable(GL_LIGHTING);
+ edm->drawMappedFaces(edm, NULL, GPU_object_material_bind, NULL, NULL, DM_DRAW_NEED_NORMALS);
+
+ GPU_object_material_unbind();
}
if (edm) edm->release(edm);
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 7f102bccff1..102bfc55a2c 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -46,7 +46,8 @@
#include "BIF_gl.h"
-#include "GPU_extensions.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
#include "view3d_intern.h" // own include
@@ -135,9 +136,9 @@ static GPUTexture *create_flame_spectrum_texture(void)
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
const float min[3], const float max[3],
- const int res[3], const float viewnormal[3])
+ const float viewnormal[3])
{
- GPUTexture *tex_spec;
+ GPUTexture *tex_spec = NULL;
GPUProgram *smoke_program;
const int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED
: GPU_PROGRAM_SMOKE;
@@ -152,7 +153,6 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
float d /*, d0 */ /* UNUSED */, dd, ds;
float (*points)[3] = NULL;
int numpoints = 0;
- float cor[3] = {1.0f, 1.0f, 1.0f};
int gl_depth = 0, gl_blend = 0;
const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0;
@@ -171,6 +171,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
};
const float size[3] = { max[0] - min[0], max[1] - min[1], max[2] - min[2] };
+ const float invsize[3] = { 1.0f / size[0], 1.0f / size[1], 1.0f / size[2] };
/* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */
const float edges[12][2][3] = {
@@ -257,16 +258,6 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
GPU_texture_bind(tex_spec, 3);
}
- if (!GPU_non_power_of_two_support()) {
- cor[0] = (float)res[0] / (float)power_of_2_max_u(res[0]);
- cor[1] = (float)res[1] / (float)power_of_2_max_u(res[1]);
- cor[2] = (float)res[2] / (float)power_of_2_max_u(res[2]);
- }
-
- cor[0] /= size[0];
- cor[1] /= size[1];
- cor[2] /= size[2];
-
/* our slices are defined by the plane equation a*x + b*y +c*z + d = 0
* (a,b,c), the plane normal, are given by viewdir
* d is the parameter along the view direction. the first d is given by
@@ -318,9 +309,9 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
GPU_program_parameter_4f(smoke_program, 2, 1.0, 0.0, 0.0, 0.0);
glBegin(GL_POLYGON);
for (i = 0; i < numpoints; i++) {
- glTexCoord3d((points[i][0] - min[0]) * cor[0],
- (points[i][1] - min[1]) * cor[1],
- (points[i][2] - min[2]) * cor[2]);
+ glTexCoord3d((points[i][0] - min[0]) * invsize[0],
+ (points[i][1] - min[1]) * invsize[1],
+ (points[i][2] - min[2]) * invsize[2]);
glVertex3f(points[i][0] * ob_sizei[0],
points[i][1] * ob_sizei[1],
points[i][2] * ob_sizei[2]);
@@ -334,9 +325,9 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
GPU_program_parameter_4f(smoke_program, 2, -1.0, 0.0, 0.0, 0.0);
glBegin(GL_POLYGON);
for (i = 0; i < numpoints; i++) {
- glTexCoord3d((points[i][0] - min[0]) * cor[0],
- (points[i][1] - min[1]) * cor[1],
- (points[i][2] - min[2]) * cor[2]);
+ glTexCoord3d((points[i][0] - min[0]) * invsize[0],
+ (points[i][1] - min[1]) * invsize[1],
+ (points[i][2] - min[2]) * invsize[2]);
glVertex3f(points[i][0] * ob_sizei[0],
points[i][1] * ob_sizei[1],
points[i][2] * ob_sizei[2]);
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index e276a46fd71..fa14ca96fe2 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -54,9 +54,9 @@
#include "ED_space_api.h"
#include "ED_screen.h"
-#include "GPU_extensions.h"
-#include "GPU_material.h"
#include "GPU_compositing.h"
+#include "GPU_framebuffer.h"
+#include "GPU_material.h"
#include "BIF_gl.h"
@@ -342,7 +342,7 @@ static SpaceLink *view3d_new(const bContext *C)
v3d->twflag |= U.tw_flag & V3D_USE_MANIPULATOR;
v3d->twtype = V3D_MANIP_TRANSLATE;
- v3d->around = V3D_CENTROID;
+ v3d->around = V3D_AROUND_CENTER_MEAN;
v3d->bundle_size = 0.2f;
v3d->bundle_drawtype = OB_PLAINAXES;
@@ -384,8 +384,8 @@ static SpaceLink *view3d_new(const bContext *C)
ar->alignment = RGN_ALIGN_RIGHT;
ar->flag = RGN_FLAG_HIDDEN;
- /* main area */
- ar = MEM_callocN(sizeof(ARegion), "main area for view3d");
+ /* main region */
+ ar = MEM_callocN(sizeof(ARegion), "main region for view3d");
BLI_addtail(&v3d->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
@@ -482,7 +482,7 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
+static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
{
ListBase *lb;
wmKeyMap *keymap;
@@ -567,7 +567,7 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
}
-static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar)
+static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
@@ -715,7 +715,7 @@ static void view3d_dropboxes(void)
/* type callback, not region itself */
-static void view3d_main_area_free(ARegion *ar)
+static void view3d_main_region_free(ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
@@ -746,7 +746,7 @@ static void view3d_main_area_free(ARegion *ar)
}
/* copy regiondata */
-static void *view3d_main_area_duplicate(void *poin)
+static void *view3d_main_region_duplicate(void *poin)
{
if (poin) {
RegionView3D *rv3d = poin, *new;
@@ -799,7 +799,7 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene
}
}
-static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *wmn)
+static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *wmn)
{
Scene *scene = sc->scene;
View3D *v3d = sa->spacedata.first;
@@ -1025,7 +1025,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
}
/* concept is to retrieve cursor type context-less */
-static void view3d_main_area_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
+static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
{
Scene *scene = win->screen->scene;
@@ -1038,7 +1038,7 @@ static void view3d_main_area_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion
}
/* add handlers, stuff you only do once or on area/region changes */
-static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar)
+static void view3d_header_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
@@ -1047,12 +1047,12 @@ static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar)
ED_region_header_init(ar);
}
-static void view3d_header_area_draw(const bContext *C, ARegion *ar)
+static void view3d_header_region_draw(const bContext *C, ARegion *ar)
{
ED_region_header(C, ar);
}
-static void view3d_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void view3d_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -1083,7 +1083,7 @@ static void view3d_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
}
/* add handlers, stuff you only do once or on area/region changes */
-static void view3d_buttons_area_init(wmWindowManager *wm, ARegion *ar)
+static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -1093,12 +1093,12 @@ static void view3d_buttons_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void view3d_buttons_area_draw(const bContext *C, ARegion *ar)
+static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, NULL, -1, true);
}
-static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void view3d_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -1189,7 +1189,7 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
}
/* add handlers, stuff you only do once or on area/region changes */
-static void view3d_tools_area_init(wmWindowManager *wm, ARegion *ar)
+static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -1199,12 +1199,12 @@ static void view3d_tools_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void view3d_tools_area_draw(const bContext *C, ARegion *ar)
+static void view3d_tools_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar, CTX_data_mode_string(C), -1, true);
}
-static void view3d_props_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void view3d_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
@@ -1223,7 +1223,7 @@ static void view3d_props_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
}
}
-/*area (not region) level listener*/
+/* area (not region) level listener */
static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn)
{
View3D *v3d = sa->spacedata.first;
@@ -1424,13 +1424,13 @@ void ED_spacetype_view3d(void)
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
art->regionid = RGN_TYPE_WINDOW;
art->keymapflag = ED_KEYMAP_GPENCIL;
- art->draw = view3d_main_area_draw;
- art->init = view3d_main_area_init;
- art->exit = view3d_main_area_exit;
- art->free = view3d_main_area_free;
- art->duplicate = view3d_main_area_duplicate;
- art->listener = view3d_main_area_listener;
- art->cursor = view3d_main_area_cursor;
+ art->draw = view3d_main_region_draw;
+ art->init = view3d_main_region_init;
+ art->exit = view3d_main_region_exit;
+ art->free = view3d_main_region_free;
+ art->duplicate = view3d_main_region_duplicate;
+ art->listener = view3d_main_region_listener;
+ art->cursor = view3d_main_region_cursor;
art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
BLI_addhead(&st->regiontypes, art);
@@ -1439,9 +1439,9 @@ void ED_spacetype_view3d(void)
art->regionid = RGN_TYPE_UI;
art->prefsizex = 180; /* XXX */
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = view3d_buttons_area_listener;
- art->init = view3d_buttons_area_init;
- art->draw = view3d_buttons_area_draw;
+ art->listener = view3d_buttons_region_listener;
+ art->init = view3d_buttons_region_init;
+ art->draw = view3d_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
view3d_buttons_register(art);
@@ -1452,9 +1452,9 @@ void ED_spacetype_view3d(void)
art->prefsizex = 160; /* XXX */
art->prefsizey = 50; /* XXX */
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = view3d_buttons_area_listener;
- art->init = view3d_tools_area_init;
- art->draw = view3d_tools_area_draw;
+ art->listener = view3d_buttons_region_listener;
+ art->init = view3d_tools_region_init;
+ art->draw = view3d_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
#if 0
@@ -1468,9 +1468,9 @@ void ED_spacetype_view3d(void)
art->prefsizex = 0;
art->prefsizey = 120;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = view3d_props_area_listener;
- art->init = view3d_tools_area_init;
- art->draw = view3d_tools_area_draw;
+ art->listener = view3d_props_region_listener;
+ art->init = view3d_tools_region_init;
+ art->draw = view3d_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
view3d_tool_props_register(art);
@@ -1481,9 +1481,9 @@ void ED_spacetype_view3d(void)
art->regionid = RGN_TYPE_HEADER;
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
- art->listener = view3d_header_area_listener;
- art->init = view3d_header_area_init;
- art->draw = view3d_header_area_draw;
+ art->listener = view3d_header_region_listener;
+ art->init = view3d_header_region_init;
+ art->draw = view3d_header_region_draw;
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index dc0047db962..e7223ddf065 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -96,8 +96,8 @@
#include "UI_resources.h"
#include "GPU_draw.h"
+#include "GPU_framebuffer.h"
#include "GPU_material.h"
-#include "GPU_extensions.h"
#include "GPU_compositing.h"
#include "view3d_intern.h" /* own include */
@@ -2225,7 +2225,7 @@ void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
{
int x, y, w, h;
rcti r;
- /* clamp rect by area */
+ /* clamp rect by region */
r.xmin = 0;
r.xmax = ar->winx - 1;
@@ -2705,7 +2705,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view
}
/**
- * Shared by #ED_view3d_draw_offscreen and #view3d_main_area_draw_objects
+ * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects
*
* \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set.
* \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here.
@@ -2906,7 +2906,7 @@ static void view3d_draw_objects(
}
}
-static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
+static void view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
{
RegionView3D *rv3d = ar->regiondata;
@@ -2970,20 +2970,19 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d)
/*
* Function to clear the view
*/
-static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
+static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
{
if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
- bool glsl = GPU_glsl_support() && BKE_scene_use_new_shading_nodes(scene) && scene->world->nodetree && scene->world->use_nodes;
+ bool glsl = BKE_scene_use_new_shading_nodes(scene) && scene->world->nodetree && scene->world->use_nodes;
if (glsl) {
RegionView3D *rv3d = ar->regiondata;
GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
- bool material_not_bound;
/* calculate full shader for background */
GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
- material_not_bound = !GPU_material_bound(gpumat);
+ bool material_not_bound = !GPU_material_bound(gpumat);
if (material_not_bound) {
glMatrixMode(GL_PROJECTION);
@@ -3027,7 +3026,7 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
#define VIEWGRAD_RES_Y 16
GLubyte grid_col[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][4];
- static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][3];
+ static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][3];
static GLushort indices[VIEWGRAD_RES_X - 1][VIEWGRAD_RES_X - 1][4];
static bool buf_calculated = false;
@@ -3228,7 +3227,7 @@ void ED_view3d_draw_offscreen(
if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
else
- view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
/* framebuffer fx needed, we need to draw offscreen first */
if (v3d->fx_settings.fx_flag && fx) {
@@ -3247,7 +3246,7 @@ void ED_view3d_draw_offscreen(
/* clear opengl buffers */
if (do_sky) {
- view3d_main_area_clear(scene, v3d, ar);
+ view3d_main_region_clear(scene, v3d, ar);
}
else {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -3314,9 +3313,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
float winmat[4][4];
if (own_ofs) {
- /* state changes make normal drawing go weird otherwise */
- glPushAttrib(GL_LIGHTING_BIT);
-
/* bind */
ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, err_out);
if (ofs == NULL) {
@@ -3581,7 +3577,7 @@ void ED_scene_draw_fps(Scene *scene, const rcti *rect)
#endif
}
-static bool view3d_main_area_do_render_draw(Scene *scene)
+static bool view3d_main_region_do_render_draw(Scene *scene)
{
RenderEngineType *type = RE_engines_find(scene->r.engine);
@@ -3595,7 +3591,7 @@ bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *
bool use_border;
/* test if there is a 3d view rendering */
- if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(scene))
+ if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene))
return false;
/* test if there is a border render */
@@ -3629,7 +3625,7 @@ bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *
return true;
}
-static bool view3d_main_area_draw_engine(const bContext *C, Scene *scene,
+static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene,
ARegion *ar, View3D *v3d,
bool clip_border, const rcti *border_rect)
{
@@ -3657,7 +3653,7 @@ static bool view3d_main_area_draw_engine(const bContext *C, Scene *scene,
}
/* setup view matrices */
- view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
+ view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
/* background draw */
ED_region_pixelspace(ar);
@@ -3697,7 +3693,7 @@ static bool view3d_main_area_draw_engine(const bContext *C, Scene *scene,
return true;
}
-static void view3d_main_area_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border)
+static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border)
{
float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
@@ -3706,7 +3702,7 @@ static void view3d_main_area_draw_engine_info(View3D *v3d, RegionView3D *rv3d, A
if (render_border) {
/* draw darkened background color. no alpha because border render does
- * partial redraw and will not redraw the area behind this info bar */
+ * partial redraw and will not redraw the region behind this info bar */
float alpha = 1.0f - fill_color[3];
Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
@@ -3753,7 +3749,7 @@ static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d,
* we have no winmatrix (i.e., projection matrix) defined at that time.
* Since the camera and the camera shift are needed for the winmat calculation
* we do a small hack to replace it temporarily so we don't need to change the
- * view3d)main_area_setup_view() code to account for that.
+ * view3d)main_region_setup_view() code to account for that.
*/
static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
{
@@ -3781,7 +3777,7 @@ static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_area_setup_view(scene, v3d, ar, viewmat, NULL);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
data->shiftx = shiftx;
BLI_unlock_thread(LOCK_VIEW3D);
@@ -3795,7 +3791,7 @@ static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
v3d->camera = camera;
BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_area_setup_view(scene, v3d, ar, viewmat, NULL);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
v3d->camera = view_ob;
BLI_unlock_thread(LOCK_VIEW3D);
@@ -3811,14 +3807,14 @@ static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *
const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
}
else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
float viewmat[4][4];
Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
}
}
@@ -3836,7 +3832,7 @@ static void update_lods(Scene *scene, float camera_pos[3])
}
#endif
-static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
+static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
ARegion *ar, const char **grid_unit)
{
RegionView3D *rv3d = ar->regiondata;
@@ -3859,7 +3855,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
if (view3d_stereo3d_active(C, scene, v3d, rv3d))
view3d_stereo3d_setup(scene, v3d, ar);
else
- view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
+ view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
rv3d->rflag &= ~RV3D_IS_GAME_ENGINE;
#ifdef WITH_GAMEENGINE
@@ -3889,7 +3885,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
}
/* clear the background */
- view3d_main_area_clear(scene, v3d, ar);
+ view3d_main_region_clear(scene, v3d, ar);
/* enables anti-aliasing for 3D view drawing */
if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
@@ -3956,7 +3952,7 @@ static bool is_cursor_visible(Scene *scene)
return true;
}
-static void view3d_main_area_draw_info(const bContext *C, Scene *scene,
+static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
ARegion *ar, View3D *v3d,
const char *grid_unit, bool render_border)
{
@@ -4006,7 +4002,7 @@ static void view3d_main_area_draw_info(const bContext *C, Scene *scene,
}
if (rv3d->render_engine) {
- view3d_main_area_draw_engine_info(v3d, rv3d, ar, render_border);
+ view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border);
return;
}
@@ -4033,7 +4029,7 @@ static void view3d_main_area_draw_info(const bContext *C, Scene *scene,
}
}
-void view3d_main_area_draw(const bContext *C, ARegion *ar)
+void view3d_main_region_draw(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -4047,8 +4043,8 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect));
/* draw viewport using opengl */
- if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(scene) || clip_border) {
- view3d_main_area_draw_objects(C, scene, v3d, ar, &grid_unit);
+ if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) {
+ view3d_main_region_draw_objects(C, scene, v3d, ar, &grid_unit);
#ifdef DEBUG_DRAW
bl_debug_draw();
@@ -4061,9 +4057,9 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
/* draw viewport using external renderer */
if (v3d->drawtype == OB_RENDER)
- view3d_main_area_draw_engine(C, scene, ar, v3d, clip_border, &border_rect);
+ view3d_main_region_draw_engine(C, scene, ar, v3d, clip_border, &border_rect);
- view3d_main_area_draw_info(C, scene, ar, v3d, grid_unit, render_border);
+ view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border);
v3d->flag |= V3D_INVALID_BACKBUF;
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 7458d819213..b09cbedb6fa 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -700,7 +700,7 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
}
else {
/* If there's no selection, lastofs is unmodified and last value since static */
- is_set = calculateTransformCenter(C, V3D_CENTROID, lastofs, NULL);
+ is_set = calculateTransformCenter(C, V3D_AROUND_CENTER_MEAN, lastofs, NULL);
}
copy_v3_v3(r_dyn_ofs, lastofs);
@@ -3757,7 +3757,7 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
float twmat[3][3];
/* same as transform manipulator when normal is set */
- ED_getTransformOrientationMatrix(C, twmat, V3D_ACTIVE);
+ ED_getTransformOrientationMatrix(C, twmat, V3D_AROUND_ACTIVE);
mat3_to_quat(obact_quat, twmat);
invert_qt_normalized(obact_quat);
@@ -5168,10 +5168,11 @@ bool ED_view3d_snap_from_ray(
/* try snap edge, then face if it fails */
ret = snapObjectsRayEx(
- scene, NULL, NULL, NULL, obedit, SCE_SNAP_MODE_FACE,
- NULL, NULL,
+ scene, NULL, NULL, NULL, obedit,
+ NULL, SNAP_ALL, SCE_SNAP_MODE_FACE,
ray_start, ray_normal, &ray_dist,
- NULL, NULL, r_co, r_no_dummy, SNAP_ALL);
+ r_co, r_no_dummy, NULL, NULL,
+ NULL, NULL);
return ret;
}
@@ -5216,8 +5217,10 @@ bool ED_view3d_snap_from_region(
ray_dist = TRANSFORM_DIST_MAX_RAY;
}
if (snapObjectsEx(
- scene, NULL, v3d, ar, obedit, elem_type[i],
- mval, &dist_px, r_co, r_no_ptr, &ray_dist, SNAP_ALL))
+ scene, v3d, ar, NULL, obedit,
+ mval, SNAP_ALL, elem_type[i],
+ &ray_dist,
+ r_co, r_no_ptr, &dist_px))
{
is_hit = true;
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 94c1db8aa5d..2c6d76240d9 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -180,7 +180,7 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
void draw_sim_debug_data(Scene *scene, View3D *v3d, ARegion *ar);
/* view3d_draw.c */
-void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar);
+void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar);
void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride);
void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d);
void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag);
@@ -274,7 +274,7 @@ extern const char *view3d_context_dir[]; /* doc access */
/* draw_volume.c */
void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob,
const float min[3], const float max[3],
- const int res[3], const float viewnormal[3]);
+ const float viewnormal[3]);
//#define SMOKE_DEBUG_VELOCITY
//#define SMOKE_DEBUG_HEAT
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 3c0987221bd..0a465c751d2 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -784,7 +784,7 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh
EDBM_backbuf_free();
- paintface_flush_flags(ob);
+ paintface_flush_flags(ob, SELECT);
}
#if 0
@@ -2462,7 +2462,7 @@ static void paint_facesel_circle_select(ViewContext *vc, const bool select, cons
if (bbsel) {
edbm_backbuf_check_and_select_tfaces(me, select);
EDBM_backbuf_free();
- paintface_flush_flags(ob);
+ paintface_flush_flags(ob, SELECT);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 8bb84d00c83..e8e7d3c62fb 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -223,7 +223,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
cursor_global = ED_view3d_cursor3d_get(scene, v3d);
if (use_offset) {
- if ((v3d && v3d->around == V3D_ACTIVE) &&
+ if ((v3d && v3d->around == V3D_AROUND_ACTIVE) &&
snap_calc_active_center(C, true, center_global))
{
/* pass */
@@ -543,7 +543,7 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
minmax_v3v3_v3(min, max, vec);
}
- if (v3d->around == V3D_CENTROID) {
+ if (v3d->around == V3D_AROUND_CENTER_MEAN) {
mul_v3_fl(centroid, 1.0f / (float)tvs.transverts_tot);
copy_v3_v3(cursor, centroid);
}
@@ -595,7 +595,7 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
return false;
}
- if (v3d->around == V3D_CENTROID) {
+ if (v3d->around == V3D_AROUND_CENTER_MEAN) {
mul_v3_fl(centroid, 1.0f / (float)count);
copy_v3_v3(cursor, centroid);
}
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 4d36d703ae7..8b3ea2a1fee 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -403,7 +403,6 @@ static void walk_navigation_mode_set(bContext *C, wmOperator *op, WalkInfo *walk
*/
static bool walk_floor_distance_get(bContext *C, RegionView3D *rv3d, WalkInfo *walk, const float dvec[3], float *r_distance)
{
- float dummy_dist_px = 0;
float ray_normal[3] = {0, 0, -1}; /* down */
float ray_start[3];
float r_location[3];
@@ -418,10 +417,12 @@ static bool walk_floor_distance_get(bContext *C, RegionView3D *rv3d, WalkInfo *w
mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
add_v3_v3(ray_start, dvec_tmp);
- ret = snapObjectsRayEx(CTX_data_scene(C), NULL, NULL, NULL, NULL, SCE_SNAP_MODE_FACE,
- NULL, NULL,
- ray_start, ray_normal, r_distance,
- NULL, &dummy_dist_px, r_location, r_normal, SNAP_ALL);
+ ret = snapObjectsRayEx(
+ CTX_data_scene(C), NULL, NULL, NULL, NULL,
+ NULL, SNAP_ALL, SCE_SNAP_MODE_FACE,
+ ray_start, ray_normal, r_distance,
+ r_location, r_normal, NULL, NULL,
+ NULL, NULL);
/* artifically scale the distance to the scene size */
*r_distance /= walk->grid;
@@ -435,7 +436,6 @@ static bool walk_floor_distance_get(bContext *C, RegionView3D *rv3d, WalkInfo *w
*/
static bool walk_ray_cast(bContext *C, RegionView3D *rv3d, WalkInfo *walk, float r_location[3], float r_normal[3], float *ray_distance)
{
- float dummy_dist_px = 0;
float ray_normal[3] = {0, 0, 1}; /* forward */
float ray_start[3];
float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
@@ -451,10 +451,12 @@ static bool walk_ray_cast(bContext *C, RegionView3D *rv3d, WalkInfo *walk, float
mul_v3_fl(ray_normal, -1);
normalize_v3(ray_normal);
- ret = snapObjectsRayEx(CTX_data_scene(C), NULL, NULL, NULL, NULL, SCE_SNAP_MODE_FACE,
- NULL, NULL,
- ray_start, ray_normal, ray_distance,
- NULL, &dummy_dist_px, r_location, r_normal, SNAP_ALL);
+ ret = snapObjectsRayEx(
+ CTX_data_scene(C), NULL, NULL, NULL, NULL,
+ NULL, SNAP_ALL, SCE_SNAP_MODE_FACE,
+ ray_start, ray_normal, ray_distance,
+ r_location, r_normal, NULL, NULL,
+ NULL, NULL);
/* dot is positive if both rays are facing the same direction */
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 57688ca9f3c..7656a8a54c6 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -203,7 +203,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2]);
static bool transdata_check_local_center(TransInfo *t, short around)
{
- return ((around == V3D_LOCAL) && (
+ return ((around == V3D_AROUND_LOCAL_ORIGINS) && (
(t->flag & (T_OBJECT | T_POSE)) ||
(t->obedit && ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) ||
(t->spacetype == SPACE_IPO) ||
@@ -213,7 +213,7 @@ static bool transdata_check_local_center(TransInfo *t, short around)
bool transdata_check_local_islands(TransInfo *t, short around)
{
- return ((around == V3D_LOCAL) && (
+ return ((around == V3D_AROUND_LOCAL_ORIGINS) && (
(t->obedit && ELEM(t->obedit->type, OB_MESH))));
}
@@ -1553,8 +1553,8 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa
initTransInfo(C, t, NULL, NULL);
- /* avoid doing connectivity lookups (when V3D_LOCAL is set) */
- t->around = V3D_CENTER;
+ /* avoid doing connectivity lookups (when V3D_AROUND_LOCAL_ORIGINS is set) */
+ t->around = V3D_AROUND_CENTER_BOUNDS;
createTransData(C, t); // make TransData structs from selection
@@ -3018,7 +3018,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
/* rotation */
if ((t->flag & T_POINTS) == 0) {
- ElementRotation(t, td, mat, V3D_LOCAL);
+ ElementRotation(t, td, mat, V3D_AROUND_LOCAL_ORIGINS);
}
/* location */
@@ -4345,14 +4345,14 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal);
- ElementRotation(t, td, mat, V3D_LOCAL);
+ ElementRotation(t, td, mat, V3D_AROUND_LOCAL_ORIGINS);
}
else {
float mat[3][3];
unit_m3(mat);
- ElementRotation(t, td, mat, V3D_LOCAL);
+ ElementRotation(t, td, mat, V3D_AROUND_LOCAL_ORIGINS);
}
}
@@ -8524,7 +8524,9 @@ bool checkUseAxisMatrix(TransInfo *t)
{
/* currently only checks for editmode */
if (t->flag & T_EDIT) {
- if ((t->around == V3D_LOCAL) && (ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) {
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)))
+ {
/* not all editmode supports axis-matrix */
return true;
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 6360535a696..dc0b153d6e9 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -129,10 +129,10 @@
static void transform_around_single_fallback(TransInfo *t)
{
if ((t->total == 1) &&
- (ELEM(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) &&
+ (ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEAN, V3D_AROUND_ACTIVE)) &&
(ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
{
- t->around = V3D_LOCAL;
+ t->around = V3D_AROUND_LOCAL_ORIGINS;
}
}
@@ -681,7 +681,7 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
}
else if ((bone->flag & BONE_TRANSFORM) &&
(mode == TFM_ROTATION || mode == TFM_TRACKBALL) &&
- (around == V3D_LOCAL))
+ (around == V3D_AROUND_LOCAL_ORIGINS))
{
bone->flag |= BONE_TRANSFORM_CHILD;
}
@@ -1275,7 +1275,9 @@ static void createTransArmatureVerts(TransInfo *t)
* causes problem with snapping (see T45974).
* However, in rotation mode, we want to keep that 'rotate bone around root with
* only its tip selected' behavior (see T46325). */
- if ((t->around == V3D_LOCAL) && ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL))) {
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL)))
+ {
copy_v3_v3(td->center, ebo->head);
}
else {
@@ -1551,7 +1553,7 @@ static void createTransCurveVerts(TransInfo *t)
TransDataCurveHandleFlags *hdata = NULL;
float axismtx[3][3];
- if (t->around == V3D_LOCAL) {
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
float normal[3], plane[3];
BKE_nurb_bezt_calc_normal(nu, bezt, normal);
@@ -1574,7 +1576,7 @@ static void createTransCurveVerts(TransInfo *t)
copy_v3_v3(td->iloc, bezt->vec[0]);
td->loc = bezt->vec[0];
copy_v3_v3(td->center, bezt->vec[(hide_handles ||
- (t->around == V3D_LOCAL) ||
+ (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
(bezt->f2 & SELECT)) ? 1 : 0]);
if (hide_handles) {
if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
@@ -1591,7 +1593,7 @@ static void createTransCurveVerts(TransInfo *t)
copy_m3_m3(td->smtx, smtx);
copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_LOCAL) {
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
copy_m3_m3(td->axismtx, axismtx);
}
@@ -1623,7 +1625,7 @@ static void createTransCurveVerts(TransInfo *t)
copy_m3_m3(td->smtx, smtx);
copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_LOCAL) {
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
copy_m3_m3(td->axismtx, axismtx);
}
@@ -1644,7 +1646,7 @@ static void createTransCurveVerts(TransInfo *t)
copy_v3_v3(td->iloc, bezt->vec[2]);
td->loc = bezt->vec[2];
copy_v3_v3(td->center, bezt->vec[(hide_handles ||
- (t->around == V3D_LOCAL) ||
+ (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
(bezt->f2 & SELECT)) ? 1 : 2]);
if (hide_handles) {
if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
@@ -1663,7 +1665,7 @@ static void createTransCurveVerts(TransInfo *t)
copy_m3_m3(td->smtx, smtx);
copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_LOCAL) {
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
copy_m3_m3(td->axismtx, axismtx);
}
@@ -2261,7 +2263,7 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
copy_v3_v3(td->center, v_island->co);
copy_m3_m3(td->axismtx, v_island->axismtx);
}
- else if (t->around == V3D_LOCAL) {
+ else if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
copy_v3_v3(td->center, td->loc);
createSpaceNormal(td->axismtx, no);
}
@@ -2392,7 +2394,7 @@ static void createTransEditVerts(TransInfo *t)
editmesh_set_connectivity_distance(em->bm, mtx, dists);
}
- if (t->around == V3D_LOCAL) {
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map);
}
@@ -2760,7 +2762,7 @@ static void createTransUVs(bContext *C, TransInfo *t)
int count = 0, countsel = 0, count_rejected = 0;
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0;
- const bool is_island_center = (t->around == V3D_LOCAL);
+ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
@@ -4019,7 +4021,8 @@ static bool graph_edit_is_translation_mode(TransInfo *t)
static bool graph_edit_use_local_center(TransInfo *t)
{
- return (t->around == V3D_LOCAL) && !graph_edit_is_translation_mode(t);
+ return ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (graph_edit_is_translation_mode(t) == false));
}
@@ -5436,7 +5439,9 @@ static void set_trans_object_base_flags(TransInfo *t)
if (parsel) {
/* rotation around local centers are allowed to propagate */
- if ((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL) {
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
+ {
base->flag |= BA_TRANSFORM_CHILD;
}
else {
@@ -5486,7 +5491,9 @@ static int count_proportional_objects(TransInfo *t)
Base *base;
/* rotations around local centers are allowed to propagate, so we take all objects */
- if (!((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL)) {
+ if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)))
+ {
/* mark all parents */
for (base = scene->base.first; base; base = base->next) {
if (TESTBASELIB_BGMODE(v3d, scene, base)) {
@@ -5607,22 +5614,22 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
do_loc = true;
}
else if (tmode == TFM_ROTATION) {
- if (v3d->around == V3D_ACTIVE) {
+ if (v3d->around == V3D_AROUND_ACTIVE) {
if (ob != OBACT)
do_loc = true;
}
- else if (v3d->around == V3D_CURSOR)
+ else if (v3d->around == V3D_AROUND_CURSOR)
do_loc = true;
if ((v3d->flag & V3D_ALIGN) == 0)
do_rot = true;
}
else if (tmode == TFM_RESIZE) {
- if (v3d->around == V3D_ACTIVE) {
+ if (v3d->around == V3D_AROUND_ACTIVE) {
if (ob != OBACT)
do_loc = true;
}
- else if (v3d->around == V3D_CURSOR)
+ else if (v3d->around == V3D_AROUND_CURSOR)
do_loc = true;
if ((v3d->flag & V3D_ALIGN) == 0)
@@ -5747,14 +5754,14 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
do_loc = true;
}
else if (tmode == TFM_ROTATION) {
- if (ELEM(v3d->around, V3D_CURSOR, V3D_ACTIVE))
+ if (ELEM(v3d->around, V3D_AROUND_CURSOR, V3D_AROUND_ACTIVE))
do_loc = true;
if ((v3d->flag & V3D_ALIGN) == 0)
do_rot = true;
}
else if (tmode == TFM_RESIZE) {
- if (ELEM(v3d->around, V3D_CURSOR, V3D_ACTIVE))
+ if (ELEM(v3d->around, V3D_AROUND_CURSOR, V3D_AROUND_ACTIVE))
do_loc = true;
if ((v3d->flag & V3D_ALIGN) == 0)
@@ -5935,6 +5942,10 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
}
EDBM_automerge(t->scene, t->obedit, true, hflag);
+
+ if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
+ EDBM_select_flush(em);
+ }
}
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 77c34b888fb..84087ec8840 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1219,13 +1219,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* bend always uses the cursor */
if (t->mode == TFM_BEND) {
- t->around = V3D_CURSOR;
+ t->around = V3D_AROUND_CURSOR;
}
t->current_orientation = v3d->twmode;
/* exceptional case */
- if (t->around == V3D_LOCAL) {
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
const bool use_island = transdata_check_local_islands(t, t->around);
@@ -1281,7 +1281,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
else if (t->spacetype == SPACE_NODE) {
// XXX for now, get View2D from the active region
t->view = &ar->v2d;
- t->around = V3D_CENTER;
+ t->around = V3D_AROUND_CENTER_BOUNDS;
}
else if (t->spacetype == SPACE_IPO) {
SpaceIpo *sipo = sa->spacedata.first;
@@ -1307,7 +1307,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
else {
t->view = NULL;
}
- t->around = V3D_CENTER;
+ t->around = V3D_AROUND_CENTER_BOUNDS;
}
if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
@@ -1778,13 +1778,13 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
void calculateCenter(TransInfo *t)
{
switch (t->around) {
- case V3D_CENTER:
+ case V3D_AROUND_CENTER_BOUNDS:
calculateCenterBound(t, t->center);
break;
- case V3D_CENTROID:
+ case V3D_AROUND_CENTER_MEAN:
calculateCenterMedian(t, t->center);
break;
- case V3D_CURSOR:
+ case V3D_AROUND_CURSOR:
if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
calculateCenterCursor2D(t, t->center);
else if (t->spacetype == SPACE_IPO)
@@ -1792,11 +1792,11 @@ void calculateCenter(TransInfo *t)
else
calculateCenterCursor(t, t->center);
break;
- case V3D_LOCAL:
+ case V3D_AROUND_LOCAL_ORIGINS:
/* Individual element center uses median center for helpline and such */
calculateCenterMedian(t, t->center);
break;
- case V3D_ACTIVE:
+ case V3D_AROUND_ACTIVE:
{
if (calculateCenterActive(t, false, t->center)) {
/* pass */
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 44779fc1cf2..b4e907c4ffe 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -51,9 +51,9 @@ static void InputSpring(TransInfo *UNUSED(t), MouseInput *mi, const double mval[
double dx, dy;
float ratio;
- dx = (mi->center[0] - mval[0]);
- dy = (mi->center[1] - mval[1]);
- ratio = hypot(dx, dy) / mi->factor;
+ dx = ((double)mi->center[0] - mval[0]);
+ dy = ((double)mi->center[1] - mval[1]);
+ ratio = hypot(dx, dy) / (double)mi->factor;
output[0] = ratio;
}
@@ -64,8 +64,8 @@ static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2],
/* flip scale */
/* values can become really big when zoomed in so use longs [#26598] */
- if ((long long int)(mi->center[0] - mval[0]) * (long long int)(mi->center[0] - mi->imval[0]) +
- (long long int)(mi->center[1] - mval[1]) * (long long int)(mi->center[1] - mi->imval[1]) < 0)
+ if ((int64_t)((int)mi->center[0] - mval[0]) * (int64_t)((int)mi->center[0] - mi->imval[0]) +
+ (int64_t)((int)mi->center[1] - mval[1]) * (int64_t)((int)mi->center[1] - mi->imval[1]) < 0)
{
output[0] *= -1.0f;
}
@@ -88,7 +88,7 @@ static void InputTrackBall(TransInfo *UNUSED(t), MouseInput *mi, const double mv
static void InputHorizontalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3])
{
- const float pad = t->ar->winx / 10;
+ const double pad = t->ar->winx / 10;
output[0] = (mval[0] - pad) / (t->ar->winx - 2 * pad);
}
@@ -105,7 +105,7 @@ static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double m
static void InputVerticalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3])
{
- const float pad = t->ar->winy / 10;
+ const double pad = t->ar->winy / 10;
output[0] = (mval[1] - pad) / (t->ar->winy - 2 * pad);
}
@@ -171,12 +171,12 @@ struct InputAngle_Data {
static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
{
struct InputAngle_Data *data = mi->data;
- double dx2 = mval[0] - mi->center[0];
- double dy2 = mval[1] - mi->center[1];
+ double dx2 = mval[0] - (double)mi->center[0];
+ double dy2 = mval[1] - (double)mi->center[1];
double B = sqrt(dx2 * dx2 + dy2 * dy2);
- double dx1 = data->mval_prev[0] - mi->center[0];
- double dy1 = data->mval_prev[1] - mi->center[1];
+ double dx1 = data->mval_prev[0] - (double)mi->center[0];
+ double dy1 = data->mval_prev[1] - (double)mi->center[1];
double A = sqrt(dx1 * dx1 + dy1 * dy1);
double dx3 = mval[0] - data->mval_prev[0];
@@ -214,7 +214,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2
if ((dx1 * dy2 - dx2 * dy1) > 0.0) dphi = -dphi;
}
- data->angle += ((double)dphi) * (mi->precision ? mi->precision_factor : 1.0f);
+ data->angle += ((double)dphi) * (mi->precision ? (double)mi->precision_factor : 1.0);
data->mval_prev[0] = mval[0];
data->mval_prev[1] = mval[1];
@@ -371,8 +371,8 @@ void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float outp
mi->virtual_mval.prev[1] += mval_delta[1];
if (mi->precision) {
- mval_delta[0] *= mi->precision_factor;
- mval_delta[1] *= mi->precision_factor;
+ mval_delta[0] *= (double)mi->precision_factor;
+ mval_delta[1] *= (double)mi->precision_factor;
}
mi->virtual_mval.accum[0] += mval_delta[0];
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 8ddd7aebc54..0c3f74dbe9d 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -321,7 +321,7 @@ static int calc_manipulator_stats(const bContext *C)
float vec[3] = {0, 0, 0};
/* USE LAST SELECTE WITH ACTIVE */
- if ((v3d->around == V3D_ACTIVE) && BM_select_history_active_get(em->bm, &ese)) {
+ if ((v3d->around == V3D_AROUND_ACTIVE) && BM_select_history_active_get(em->bm, &ese)) {
BM_editselection_center(&ese, vec);
calc_tw_center(scene, vec);
totsel = 1;
@@ -346,7 +346,7 @@ static int calc_manipulator_stats(const bContext *C)
bArmature *arm = obedit->data;
EditBone *ebo;
- if ((v3d->around == V3D_ACTIVE) && (ebo = arm->act_edbone)) {
+ if ((v3d->around == V3D_AROUND_ACTIVE) && (ebo = arm->act_edbone)) {
/* doesn't check selection or visibility intentionally */
if (ebo->flag & BONE_TIPSEL) {
calc_tw_center(scene, ebo->tail);
@@ -382,7 +382,7 @@ static int calc_manipulator_stats(const bContext *C)
Curve *cu = obedit->data;
float center[3];
- if (v3d->around == V3D_ACTIVE && ED_curve_active_center(cu, center)) {
+ if (v3d->around == V3D_AROUND_ACTIVE && ED_curve_active_center(cu, center)) {
calc_tw_center(scene, center);
totsel++;
}
@@ -414,11 +414,11 @@ static int calc_manipulator_stats(const bContext *C)
}
else {
if (bezt->f1 & SELECT) {
- calc_tw_center(scene, bezt->vec[(v3d->around == V3D_LOCAL) ? 1 : 0]);
+ calc_tw_center(scene, bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0]);
totsel++;
}
if (bezt->f3 & SELECT) {
- calc_tw_center(scene, bezt->vec[(v3d->around == V3D_LOCAL) ? 1 : 2]);
+ calc_tw_center(scene, bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2]);
totsel++;
}
}
@@ -444,7 +444,7 @@ static int calc_manipulator_stats(const bContext *C)
MetaBall *mb = (MetaBall *)obedit->data;
MetaElem *ml;
- if ((v3d->around == V3D_ACTIVE) && (ml = mb->lastelem)) {
+ if ((v3d->around == V3D_AROUND_ACTIVE) && (ml = mb->lastelem)) {
calc_tw_center(scene, &ml->x);
totsel++;
}
@@ -461,7 +461,7 @@ static int calc_manipulator_stats(const bContext *C)
Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
BPoint *bp;
- if ((v3d->around == V3D_ACTIVE) && (bp = BKE_lattice_active_point_get(lt))) {
+ if ((v3d->around == V3D_AROUND_ACTIVE) && (bp = BKE_lattice_active_point_get(lt))) {
calc_tw_center(scene, bp->vec);
totsel++;
}
@@ -493,7 +493,7 @@ static int calc_manipulator_stats(const bContext *C)
if ((ob->lay & v3d->lay) == 0) return 0;
- if ((v3d->around == V3D_ACTIVE) && (pchan = BKE_pose_channel_active(ob))) {
+ if ((v3d->around == V3D_AROUND_ACTIVE) && (pchan = BKE_pose_channel_active(ob))) {
/* doesn't check selection or visibility intentionally */
Bone *bone = pchan->bone;
if (bone) {
@@ -1620,13 +1620,10 @@ void BIF_draw_manipulator(const bContext *C)
/* now we can define center */
switch (v3d->around) {
- case V3D_CENTER:
- case V3D_ACTIVE:
+ case V3D_AROUND_CENTER_BOUNDS:
+ case V3D_AROUND_ACTIVE:
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- Object *ob = OBACT;
-
- if (((v3d->around == V3D_ACTIVE) && (scene->obedit == NULL)) &&
+ if (((v3d->around == V3D_AROUND_ACTIVE) && (scene->obedit == NULL)) &&
((gpd == NULL) || !(gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
(!(ob->mode & OB_MODE_POSE)))
{
@@ -1637,11 +1634,11 @@ void BIF_draw_manipulator(const bContext *C)
}
break;
}
- case V3D_LOCAL:
- case V3D_CENTROID:
+ case V3D_AROUND_LOCAL_ORIGINS:
+ case V3D_AROUND_CENTER_MEAN:
copy_v3_v3(rv3d->twmat[3], scene->twcent);
break;
- case V3D_CURSOR:
+ case V3D_AROUND_CURSOR:
copy_v3_v3(rv3d->twmat[3], ED_view3d_cursor3d_get(scene, v3d));
break;
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index a1bb6f4e0f3..2ea18d509f0 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -591,7 +591,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
Base *base;
Object *ob = OBACT;
int result = ORIENTATION_NONE;
- const bool activeOnly = (around == V3D_ACTIVE);
+ const bool activeOnly = (around == V3D_AROUND_ACTIVE);
zero_v3(normal);
zero_v3(plane);
@@ -854,7 +854,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
/* exception */
if (flag) {
float tvec[3];
- if ((around == V3D_LOCAL) ||
+ if ((around == V3D_AROUND_LOCAL_ORIGINS) ||
ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
{
BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
@@ -1044,8 +1044,8 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
{
- /* dummy value, not V3D_ACTIVE and not V3D_LOCAL */
- short around = V3D_CENTER;
+ /* dummy value, not V3D_AROUND_ACTIVE and not V3D_AROUND_LOCAL_ORIGINS */
+ short around = V3D_AROUND_CENTER_BOUNDS;
return getTransformOrientation_ex(C, normal, plane, around);
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 2251dedc268..359e191c90d 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -112,7 +112,7 @@ static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]);
/****************** IMPLEMENTATIONS *********************/
-static bool snapNodeTest(View2D *v2d, bNode *node, SnapMode mode);
+static bool snapNodeTest(View2D *v2d, bNode *node, SnapSelect snap_select);
static NodeBorder snapNodeBorder(int snap_node_mode);
#if 0
@@ -330,7 +330,10 @@ void applyProject(TransInfo *t)
}
if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- if (snapObjectsTransform(t, mval_fl, &dist_px, loc, no, t->tsnap.modeSelect)) {
+ if (snapObjectsTransform(
+ t, mval_fl, t->tsnap.modeSelect,
+ loc, no, &dist_px))
+ {
// if (t->flag & (T_EDIT|T_POSE)) {
// mul_m4_v3(imat, loc);
// }
@@ -933,7 +936,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
BLI_listbase_clear(&depth_peels);
- peelObjectsTransForm(t, &depth_peels, mval, t->tsnap.modeSelect);
+ peelObjectsTransForm(t, mval, t->tsnap.modeSelect, &depth_peels);
// if (LAST_SNAP_POINT_VALID)
// {
@@ -1008,7 +1011,9 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
}
else {
zero_v3(no); /* objects won't set this */
- found = snapObjectsTransform(t, mval, &dist_px, loc, no, t->tsnap.modeSelect);
+ found = snapObjectsTransform(
+ t, mval, t->tsnap.modeSelect,
+ loc, no, &dist_px);
}
if (found == true) {
@@ -1052,7 +1057,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
char node_border;
- if (snapNodesTransform(t, t->mval, &dist_px, loc, &node_border, t->tsnap.modeSelect)) {
+ if (snapNodesTransform(t, t->mval, t->tsnap.modeSelect, loc, &dist_px, &node_border)) {
copy_v2_v2(t->tsnap.snapPoint, loc);
t->tsnap.snapNodeBorder = node_border;
@@ -1242,9 +1247,11 @@ static void TargetSnapClosest(TransInfo *t)
}
}
-static bool snapEdge(ARegion *ar, const float v1co[3], const short v1no[3], const float v2co[3], const short v2no[3], float obmat[4][4], float timat[3][3],
- const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2],
- float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
+static bool snapEdge(
+ ARegion *ar, const float v1co[3], const short v1no[3], const float v2co[3], const short v2no[3],
+ float obmat[4][4], float timat[3][3], const float mval_fl[2],
+ const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], float *ray_depth,
+ float r_loc[3], float r_no[3], float *r_dist_px)
{
float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
int result;
@@ -1300,10 +1307,10 @@ static bool snapEdge(ARegion *ar, const float v1co[3], const short v1no[3], cons
* this takes care of series of connected edges a bit slanted w.r.t the viewport
* otherwise, it would stick to the verts of the closest edge and not slide along merrily
* */
- if (new_dist <= *r_dist_px && new_depth < *r_depth * 1.001f) {
+ if (new_dist <= *r_dist_px && new_depth < *ray_depth * 1.001f) {
float n1[3], n2[3];
- *r_depth = new_depth;
+ *ray_depth = new_depth;
retval = true;
sub_v3_v3v3(edge_loc, v1co, v2co);
@@ -1329,9 +1336,11 @@ static bool snapEdge(ARegion *ar, const float v1co[3], const short v1no[3], cons
return retval;
}
-static bool snapVertex(ARegion *ar, const float vco[3], const short vno[3], float obmat[4][4], float timat[3][3],
- const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2],
- float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
+static bool snapVertex(
+ ARegion *ar, const float vco[3], const short vno[3],
+ float obmat[4][4], float timat[3][3], const float mval_fl[2],
+ const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], float *ray_depth,
+ float r_loc[3], float r_no[3], float *r_dist_px)
{
bool retval = false;
float dvec[3];
@@ -1358,8 +1367,8 @@ static bool snapVertex(ARegion *ar, const float vco[3], const short vno[3], floa
}
- if (new_dist <= *r_dist_px && new_depth < *r_depth) {
- *r_depth = new_depth;
+ if (new_dist <= *r_dist_px && new_depth < *ray_depth) {
+ *ray_depth = new_depth;
retval = true;
copy_v3_v3(r_loc, location);
@@ -1377,9 +1386,11 @@ static bool snapVertex(ARegion *ar, const float vco[3], const short vno[3], floa
return retval;
}
-static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float *UNUSED(r_no), float *r_dist_px, float *r_depth)
+static bool snapArmature(
+ ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
+ const float mval[2], const short snap_to,
+ const float ray_start[3], const float ray_normal[3], float *ray_depth,
+ float r_loc[3], float *UNUSED(r_no), float *r_dist_px)
{
float imat[4][4];
float ray_start_local[3], ray_normal_local[3];
@@ -1397,13 +1408,13 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar
if (eBone->layer & arm->layer) {
/* skip hidden or moving (selected) bones */
if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
- switch (snap_mode) {
+ switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
- retval |= snapVertex(ar, eBone->head, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
- retval |= snapVertex(ar, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, eBone->head, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
+ retval |= snapVertex(ar, eBone->tail, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
break;
case SCE_SNAP_MODE_EDGE:
- retval |= snapEdge(ar, eBone->head, NULL, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapEdge(ar, eBone->head, NULL, eBone->tail, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
break;
}
}
@@ -1421,13 +1432,13 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar
const float *head_vec = pchan->pose_head;
const float *tail_vec = pchan->pose_tail;
- switch (snap_mode) {
+ switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
- retval |= snapVertex(ar, head_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
- retval |= snapVertex(ar, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, head_vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
+ retval |= snapVertex(ar, tail_vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
break;
case SCE_SNAP_MODE_EDGE:
- retval |= snapEdge(ar, head_vec, NULL, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapEdge(ar, head_vec, NULL, tail_vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
break;
}
}
@@ -1437,9 +1448,11 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar
return retval;
}
-static bool snapCurve(short snap_mode, ARegion *ar, Object *ob, Curve *cu, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float *UNUSED(r_no), float *r_dist_px, float *r_depth)
+static bool snapCurve(
+ ARegion *ar, Object *ob, Curve *cu, float obmat[4][4],
+ const float mval[2], const short snap_to,
+ const float ray_start[3], const float ray_normal[3], float *ray_depth,
+ float r_loc[3], float *UNUSED(r_no), float *r_dist_px)
{
float imat[4][4];
float ray_start_local[3], ray_normal_local[3];
@@ -1449,7 +1462,7 @@ static bool snapCurve(short snap_mode, ARegion *ar, Object *ob, Curve *cu, float
Nurb *nu;
/* only vertex snapping mode (eg control points and handles) supported for now) */
- if (snap_mode != SCE_SNAP_MODE_VERTEX) {
+ if (snap_to != SCE_SNAP_MODE_VERTEX) {
return retval;
}
@@ -1463,7 +1476,7 @@ static bool snapCurve(short snap_mode, ARegion *ar, Object *ob, Curve *cu, float
for (nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
for (u = 0; u < nu->pntsu; u++) {
- switch (snap_mode) {
+ switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
if (ob->mode == OB_MODE_EDIT) {
@@ -1472,13 +1485,13 @@ static bool snapCurve(short snap_mode, ARegion *ar, Object *ob, Curve *cu, float
if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
break;
}
- retval |= snapVertex(ar, nu->bezt[u].vec[1], NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, nu->bezt[u].vec[1], NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
/* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
if (!(nu->bezt[u].f1 & SELECT) && !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) {
- retval |= snapVertex(ar, nu->bezt[u].vec[0], NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, nu->bezt[u].vec[0], NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
}
if (!(nu->bezt[u].f3 & SELECT) && !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) {
- retval |= snapVertex(ar, nu->bezt[u].vec[2], NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, nu->bezt[u].vec[2], NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
}
}
else {
@@ -1486,17 +1499,17 @@ static bool snapCurve(short snap_mode, ARegion *ar, Object *ob, Curve *cu, float
if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
break;
}
- retval |= snapVertex(ar, nu->bp[u].vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, nu->bp[u].vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
}
}
else {
/* curve is not visible outside editmode if nurb length less than two */
if (nu->pntsu > 1) {
if (nu->bezt) {
- retval |= snapVertex(ar, nu->bezt[u].vec[1], NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, nu->bezt[u].vec[1], NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
}
else {
- retval |= snapVertex(ar, nu->bp[u].vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(ar, nu->bp[u].vec, NULL, obmat, NULL, mval, ray_start, ray_start_local, ray_normal_local, ray_depth, r_loc, NULL, r_dist_px);
}
}
}
@@ -1510,13 +1523,22 @@ static bool snapCurve(short snap_mode, ARegion *ar, Object *ob, Curve *cu, float
return retval;
}
-static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float ray_origin[3],
- const float mval[2], float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth, bool do_bb)
+static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
+{
+ const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
+}
+
+static bool snapDerivedMesh(
+ ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4],
+ const float mval[2], const short snap_to, bool do_bb,
+ const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
+ float r_loc[3], float r_no[3], float *r_dist_px, int *r_index)
{
bool retval = false;
- const bool do_ray_start_correction = (snap_mode == SCE_SNAP_MODE_FACE && ar &&
- !((RegionView3D *)ar->regiondata)->is_persp);
+ const bool do_ray_start_correction = (
+ (snap_to == SCE_SNAP_MODE_FACE) &&
+ (ar && !((RegionView3D *)ar->regiondata)->is_persp));
int totvert = dm->getNumVerts(dm);
if (totvert > 0) {
@@ -1548,7 +1570,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
/* Exact value here is arbitrary (ideally we would scale in pixel-space based on 'r_dist_px'),
* scale up so we can snap against verts & edges on the boundbox, see T46816. */
- if (ELEM(snap_mode, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
+ if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
BKE_boundbox_scale(&bb_temp, bb, 1.0f + 1e-1f);
bb = &bb_temp;
}
@@ -1582,7 +1604,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
free_bvhtree_from_mesh(&treeData);
}
- switch (snap_mode) {
+ switch (snap_to) {
case SCE_SNAP_MODE_FACE:
{
BVHTreeRayHit hit;
@@ -1614,7 +1636,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 4, 6);
hit.index = -1;
- hit.dist = *r_depth;
+ hit.dist = *ray_depth;
if (hit.dist != TRANSFORM_DIST_MAX_RAY) {
hit.dist *= local_scale;
hit.dist -= len_diff;
@@ -1626,8 +1648,8 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
{
hit.dist += len_diff;
hit.dist /= local_scale;
- if (hit.dist <= *r_depth) {
- *r_depth = hit.dist;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
copy_v3_v3(r_loc, hit.co);
copy_v3_v3(r_no, hit.no);
@@ -1637,6 +1659,10 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
normalize_v3(r_no);
retval = true;
+
+ if (r_index) {
+ *r_index = dm_looptri_to_poly_index(dm, &treeData.looptri[hit.index]);
+ }
}
}
free_bvhtree_from_mesh(&treeData);
@@ -1682,8 +1708,10 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
}
if (test) {
- retval |= snapVertex(ar, v->co, v->no, obmat, timat, ray_start, ray_start_local,
- ray_normal_local, mval, r_loc, r_no, r_dist_px, r_depth);
+ retval |= snapVertex(
+ ar, v->co, v->no, obmat, timat, mval,
+ ray_start, ray_start_local, ray_normal_local, ray_depth,
+ r_loc, r_no, r_dist_px);
}
}
@@ -1731,9 +1759,10 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
}
if (test) {
- retval |= snapEdge(ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no,
- obmat, timat, ray_start, ray_start_local, ray_normal_local, mval,
- r_loc, r_no, r_dist_px, r_depth);
+ retval |= snapEdge(
+ ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no, obmat, timat,
+ mval, ray_start, ray_start_local, ray_normal_local, ray_depth,
+ r_loc, r_no, r_dist_px);
}
}
@@ -1746,9 +1775,11 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
}
/* may extend later (for now just snaps to empty center) */
-static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float *UNUSED(r_no), float *r_dist_px, float *r_depth)
+static bool snapEmpty(
+ ARegion *ar, Object *ob, float obmat[4][4],
+ const float mval[2], const short snap_to,
+ const float ray_start[3], const float ray_normal[3], float *ray_depth,
+ float r_loc[3], float *UNUSED(r_no), float *r_dist_px)
{
float imat[4][4];
float ray_start_local[3], ray_normal_local[3];
@@ -1758,7 +1789,7 @@ static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4
return retval;
}
/* for now only vertex supported */
- if (snap_mode != SCE_SNAP_MODE_VERTEX) {
+ if (snap_to != SCE_SNAP_MODE_VERTEX) {
return retval;
}
@@ -1767,11 +1798,14 @@ static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4
mul_v3_m4v3(ray_start_local, imat, ray_start);
mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
- switch (snap_mode) {
+ switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
const float zero_co[3] = {0.0f};
- retval |= snapVertex(ar, zero_co, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(
+ ar, zero_co, NULL, obmat, NULL, mval,
+ ray_start, ray_start_local, ray_normal_local, ray_depth,
+ r_loc, NULL, r_dist_px);
break;
}
default:
@@ -1781,9 +1815,11 @@ static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4
return retval;
}
-static bool snapCamera(short snap_mode, ARegion *ar, Scene *scene, Object *object, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float *UNUSED(r_no), float *r_dist_px, float *r_depth)
+static bool snapCamera(
+ ARegion *ar, Scene *scene, Object *object, float obmat[4][4],
+ const float mval[2], const short snap_to,
+ const float ray_start[3], const float ray_normal[3], float *ray_depth,
+ float r_loc[3], float *UNUSED(r_no), float *r_dist_px)
{
float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
bool retval = false;
@@ -1805,7 +1841,7 @@ static bool snapCamera(short snap_mode, ARegion *ar, Scene *scene, Object *objec
invert_m4_m4(orig_camera_imat, orig_camera_mat);
invert_m4_m4(imat, obmat);
- switch (snap_mode) {
+ switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
MovieTrackingObject *tracking_object;
@@ -1850,9 +1886,10 @@ static bool snapCamera(short snap_mode, ARegion *ar, Scene *scene, Object *objec
vertex_obmat = obmat;
}
- retval |= snapVertex(ar, bundle_pos, NULL, vertex_obmat, NULL,
- ray_start, ray_start_local, ray_normal_local, mval,
- r_loc, NULL, r_dist_px, r_depth);
+ retval |= snapVertex(
+ ar, bundle_pos, NULL, vertex_obmat, NULL, mval,
+ ray_start, ray_start_local, ray_normal_local, ray_depth,
+ r_loc, NULL, r_dist_px);
}
}
@@ -1865,10 +1902,13 @@ static bool snapCamera(short snap_mode, ARegion *ar, Scene *scene, Object *objec
return retval;
}
-static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, float obmat[4][4], bool use_obedit,
- Object **r_ob, float r_obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float ray_origin[3],
- const float mval[2], float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
+static bool snapObject(
+ Scene *scene, ARegion *ar, Object *ob, float obmat[4][4], bool use_obedit,
+ const float mval[2], const short snap_to,
+ const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
+ Object **r_ob, float r_obmat[4][4])
{
bool retval = false;
@@ -1895,21 +1935,36 @@ static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, f
em = NULL;
}
- retval = snapDerivedMesh(snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_depth, do_bb);
+ retval = snapDerivedMesh(
+ ar, ob, dm, em, obmat, mval, snap_to, do_bb,
+ ray_start, ray_normal, ray_origin, ray_depth,
+ r_loc, r_no, r_dist_px, r_index);
dm->release(dm);
}
else if (ob->type == OB_ARMATURE) {
- retval = snapArmature(snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
+ retval = snapArmature(
+ ar, ob, ob->data, obmat, mval, snap_to,
+ ray_start, ray_normal, ray_depth,
+ r_loc, r_no, r_dist_px);
}
else if (ob->type == OB_CURVE) {
- retval = snapCurve(snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
+ retval = snapCurve(
+ ar, ob, ob->data, obmat, mval, snap_to,
+ ray_start, ray_normal, ray_depth,
+ r_loc, r_no, r_dist_px);
}
else if (ob->type == OB_EMPTY) {
- retval = snapEmpty(snap_mode, ar, ob, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
+ retval = snapEmpty(
+ ar, ob, obmat, mval, snap_to,
+ ray_start, ray_normal, ray_depth,
+ r_loc, r_no, r_dist_px);
}
else if (ob->type == OB_CAMERA) {
- retval = snapCamera(snap_mode, ar, scene, ob, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
+ retval = snapCamera(
+ ar, scene, ob, obmat, mval, snap_to,
+ ray_start, ray_normal, ray_depth,
+ r_loc, r_no, r_dist_px);
}
if (retval) {
@@ -1922,21 +1977,25 @@ static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, f
return retval;
}
-static bool snapObjectsRay(Scene *scene, short snap_mode, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit,
- Object **r_ob, float r_obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float ray_origin[3],
- float *r_ray_dist,
- const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
+static bool snapObjectsRay(
+ Scene *scene, View3D *v3d, ARegion *ar, Base *base_act, Object *obedit,
+ const float mval[2], SnapSelect snap_select, const short snap_to,
+ const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
+ Object **r_ob, float r_obmat[4][4])
{
Base *base;
bool retval = false;
- if (mode == SNAP_ALL && obedit) {
+ if (snap_select == SNAP_ALL && obedit) {
Object *ob = obedit;
- retval |= snapObject(scene, snap_mode, ar, ob, ob->obmat, true,
- r_ob, r_obmat,
- ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_ray_dist);
+ retval |= snapObject(
+ scene, ar, ob, ob->obmat, true,
+ mval, snap_to,
+ ray_start, ray_normal, ray_origin, ray_depth,
+ r_loc, r_no, r_dist_px, r_index, r_ob, r_obmat);
}
/* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
@@ -1947,17 +2006,19 @@ static bool snapObjectsRay(Scene *scene, short snap_mode, Base *base_act, View3D
base = base_act;
if (base && base->object && base->object->mode & OB_MODE_PARTICLE_EDIT) {
Object *ob = base->object;
- retval |= snapObject(scene, snap_mode, ar, ob, ob->obmat, false,
- r_ob, r_obmat,
- ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_ray_dist);
+ retval |= snapObject(
+ scene, ar, ob, ob->obmat, false,
+ mval, snap_to,
+ ray_start, ray_normal, ray_origin, ray_depth,
+ r_loc, r_no, r_dist_px, r_index, r_ob, r_obmat);
}
for (base = FIRSTBASE; base != NULL; base = base->next) {
if ((BASE_VISIBLE_BGMODE(v3d, scene, base)) &&
(base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
- ((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) ||
- (ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT) && base != base_act)))
+ ((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) ||
+ (ELEM(snap_select, SNAP_ALL, SNAP_NOT_OBEDIT) && base != base_act)))
{
Object *ob = base->object;
Object *ob_snap = ob;
@@ -1977,25 +2038,31 @@ static bool snapObjectsRay(Scene *scene, short snap_mode, Base *base_act, View3D
bool use_obedit_dupli = (obedit && dupli_ob->ob->data == obedit->data);
Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
- retval |= snapObject(scene, snap_mode, ar, dupli_snap, dupli_ob->mat, use_obedit_dupli,
- r_ob, r_obmat,
- ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_ray_dist);
+ retval |= snapObject(
+ scene, ar, dupli_snap, dupli_ob->mat, use_obedit_dupli,
+ mval, snap_to,
+ ray_start, ray_normal, ray_origin, ray_depth,
+ r_loc, r_no, r_dist_px, r_index, r_ob, r_obmat);
}
free_object_duplilist(lb);
}
- retval |= snapObject(scene, snap_mode, ar, ob_snap, ob->obmat, use_obedit,
- r_ob, r_obmat,
- ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_ray_dist);
+ retval |= snapObject(
+ scene, ar, ob_snap, ob->obmat, use_obedit,
+ mval, snap_to,
+ ray_start, ray_normal, ray_origin, ray_depth,
+ r_loc, r_no, r_dist_px, r_index, r_ob, r_obmat);
}
}
return retval;
}
-static bool snapObjects(Scene *scene, short snap_mode, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit,
- const float mval[2], float *r_dist_px,
- float r_loc[3], float r_no[3], float *r_ray_dist, SnapMode mode)
+static bool snapObjects(
+ Scene *scene, View3D *v3d, ARegion *ar, Base *base_act, Object *obedit,
+ const float mval[2], SnapSelect snap_select, const short snap_to,
+ float *ray_depth,
+ float r_loc[3], float r_no[3], float *r_dist_px, int *r_index)
{
float ray_start[3], ray_normal[3], ray_orgigin[3];
@@ -2003,13 +2070,16 @@ static bool snapObjects(Scene *scene, short snap_mode, Base *base_act, View3D *v
return false;
}
- return snapObjectsRay(scene, snap_mode, base_act, v3d, ar, obedit,
- NULL, NULL,
- ray_start, ray_normal, ray_orgigin, r_ray_dist,
- mval, r_dist_px, r_loc, r_no, mode);
+ return snapObjectsRay(
+ scene, v3d, ar, base_act, obedit,
+ mval, snap_select, snap_to,
+ ray_start, ray_normal, ray_orgigin, ray_depth,
+ r_loc, r_no, r_dist_px, r_index, NULL, NULL);
}
-bool snapObjectsTransform(TransInfo *t, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
+bool snapObjectsTransform(
+ TransInfo *t, const float mval[2], SnapSelect snap_select,
+ float r_loc[3], float r_no[3], float *r_dist_px)
{
float ray_dist = TRANSFORM_DIST_MAX_RAY;
Object *obedit = NULL;
@@ -2024,11 +2094,15 @@ bool snapObjectsTransform(TransInfo *t, const float mval[2], float *r_dist_px, f
}
return snapObjects(
- t->scene, t->scene->toolsettings->snap_mode, base_act, t->view, t->ar, obedit,
- mval, r_dist_px, r_loc, r_no, &ray_dist, mode);
+ t->scene, t->view, t->ar, base_act, obedit,
+ mval, snap_select, t->scene->toolsettings->snap_mode,
+ &ray_dist,
+ r_loc, r_no, r_dist_px, NULL);
}
-bool snapObjectsContext(bContext *C, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
+bool snapObjectsContext(
+ bContext *C, const float mval[2], SnapSelect snap_select,
+ float r_loc[3], float r_no[3], float *r_dist_px)
{
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
@@ -2037,27 +2111,38 @@ bool snapObjectsContext(bContext *C, const float mval[2], float *r_dist_px, floa
Object *obedit = CTX_data_edit_object(C);
float ray_dist = TRANSFORM_DIST_MAX_RAY;
- return snapObjects(scene, scene->toolsettings->snap_mode, scene->basact, v3d, ar, obedit,
- mval, r_dist_px, r_loc, r_no, &ray_dist, mode);
+ return snapObjects(
+ scene, v3d, ar, scene->basact, obedit,
+ mval, snap_select, scene->toolsettings->snap_mode,
+ &ray_dist,
+ r_loc, r_no, r_dist_px, NULL);
}
-bool snapObjectsEx(Scene *scene, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit, short snap_mode,
- const float mval[2], float *r_dist_px,
- float r_loc[3], float r_no[3], float *r_ray_dist, SnapMode mode)
+bool snapObjectsEx(
+ Scene *scene, View3D *v3d, ARegion *ar, Base *base_act, Object *obedit,
+ const float mval[2], SnapSelect snap_select, const short snap_to,
+ float *ray_depth,
+ float r_loc[3], float r_no[3], float *r_dist_px)
{
- return snapObjects(scene, snap_mode, base_act, v3d, ar, obedit,
- mval, r_dist_px,
- r_loc, r_no, r_ray_dist, mode);
+ return snapObjects(
+ scene, v3d, ar, base_act, obedit,
+ mval, snap_select, snap_to,
+ ray_depth,
+ r_loc, r_no, r_dist_px, NULL);
}
-bool snapObjectsRayEx(Scene *scene, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit, short snap_mode,
- Object **r_ob, float r_obmat[4][4],
- const float ray_start[3], const float ray_normal[3], float *r_ray_dist,
- const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
-{
- return snapObjectsRay(scene, snap_mode, base_act, v3d, ar, obedit,
- r_ob, r_obmat,
- ray_start, ray_normal, ray_start, r_ray_dist,
- mval, r_dist_px, r_loc, r_no, mode);
+bool snapObjectsRayEx(
+ Scene *scene, View3D *v3d, ARegion *ar, Base *base_act, Object *obedit,
+ const float mval[2], SnapSelect snap_select, const short snap_to,
+ const float ray_start[3], const float ray_normal[3], float *ray_depth,
+ float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
+ Object **r_ob, float r_obmat[4][4])
+{
+ return snapObjectsRay(
+ scene, v3d, ar, base_act, obedit,
+ mval, snap_select, snap_to,
+ ray_start, ray_normal, ray_start, ray_depth,
+ r_loc, r_no, r_dist_px, r_index,
+ r_ob, r_obmat);
}
/******************** PEELING *********************************/
@@ -2220,8 +2305,10 @@ static bool peelDerivedMesh(
return retval;
}
-static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
- ListBase *depth_peels, const float mval[2], SnapMode mode)
+static bool peelObjects(
+ Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
+ const float mval[2], SnapSelect snap_select,
+ ListBase *r_depth_peels)
{
Base *base;
bool retval = false;
@@ -2250,13 +2337,13 @@ static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
if (dob != obedit) {
dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH);
- val = peelDerivedMesh(dob, dm, NULL, dob->obmat, ray_start, ray_normal, mval, depth_peels);
+ val = peelDerivedMesh(dob, dm, NULL, dob->obmat, ray_start, ray_normal, mval, r_depth_peels);
}
else {
em = BKE_editmesh_from_object(dob);
dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
- val = peelDerivedMesh(dob, dm, em, dob->obmat, ray_start, ray_normal, mval, depth_peels);
+ val = peelDerivedMesh(dob, dm, em, dob->obmat, ray_start, ray_normal, mval, r_depth_peels);
}
retval = retval || val;
@@ -2271,17 +2358,17 @@ static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
if (ob->type == OB_MESH) {
bool val = false;
- if (ob != obedit && ((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) || ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT))) {
+ if (ob != obedit && ((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) || ELEM(snap_select, SNAP_ALL, SNAP_NOT_OBEDIT))) {
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, depth_peels);
+ val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
dm->release(dm);
}
- else if (ob == obedit && mode != SNAP_NOT_OBEDIT) {
+ else if (ob == obedit && snap_select != SNAP_NOT_OBEDIT) {
BMEditMesh *em = BKE_editmesh_from_object(ob);
DerivedMesh *dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
- val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, depth_peels);
+ val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
dm->release(dm);
}
@@ -2291,18 +2378,22 @@ static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
}
}
- BLI_listbase_sort(depth_peels, cmpPeel);
- removeDoublesPeel(depth_peels);
+ BLI_listbase_sort(r_depth_peels, cmpPeel);
+ removeDoublesPeel(r_depth_peels);
return retval;
}
-bool peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, const float mval[2], SnapMode mode)
+bool peelObjectsTransForm(
+ TransInfo *t, const float mval[2], SnapSelect snap_select,
+ ListBase *r_depth_peels)
{
- return peelObjects(t->scene, t->view, t->ar, t->obedit, depth_peels, mval, mode);
+ return peelObjects(t->scene, t->view, t->ar, t->obedit, mval, snap_select, r_depth_peels);
}
-bool peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], SnapMode mode)
+bool peelObjectsContext(
+ bContext *C, const float mval[2], SnapSelect snap_select,
+ ListBase *r_depth_peels)
{
Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
@@ -2310,16 +2401,16 @@ bool peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2],
ARegion *ar = CTX_wm_region(C);
Object *obedit = CTX_data_edit_object(C);
- return peelObjects(scene, v3d, ar, obedit, depth_peels, mval, mode);
+ return peelObjects(scene, v3d, ar, obedit, mval, snap_select, r_depth_peels);
}
/******************** NODES ***********************************/
-static bool snapNodeTest(View2D *v2d, bNode *node, SnapMode mode)
+static bool snapNodeTest(View2D *v2d, bNode *node, SnapSelect snap_select)
{
/* node is use for snapping only if a) snap mode matches and b) node is inside the view */
- return ((mode == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) ||
- (mode == SNAP_ALL && !(node->flag & NODE_ACTIVE))) &&
+ return ((snap_select == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) ||
+ (snap_select == SNAP_ALL && !(node->flag & NODE_ACTIVE))) &&
(node->totr.xmin < v2d->cur.xmax && node->totr.xmax > v2d->cur.xmin &&
node->totr.ymin < v2d->cur.ymax && node->totr.ymax > v2d->cur.ymin);
}
@@ -2337,8 +2428,9 @@ static NodeBorder snapNodeBorder(int snap_node_mode)
return 0;
}
-static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2],
- float r_loc[2], float *r_dist_px, char *r_node_border)
+static bool snapNode(
+ ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2],
+ float r_loc[2], float *r_dist_px, char *r_node_border)
{
View2D *v2d = &ar->v2d;
NodeBorder border = snapNodeBorder(ts->snap_node_mode);
@@ -2391,8 +2483,10 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN
return retval;
}
-static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2],
- float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode)
+static bool snapNodes(
+ ToolSettings *ts, SpaceNode *snode, ARegion *ar,
+ const int mval[2], SnapSelect snap_select,
+ float r_loc[2], float *r_dist_px, char *r_node_border)
{
bNodeTree *ntree = snode->edittree;
bNode *node;
@@ -2401,23 +2495,32 @@ static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int
*r_node_border = 0;
for (node = ntree->nodes.first; node; node = node->next) {
- if (snapNodeTest(&ar->v2d, node, mode))
+ if (snapNodeTest(&ar->v2d, node, snap_select)) {
retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist_px, r_node_border);
+ }
}
return retval;
}
-bool snapNodesTransform(TransInfo *t, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode)
+bool snapNodesTransform(
+ TransInfo *t, const int mval[2], SnapSelect snap_select,
+ float r_loc[2], float *r_dist_px, char *r_node_border)
{
- return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist_px, r_loc, r_node_border, mode);
+ return snapNodes(
+ t->settings, t->sa->spacedata.first, t->ar, mval, snap_select,
+ r_loc, r_dist_px, r_node_border);
}
-bool snapNodesContext(bContext *C, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode)
+bool snapNodesContext(
+ bContext *C, const int mval[2], SnapSelect snap_select,
+ float r_loc[2], float *r_dist_px, char *r_node_border)
{
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
- return snapNodes(scene->toolsettings, CTX_wm_space_node(C), ar, mval, r_dist_px, r_loc, r_node_border, mode);
+ return snapNodes(
+ scene->toolsettings, CTX_wm_space_node(C), ar, mval, snap_select,
+ r_loc, r_dist_px, r_node_border);
}
/*================================================================*/
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index f727f48e993..0463980dacd 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -344,3 +344,23 @@ void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id)
break;
}
}
+
+static int ed_flush_edits_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ ED_editors_flush_edits(C, false);
+ return OPERATOR_FINISHED;
+}
+
+void ED_OT_flush_edits(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Flush Edits";
+ ot->description = "Flush edit data from active editing modes";
+ ot->idname = "ED_OT_flush_edits";
+
+ /* api callbacks */
+ ot->exec = ed_flush_edits_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+}
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index a90763eed4e..543ef0e0663 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -29,6 +29,7 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/eigen
../../../../intern/glew-mx
)
@@ -52,13 +53,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
-if(WITH_OPENNL)
- add_definitions(-DWITH_OPENNL)
- list(APPEND INC_SYS
- ../../../../intern/opennl/extern
- )
-endif()
-
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_editor_uvedit "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/uvedit/SConscript b/source/blender/editors/uvedit/SConscript
index b5cccab4002..85ea7f45536 100644
--- a/source/blender/editors/uvedit/SConscript
+++ b/source/blender/editors/uvedit/SConscript
@@ -34,9 +34,9 @@ sources = env.Glob('*.c')
incs = [
'#/intern/guardedalloc',
+ '#/intern/eigen',
env['BF_GLEW_INC'],
'#/intern/glew-mx',
- '#/intern/opennl/extern',
'../include',
'../../blenkernel',
'../../blenlib',
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 3fc0b654b82..1a106b40f32 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -727,7 +727,7 @@ static bool uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2
{
bool changed = false;
- if (mode == V3D_CENTER) { /* bounding box */
+ if (mode == V3D_AROUND_CENTER_BOUNDS) { /* bounding box */
float min[2], max[2];
if (ED_uvedit_minmax(scene, ima, obedit, min, max)) {
mid_v2_v2v2(cent, min, max);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 311c152a239..e1495b617f8 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -44,9 +44,7 @@
#include "BLI_sys_types.h" /* for intptr_t support */
-#ifdef WITH_OPENNL
-
-#include "ONL_opennl.h"
+#include "eigen_capi.h"
/* Utils */
@@ -193,7 +191,7 @@ typedef struct PChart {
union PChartUnion {
struct PChartLscm {
- NLContext *context;
+ LinearSolver *context;
float *abf_alpha;
PVert *pin1, *pin2;
} lscm;
@@ -2471,17 +2469,12 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
PEdge *e;
int i, j, ninterior = sys->ninterior, nvar = 2 * sys->ninterior;
PBool success;
- NLContext *context;
-
- context = nlNewContext();
- nlSolverParameteri(context, NL_NB_VARIABLES, nvar);
+ LinearSolver *context;
- nlBegin(context, NL_SYSTEM);
-
- nlBegin(context, NL_MATRIX);
+ context = EIG_linear_solver_new(0, nvar, 1);
for (i = 0; i < nvar; i++)
- nlRightHandSideAdd(context, 0, i, sys->bInterior[i]);
+ EIG_linear_solver_right_hand_side_add(context, 0, i, sys->bInterior[i]);
for (f = chart->faces; f; f = f->nextlink) {
float wi1, wi2, wi3, b, si, beta[3], j2[3][3], W[3][3];
@@ -2527,8 +2520,8 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
sys->J2dt[e2->u.id][0] = j2[1][0] = p_abf_compute_sin_product(sys, v1, e2->u.id) * wi2;
sys->J2dt[e3->u.id][0] = j2[2][0] = p_abf_compute_sin_product(sys, v1, e3->u.id) * wi3;
- nlRightHandSideAdd(context, 0, v1->u.id, j2[0][0] * beta[0]);
- nlRightHandSideAdd(context, 0, ninterior + v1->u.id, j2[1][0] * beta[1] + j2[2][0] * beta[2]);
+ EIG_linear_solver_right_hand_side_add(context, 0, v1->u.id, j2[0][0] * beta[0]);
+ EIG_linear_solver_right_hand_side_add(context, 0, ninterior + v1->u.id, j2[1][0] * beta[1] + j2[2][0] * beta[2]);
row1[0] = j2[0][0] * W[0][0];
row2[0] = j2[0][0] * W[1][0];
@@ -2547,8 +2540,8 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
sys->J2dt[e2->u.id][1] = j2[1][1] = 1.0f * wi2;
sys->J2dt[e3->u.id][1] = j2[2][1] = p_abf_compute_sin_product(sys, v2, e3->u.id) * wi3;
- nlRightHandSideAdd(context, 0, v2->u.id, j2[1][1] * beta[1]);
- nlRightHandSideAdd(context, 0, ninterior + v2->u.id, j2[0][1] * beta[0] + j2[2][1] * beta[2]);
+ EIG_linear_solver_right_hand_side_add(context, 0, v2->u.id, j2[1][1] * beta[1]);
+ EIG_linear_solver_right_hand_side_add(context, 0, ninterior + v2->u.id, j2[0][1] * beta[0] + j2[2][1] * beta[2]);
row1[1] = j2[1][1] * W[0][1];
row2[1] = j2[1][1] * W[1][1];
@@ -2567,8 +2560,8 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
sys->J2dt[e2->u.id][2] = j2[1][2] = p_abf_compute_sin_product(sys, v3, e2->u.id) * wi2;
sys->J2dt[e3->u.id][2] = j2[2][2] = 1.0f * wi3;
- nlRightHandSideAdd(context, 0, v3->u.id, j2[2][2] * beta[2]);
- nlRightHandSideAdd(context, 0, ninterior + v3->u.id, j2[0][2] * beta[0] + j2[1][2] * beta[1]);
+ EIG_linear_solver_right_hand_side_add(context, 0, v3->u.id, j2[2][2] * beta[2]);
+ EIG_linear_solver_right_hand_side_add(context, 0, ninterior + v3->u.id, j2[0][2] * beta[0] + j2[1][2] * beta[1]);
row1[2] = j2[2][2] * W[0][2];
row2[2] = j2[2][2] * W[1][2];
@@ -2592,29 +2585,25 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
continue;
if (i == 0)
- nlMatrixAdd(context, r, c, j2[0][i] * row1[j]);
+ EIG_linear_solver_matrix_add(context, r, c, j2[0][i] * row1[j]);
else
- nlMatrixAdd(context, r + ninterior, c, j2[0][i] * row1[j]);
+ EIG_linear_solver_matrix_add(context, r + ninterior, c, j2[0][i] * row1[j]);
if (i == 1)
- nlMatrixAdd(context, r, c, j2[1][i] * row2[j]);
+ EIG_linear_solver_matrix_add(context, r, c, j2[1][i] * row2[j]);
else
- nlMatrixAdd(context, r + ninterior, c, j2[1][i] * row2[j]);
+ EIG_linear_solver_matrix_add(context, r + ninterior, c, j2[1][i] * row2[j]);
if (i == 2)
- nlMatrixAdd(context, r, c, j2[2][i] * row3[j]);
+ EIG_linear_solver_matrix_add(context, r, c, j2[2][i] * row3[j]);
else
- nlMatrixAdd(context, r + ninterior, c, j2[2][i] * row3[j]);
+ EIG_linear_solver_matrix_add(context, r + ninterior, c, j2[2][i] * row3[j]);
}
}
}
- nlEnd(context, NL_MATRIX);
-
- nlEnd(context, NL_SYSTEM);
-
- success = nlSolve(context, NL_FALSE);
+ success = EIG_linear_solver_solve(context);
if (success) {
for (f = chart->faces; f; f = f->nextlink) {
@@ -2625,24 +2614,24 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
pre[0] = pre[1] = pre[2] = 0.0;
if (v1->flag & PVERT_INTERIOR) {
- float x = nlGetVariable(context, 0, v1->u.id);
- float x2 = nlGetVariable(context, 0, ninterior + v1->u.id);
+ float x = EIG_linear_solver_variable_get(context, 0, v1->u.id);
+ float x2 = EIG_linear_solver_variable_get(context, 0, ninterior + v1->u.id);
pre[0] += sys->J2dt[e1->u.id][0] * x;
pre[1] += sys->J2dt[e2->u.id][0] * x2;
pre[2] += sys->J2dt[e3->u.id][0] * x2;
}
if (v2->flag & PVERT_INTERIOR) {
- float x = nlGetVariable(context, 0, v2->u.id);
- float x2 = nlGetVariable(context, 0, ninterior + v2->u.id);
+ float x = EIG_linear_solver_variable_get(context, 0, v2->u.id);
+ float x2 = EIG_linear_solver_variable_get(context, 0, ninterior + v2->u.id);
pre[0] += sys->J2dt[e1->u.id][1] * x2;
pre[1] += sys->J2dt[e2->u.id][1] * x;
pre[2] += sys->J2dt[e3->u.id][1] * x2;
}
if (v3->flag & PVERT_INTERIOR) {
- float x = nlGetVariable(context, 0, v3->u.id);
- float x2 = nlGetVariable(context, 0, ninterior + v3->u.id);
+ float x = EIG_linear_solver_variable_get(context, 0, v3->u.id);
+ float x2 = EIG_linear_solver_variable_get(context, 0, ninterior + v3->u.id);
pre[0] += sys->J2dt[e1->u.id][2] * x2;
pre[1] += sys->J2dt[e2->u.id][2] * x2;
pre[2] += sys->J2dt[e3->u.id][2] * x;
@@ -2673,12 +2662,12 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
}
for (i = 0; i < ninterior; i++) {
- sys->lambdaPlanar[i] += (float)nlGetVariable(context, 0, i);
- sys->lambdaLength[i] += (float)nlGetVariable(context, 0, ninterior + i);
+ sys->lambdaPlanar[i] += (float)EIG_linear_solver_variable_get(context, 0, i);
+ sys->lambdaLength[i] += (float)EIG_linear_solver_variable_get(context, 0, ninterior + i);
}
}
- nlDeleteContext(context);
+ EIG_linear_solver_delete(context);
return success;
}
@@ -3004,12 +2993,12 @@ static void p_chart_extrema_verts(PChart *chart, PVert **pin1, PVert **pin2)
static void p_chart_lscm_load_solution(PChart *chart)
{
- NLContext *context = chart->u.lscm.context;
+ LinearSolver *context = chart->u.lscm.context;
PVert *v;
for (v = chart->verts; v; v = v->nextlink) {
- v->uv[0] = nlGetVariable(context, 0, 2 * v->u.id);
- v->uv[1] = nlGetVariable(context, 0, 2 * v->u.id + 1);
+ v->uv[0] = EIG_linear_solver_variable_get(context, 0, 2 * v->u.id);
+ v->uv[1] = EIG_linear_solver_variable_get(context, 0, 2 * v->u.id + 1);
}
}
@@ -3064,16 +3053,13 @@ static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
for (v = chart->verts; v; v = v->nextlink)
v->u.id = id++;
- chart->u.lscm.context = nlNewContext();
- nlSolverParameteri(chart->u.lscm.context, NL_NB_VARIABLES, 2 * chart->nverts);
- nlSolverParameteri(chart->u.lscm.context, NL_NB_ROWS, 2 * chart->nfaces);
- nlSolverParameteri(chart->u.lscm.context, NL_LEAST_SQUARES, NL_TRUE);
+ chart->u.lscm.context = EIG_linear_least_squares_solver_new(2 * chart->nfaces, 2 * chart->nverts, 1);
}
}
static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
{
- NLContext *context = chart->u.lscm.context;
+ LinearSolver *context = chart->u.lscm.context;
PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
PFace *f;
float *alpha = chart->u.lscm.abf_alpha;
@@ -3081,8 +3067,6 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
bool flip_faces;
int row;
- nlBegin(context, NL_SYSTEM);
-
#if 0
/* TODO: make loading pins work for simplify/complexify. */
#endif
@@ -3092,25 +3076,25 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
p_vert_load_pin_select_uvs(handle, v); /* reload for live */
if (chart->u.lscm.pin1) {
- nlLockVariable(context, 2 * pin1->u.id);
- nlLockVariable(context, 2 * pin1->u.id + 1);
- nlLockVariable(context, 2 * pin2->u.id);
- nlLockVariable(context, 2 * pin2->u.id + 1);
+ EIG_linear_solver_variable_lock(context, 2 * pin1->u.id);
+ EIG_linear_solver_variable_lock(context, 2 * pin1->u.id + 1);
+ EIG_linear_solver_variable_lock(context, 2 * pin2->u.id);
+ EIG_linear_solver_variable_lock(context, 2 * pin2->u.id + 1);
- nlSetVariable(context, 0, 2 * pin1->u.id, pin1->uv[0]);
- nlSetVariable(context, 0, 2 * pin1->u.id + 1, pin1->uv[1]);
- nlSetVariable(context, 0, 2 * pin2->u.id, pin2->uv[0]);
- nlSetVariable(context, 0, 2 * pin2->u.id + 1, pin2->uv[1]);
+ EIG_linear_solver_variable_set(context, 0, 2 * pin1->u.id, pin1->uv[0]);
+ EIG_linear_solver_variable_set(context, 0, 2 * pin1->u.id + 1, pin1->uv[1]);
+ EIG_linear_solver_variable_set(context, 0, 2 * pin2->u.id, pin2->uv[0]);
+ EIG_linear_solver_variable_set(context, 0, 2 * pin2->u.id + 1, pin2->uv[1]);
}
else {
/* set and lock the pins */
for (v = chart->verts; v; v = v->nextlink) {
if (v->flag & PVERT_PIN) {
- nlLockVariable(context, 2 * v->u.id);
- nlLockVariable(context, 2 * v->u.id + 1);
+ EIG_linear_solver_variable_lock(context, 2 * v->u.id);
+ EIG_linear_solver_variable_lock(context, 2 * v->u.id + 1);
- nlSetVariable(context, 0, 2 * v->u.id, v->uv[0]);
- nlSetVariable(context, 0, 2 * v->u.id + 1, v->uv[1]);
+ EIG_linear_solver_variable_set(context, 0, 2 * v->u.id, v->uv[0]);
+ EIG_linear_solver_variable_set(context, 0, 2 * v->u.id + 1, v->uv[1]);
}
}
}
@@ -3137,8 +3121,6 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
/* construct matrix */
- nlBegin(context, NL_MATRIX);
-
row = 0;
for (f = chart->faces; f; f = f->nextlink) {
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
@@ -3185,26 +3167,22 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
cosine = cosf(a1) * ratio;
sine = sina1 * ratio;
- nlMatrixAdd(context, row, 2 * v1->u.id, cosine - 1.0f);
- nlMatrixAdd(context, row, 2 * v1->u.id + 1, -sine);
- nlMatrixAdd(context, row, 2 * v2->u.id, -cosine);
- nlMatrixAdd(context, row, 2 * v2->u.id + 1, sine);
- nlMatrixAdd(context, row, 2 * v3->u.id, 1.0);
+ EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id, cosine - 1.0f);
+ EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id + 1, -sine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id, -cosine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id + 1, sine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v3->u.id, 1.0);
row++;
- nlMatrixAdd(context, row, 2 * v1->u.id, sine);
- nlMatrixAdd(context, row, 2 * v1->u.id + 1, cosine - 1.0f);
- nlMatrixAdd(context, row, 2 * v2->u.id, -sine);
- nlMatrixAdd(context, row, 2 * v2->u.id + 1, -cosine);
- nlMatrixAdd(context, row, 2 * v3->u.id + 1, 1.0);
+ EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id, sine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id + 1, cosine - 1.0f);
+ EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id, -sine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v2->u.id + 1, -cosine);
+ EIG_linear_solver_matrix_add(context, row, 2 * v3->u.id + 1, 1.0);
row++;
}
- nlEnd(context, NL_MATRIX);
-
- nlEnd(context, NL_SYSTEM);
-
- if (nlSolve(context, NL_TRUE)) {
+ if (EIG_linear_solver_solve(context)) {
p_chart_lscm_load_solution(chart);
return P_TRUE;
}
@@ -3221,7 +3199,7 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
static void p_chart_lscm_end(PChart *chart)
{
if (chart->u.lscm.context)
- nlDeleteContext(chart->u.lscm.context);
+ EIG_linear_solver_delete(chart->u.lscm.context);
if (chart->u.lscm.abf_alpha) {
MEM_freeN(chart->u.lscm.abf_alpha);
@@ -4700,36 +4678,3 @@ void param_flush_restore(ParamHandle *handle)
}
}
-#else /* WITH_OPENNL */
-
-#ifdef __GNUC__
-# pragma GCC diagnostic ignored "-Wunused-parameter"
-#endif
-
-/* stubs */
-void param_face_add(ParamHandle *handle, ParamKey key, int nverts,
- ParamKey *vkeys, float **co, float **uv,
- ParamBool *pin, ParamBool *select, float normal[3]) {}
-void param_edge_set_seam(ParamHandle *handle,
- ParamKey *vkeys) {}
-void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy) {}
-ParamHandle *param_construct_begin(void) { return NULL; }
-void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl) {}
-void param_delete(ParamHandle *handle) {}
-
-void param_stretch_begin(ParamHandle *handle) {}
-void param_stretch_blend(ParamHandle *handle, float blend) {}
-void param_stretch_iter(ParamHandle *handle) {}
-void param_stretch_end(ParamHandle *handle) {}
-
-void param_pack(ParamHandle *handle, float margin, bool do_rotate) {}
-void param_average(ParamHandle *handle) {}
-
-void param_flush(ParamHandle *handle) {}
-void param_flush_restore(ParamHandle *handle) {}
-
-void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf) {}
-void param_lscm_solve(ParamHandle *handle) {}
-void param_lscm_end(ParamHandle *handle) {}
-
-#endif /* WITH_OPENNL */
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 3ff3e29f79d..3f218136751 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -859,12 +859,12 @@ void ED_uvedit_live_unwrap(Scene *scene, Object *obedit)
static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result,
Object *ob, BMEditMesh *em)
{
- int around = (v3d) ? v3d->around : V3D_CENTER;
+ const int around = (v3d) ? v3d->around : V3D_AROUND_CENTER_BOUNDS;
/* only operates on the edit object - this is all that's needed now */
switch (around) {
- case V3D_CENTER: /* bounding box center */
+ case V3D_AROUND_CENTER_BOUNDS: /* bounding box center */
{
BMFace *efa;
BMLoop *l;
@@ -883,15 +883,15 @@ static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result,
mid_v3_v3v3(result, min, max);
break;
}
- case V3D_CURSOR: /* cursor center */
+ case V3D_AROUND_CURSOR: /* cursor center */
{
const float *curs = ED_view3d_cursor3d_get(scene, v3d);
/* shift to objects world */
sub_v3_v3v3(result, curs, ob->obmat[3]);
break;
}
- case V3D_LOCAL: /* object center */
- case V3D_CENTROID: /* multiple objects centers, only one object here*/
+ case V3D_AROUND_LOCAL_ORIGINS: /* object center */
+ case V3D_AROUND_CENTER_MEAN: /* multiple objects centers, only one object here*/
default:
zero_v3(result);
break;
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 328623f884f..6d3a5d37d66 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -46,16 +46,19 @@ set(INC_SYS
)
set(SRC
+ intern/gpu_basic_shader.c
intern/gpu_buffers.c
intern/gpu_codegen.c
+ intern/gpu_compositing.c
+ intern/gpu_debug.c
intern/gpu_draw.c
intern/gpu_extensions.c
+ intern/gpu_framebuffer.c
intern/gpu_init_exit.c
intern/gpu_material.c
- intern/gpu_simple_shader.c
intern/gpu_select.c
- intern/gpu_compositing.c
- intern/gpu_debug.c
+ intern/gpu_shader.c
+ intern/gpu_texture.c
shaders/gpu_program_smoke_frag.glsl
shaders/gpu_program_smoke_color_frag.glsl
@@ -71,23 +74,26 @@ set(SRC
shaders/gpu_shader_material.glsl
shaders/gpu_shader_sep_gaussian_blur_frag.glsl
shaders/gpu_shader_sep_gaussian_blur_vert.glsl
- shaders/gpu_shader_simple_frag.glsl
- shaders/gpu_shader_simple_vert.glsl
+ shaders/gpu_shader_basic_frag.glsl
+ shaders/gpu_shader_basic_vert.glsl
shaders/gpu_shader_vertex.glsl
shaders/gpu_shader_vsm_store_frag.glsl
shaders/gpu_shader_vsm_store_vert.glsl
shaders/gpu_shader_fx_depth_resolve.glsl
+ GPU_basic_shader.h
GPU_buffers.h
- GPU_draw.h
+ GPU_compositing.h
GPU_debug.h
+ GPU_draw.h
GPU_extensions.h
+ GPU_framebuffer.h
GPU_glew.h
GPU_init_exit.h
GPU_material.h
- GPU_simple_shader.h
GPU_select.h
- GPU_compositing.h
+ GPU_shader.h
+ GPU_texture.h
intern/gpu_codegen.h
intern/gpu_private.h
)
@@ -98,8 +104,8 @@ data_to_c_simple(shaders/gpu_program_smoke_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_material.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_simple_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_simple_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_basic_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_basic_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
diff --git a/source/blender/gpu/GPU_simple_shader.h b/source/blender/gpu/GPU_basic_shader.h
index 239296209b4..3298f0f35b4 100644
--- a/source/blender/gpu/GPU_simple_shader.h
+++ b/source/blender/gpu/GPU_basic_shader.h
@@ -25,12 +25,12 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file GPU_simple_shader.h
+/** \file GPU_basic_shader.h
* \ingroup gpu
*/
-#ifndef __GPU_SIMPLE_SHADER_H__
-#define __GPU_SIMPLE_SHADER_H__
+#ifndef __GPU_BASIC_SHADER_H__
+#define __GPU_BASIC_SHADER_H__
#include "BLI_utildefines.h"
@@ -40,8 +40,8 @@ extern "C" {
/* Fixed Function Shader */
-typedef enum GPUSimpleShaderOption {
- GPU_SHADER_OVERRIDE_DIFFUSE = (1<<0), /* replace diffuse with glcolor */
+typedef enum GPUBasicShaderOption {
+ GPU_SHADER_USE_COLOR = (1<<0), /* use glColor, for lighting it replaces diffuse */
GPU_SHADER_LIGHTING = (1<<1), /* use lighting */
GPU_SHADER_TWO_SIDED = (1<<2), /* flip normals towards viewer */
GPU_SHADER_TEXTURE_2D = (1<<3), /* use 2D texture to replace diffuse color */
@@ -49,37 +49,44 @@ typedef enum GPUSimpleShaderOption {
GPU_SHADER_SOLID_LIGHTING = (1<<4), /* use faster lighting (set automatically) */
GPU_SHADER_OPTIONS_NUM = 5,
GPU_SHADER_OPTION_COMBINATIONS = (1<<GPU_SHADER_OPTIONS_NUM)
-} GPUSimpleShaderOption;
+} GPUBasicShaderOption;
-void GPU_simple_shaders_init(void);
-void GPU_simple_shaders_exit(void);
+void GPU_basic_shaders_init(void);
+void GPU_basic_shaders_exit(void);
-void GPU_simple_shader_bind(int options);
-void GPU_simple_shader_unbind(void);
+void GPU_basic_shader_bind(int options);
+int GPU_basic_shader_bound_options(void);
-void GPU_simple_shader_colors(const float diffuse[3], const float specular[3],
+void GPU_basic_shader_colors(const float diffuse[3], const float specular[3],
int shininess, float alpha);
-bool GPU_simple_shader_need_normals(void);
-
/* Fixed Function Lighting */
+typedef enum GPULightType {
+ GPU_LIGHT_POINT,
+ GPU_LIGHT_SPOT,
+ GPU_LIGHT_SUN
+} GPULightType;
+
typedef struct GPULightData {
- float position[4];
- float diffuse[4];
- float specular[4];
+ GPULightType type;
+
+ float position[3];
+ float direction[3];
+
+ float diffuse[3];
+ float specular[3];
float constant_attenuation;
float linear_attenuation;
float quadratic_attenuation;
- float spot_direction[3];
float spot_cutoff;
float spot_exponent;
} GPULightData;
-void GPU_simple_shader_light_set(int light_num, GPULightData *light);
-void GPU_simple_shader_light_set_viewer(bool local);
+void GPU_basic_shader_light_set(int light_num, GPULightData *light);
+void GPU_basic_shader_light_set_viewer(bool local);
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 9c67f404a12..a8656c05224 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -229,7 +229,7 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
unsigned int **grid_hidden, int gridsize, const struct CCGKey *key);
-GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading);
+GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading);
/* update */
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 0992f8e9d21..3e6c26f608c 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -63,7 +63,7 @@ void GPU_state_init(void);
* - first the state is initialized by a particular object and
* it's materials
* - after this, materials can be quickly enabled by their number,
- * GPU_enable_material returns 0 if drawing should be skipped
+ * GPU_object_material_bind returns 0 if drawing should be skipped
* - after drawing, the material must be disabled again */
void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
@@ -71,8 +71,9 @@ void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
void GPU_end_object_materials(void);
bool GPU_object_materials_check(void);
-int GPU_enable_material(int nr, void *attribs);
-void GPU_disable_material(void);
+int GPU_object_material_bind(int nr, void *attribs);
+void GPU_object_material_unbind(void);
+int GPU_object_material_visible(int nr, void *attribs);
void GPU_begin_dupli_object(struct DupliObject *dob);
void GPU_end_dupli_object(void);
@@ -128,7 +129,7 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap);
/* Image updates and free
* - these deal with images bound as opengl textures */
-void GPU_paint_update_image(struct Image *ima, ImageUser *iuser, int x, int y, int w, int h);
+void GPU_paint_update_image(struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h);
void GPU_update_images_framechange(void);
int GPU_update_image_time(struct Image *ima, double time);
int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, bool compare, bool mipmap, bool is_data);
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index e07f9025090..f3be52f324b 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -36,37 +36,22 @@
extern "C" {
#endif
-struct Image;
-struct ImageUser;
-struct PreviewImage;
-
-struct GPUTexture;
-typedef struct GPUTexture GPUTexture;
-
-struct GPUFrameBuffer;
-typedef struct GPUFrameBuffer GPUFrameBuffer;
-
-struct GPUOffScreen;
-typedef struct GPUOffScreen GPUOffScreen;
-
-struct GPUShader;
-typedef struct GPUShader GPUShader;
-
-struct GPUProgram;
-typedef struct GPUProgram GPUProgram;
-
/* GPU extensions support */
void GPU_extensions_disable(void);
+bool GPU_legacy_support(void);
bool GPU_glsl_support(void);
-bool GPU_non_power_of_two_support(void);
+bool GPU_full_non_power_of_two_support(void);
bool GPU_display_list_support(void);
bool GPU_bicubic_bump_support(void);
bool GPU_geometry_shader_support(void);
+bool GPU_geometry_shader_support_via_extension(void);
bool GPU_instanced_drawing_support(void);
int GPU_max_texture_size(void);
+int GPU_max_textures(void);
+int GPU_max_color_texture_samples(void);
int GPU_color_depth(void);
void GPU_get_dfdy_factors(float fac[2]);
@@ -102,173 +87,6 @@ typedef enum GPUDriverType {
bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
-/* GPU Texture
- * - always returns unsigned char RGBA textures
- * - if texture with non square dimensions is created, depending on the
- * graphics card capabilities the texture may actually be stored in a
- * larger texture with power of two dimensions. the actual dimensions
- * may be queried with GPU_texture_opengl_width/height. GPU_texture_coord_2f
- * calls glTexCoord2f with the coordinates adjusted for this.
- * - can use reference counting:
- * - reference counter after GPU_texture_create is 1
- * - GPU_texture_ref increases by one
- * - GPU_texture_free decreases by one, and frees if 0
- * - if created with from_blender, will not free the texture
- */
-
-typedef enum GPUHDRType {
- GPU_HDR_NONE = 0,
- GPU_HDR_HALF_FLOAT = 1,
- GPU_HDR_FULL_FLOAT = (1 << 1),
-} GPUHDRType;
-
-GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]);
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels);
-GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
-GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
-GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]);
-GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
-GPUTexture *GPU_texture_from_blender(struct Image *ima,
- struct ImageUser *iuser, bool is_data, double time, int mipmap);
-GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
-void GPU_invalid_tex_init(void);
-void GPU_invalid_tex_bind(int mode);
-void GPU_invalid_tex_free(void);
-
-void GPU_texture_free(GPUTexture *tex);
-
-void GPU_texture_ref(GPUTexture *tex);
-
-void GPU_texture_bind(GPUTexture *tex, int number);
-void GPU_texture_unbind(GPUTexture *tex);
-
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter);
-
-GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
-
-int GPU_texture_target(const GPUTexture *tex);
-int GPU_texture_opengl_width(const GPUTexture *tex);
-int GPU_texture_opengl_height(const GPUTexture *tex);
-int GPU_texture_opengl_bindcode(const GPUTexture *tex);
-
-/* GPU Framebuffer
- * - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
- * multiple FBO's may be created, to get around limitations on the number
- * of attached textures and the dimension requirements.
- * - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
- * be called before rendering to the window framebuffer again */
-
-void GPU_texture_bind_as_framebuffer(GPUTexture *tex);
-
-GPUFrameBuffer *GPU_framebuffer_create(void);
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
-void GPU_framebuffer_texture_detach(GPUTexture *tex);
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
-void GPU_framebuffer_free(GPUFrameBuffer *fb);
-bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
-
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
-
-void GPU_framebuffer_restore(void);
-void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex);
-
-/* GPU OffScreen
- * - wrapper around framebuffer and texture for simple offscreen drawing
- * - changes size if graphics card can't support it */
-
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]);
-void GPU_offscreen_free(GPUOffScreen *ofs);
-void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
-void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
-void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
-int GPU_offscreen_width(const GPUOffScreen *ofs);
-int GPU_offscreen_height(const GPUOffScreen *ofs);
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
-
-/* Builtin/Non-generated shaders */
-typedef enum GPUProgramType {
- GPU_PROGRAM_TYPE_FRAGMENT = 0
-} GPUProgramType;
-
-/* TODO: remove ARB program support (recode smoke shader in GLSL) */
-GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code);
-void GPU_program_free(GPUProgram *program);
-void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w);
-void GPU_program_bind(GPUProgram *);
-void GPU_program_unbind(GPUProgram *);
-
-/* GPU Shader
- * - only for fragment shaders now
- * - must call texture bind before setting a texture as uniform! */
-
-GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number);
-enum {
- GPU_SHADER_FLAGS_NONE = 0,
- GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV = (1 << 0),
-};
-GPUShader *GPU_shader_create_ex(const char *vertexcode,
- const char *fragcode,
- const char *geocode,
- const char *libcode,
- const char *defines,
- int input,
- int output,
- int number,
- const int flags);
-void GPU_shader_free(GPUShader *shader);
-
-void GPU_shader_bind(GPUShader *shader);
-void GPU_shader_unbind(void);
-
-int GPU_shader_get_uniform(GPUShader *shader, const char *name);
-void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
- int arraysize, const float *value);
-void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
- int arraysize, const int *value);
-
-void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
-void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
-void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
-
-int GPU_shader_get_attribute(GPUShader *shader, const char *name);
-
-/* Builtin/Non-generated shaders */
-typedef enum GPUBuiltinShader {
- GPU_SHADER_VSM_STORE = 0,
- GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
-} GPUBuiltinShader;
-
-typedef enum GPUBuiltinProgram {
- GPU_PROGRAM_SMOKE = 0,
- GPU_PROGRAM_SMOKE_COLORED = 1,
-} GPUBuiltinProgram;
-
-GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
-GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program);
-GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
-
-void GPU_shader_free_builtin_shaders(void);
-
-/* Vertex attributes for shaders */
-
-#define GPU_MAX_ATTRIB 32
-
-typedef struct GPUVertexAttribs {
- struct {
- int type;
- int glindex;
- int gltexco;
- int attribid;
- char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
- } layer[GPU_MAX_ATTRIB];
-
- int totlayer;
-} GPUVertexAttribs;
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
new file mode 100644
index 00000000000..4a7b0454181
--- /dev/null
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -0,0 +1,84 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_framebuffer.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_FRAMEBUFFER_H__
+#define __GPU_FRAMEBUFFER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct GPUFrameBuffer GPUFrameBuffer;
+typedef struct GPUOffScreen GPUOffScreen;
+typedef struct GPUTexture GPUTexture;
+
+/* GPU Framebuffer
+ * - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
+ * multiple FBO's may be created, to get around limitations on the number
+ * of attached textures and the dimension requirements.
+ * - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
+ * be called before rendering to the window framebuffer again */
+
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex);
+
+GPUFrameBuffer *GPU_framebuffer_create(void);
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
+void GPU_framebuffer_texture_detach(GPUTexture *tex);
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
+void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
+void GPU_framebuffer_free(GPUFrameBuffer *fb);
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
+
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
+
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
+
+void GPU_framebuffer_restore(void);
+void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex);
+
+/* GPU OffScreen
+ * - wrapper around framebuffer and texture for simple offscreen drawing
+ * - changes size if graphics card can't support it */
+
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]);
+void GPU_offscreen_free(GPUOffScreen *ofs);
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
+void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
+int GPU_offscreen_width(const GPUOffScreen *ofs);
+int GPU_offscreen_height(const GPUOffScreen *ofs);
+int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_FRAMEBUFFER_H__ */
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
new file mode 100644
index 00000000000..a7cfd4e262f
--- /dev/null
+++ b/source/blender/gpu/GPU_shader.h
@@ -0,0 +1,127 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_shader.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_SHADER_H__
+#define __GPU_SHADER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct GPUShader GPUShader;
+typedef struct GPUProgram GPUProgram;
+typedef struct GPUTexture GPUTexture;
+
+/* Builtin/Non-generated shaders */
+typedef enum GPUProgramType {
+ GPU_PROGRAM_TYPE_FRAGMENT = 0
+} GPUProgramType;
+
+/* TODO: remove ARB program support (recode smoke shader in GLSL) */
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code);
+void GPU_program_free(GPUProgram *program);
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w);
+void GPU_program_bind(GPUProgram *);
+void GPU_program_unbind(GPUProgram *);
+
+/* GPU Shader
+ * - only for fragment shaders now
+ * - must call texture bind before setting a texture as uniform! */
+
+GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number);
+enum {
+ GPU_SHADER_FLAGS_NONE = 0,
+ GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV = (1 << 0),
+};
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags);
+void GPU_shader_free(GPUShader *shader);
+
+void GPU_shader_bind(GPUShader *shader);
+void GPU_shader_unbind(void);
+
+int GPU_shader_get_uniform(GPUShader *shader, const char *name);
+void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
+ int arraysize, const float *value);
+void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
+ int arraysize, const int *value);
+
+void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
+void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
+void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
+
+int GPU_shader_get_attribute(GPUShader *shader, const char *name);
+
+/* Builtin/Non-generated shaders */
+typedef enum GPUBuiltinShader {
+ GPU_SHADER_VSM_STORE = 0,
+ GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
+} GPUBuiltinShader;
+
+typedef enum GPUBuiltinProgram {
+ GPU_PROGRAM_SMOKE = 0,
+ GPU_PROGRAM_SMOKE_COLORED = 1,
+} GPUBuiltinProgram;
+
+GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program);
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
+
+void GPU_shader_free_builtin_shaders(void);
+
+/* Vertex attributes for shaders */
+
+#define GPU_MAX_ATTRIB 32
+
+typedef struct GPUVertexAttribs {
+ struct {
+ int type;
+ int glindex;
+ int gltexco;
+ int attribid;
+ char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ } layer[GPU_MAX_ATTRIB];
+
+ int totlayer;
+} GPUVertexAttribs;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_SHADER_H__ */
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
new file mode 100644
index 00000000000..a17da53b890
--- /dev/null
+++ b/source/blender/gpu/GPU_texture.h
@@ -0,0 +1,104 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_texture.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_TEXTURE_H__
+#define __GPU_TEXTURE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Image;
+struct ImageUser;
+struct PreviewImage;
+
+typedef struct GPUFrameBuffer GPUFrameBuffer;
+typedef struct GPUTexture GPUTexture;
+
+/* GPU Texture
+ * - always returns unsigned char RGBA textures
+ * - if texture with non square dimensions is created, depending on the
+ * graphics card capabilities the texture may actually be stored in a
+ * larger texture with power of two dimensions.
+ * - can use reference counting:
+ * - reference counter after GPU_texture_create is 1
+ * - GPU_texture_ref increases by one
+ * - GPU_texture_free decreases by one, and frees if 0
+ * - if created with from_blender, will not free the texture
+ */
+
+typedef enum GPUHDRType {
+ GPU_HDR_NONE = 0,
+ GPU_HDR_HALF_FLOAT = 1,
+ GPU_HDR_FULL_FLOAT = (1 << 1),
+} GPUHDRType;
+
+GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]);
+GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels);
+GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
+GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
+GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
+GPUTexture *GPU_texture_from_blender(struct Image *ima,
+ struct ImageUser *iuser, bool is_data, double time, int mipmap);
+GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
+void GPU_invalid_tex_init(void);
+void GPU_invalid_tex_bind(int mode);
+void GPU_invalid_tex_free(void);
+
+void GPU_texture_free(GPUTexture *tex);
+
+void GPU_texture_ref(GPUTexture *tex);
+
+void GPU_texture_bind(GPUTexture *tex, int number);
+void GPU_texture_unbind(GPUTexture *tex);
+int GPU_texture_bound_number(GPUTexture *tex);
+
+void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter);
+
+GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
+int GPU_texture_framebuffer_attachment(GPUTexture *tex);
+void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment);
+
+int GPU_texture_target(const GPUTexture *tex);
+int GPU_texture_width(const GPUTexture *tex);
+int GPU_texture_height(const GPUTexture *tex);
+int GPU_texture_depth(const GPUTexture *tex);
+int GPU_texture_opengl_bindcode(const GPUTexture *tex);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_TEXTURE_H__ */
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
index d27d5b09b56..15898f5c203 100644
--- a/source/blender/gpu/SConscript
+++ b/source/blender/gpu/SConscript
@@ -70,8 +70,8 @@ sources.extend((
os.path.join(env['DATA_SOURCES'], "gpu_shader_geometry.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_color_frag.glsl.c"),
- os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"),
- os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_basic_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_basic_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_vert.glsl.c"),
diff --git a/source/blender/gpu/intern/gpu_simple_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c
index 89d3c0f59df..6b01ee85170 100644
--- a/source/blender/gpu/intern/gpu_simple_shader.c
+++ b/source/blender/gpu/intern/gpu_basic_shader.c
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/gpu/intern/gpu_simple_shader.c
+/** \file blender/gpu/intern/gpu_basic_shader.c
* \ingroup gpu
*
* GLSL shaders to replace fixed function OpenGL materials and lighting. These
@@ -42,23 +42,22 @@
* - Optimize for case where no texture matrix is used.
*/
-#include "GPU_glew.h"
-
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "GPU_extensions.h"
-#include "GPU_simple_shader.h"
+#include "GPU_basic_shader.h"
+#include "GPU_glew.h"
+#include "GPU_shader.h"
/* State */
-// #define NUM_OPENGL_LIGHTS 8
+static const bool USE_GLSL = false;
static struct {
GPUShader *cached_shaders[GPU_SHADER_OPTION_COMBINATIONS];
bool failed_shaders[GPU_SHADER_OPTION_COMBINATIONS];
- bool need_normals;
+ int bound_options;
int lights_enabled;
int lights_directional;
@@ -66,12 +65,12 @@ static struct {
/* Init / exit */
-void GPU_simple_shaders_init(void)
+void GPU_basic_shaders_init(void)
{
memset(&GPU_MATERIAL_STATE, 0, sizeof(GPU_MATERIAL_STATE));
}
-void GPU_simple_shaders_exit(void)
+void GPU_basic_shaders_exit(void)
{
int i;
@@ -104,7 +103,7 @@ static int detect_options()
if (glIsEnabled(GL_TEXTURE_2D))
options |= GPU_SHADER_TEXTURE_2D;
if (glIsEnabled(GL_COLOR_MATERIAL))
- options |= GPU_SHADER_OVERRIDE_DIFFUSE;
+ options |= GPU_SHADER_USE_COLOR;
if (glIsEnabled(GL_LIGHTING))
options |= GPU_SHADER_LIGHTING;
@@ -117,11 +116,11 @@ static int detect_options()
}
#endif
-static GPUShader *gpu_simple_shader(int options)
+static GPUShader *gpu_basic_shader(int options)
{
/* glsl code */
- extern char datatoc_gpu_shader_simple_vert_glsl[];
- extern char datatoc_gpu_shader_simple_frag_glsl[];
+ extern char datatoc_gpu_shader_basic_vert_glsl[];
+ extern char datatoc_gpu_shader_basic_frag_glsl[];
GPUShader *shader;
/* detect if we can do faster lighting for solid draw mode */
@@ -136,7 +135,7 @@ static GPUShader *gpu_simple_shader(int options)
/* create shader if it doesn't exist yet */
char defines[64*GPU_SHADER_OPTIONS_NUM] = "";
- if (options & GPU_SHADER_OVERRIDE_DIFFUSE)
+ if (options & GPU_SHADER_USE_COLOR)
strcat(defines, "#define USE_COLOR\n");
if (options & GPU_SHADER_TWO_SIDED)
strcat(defines, "#define USE_TWO_SIDED\n");
@@ -149,8 +148,8 @@ static GPUShader *gpu_simple_shader(int options)
strcat(defines, "#define USE_SCENE_LIGHTING\n");
shader = GPU_shader_create(
- datatoc_gpu_shader_simple_vert_glsl,
- datatoc_gpu_shader_simple_frag_glsl,
+ datatoc_gpu_shader_basic_vert_glsl,
+ datatoc_gpu_shader_basic_frag_glsl,
NULL,
NULL,
defines, 0, 0, 0);
@@ -171,60 +170,74 @@ static GPUShader *gpu_simple_shader(int options)
/* Bind / unbind */
-void GPU_simple_shader_bind(int options)
+void GPU_basic_shader_bind(int options)
{
- if (GPU_glsl_support()) {
- GPUShader *shader = gpu_simple_shader(options);
+ if (USE_GLSL) {
+ if (options) {
+ GPUShader *shader = gpu_basic_shader(options);
- if (shader)
- GPU_shader_bind(shader);
+ if (shader)
+ GPU_shader_bind(shader);
+ }
+ else {
+ GPU_shader_unbind();
+ }
}
else {
- // XXX where does this fit, depends on ortho/persp?
+ int bound_options = GPU_MATERIAL_STATE.bound_options;
- if (options & GPU_SHADER_LIGHTING)
+ if (options & GPU_SHADER_LIGHTING) {
glEnable(GL_LIGHTING);
- if (options & GPU_SHADER_TWO_SIDED)
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
+ if (options & GPU_SHADER_USE_COLOR)
+ glEnable(GL_COLOR_MATERIAL);
+ else
+ glDisable(GL_COLOR_MATERIAL);
- if (options & GPU_SHADER_OVERRIDE_DIFFUSE) {
- glEnable(GL_COLOR_MATERIAL);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ if (options & GPU_SHADER_TWO_SIDED)
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
+ else
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
+ }
+ else if (bound_options & GPU_SHADER_LIGHTING) {
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
}
if (options & GPU_SHADER_TEXTURE_2D)
glEnable(GL_TEXTURE_2D);
+ else if (bound_options & GPU_SHADER_TEXTURE_2D)
+ glDisable(GL_TEXTURE_2D);
}
- /* temporary hack, should be solved outside of this file */
- GPU_MATERIAL_STATE.need_normals = (options & GPU_SHADER_LIGHTING);
+ GPU_MATERIAL_STATE.bound_options = options;
}
-void GPU_simple_shader_unbind(void)
+int GPU_basic_shader_bound_options(void)
{
- if (GPU_glsl_support()) {
- GPU_shader_unbind();
- }
- else {
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_TEXTURE_2D);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
- }
+ /* ideally this should disappear, anything that uses this is making fragile
+ * assumptions that the basic shader is bound and not another shader */
+ return GPU_MATERIAL_STATE.bound_options;
}
/* Material Colors */
-void GPU_simple_shader_colors(const float diffuse[3], const float specular[3],
+void GPU_basic_shader_colors(const float diffuse[3], const float specular[3],
int shininess, float alpha)
{
float gl_diffuse[4], gl_specular[4];
- copy_v3_v3(gl_diffuse, diffuse);
+ if (diffuse)
+ copy_v3_v3(gl_diffuse, diffuse);
+ else
+ zero_v3(gl_diffuse);
gl_diffuse[3] = alpha;
- copy_v3_v3(gl_specular, specular);
+ if (specular)
+ copy_v3_v3(gl_specular, specular);
+ else
+ zero_v3(gl_specular);
gl_specular[3] = 1.0f;
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse);
@@ -232,49 +245,81 @@ void GPU_simple_shader_colors(const float diffuse[3], const float specular[3],
glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128));
}
-bool GPU_simple_shader_need_normals(void)
-{
- return GPU_MATERIAL_STATE.need_normals;
-}
-
-void GPU_simple_shader_light_set(int light_num, GPULightData *light)
+void GPU_basic_shader_light_set(int light_num, GPULightData *light)
{
int light_bit = (1 << light_num);
+ /* note that light position is affected by the current modelview matrix! */
+
GPU_MATERIAL_STATE.lights_enabled &= ~light_bit;
GPU_MATERIAL_STATE.lights_directional &= ~light_bit;
if (light) {
- glEnable(GL_LIGHT0+light_num);
+ float position[4], diffuse[4], specular[4];
- glLightfv(GL_LIGHT0+light_num, GL_POSITION, light->position);
- glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, light->diffuse);
- glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, light->specular);
+ glEnable(GL_LIGHT0+light_num);
- glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation);
- glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation);
- glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation);
+ /* position */
+ if (light->type == GPU_LIGHT_SUN) {
+ copy_v3_v3(position, light->direction);
+ position[3] = 0.0f;
+ }
+ else {
+ copy_v3_v3(position, light->position);
+ position[3] = 1.0f;
+ }
+ glLightfv(GL_LIGHT0+light_num, GL_POSITION, position);
+
+ /* energy */
+ copy_v3_v3(diffuse, light->diffuse);
+ copy_v3_v3(specular, light->specular);
+ diffuse[3] = 1.0f;
+ specular[3] = 1.0f;
+ glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, diffuse);
+ glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, specular);
+
+ /* attenuation */
+ if (light->type == GPU_LIGHT_SUN) {
+ glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, 1.0f);
+ glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, 0.0f);
+ glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, 0.0f);
+ }
+ else {
+ glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation);
+ glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation);
+ glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation);
+ }
- glLightfv(GL_LIGHT0+light_num, GL_SPOT_DIRECTION, light->spot_direction);
- glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, light->spot_cutoff);
- glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, light->spot_exponent);
+ /* spot */
+ glLightfv(GL_LIGHT0+light_num, GL_SPOT_DIRECTION, light->direction);
+ if (light->type == GPU_LIGHT_SPOT) {
+ glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, light->spot_cutoff);
+ glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, light->spot_exponent);
+ }
+ else {
+ glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, 180.0f);
+ glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, 0.0f);
+ }
GPU_MATERIAL_STATE.lights_enabled |= light_bit;
- if (light->position[3] == 0.0f)
+ if (position[3] == 0.0f)
GPU_MATERIAL_STATE.lights_directional |= light_bit;
}
else {
- const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ if (USE_GLSL) {
+ /* glsl shader needs these zero to skip them */
+ const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- glLightfv(GL_LIGHT0+light_num, GL_POSITION, zero);
- glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, zero);
- glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, zero);
+ glLightfv(GL_LIGHT0+light_num, GL_POSITION, zero);
+ glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, zero);
+ glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, zero);
+ }
glDisable(GL_LIGHT0+light_num);
}
}
-void GPU_simple_shader_light_set_viewer(bool local)
+void GPU_basic_shader_light_set_viewer(bool local)
{
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (local)? GL_TRUE: GL_FALSE);
}
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 69aca31e21a..3c44811324c 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -28,8 +28,7 @@
/** \file blender/gpu/intern/gpu_buffers.c
* \ingroup gpu
*
- * Mesh drawing using OpenGL VBO (Vertex Buffer Objects),
- * with fall-back to vertex arrays.
+ * Mesh drawing using OpenGL VBO (Vertex Buffer Objects)
*/
#include <limits.h>
@@ -58,6 +57,7 @@
#include "GPU_buffers.h"
#include "GPU_draw.h"
+#include "GPU_basic_shader.h"
#include "bmesh.h"
@@ -101,7 +101,6 @@ const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
-/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
static GPUBufferState GLStates = 0;
static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
@@ -527,6 +526,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
if (!(buffer && (varray = glMapBuffer(target, GL_WRITE_ONLY)))) {
if (buffer)
gpu_buffer_free_intern(buffer);
+ BLI_mutex_unlock(&buffer_mutex);
return NULL;
}
}
@@ -864,10 +864,9 @@ void GPU_buffers_unbind(void)
}
if (GLStates & GPU_BUFFER_COLOR_STATE)
glDisableClientState(GL_COLOR_ARRAY);
- if (GLStates & GPU_BUFFER_ELEMENT_STATE) {
- /* not guaranteed we used VBOs but in that case it's just a no-op */
+ if (GLStates & GPU_BUFFER_ELEMENT_STATE)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
+
GLStates &= ~(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE |
GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_2_STATE |
GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE);
@@ -881,7 +880,6 @@ void GPU_buffers_unbind(void)
}
attribData[0].index = -1;
- /* not guaranteed we used VBOs but in that case it's just a no-op */
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
@@ -1004,41 +1002,21 @@ struct GPU_PBVH_Buffers {
BLI_bitmap * const *grid_hidden;
const int *grid_indices;
int totgrid;
- int has_hidden;
+ bool has_hidden;
- int use_bmesh;
+ bool use_bmesh;
unsigned int tot_tri, tot_quad;
/* The PBVH ensures that either all faces in the node are
* smooth-shaded or all faces are flat-shaded */
- int smooth;
+ bool smooth;
bool show_diffuse_color;
bool use_matcaps;
float diffuse_color[4];
};
-typedef enum {
- VBO_ENABLED,
- VBO_DISABLED
-} VBO_State;
-
-static void gpu_colors_enable(VBO_State vbo_state)
-{
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_COLOR_MATERIAL);
- if (vbo_state == VBO_ENABLED)
- glEnableClientState(GL_COLOR_ARRAY);
-}
-
-static void gpu_colors_disable(VBO_State vbo_state)
-{
- glDisable(GL_COLOR_MATERIAL);
- if (vbo_state == VBO_ENABLED)
- glDisableClientState(GL_COLOR_ARRAY);
-}
-
static float gpu_color_from_mask(float mask)
{
return 1.0f - mask * 0.75f;
@@ -1290,10 +1268,10 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
buffers->show_diffuse_color = show_diffuse_color;
buffers->use_matcaps = GPU_material_use_matcaps_get();
+ buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
/* Build VBO */
if (buffers->vert_buf) {
- int smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
const int has_mask = key->has_mask;
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
@@ -1318,7 +1296,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
CCGElem *elem = CCG_grid_elem(key, grid, x, y);
copy_v3_v3(vd->co, CCG_elem_co(key, elem));
- if (smooth) {
+ if (buffers->smooth) {
normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem));
if (has_mask) {
@@ -1330,7 +1308,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
}
}
- if (!smooth) {
+ if (!buffers->smooth) {
/* for flat shading, recalc normals and set the last vertex of
* each triangle in the index buffer to have the flat normal as
* that is what opengl will use */
@@ -1383,8 +1361,6 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
buffers->grid_flag_mats = grid_flag_mats;
buffers->gridkey = *key;
- buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
-
//printf("node updated %p\n", buffers);
}
@@ -1525,7 +1501,7 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
if (totquad == fully_visible_totquad) {
buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad);
- buffers->has_hidden = 0;
+ buffers->has_hidden = false;
}
else {
buffers->tot_quad = totquad;
@@ -1539,7 +1515,7 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf);
}
- buffers->has_hidden = 1;
+ buffers->has_hidden = true;
}
/* Build coord/normal VBO */
@@ -1819,7 +1795,7 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
}
}
-GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading)
+GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading)
{
GPU_PBVH_Buffers *buffers;
@@ -1861,10 +1837,15 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
if (buffers->vert_buf) {
char *base = NULL;
char *index_base = NULL;
+ int bound_options = 0;
glEnableClientState(GL_VERTEX_ARRAY);
if (!wireframe) {
glEnableClientState(GL_NORMAL_ARRAY);
- gpu_colors_enable(VBO_ENABLED);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ /* weak inspection of bound options, should not be necessary ideally */
+ bound_options = GPU_basic_shader_bound_options();
+ GPU_basic_shader_bind(bound_options | GPU_SHADER_USE_COLOR);
}
GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY);
@@ -1943,7 +1924,8 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
glDisableClientState(GL_VERTEX_ARRAY);
if (!wireframe) {
glDisableClientState(GL_NORMAL_ARRAY);
- gpu_colors_disable(VBO_ENABLED);
+ glDisableClientState(GL_COLOR_ARRAY);
+ GPU_basic_shader_bind(bound_options);
}
}
}
@@ -2059,8 +2041,6 @@ void GPU_init_draw_pbvh_BB(void)
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index d479415556e..1db44c5b3a9 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -42,9 +42,11 @@
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
+#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_material.h"
-#include "GPU_extensions.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
#include "BLI_sys_types.h" /* for intptr_t support */
@@ -829,10 +831,11 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
if (input->attribtype == CD_MTFACE) {
- BLI_dynstr_appendf(ds, "%s %s var%d;\n",
+ BLI_dynstr_appendf(ds, "%s %s var%d%s;\n",
GLEW_VERSION_3_0 ? "in" : "varying",
GPU_DATATYPE_STR[input->type],
- input->attribid);
+ input->attribid,
+ GLEW_VERSION_3_0 ? "[]" : "");
BLI_dynstr_appendf(ds, "uniform int fvar%d_offset;\n",
input->attribid);
}
@@ -997,18 +1000,21 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
GPU_shader_bind(shader);
- /* now bind the textures */
+ /* create the textures */
for (input = inputs->first; input; input = input->next) {
if (input->ima)
input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap);
else if (input->prv)
input->tex = GPU_texture_from_preview(input->prv, mipmap);
+ }
+ /* bind the textures, in second loop so texture binding during
+ * create doesn't overwrite already bound textures */
+ for (input = inputs->first; input; input = input->next) {
if (input->tex && input->bindtex) {
GPU_texture_bind(input->tex, input->texid);
GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
}
-
}
}
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index 1ad35c1edae..05968bf1e4c 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -47,10 +47,12 @@
#include "DNA_camera_types.h"
#include "DNA_gpu_types.h"
-#include "GPU_extensions.h"
#include "GPU_compositing.h"
-
+#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
#include "GPU_glew.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
#include "MEM_guardedalloc.h"
@@ -304,7 +306,7 @@ bool GPU_fx_compositor_initialize_passes(
fx->effects = 0;
- if (!GPU_non_power_of_two_support() || !GLEW_EXT_framebuffer_object)
+ if (!GLEW_EXT_framebuffer_object)
return false;
if (!fx_settings) {
@@ -1082,12 +1084,12 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str
{
int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
int viewvecs_uniform;
- float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
- 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
+ float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
+ 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
float tmp = invrendertargetdim[0];
invrendertargetdim[0] = 0.0f;
- dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
+ dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim");
@@ -1174,8 +1176,8 @@ bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, str
{
int near_coc_downsampled;
int invrendertargetdim_uniform;
- float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
- 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
+ float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
+ 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer");
invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim");
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index aaf4037197e..05d11549656 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -49,6 +49,7 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
@@ -74,10 +75,13 @@
#include "BKE_subsurf.h"
#include "BKE_DerivedMesh.h"
+#include "GPU_basic_shader.h"
#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_material.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
#include "PIL_time.h"
@@ -728,7 +732,7 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int
/* scale if not a power of two. this is not strictly necessary for newer
* GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures
* Then don't bother scaling for hardware that supports NPOT textures! */
- if ((!GPU_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) ||
+ if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) ||
is_over_resolution_limit(rectw, recth)) {
rectw = smaller_power_of_2_limit(rectw);
recth = smaller_power_of_2_limit(recth);
@@ -753,12 +757,12 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int
if (use_high_bit_depth) {
if (GLEW_ARB_texture_float)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
}
else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
@@ -784,12 +788,12 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int
ImBuf *mip = ibuf->mipmap[i - 1];
if (use_high_bit_depth) {
if (GLEW_ARB_texture_float)
- glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F_ARB, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
else
glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
}
else {
- glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA8, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
}
}
}
@@ -804,8 +808,6 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int
if (GLEW_EXT_texture_filter_anisotropic)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- /* set to modulate with vertex color */
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
if (ibuf)
IMB_freeImBuf(ibuf);
@@ -847,8 +849,6 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
if (GLEW_EXT_texture_filter_anisotropic)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
@@ -1002,7 +1002,7 @@ void GPU_paint_set_mipmap(bool mipmap)
/* check if image has been downscaled and do scaled partial update */
static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
{
- if ((!GPU_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) ||
+ if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) ||
is_over_resolution_limit(ibuf->x, ibuf->y))
{
int x_limit = smaller_power_of_2_limit(ibuf->x);
@@ -1403,9 +1403,10 @@ void GPU_free_images_old(void)
/* OpenGL state caching for materials */
typedef struct GPUMaterialFixed {
- float diff[4];
- float spec[4];
+ float diff[3];
+ float spec[3];
int hard;
+ float alpha;
} GPUMaterialFixed;
static struct GPUMaterialState {
@@ -1414,7 +1415,7 @@ static struct GPUMaterialState {
int totmat;
/* set when called inside GPU_begin_object_materials / GPU_end_object_materials
- * otherwise calling GPU_enable_material returns zero */
+ * otherwise calling GPU_object_material_bind returns zero */
bool is_enabled;
Material **gmatbuf;
@@ -1430,6 +1431,7 @@ static struct GPUMaterialState {
float (*gviewcamtexcofac);
bool backface_culling;
+ bool two_sided_lighting;
GPUBlendMode *alphablend;
GPUBlendMode alphablend_fixed[FIXEDMAT];
@@ -1447,20 +1449,18 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat,
{
if (bmat->mode & MA_SHLESS) {
copy_v3_v3(smat->diff, &bmat->r);
- smat->diff[3] = 1.0;
if (gamma)
linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
- zero_v4(smat->spec);
+ zero_v3(smat->spec);
+ smat->alpha = 1.0f;
smat->hard = 0;
}
else if (new_shading_nodes) {
copy_v3_v3(smat->diff, &bmat->r);
- smat->diff[3] = 1.0;
-
copy_v3_v3(smat->spec, &bmat->specr);
- smat->spec[3] = 1.0;
+ smat->alpha = 1.0f;
smat->hard = CLAMPIS(bmat->har, 0, 128);
if (dimdown) {
@@ -1475,14 +1475,13 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat,
}
else {
mul_v3_v3fl(smat->diff, &bmat->r, bmat->ref + bmat->emit);
- smat->diff[3] = 1.0; /* caller may set this to bmat->alpha */
if (bmat->shade_flag & MA_OBCOLOR)
mul_v3_v3(smat->diff, ob->col);
mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec);
- smat->spec[3] = 1.0; /* always 1 */
- smat->hard= CLAMPIS(bmat->har, 0, 128);
+ smat->hard = CLAMPIS(bmat->har, 1, 128);
+ smat->alpha = 1.0f;
if (gamma) {
linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
@@ -1570,6 +1569,10 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GMS.backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0;
+ GMS.two_sided_lighting = false;
+ if (ob && ob->type == OB_MESH)
+ GMS.two_sided_lighting = (((Mesh*)ob->data)->flag & ME_TWOSIDED) != 0;
+
GMS.gob = ob;
GMS.gscene = scene;
GMS.is_opensubdiv = use_opensubdiv;
@@ -1648,11 +1651,11 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes, false);
if (GMS.use_alpha_pass && ((ma->mode & MA_TRANSP) || (new_shading_nodes && ma->alpha != 1.0f))) {
- GMS.matbuf[a].diff[3] = ma->alpha;
+ GMS.matbuf[a].alpha = ma->alpha;
alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
}
else {
- GMS.matbuf[a].diff[3] = 1.0f;
+ GMS.matbuf[a].alpha = 1.0f;
alphablend = GPU_BLEND_SOLID;
}
}
@@ -1668,7 +1671,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
}
/* let's start with a clean state */
- GPU_disable_material();
+ GPU_object_material_unbind();
}
static int GPU_get_particle_info(GPUParticleInfo *pi)
@@ -1701,7 +1704,7 @@ static int GPU_get_particle_info(GPUParticleInfo *pi)
return 0;
}
-int GPU_enable_material(int nr, void *attribs)
+int GPU_object_material_bind(int nr, void *attribs)
{
GPUVertexAttribs *gattribs = attribs;
GPUMaterial *gpumat;
@@ -1709,19 +1712,17 @@ int GPU_enable_material(int nr, void *attribs)
/* no GPU_begin_object_materials, use default material */
if (!GMS.matbuf) {
- float diff[4], spec[4];
-
memset(&GMS, 0, sizeof(GMS));
- mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit);
- diff[3] = 1.0;
-
- mul_v3_v3fl(spec, &defmaterial.specr, defmaterial.spec);
- spec[3] = 1.0;
+ float diffuse[3], specular[3];
+ mul_v3_v3fl(diffuse, &defmaterial.r, defmaterial.ref + defmaterial.emit);
+ mul_v3_v3fl(specular, &defmaterial.specr, defmaterial.spec);
+ GPU_basic_shader_colors(diffuse, specular, 35, 1.0f);
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 35); /* blender default */
+ if (GMS.two_sided_lighting)
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_TWO_SIDED);
+ else
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
return 0;
}
@@ -1798,9 +1799,13 @@ int GPU_enable_material(int nr, void *attribs)
}
else {
/* or do fixed function opengl material */
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr].diff);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr].spec);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, GMS.matbuf[nr].hard);
+ GPU_basic_shader_colors(GMS.matbuf[nr].diff,
+ GMS.matbuf[nr].spec, GMS.matbuf[nr].hard, GMS.matbuf[nr].alpha);
+
+ if (GMS.two_sided_lighting)
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_TWO_SIDED);
+ else
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
}
/* set (alpha) blending mode */
@@ -1810,6 +1815,31 @@ int GPU_enable_material(int nr, void *attribs)
return GMS.lastretval;
}
+int GPU_object_material_visible(int nr, void *attribs)
+{
+ GPUVertexAttribs *gattribs = attribs;
+ int visible;
+
+ if (!GMS.matbuf)
+ return 0;
+
+ if (gattribs)
+ memset(gattribs, 0, sizeof(*gattribs));
+
+ if (nr>=GMS.totmat)
+ nr = 0;
+
+ if (GMS.use_alpha_pass) {
+ visible = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
+ if (GMS.is_alpha_pass)
+ visible = !visible;
+ }
+ else
+ visible = !GMS.is_alpha_pass;
+
+ return visible;
+}
+
void GPU_set_material_alpha_blend(int alphablend)
{
if (GMS.lastalphablend == alphablend)
@@ -1824,7 +1854,7 @@ int GPU_get_material_alpha_blend(void)
return GMS.lastalphablend;
}
-void GPU_disable_material(void)
+void GPU_object_material_unbind(void)
{
GMS.lastmatnr = -1;
GMS.lastretval = 1;
@@ -1837,6 +1867,8 @@ void GPU_disable_material(void)
GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv));
GMS.gboundmat = NULL;
}
+ else
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
}
@@ -1852,7 +1884,8 @@ void GPU_material_diffuse_get(int nr, float diff[4])
mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit);
}
else {
- copy_v4_v4(diff, GMS.matbuf[nr].diff);
+ copy_v3_v3(diff, GMS.matbuf[nr].diff);
+ diff[3] = GMS.matbuf[nr].alpha;
}
}
@@ -1868,7 +1901,7 @@ bool GPU_object_materials_check(void)
void GPU_end_object_materials(void)
{
- GPU_disable_material();
+ GPU_object_material_unbind();
GMS.is_enabled = false;
@@ -1881,6 +1914,7 @@ void GPU_end_object_materials(void)
GMS.matbuf = NULL;
GMS.gmatbuf = NULL;
GMS.alphablend = NULL;
+ GMS.two_sided_lighting = false;
/* resetting the texture matrix after the scaling needed for tiled textures */
if (GTS.tilemode) {
@@ -1894,7 +1928,6 @@ void GPU_end_object_materials(void)
int GPU_default_lights(void)
{
- float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}, position[4];
int a, count = 0;
/* initialize */
@@ -1918,42 +1951,25 @@ int GPU_default_lights(void)
U.light[2].spec[3] = 1.0;
}
- glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
+ GPU_basic_shader_light_set_viewer(false);
for (a = 0; a < 8; a++) {
- if (a < 3) {
- if (U.light[a].flag) {
- glEnable(GL_LIGHT0 + a);
+ if (a < 3 && U.light[a].flag) {
+ GPULightData light = {0};
- normalize_v3_v3(position, U.light[a].vec);
- position[3] = 0.0f;
-
- glLightfv(GL_LIGHT0 + a, GL_POSITION, position);
- glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, U.light[a].col);
- glLightfv(GL_LIGHT0 + a, GL_SPECULAR, U.light[a].spec);
+ light.type = GPU_LIGHT_SUN;
- count++;
- }
- else {
- glDisable(GL_LIGHT0 + a);
+ normalize_v3_v3(light.direction, U.light[a].vec);
+ copy_v3_v3(light.diffuse, U.light[a].col);
+ copy_v3_v3(light.specular, U.light[a].spec);
- glLightfv(GL_LIGHT0 + a, GL_POSITION, zero);
- glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, zero);
- glLightfv(GL_LIGHT0 + a, GL_SPECULAR, zero);
- }
+ GPU_basic_shader_light_set(a, &light);
- /* clear stuff from other opengl lamp usage */
- glLightf(GL_LIGHT0 + a, GL_SPOT_CUTOFF, 180.0);
- glLightf(GL_LIGHT0 + a, GL_CONSTANT_ATTENUATION, 1.0);
- glLightf(GL_LIGHT0 + a, GL_LINEAR_ATTENUATION, 0.0);
+ count++;
}
else
- glDisable(GL_LIGHT0 + a);
+ GPU_basic_shader_light_set(a, NULL);
}
-
- glDisable(GL_LIGHTING);
-
- glDisable(GL_COLOR_MATERIAL);
return count;
}
@@ -1963,15 +1979,14 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
Base *base;
Lamp *la;
int count;
- float position[4], direction[4], energy[4];
/* disable all lights */
for (count = 0; count < 8; count++)
- glDisable(GL_LIGHT0 + count);
+ GPU_basic_shader_light_set(count, NULL);
/* view direction for specular is not computed correct by default in
* opengl, so we set the settings ourselfs */
- glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, ortho ? GL_FALSE : GL_TRUE);
+ GPU_basic_shader_light_set_viewer(!ortho);
count = 0;
@@ -1988,41 +2003,37 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
glPushMatrix();
glLoadMatrixf((float *)viewmat);
- if (la->type == LA_SUN) {
- /* sun lamp */
- copy_v3_v3(direction, base->object->obmat[2]);
- direction[3] = 0.0;
+ /* setup light */
+ GPULightData light = {0};
- glLightfv(GL_LIGHT0+count, GL_POSITION, direction);
+ mul_v3_v3fl(light.diffuse, &la->r, la->energy);
+ mul_v3_v3fl(light.specular, &la->r, la->energy);
+
+ if (la->type == LA_SUN) {
+ /* directional sun light */
+ light.type = GPU_LIGHT_SUN;
+ normalize_v3_v3(light.direction, base->object->obmat[2]);
}
else {
- /* other lamps with attenuation */
- copy_v3_v3(position, base->object->obmat[3]);
- position[3] = 1.0f;
-
- glLightfv(GL_LIGHT0+count, GL_POSITION, position);
- glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
- glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1 / la->dist);
- glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2 / (la->dist * la->dist));
+ /* other lamps with position attenuation */
+ copy_v3_v3(light.position, base->object->obmat[3]);
+
+ light.constant_attenuation = 1.0f;
+ light.linear_attenuation = la->att1 / la->dist;
+ light.quadratic_attenuation = la->att2 / (la->dist * la->dist);
if (la->type == LA_SPOT) {
- /* spot lamp */
- negate_v3_v3(direction, base->object->obmat[2]);
- glLightfv(GL_LIGHT0 + count, GL_SPOT_DIRECTION, direction);
- glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, RAD2DEGF(la->spotsize * 0.5f));
- glLightf(GL_LIGHT0 + count, GL_SPOT_EXPONENT, 128.0f * la->spotblend);
+ light.type = GPU_LIGHT_SPOT;
+ negate_v3_v3(light.direction, base->object->obmat[2]);
+ normalize_v3(light.direction);
+ light.spot_cutoff = RAD2DEGF(la->spotsize * 0.5f);
+ light.spot_exponent = 128.0f * la->spotblend;
}
else
- glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, 180.0);
+ light.type = GPU_LIGHT_POINT;
}
- /* setup energy */
- mul_v3_v3fl(energy, &la->r, la->energy);
- energy[3] = 1.0;
-
- glLightfv(GL_LIGHT0 + count, GL_DIFFUSE, energy);
- glLightfv(GL_LIGHT0 + count, GL_SPECULAR, energy);
- glEnable(GL_LIGHT0 + count);
+ GPU_basic_shader_light_set(count, &light);
glPopMatrix();
@@ -2063,11 +2074,15 @@ static void gpu_multisample(bool enable)
#endif
}
-/* Default OpenGL State */
+/* Default OpenGL State
+ *
+ * This is called on startup, for opengl offscreen render and to restore state
+ * for the game engine. Generally we should always return to this state when
+ * temporarily modifying the state for drawing, though that are (undocumented)
+ * exceptions that we should try to get rid of. */
void GPU_state_init(void)
{
- /* also called when doing opengl rendering and in the game engine */
float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
int a, x, y;
@@ -2078,6 +2093,7 @@ void GPU_state_init(void)
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 35);
+ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
GPU_default_lights();
@@ -2092,6 +2108,7 @@ void GPU_state_init(void)
glDisable(GL_DEPTH_TEST);
glDisable(GL_FOG);
glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LOGIC_OP);
glDisable(GL_STENCIL_TEST);
glDisable(GL_TEXTURE_1D);
@@ -2136,6 +2153,8 @@ void GPU_state_init(void)
glDisable(GL_CULL_FACE);
gpu_multisample(false);
+
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
#ifdef WITH_OPENSUBDIV
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 3ff8ab5b4c8..c855c53ace4 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -32,9 +32,6 @@
* with checks for drivers and GPU support.
*/
-
-#include "DNA_image_types.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
@@ -44,12 +41,11 @@
#include "BKE_global.h"
-#include "GPU_glew.h"
-#include "GPU_debug.h"
+#include "GPU_basic_shader.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
-#include "GPU_compositing.h"
-#include "GPU_simple_shader.h"
+#include "GPU_glew.h"
+#include "GPU_texture.h"
#include "intern/gpu_private.h"
@@ -61,17 +57,14 @@
# include "BLI_winstuff.h"
#endif
-/* TODO(sergey): Find better default values for this constants. */
-#define MAX_DEFINE_LENGTH 1024
-#define MAX_EXT_DEFINE_LENGTH 1024
-
/* Extensions support */
/* -- extension: version of GL that absorbs it
* ARB_fragment_program: 2.0
* ARB_framebuffer object: 3.0
- * EXT_framebuffer_multisample: 3.0
+ * EXT_framebuffer_object: 3.0
* EXT_framebuffer_blit: 3.0
+ * EXT_framebuffer_multisample: 3.0
* EXT_framebuffer_multisample_blit_scaled: ???
* ARB_draw_instanced: 3.1
* ARB_texture_multisample: 3.2
@@ -79,64 +72,20 @@
* ARB_texture_query_lod: 4.0
*/
-/* Non-generated shaders */
-extern char datatoc_gpu_program_smoke_frag_glsl[];
-extern char datatoc_gpu_program_smoke_color_frag_glsl[];
-extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
-extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
-extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
-extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
-extern char datatoc_gpu_shader_fx_vert_glsl[];
-extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
-extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
-extern char datatoc_gpu_shader_fx_lib_glsl[];
-
-typedef struct GPUShaders {
- GPUShader *vsm_store;
- GPUShader *sep_gaussian_blur;
- GPUProgram *smoke;
- GPUProgram *smoke_colored;
- /* cache for shader fx. Those can exist in combinations so store them here */
- GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
-} GPUShaders;
-
static struct GPUGlobal {
GLint maxtexsize;
GLint maxtextures;
- GLuint currentfb;
- int glslsupport;
- int extdisabled;
+ bool extdisabled;
int colordepth;
int samples_color_texture_max;
- int npotdisabled; /* ATI 3xx-5xx (and more) chipsets support NPoT partially (== not enough) */
- int dlistsdisabled; /* Legacy ATI driver does not support display lists well */
GPUDeviceType device;
GPUOSType os;
GPUDriverType driver;
- GPUShaders shaders;
- GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
- GPUTexture *invalid_tex_2D;
- GPUTexture *invalid_tex_3D;
float dfdyfactors[2]; /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
calculate dfdy in shader differently when drawing to an offscreen buffer. First
number is factor on screen and second is off-screen */
} GG = {1, 0};
-/* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
-#define GPU_FB_MAX_SLOTS 4
-
-struct GPUFrameBuffer {
- GLuint object;
- GPUTexture *colortex[GPU_FB_MAX_SLOTS];
- GPUTexture *depthtex;
-};
-
-
/* GPU Types */
bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
@@ -148,7 +97,7 @@ bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
void GPU_extensions_disable(void)
{
- GG.extdisabled = 1;
+ GG.extdisabled = true;
}
int GPU_max_texture_size(void)
@@ -156,6 +105,16 @@ int GPU_max_texture_size(void)
return GG.maxtexsize;
}
+int GPU_max_textures(void)
+{
+ return GG.maxtextures;
+}
+
+int GPU_max_color_texture_samples(void)
+{
+ return GG.samples_color_texture_max;
+}
+
void GPU_get_dfdy_factors(float fac[2])
{
copy_v2_v2(fac, GG.dfdyfactors);
@@ -163,9 +122,6 @@ void GPU_get_dfdy_factors(float fac[2])
void gpu_extensions_init(void)
{
- GLint r, g, b;
- const char *vendor, *renderer, *version;
-
/* BLI_assert(GLEW_VERSION_2_1); */
/* ^-- maybe a bit extreme? */
@@ -173,8 +129,7 @@ void gpu_extensions_init(void)
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
- GG.glslsupport = 1;
-
+ GLint r, g, b;
glGetIntegerv(GL_RED_BITS, &r);
glGetIntegerv(GL_GREEN_BITS, &g);
glGetIntegerv(GL_BLUE_BITS, &b);
@@ -184,9 +139,9 @@ void gpu_extensions_init(void)
glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES , &GG.samples_color_texture_max);
}
- vendor = (const char *)glGetString(GL_VENDOR);
- renderer = (const char *)glGetString(GL_RENDERER);
- version = (const char *)glGetString(GL_VERSION);
+ const char *vendor = (const char *)glGetString(GL_VENDOR);
+ const char *renderer = (const char *)glGetString(GL_RENDERER);
+ const char *version = (const char *)glGetString(GL_VERSION);
if (strstr(vendor, "ATI")) {
GG.device = GPU_DEVICE_ATI;
@@ -263,2048 +218,85 @@ void gpu_extensions_init(void)
GPU_invalid_tex_init();
- GPU_simple_shaders_init();
+ GPU_basic_shaders_init();
}
void gpu_extensions_exit(void)
{
- GPU_simple_shaders_exit();
+ GPU_basic_shaders_exit();
GPU_invalid_tex_free();
}
-bool GPU_glsl_support(void)
-{
- return GG.glslsupport;
-}
-
-bool GPU_non_power_of_two_support(void)
-{
- /* still relevant for OpenGL ES */
- return !GG.npotdisabled;
-}
-
-bool GPU_display_list_support(void)
-{
- return !GG.dlistsdisabled;
-}
-
-bool GPU_bicubic_bump_support(void)
-{
- return GLEW_VERSION_4_0 || (GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0);
-}
-
-
-bool GPU_geometry_shader_support(void)
-{
- /* in GL 3.2 geometry shaders are fully supported
- * core profile clashes with our other shaders so accept compatibility only
- * other GL versions can use EXT_geometry_shader4 if available
- */
- return (GLEW_VERSION_3_2 && GLEW_ARB_compatibility) || GLEW_EXT_geometry_shader4;
-}
-
-static bool GPU_geometry_shader_support_via_extension(void)
-{
- return GLEW_EXT_geometry_shader4 && !(GLEW_VERSION_3_2 && GLEW_ARB_compatibility);
-}
-
-bool GPU_instanced_drawing_support(void)
-{
- return GLEW_VERSION_3_1 || GLEW_ARB_draw_instanced;
-}
-
-int GPU_color_depth(void)
-{
- return GG.colordepth;
-}
-
-static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
-{
- const char *err = "unknown";
-
- switch (status) {
- case GL_FRAMEBUFFER_COMPLETE_EXT:
- break;
- case GL_INVALID_OPERATION:
- err = "Invalid operation";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- err = "Incomplete attachment";
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- err = "Unsupported framebuffer format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- err = "Missing attachment";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- err = "Attached images must have same dimensions";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- err = "Attached images must have same format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- err = "Missing draw buffer";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- err = "Missing read buffer";
- break;
- }
-
- if (err_out) {
- BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
- (int)status, err);
- }
- else {
- fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
- (int)status, err);
- }
-}
-
-/* GPUTexture */
-
-struct GPUTexture {
- int w, h; /* width/height */
- int w_orig, h_orig; /* width/height (before power of 2 is applied) */
- int number; /* number for multitexture binding */
- int refcount; /* reference count */
- GLenum target; /* GL_TEXTURE_* */
- GLenum target_base; /* same as target, (but no multisample) */
- GLuint bindcode; /* opengl identifier for texture */
- int fromblender; /* we got the texture from Blender */
-
- GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
- int fb_attachment; /* slot the texture is attached to */
- int depth; /* is a depth texture? if 3D how deep? */
- int depth_orig; /* depth (before power of 2 is applied) */
-};
-
-static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
-{
- unsigned char *pixels, *p;
- const float *fp = fpixels;
- const int len = 4 * length;
- int a;
-
- p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
-
- for (a = 0; a < len; a++, p++, fp++)
- *p = FTOCHAR((*fp));
-
- return pixels;
-}
-
-static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
-{
- void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
-
- if (target == GL_TEXTURE_1D)
- glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
- else
- glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
-
- MEM_freeN(pixels);
-}
-
-static GPUTexture *GPU_texture_create_nD(
- int w, int h, int n, const float *fpixels, int depth,
- GPUHDRType hdr_type, int components, int samples,
- char err_out[256])
-{
- GPUTexture *tex;
- GLenum type, format, internalformat;
- void *pixels = NULL;
-
- if (samples) {
- CLAMP_MAX(samples, GG.samples_color_texture_max);
- }
-
- tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = tex->w_orig = w;
- tex->h = tex->h_orig = h;
- tex->number = -1;
- tex->refcount = 1;
- tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
- tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
- tex->depth = tex->depth_orig = depth;
- tex->fb_attachment = -1;
-
- glGenTextures(1, &tex->bindcode);
-
- if (!tex->bindcode) {
- if (err_out) {
- BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
- (int)glGetError());
- }
- else {
- fprintf(stderr, "GPUTexture: texture create failed: %d\n",
- (int)glGetError());
- }
- GPU_texture_free(tex);
- return NULL;
- }
-
- if (!GPU_non_power_of_two_support()) {
- tex->w = power_of_2_max_i(tex->w);
- tex->h = power_of_2_max_i(tex->h);
- }
-
- tex->number = 0;
- glBindTexture(tex->target, tex->bindcode);
-
- if (depth) {
- type = GL_UNSIGNED_BYTE;
- format = GL_DEPTH_COMPONENT;
- internalformat = GL_DEPTH_COMPONENT;
- }
- else {
- type = GL_FLOAT;
-
- if (components == 4) {
- format = GL_RGBA;
- switch (hdr_type) {
- case GPU_HDR_NONE:
- internalformat = GL_RGBA8;
- break;
- case GPU_HDR_HALF_FLOAT:
- internalformat = GL_RGBA16F;
- break;
- case GPU_HDR_FULL_FLOAT:
- internalformat = GL_RGBA32F;
- break;
- default:
- break;
- }
- }
- else if (components == 2) {
- format = GL_RG;
- switch (hdr_type) {
- case GPU_HDR_NONE:
- internalformat = GL_RG8;
- break;
- case GPU_HDR_HALF_FLOAT:
- internalformat = GL_RG16F;
- break;
- case GPU_HDR_FULL_FLOAT:
- internalformat = GL_RG32F;
- break;
- default:
- break;
- }
- }
-
- if (fpixels && hdr_type == GPU_HDR_NONE) {
- type = GL_UNSIGNED_BYTE;
- pixels = GPU_texture_convert_pixels(w*h, fpixels);
- }
- }
-
- if (tex->target == GL_TEXTURE_1D) {
- glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
-
- if (fpixels) {
- glTexSubImage1D(tex->target, 0, 0, w, format, type,
- pixels ? pixels : fpixels);
-
- if (tex->w > w)
- GPU_glTexSubImageEmpty(tex->target, format, w, 0,
- tex->w-w, 1);
- }
- }
- else {
- if (samples) {
- glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
- }
- else {
- glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
- format, type, NULL);
- }
-
- if (fpixels) {
- glTexSubImage2D(tex->target, 0, 0, 0, w, h,
- format, type, pixels ? pixels : fpixels);
-
- if (tex->w > w)
- GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h);
- if (tex->h > h)
- GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h);
- }
- }
-
- if (pixels)
- MEM_freeN(pixels);
-
- if (depth) {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
- }
- else {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
- if (tex->target_base != GL_TEXTURE_1D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- else
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-
- return tex;
-}
-
-
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
-{
- GPUTexture *tex;
- GLenum type, format, internalformat;
- void *pixels = NULL;
- int r_width;
- bool rescale = false;
-
- if (!GLEW_VERSION_1_2)
- return NULL;
-
- tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = tex->w_orig = w;
- tex->h = tex->h_orig = h;
- tex->depth = tex->depth_orig = depth;
- tex->number = -1;
- tex->refcount = 1;
- tex->target = GL_TEXTURE_3D;
- tex->target_base = GL_TEXTURE_3D;
-
- glGenTextures(1, &tex->bindcode);
-
- if (!tex->bindcode) {
- fprintf(stderr, "GPUTexture: texture create failed: %d\n",
- (int)glGetError());
- GPU_texture_free(tex);
- return NULL;
- }
-
- if (!GPU_non_power_of_two_support()) {
- tex->w = power_of_2_max_i(tex->w);
- tex->h = power_of_2_max_i(tex->h);
- tex->depth = power_of_2_max_i(tex->depth);
- }
-
- tex->number = 0;
- glBindTexture(tex->target, tex->bindcode);
-
- GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
-
- type = GL_FLOAT;
- if (channels == 4) {
- format = GL_RGBA;
- internalformat = GL_RGBA;
- }
- else {
- format = GL_RED;
- internalformat = GL_INTENSITY;
- }
-
- /* 3D textures are quite heavy, test if it's possible to create them first */
- glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
-
- while (r_width == 0) {
- rescale = true;
- tex->w /= 2;
- tex->h /= 2;
- tex->depth /= 2;
- glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
- }
-
- /* really unlikely to happen but keep this just in case */
- tex->w = max_ii(tex->w, 1);
- tex->h = max_ii(tex->h, 1);
- tex->depth = max_ii(tex->depth, 1);
-
-#if 0
- if (fpixels)
- pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
-#endif
-
- GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
-
- /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
- * for gooseberry */
- if (rescale && fpixels) {
- unsigned int i, j, k;
- unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
- float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d");
-
- GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
-
- for (k = 0; k < tex->depth; k++) {
- for (j = 0; j < tex->h; j++) {
- for (i = 0; i < tex->w; i++) {
- /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */
- float xb = i * xf;
- float yb = j * yf;
- float zb = k * zf;
- unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
- unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
-
- if (channels == 4) {
- tex3d[offset * 4] = fpixels[offset_orig * 4];
- tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
- tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
- tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
- }
- else
- tex3d[offset] = fpixels[offset_orig];
- }
- }
- }
-
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
-
- MEM_freeN(tex3d);
- }
- else {
- if (fpixels) {
- if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
- /* clear first to avoid unitialized pixels */
- float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
- glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, GL_INTENSITY, GL_FLOAT, zero);
- glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
- MEM_freeN(zero);
- }
- else {
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
- }
-
- GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
- }
- }
-
-
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- if (pixels)
- MEM_freeN(pixels);
-
- GPU_texture_unbind(tex);
-
- return tex;
-}
-
-GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data, double time, int mipmap)
-{
- GPUTexture *tex;
- GLint w, h, border, lastbindcode, bindcode;
-
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
-
- GPU_update_image_time(ima, time);
- /* this binds a texture, so that's why to restore it with lastbindcode */
- bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, is_data);
-
- if (ima->gputexture) {
- ima->gputexture->bindcode = bindcode;
- glBindTexture(GL_TEXTURE_2D, lastbindcode);
- return ima->gputexture;
- }
-
- tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->bindcode = bindcode;
- tex->number = -1;
- tex->refcount = 1;
- tex->target = GL_TEXTURE_2D;
- tex->target_base = GL_TEXTURE_2D;
- tex->fromblender = 1;
-
- ima->gputexture= tex;
-
- if (!glIsTexture(tex->bindcode)) {
- GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
- }
- else {
- glBindTexture(GL_TEXTURE_2D, tex->bindcode);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
-
- tex->w = tex->w_orig = w - border;
- tex->h = tex->h_orig = h - border;
- }
-
- glBindTexture(GL_TEXTURE_2D, lastbindcode);
-
- return tex;
-}
-
-GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
-{
- GPUTexture *tex = prv->gputexture[0];
- GLint w, h, lastbindcode;
- GLuint bindcode = 0;
-
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
-
- if (tex)
- bindcode = tex->bindcode;
-
- /* this binds a texture, so that's why to restore it */
- if (bindcode == 0) {
- GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL);
- }
- if (tex) {
- tex->bindcode = bindcode;
- glBindTexture(GL_TEXTURE_2D, lastbindcode);
- return tex;
- }
-
- tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->bindcode = bindcode;
- tex->number = -1;
- tex->refcount = 1;
- tex->target = GL_TEXTURE_2D;
- tex->target_base = GL_TEXTURE_2D;
-
- prv->gputexture[0] = tex;
-
- if (!glIsTexture(tex->bindcode)) {
- GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
- }
- else {
- glBindTexture(GL_TEXTURE_2D, tex->bindcode);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
-
- tex->w = tex->w_orig = w;
- tex->h = tex->h_orig = h;
- }
-
- glBindTexture(GL_TEXTURE_2D, lastbindcode);
-
- return tex;
-
-}
-
-GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
-}
-
-GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
-}
-GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
-}
-
-GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
-}
-GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
-}
-
-/**
- * A shadow map for VSM needs two components (depth and depth^2)
- */
-GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- GPU_texture_unbind(tex);
- }
-
- return tex;
-}
-
-GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- if (repeat) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
- GPU_texture_unbind(tex);
- }
-
- return tex;
-}
-
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
- GPU_texture_unbind(tex);
- }
-
- return tex;
-}
-
-void GPU_invalid_tex_init(void)
-{
- const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
- GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
- GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
- GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
-}
-
-void GPU_invalid_tex_bind(int mode)
-{
- switch (mode) {
- case GL_TEXTURE_1D:
- glBindTexture(GL_TEXTURE_1D, GG.invalid_tex_1D->bindcode);
- break;
- case GL_TEXTURE_2D:
- glBindTexture(GL_TEXTURE_2D, GG.invalid_tex_2D->bindcode);
- break;
- case GL_TEXTURE_3D:
- glBindTexture(GL_TEXTURE_3D, GG.invalid_tex_3D->bindcode);
- break;
- }
-}
-
-void GPU_invalid_tex_free(void)
-{
- if (GG.invalid_tex_1D)
- GPU_texture_free(GG.invalid_tex_1D);
- if (GG.invalid_tex_2D)
- GPU_texture_free(GG.invalid_tex_2D);
- if (GG.invalid_tex_3D)
- GPU_texture_free(GG.invalid_tex_3D);
-}
-
-
-void GPU_texture_bind(GPUTexture *tex, int number)
+bool GPU_legacy_support(void)
{
- GLenum arbnumber;
-
- if (number >= GG.maxtextures) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
- if ((G.debug & G_DEBUG)) {
- if (tex->fb && tex->fb->object == GG.currentfb) {
- fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
- }
- }
-
- if (number < 0)
- return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
-
- arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
- if (number != 0) glActiveTexture(arbnumber);
- if (tex->bindcode != 0) {
- glBindTexture(tex->target, tex->bindcode);
- }
- else
- GPU_invalid_tex_bind(tex->target);
- glEnable(tex->target);
- if (number != 0) glActiveTexture(GL_TEXTURE0);
-
- tex->number = number;
-
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
-}
+ // return whether or not current GL context is compatible with legacy OpenGL
-void GPU_texture_unbind(GPUTexture *tex)
-{
- GLenum arbnumber;
-
- if (tex->number >= GG.maxtextures) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
- if (tex->number == -1)
- return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
-
- arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
- if (tex->number != 0) glActiveTexture(arbnumber);
- glBindTexture(tex->target, 0);
- glDisable(tex->target_base);
- if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
-
- tex->number = -1;
-
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
-}
-
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
-{
- GLenum arbnumber;
-
- if (tex->number >= GG.maxtextures) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
- if (tex->number == -1)
- return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
-
- arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
- if (tex->number != 0) glActiveTexture(arbnumber);
-
- if (tex->depth) {
- if (compare)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
- else
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- }
-
- if (use_filter) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
- else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
- if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
-}
-
-void GPU_texture_free(GPUTexture *tex)
-{
- tex->refcount--;
-
- if (tex->refcount < 0)
- fprintf(stderr, "GPUTexture: negative refcount\n");
-
- if (tex->refcount == 0) {
- if (tex->fb)
- GPU_framebuffer_texture_detach(tex);
- if (tex->bindcode && !tex->fromblender)
- glDeleteTextures(1, &tex->bindcode);
-
- MEM_freeN(tex);
- }
-}
-
-void GPU_texture_ref(GPUTexture *tex)
-{
- tex->refcount++;
-}
-
-int GPU_texture_target(const GPUTexture *tex)
-{
- return tex->target;
-}
-
-int GPU_texture_opengl_width(const GPUTexture *tex)
-{
- return tex->w;
-}
-
-int GPU_texture_opengl_height(const GPUTexture *tex)
-{
- return tex->h;
-}
-
-int GPU_texture_opengl_bindcode(const GPUTexture *tex)
-{
- return tex->bindcode;
-}
-
-GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
-{
- return tex->fb;
-}
-
-/* GPUFrameBuffer */
-
-GPUFrameBuffer *GPU_framebuffer_create(void)
-{
- GPUFrameBuffer *fb;
-
- if (!GLEW_EXT_framebuffer_object)
- return NULL;
-
- fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
- glGenFramebuffersEXT(1, &fb->object);
-
- if (!fb->object) {
- fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
- (int)glGetError());
- GPU_framebuffer_free(fb);
- return NULL;
- }
-
- /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- glReadBuffer(GL_NONE);
- glDrawBuffer(GL_NONE);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-
- return fb;
-}
-
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
-{
- GLenum attachment;
- GLenum error;
-
- if (slot >= GPU_FB_MAX_SLOTS) {
- fprintf(stderr,
- "Attaching to index %d framebuffer slot unsupported. "
- "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return 0;
- }
+ if (GLEW_VERSION_3_2) {
+ static GLint profile = 0;
- if ((G.debug & G_DEBUG)) {
- if (tex->number != -1) {
- fprintf(stderr,
- "Feedback loop warning!: "
- "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
+ if (profile == 0) {
+ glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
}
- }
-
- if (tex->depth)
- attachment = GL_DEPTH_ATTACHMENT_EXT;
- else
- attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- GG.currentfb = fb->object;
-
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
-
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
- tex->target, tex->bindcode, 0);
- error = glGetError();
-
- if (error == GL_INVALID_OPERATION) {
- GPU_framebuffer_restore();
- GPU_print_framebuffer_error(error, err_out);
- return 0;
+ return profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
}
-
- if (tex->depth)
- fb->depthtex = tex;
- else
- fb->colortex[slot] = tex;
-
- tex->fb= fb;
- tex->fb_attachment = slot;
-
- return 1;
-}
-
-void GPU_framebuffer_texture_detach(GPUTexture *tex)
-{
- GLenum attachment;
- GPUFrameBuffer *fb;
-
- if (!tex->fb)
- return;
-
- fb = tex->fb;
-
- if (GG.currentfb != fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- GG.currentfb = tex->fb->object;
- }
-
- if (tex->depth) {
- fb->depthtex = NULL;
- attachment = GL_DEPTH_ATTACHMENT_EXT;
- }
- else {
- BLI_assert(fb->colortex[tex->fb_attachment] == tex);
- fb->colortex[tex->fb_attachment] = NULL;
- attachment = GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment;
- }
-
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, tex->target, 0, 0);
-
- tex->fb = NULL;
- tex->fb_attachment = -1;
-}
-
-void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
-{
- if (!tex->fb) {
- fprintf(stderr, "Error, texture not bound to framebuffer!\n");
- return;
- }
-
- /* push attributes */
- glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
-
- /* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
-
- if (tex->depth) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
+ else if (GLEW_VERSION_3_1) {
+ return GLEW_ARB_compatibility;
}
else {
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
- }
-
- if (tex->target == GL_TEXTURE_2D_MULTISAMPLE) {
- glEnable(GL_MULTISAMPLE);
- }
-
- /* push matrices and set default viewport and matrix */
- glViewport(0, 0, tex->w_orig, tex->h_orig);
- GG.currentfb = tex->fb->object;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-}
-
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
-{
- int numslots = 0, i;
- GLenum attachments[4];
-
- if (!fb->colortex[slot]) {
- fprintf(stderr, "Error, framebuffer slot empty!\n");
- return;
- }
-
- for (i = 0; i < 4; i++) {
- if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
- numslots++;
- }
+ return true;
}
-
- /* push attributes */
- glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
-
- /* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
-
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffers(numslots, attachments);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
-
- /* push matrices and set default viewport and matrix */
- glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
- GG.currentfb = fb->object;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
}
-
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
-{
- /* restore matrix */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- /* restore attributes */
- glPopAttrib();
-}
-
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
-{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
-
- /* push matrices and set default viewport and matrix */
- glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
- GG.currentfb = fb->object;
- GG.currentfb = fb->object;
-}
-
-bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
+bool GPU_glsl_support(void)
{
- GLenum status;
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- GG.currentfb = fb->object;
-
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
-
- status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- GPU_framebuffer_restore();
- GPU_print_framebuffer_error(status, err_out);
- return false;
- }
-
+ /* always supported, still queried by game engine */
return true;
}
-void GPU_framebuffer_free(GPUFrameBuffer *fb)
+bool GPU_full_non_power_of_two_support(void)
{
- int i;
- if (fb->depthtex)
- GPU_framebuffer_texture_detach(fb->depthtex);
-
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- GPU_framebuffer_texture_detach(fb->colortex[i]);
- }
- }
-
- if (fb->object) {
- glDeleteFramebuffersEXT(1, &fb->object);
-
- if (GG.currentfb == fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- GG.currentfb = 0;
- }
- }
-
- MEM_freeN(fb);
-}
-
-void GPU_framebuffer_restore(void)
-{
- if (GG.currentfb != 0) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- GG.currentfb = 0;
- }
-}
-
-void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
-{
- const float scaleh[2] = {1.0f / blurtex->w_orig, 0.0f};
- const float scalev[2] = {0.0f, 1.0f / tex->h_orig};
-
- GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
- int scale_uniform, texture_source_uniform;
-
- if (!blur_shader)
- return;
-
- scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
- texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
-
- /* Blurring horizontally */
-
- /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
- * pushing unnecessary matrices onto the OpenGL stack. */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
-
- /* avoid warnings from texture binding */
- GG.currentfb = blurfb->object;
-
- GPU_shader_bind(blur_shader);
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
- glViewport(0, 0, blurtex->w_orig, blurtex->h_orig);
-
- /* Peparing to draw quad */
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glDisable(GL_DEPTH_TEST);
-
- GPU_texture_bind(tex, 0);
-
- /* Drawing quad */
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
-
- /* Blurring vertically */
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
-
- GG.currentfb = fb->object;
-
- glViewport(0, 0, tex->w_orig, tex->h_orig);
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
- GPU_texture_bind(blurtex, 0);
-
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
-
- GPU_shader_unbind();
-}
-
-/* GPUOffScreen */
-
-struct GPUOffScreen {
- GPUFrameBuffer *fb;
- GPUTexture *color;
- GPUTexture *depth;
-};
-
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256])
-{
- GPUOffScreen *ofs;
-
- ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
-
- ofs->fb = GPU_framebuffer_create();
- if (!ofs->fb) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- if (samples) {
- if (!GLEW_EXT_framebuffer_multisample ||
- !GLEW_ARB_texture_multisample ||
- /* Only needed for GPU_offscreen_read_pixels.
- * We could add an arg if we intend to use multi-sample
- * offscreen buffers w/o reading their pixels */
- !GLEW_EXT_framebuffer_blit ||
- /* This is required when blitting from a multi-sampled buffers,
- * even though we're not scaling. */
- !GLEW_EXT_framebuffer_multisample_blit_scaled)
- {
- samples = 0;
- }
- }
-
- ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out);
- if (!ofs->depth) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
- if (!ofs->color) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- /* check validity at the very end! */
- if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- GPU_framebuffer_restore();
-
- return ofs;
-}
-
-void GPU_offscreen_free(GPUOffScreen *ofs)
-{
- if (ofs->fb)
- GPU_framebuffer_free(ofs->fb);
- if (ofs->color)
- GPU_texture_free(ofs->color);
- if (ofs->depth)
- GPU_texture_free(ofs->depth);
-
- MEM_freeN(ofs);
-}
-
-void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
-{
- glDisable(GL_SCISSOR_TEST);
- if (save)
- GPU_texture_bind_as_framebuffer(ofs->color);
- else {
- GPU_framebuffer_bind_no_save(ofs->fb, 0);
- }
-}
-
-void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
-{
- if (restore)
- GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
- GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
-}
-
-void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
-{
- const int w = ofs->color->w_orig;
- const int h = ofs->color->h_orig;
-
- if (ofs->color->target == GL_TEXTURE_2D_MULTISAMPLE) {
- /* For a multi-sample texture,
- * we need to create an intermediate buffer to blit to,
- * before its copied using 'glReadPixels' */
-
- /* not needed since 'ofs' needs to be bound to the framebuffer already */
-// #define USE_FBO_CTX_SWITCH
-
- GLuint fbo_blit = 0;
- GLuint tex_blit = 0;
- GLenum status;
-
- /* create texture for new 'fbo_blit' */
- glGenTextures(1, &tex_blit);
- if (!tex_blit) {
- goto finally;
- }
-
- glBindTexture(GL_TEXTURE_2D, tex_blit);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, type, 0);
-
-#ifdef USE_FBO_CTX_SWITCH
- /* read from multi-sample buffer */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
- glFramebufferTexture2DEXT(
- GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
- GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
- status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- goto finally;
- }
-#endif
-
- /* write into new single-sample buffer */
- glGenFramebuffersEXT(1, &fbo_blit);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
- glFramebufferTexture2DEXT(
- GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, tex_blit, 0);
- status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- goto finally;
- }
-
- /* perform the copy */
- glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
-
- /* read the results */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER, fbo_blit);
- glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
-
-#ifdef USE_FBO_CTX_SWITCH
- /* restore the original frame-bufer */
- glBindFramebufferEXT(GL_FRAMEBUFFER, ofs->color->fb->object);
-#undef USE_FBO_CTX_SWITCH
-#endif
-
-
-finally:
- /* cleanup */
- if (tex_blit) {
- glDeleteTextures(1, &tex_blit);
- }
- if (fbo_blit) {
- glDeleteFramebuffersEXT(1, &fbo_blit);
- }
-
- GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
- }
- else {
- glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
- }
-}
-
-int GPU_offscreen_width(const GPUOffScreen *ofs)
-{
- return ofs->color->w_orig;
-}
-
-int GPU_offscreen_height(const GPUOffScreen *ofs)
-{
- return ofs->color->h_orig;
-}
-
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
-{
- return ofs->color->bindcode;
-}
-
-/* GPUShader */
-
-struct GPUShader {
- GLuint program; /* handle for full program (links shader stages below) */
-
- GLuint vertex; /* handle for vertex shader */
- GLuint geometry; /* handle for geometry shader */
- GLuint fragment; /* handle for fragment shader */
-
- int totattrib; /* total number of attributes */
- int uniforms; /* required uniforms */
-};
-
-struct GPUProgram {
- GPUProgramType type;
- GLuint prog;
-};
-
-
-static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
-{
- int i;
- int line = 1;
-
- fprintf(stderr, "GPUShader: %s error:\n", task);
-
- for (i = 0; i < totcode; i++) {
- const char *c, *pos, *end = code[i] + strlen(code[i]);
-
- if (G.debug & G_DEBUG) {
- fprintf(stderr, "===== shader string %d ====\n", i + 1);
-
- c = code[i];
- while ((c < end) && (pos = strchr(c, '\n'))) {
- fprintf(stderr, "%2d ", line);
- fwrite(c, (pos + 1) - c, 1, stderr);
- c = pos + 1;
- line++;
- }
-
- fprintf(stderr, "%s", c);
- }
- }
-
- fprintf(stderr, "%s\n", log);
-}
-
-static const char *gpu_shader_version(void)
-{
- if (GLEW_VERSION_3_2) {
- if (GLEW_ARB_compatibility) {
- return "#version 150 compatibility\n";
- /* highest version that is widely supported
- * gives us native geometry shaders!
- * use compatibility profile so we can continue using builtin shader input/output names
- */
- }
- else {
- return "#version 130\n";
- /* latest version that is compatible with existing shaders */
- }
- }
- else if (GLEW_VERSION_3_1) {
- if (GLEW_ARB_compatibility) {
- return "#version 140\n";
- /* also need the ARB_compatibility extension, handled below */
- }
- else {
- return "#version 130\n";
- /* latest version that is compatible with existing shaders */
- }
- }
- else if (GLEW_VERSION_3_0) {
- return "#version 130\n";
- /* GLSL 1.3 has modern syntax/keywords/datatypes so use if available
- * older features are deprecated but still available without compatibility extension or profile
- */
- }
- else {
- return "#version 120\n";
- /* minimum supported */
- }
+ /* always supported on full GL but still relevant for OpenGL ES 2.0 where
+ * NPOT textures can't use mipmaps or repeat wrap mode */
+ return true;
}
-
-static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_geometry_shader)
+bool GPU_display_list_support(void)
{
- /* enable extensions for features that are not part of our base GLSL version
- * don't use an extension for something already available!
+ /* deprecated in GL 3
+ * supported on older GL and compatibility profile
+ * still queried by game engine
*/
-
- if (GLEW_ARB_texture_query_lod) {
- /* a #version 400 feature, but we use #version 150 maximum so use extension */
- strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
- }
-
- if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) {
- strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
- }
-
- if (GLEW_VERSION_3_1 && !GLEW_VERSION_3_2 && GLEW_ARB_compatibility) {
- strcat(defines, "#extension GL_ARB_compatibility: enable\n");
- }
-
- if (!GLEW_VERSION_3_1) {
- if (GLEW_ARB_draw_instanced) {
- strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
- }
-
- if (!GLEW_VERSION_3_0 && GLEW_EXT_gpu_shader4) {
- strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
- /* TODO: maybe require this? shaders become so much nicer */
- }
- }
-}
-
-static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], bool use_opensubdiv)
-{
- /* some useful defines to detect GPU type */
- if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
- strcat(defines, "#define GPU_ATI\n");
- if (GLEW_VERSION_3_0) {
- /* TODO(merwin): revisit this version check; GLEW_VERSION_3_0 means GL 3.0 or newer */
- strcat(defines, "#define CLIP_WORKAROUND\n");
- }
- }
- else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
- strcat(defines, "#define GPU_NVIDIA\n");
- else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
- strcat(defines, "#define GPU_INTEL\n");
-
- if (GPU_bicubic_bump_support())
- strcat(defines, "#define BUMP_BICUBIC\n");
-
-#ifdef WITH_OPENSUBDIV
- /* TODO(sergey): Check whether we actually compiling shader for
- * the OpenSubdiv mesh.
- */
- if (use_opensubdiv) {
- strcat(defines, "#define USE_OPENSUBDIV\n");
-
- /* TODO(sergey): not strictly speaking a define, but this is
- * a global typedef which we don't have better place to define
- * in yet.
- */
- strcat(defines, "struct VertexData {\n"
- " vec4 position;\n"
- " vec3 normal;\n"
- " vec2 uv;"
- "};\n");
- }
-#else
- UNUSED_VARS(use_opensubdiv);
-#endif
-
- return;
-}
-
-void GPU_program_bind(GPUProgram *program)
-{
- glEnable(program->type);
- glBindProgramARB(program->type, program->prog);
-}
-
-void GPU_program_unbind(GPUProgram *program)
-{
- glDisable(program->type);
- glBindProgramARB(program->type, 0);
-}
-
-
-GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code)
-{
- /* TODO(merwin): remove ARB program support (recode smoke shader in GLSL) */
-
- GPUProgram *program;
- GLint error_pos, is_native;
-
- if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT))
- return NULL;
-
- program = MEM_callocN(sizeof(GPUProgram), "GPUProgram");
-
- switch (type) {
- case GPU_PROGRAM_TYPE_FRAGMENT:
- program->type = GL_FRAGMENT_PROGRAM_ARB;
- break;
- }
-
- /* create the object and set its code string */
- glGenProgramsARB(1, &program->prog);
- glBindProgramARB(program->type, program->prog);
-
- glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code);
-
- glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native);
- if ((error_pos == -1) && (is_native == 1)) {
- return program;
- }
- else {
- /* glGetError is set before that, clear it */
- while (glGetError() != GL_NO_ERROR)
- ;
- shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1);
- MEM_freeN(program);
- }
-
- return NULL;
-}
-
-void GPU_program_free(GPUProgram *program)
-{
- glDeleteProgramsARB(1, &program->prog);
- MEM_freeN(program);
-}
-
-void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w)
-{
- glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
+ return true;
}
-GPUShader *GPU_shader_create(const char *vertexcode,
- const char *fragcode,
- const char *geocode,
- const char *libcode,
- const char *defines,
- int input,
- int output,
- int number)
+bool GPU_bicubic_bump_support(void)
{
- return GPU_shader_create_ex(vertexcode,
- fragcode,
- geocode,
- libcode,
- defines,
- input,
- output,
- number,
- GPU_SHADER_FLAGS_NONE);
+ return GLEW_VERSION_4_0 || (GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0);
}
-GPUShader *GPU_shader_create_ex(const char *vertexcode,
- const char *fragcode,
- const char *geocode,
- const char *libcode,
- const char *defines,
- int input,
- int output,
- int number,
- const int flags)
+bool GPU_geometry_shader_support(void)
{
-#ifdef WITH_OPENSUBDIV
- /* TODO(sergey): used to add #version 150 to the geometry shader.
- * Could safely be renamed to "use_geometry_code" since it's very
- * likely any of geometry code will want to use GLSL 1.5.
+ /* in GL 3.2 geometry shaders are fully supported
+ * core profile clashes with our other shaders so accept compatibility only
+ * other GL versions can use EXT_geometry_shader4 if available
*/
- bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
-#else
- UNUSED_VARS(flags);
- bool use_opensubdiv = false;
-#endif
- GLint status;
- GLchar log[5000];
- GLsizei length = 0;
- GPUShader *shader;
- char standard_defines[MAX_DEFINE_LENGTH] = "";
- char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
-
- if (geocode && !GPU_geometry_shader_support())
- return NULL;
-
- shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
-
- if (vertexcode)
- shader->vertex = glCreateShader(GL_VERTEX_SHADER);
- if (fragcode)
- shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
- if (geocode)
- shader->geometry = glCreateShader(GL_GEOMETRY_SHADER_EXT);
-
- shader->program = glCreateProgram();
-
- if (!shader->program ||
- (vertexcode && !shader->vertex) ||
- (fragcode && !shader->fragment) ||
- (geocode && !shader->geometry))
- {
- fprintf(stderr, "GPUShader, object creation failed.\n");
- GPU_shader_free(shader);
- return NULL;
- }
-
- gpu_shader_standard_defines(standard_defines, use_opensubdiv);
- gpu_shader_standard_extensions(standard_extensions, geocode != NULL);
-
- if (vertexcode) {
- const char *source[5];
- /* custom limit, may be too small, beware */
- int num_source = 0;
-
- source[num_source++] = gpu_shader_version();
- source[num_source++] = standard_extensions;
- source[num_source++] = standard_defines;
-
- if (defines) source[num_source++] = defines;
- source[num_source++] = vertexcode;
-
- glAttachShader(shader->program, shader->vertex);
- glShaderSource(shader->vertex, num_source, source, NULL);
-
- glCompileShader(shader->vertex);
- glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status);
-
- if (!status) {
- glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log);
- shader_print_errors("compile", log, source, num_source);
-
- GPU_shader_free(shader);
- return NULL;
- }
- }
-
- if (fragcode) {
- const char *source[7];
- int num_source = 0;
-
- source[num_source++] = gpu_shader_version();
- source[num_source++] = standard_extensions;
- source[num_source++] = standard_defines;
-
-#ifdef WITH_OPENSUBDIV
- /* TODO(sergey): Move to fragment shader source code generation. */
- if (use_opensubdiv) {
- source[num_source++] =
- "#ifdef USE_OPENSUBDIV\n"
- "in block {\n"
- " VertexData v;\n"
- "} inpt;\n"
- "#endif\n";
- }
-#endif
-
- if (defines) source[num_source++] = defines;
- if (libcode) source[num_source++] = libcode;
- source[num_source++] = fragcode;
-
- glAttachShader(shader->program, shader->fragment);
- glShaderSource(shader->fragment, num_source, source, NULL);
-
- glCompileShader(shader->fragment);
- glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status);
-
- if (!status) {
- glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log);
- shader_print_errors("compile", log, source, num_source);
-
- GPU_shader_free(shader);
- return NULL;
- }
- }
-
- if (geocode) {
- const char *source[6];
- int num_source = 0;
-
- source[num_source++] = gpu_shader_version();
- source[num_source++] = standard_extensions;
- source[num_source++] = standard_defines;
-
- if (defines) source[num_source++] = defines;
- source[num_source++] = geocode;
-
- glAttachShader(shader->program, shader->geometry);
- glShaderSource(shader->geometry, num_source, source, NULL);
-
- glCompileShader(shader->geometry);
- glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status);
-
- if (!status) {
- glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log);
- shader_print_errors("compile", log, source, num_source);
-
- GPU_shader_free(shader);
- return NULL;
- }
-
- if (!use_opensubdiv) {
- GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
- }
- }
-
-#ifdef WITH_OPENSUBDIV
- if (use_opensubdiv) {
- glBindAttribLocation(shader->program, 0, "position");
- glBindAttribLocation(shader->program, 1, "normal");
- GPU_shader_geometry_stage_primitive_io(shader,
- GL_LINES_ADJACENCY_EXT,
- GL_TRIANGLE_STRIP,
- 4);
- }
-#endif
-
- glLinkProgram(shader->program);
- glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
- if (!status) {
- glGetProgramInfoLog(shader->program, sizeof(log), &length, log);
- /* print attached shaders in pipeline order */
- if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1);
- if (geocode) shader_print_errors("linking", log, &geocode, 1);
- if (libcode) shader_print_errors("linking", log, &libcode, 1);
- if (fragcode) shader_print_errors("linking", log, &fragcode, 1);
-
- GPU_shader_free(shader);
- return NULL;
- }
-
-#ifdef WITH_OPENSUBDIV
- /* TODO(sergey): Find a better place for this. */
- if (use_opensubdiv && GLEW_VERSION_4_1) {
- glProgramUniform1i(shader->program,
- glGetUniformLocation(shader->program, "FVarDataBuffer"),
- 31); /* GL_TEXTURE31 */
- }
-#endif
-
- return shader;
-}
-
-void GPU_shader_bind(GPUShader *shader)
-{
- GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
- glUseProgram(shader->program);
- GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
-}
-
-void GPU_shader_unbind(void)
-{
- GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
- glUseProgram(0);
- GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
-}
-
-void GPU_shader_free(GPUShader *shader)
-{
- if (shader->vertex)
- glDeleteShader(shader->vertex);
- if (shader->geometry)
- glDeleteShader(shader->geometry);
- if (shader->fragment)
- glDeleteShader(shader->fragment);
- if (shader->program)
- glDeleteProgram(shader->program);
- MEM_freeN(shader);
-}
-
-int GPU_shader_get_uniform(GPUShader *shader, const char *name)
-{
- return glGetUniformLocation(shader->program, name);
-}
-
-void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
-{
- if (location == -1 || value == NULL)
- return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
- if (length == 1) glUniform1fv(location, arraysize, value);
- else if (length == 2) glUniform2fv(location, arraysize, value);
- else if (length == 3) glUniform3fv(location, arraysize, value);
- else if (length == 4) glUniform4fv(location, arraysize, value);
- else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value);
- else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
-}
-
-void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
-{
- if (location == -1)
- return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
- if (length == 1) glUniform1iv(location, arraysize, value);
- else if (length == 2) glUniform2iv(location, arraysize, value);
- else if (length == 3) glUniform3iv(location, arraysize, value);
- else if (length == 4) glUniform4iv(location, arraysize, value);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
-}
-
-void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
-{
- if (location == -1)
- return;
-
- GPU_CHECK_ERRORS_AROUND(glUniform1i(location, value));
-}
-
-void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
-{
- if (GPU_geometry_shader_support_via_extension()) {
- /* geometry shaders must provide this info themselves for #version 150 and up */
- glProgramParameteriEXT(shader->program, GL_GEOMETRY_INPUT_TYPE_EXT, input);
- glProgramParameteriEXT(shader->program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
- glProgramParameteriEXT(shader->program, GL_GEOMETRY_VERTICES_OUT_EXT, number);
- }
-}
-
-void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
-{
- GLenum arbnumber;
-
- if (tex->number >= GG.maxtextures) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
- if (tex->number == -1)
- return;
-
- if (location == -1)
- return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
-
- arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
-
- if (tex->number != 0) glActiveTexture(arbnumber);
- if (tex->bindcode != 0)
- glBindTexture(tex->target, tex->bindcode);
- else
- GPU_invalid_tex_bind(tex->target);
- glUniform1i(location, tex->number);
- glEnable(tex->target);
- if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
-}
-
-int GPU_shader_get_attribute(GPUShader *shader, const char *name)
-{
- int index;
-
- GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocation(shader->program, name));
-
- return index;
-}
-
-GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
-{
- GPUShader *retval = NULL;
-
- switch (shader) {
- case GPU_SHADER_VSM_STORE:
- if (!GG.shaders.vsm_store)
- GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.vsm_store;
- break;
- case GPU_SHADER_SEP_GAUSSIAN_BLUR:
- if (!GG.shaders.sep_gaussian_blur)
- GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.sep_gaussian_blur;
- break;
- }
-
- if (retval == NULL)
- printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
-
- return retval;
+ return (GLEW_VERSION_3_2 && GPU_legacy_support()) || GLEW_EXT_geometry_shader4;
}
-GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program)
+bool GPU_geometry_shader_support_via_extension(void)
{
- GPUProgram *retval = NULL;
-
- switch (program) {
- case GPU_PROGRAM_SMOKE:
- if (!GG.shaders.smoke)
- GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl);
- retval = GG.shaders.smoke;
- break;
- case GPU_PROGRAM_SMOKE_COLORED:
- if (!GG.shaders.smoke_colored)
- GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl);
- retval = GG.shaders.smoke_colored;
- break;
- }
-
- if (retval == NULL)
- printf("Unable to create a GPUProgram for builtin program: %u\n", program);
-
- return retval;
+ return GLEW_EXT_geometry_shader4 && !(GLEW_VERSION_3_2 && GPU_legacy_support());
}
-#define MAX_DEFINES 100
-
-GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
+bool GPU_instanced_drawing_support(void)
{
- int offset;
- char defines[MAX_DEFINES] = "";
- /* avoid shaders out of range */
- if (effects >= MAX_FX_SHADERS)
- return NULL;
-
- offset = 2 * effects;
-
- if (persp) {
- offset += 1;
- strcat(defines, "#define PERSP_MATRIX\n");
- }
-
- if (!GG.shaders.fx_shaders[offset]) {
- GPUShader *shader;
-
- switch (effects) {
- case GPU_SHADER_FX_SSAO:
- GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
- strcat(defines, "#define FIRST_PASS\n");
- GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
- strcat(defines, "#define SECOND_PASS\n");
- GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
- strcat(defines, "#define THIRD_PASS\n");
- GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
- strcat(defines, "#define FOURTH_PASS\n");
- GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
- strcat(defines, "#define FIFTH_PASS\n");
- GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
- strcat(defines, "#define FIRST_PASS\n");
- GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
- strcat(defines, "#define SECOND_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
- defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
- GG.shaders.fx_shaders[offset] = shader;
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
- strcat(defines, "#define THIRD_PASS\n");
- GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
- break;
-
- case GPU_SHADER_FX_DEPTH_RESOLVE:
- GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
- }
- }
-
- return GG.shaders.fx_shaders[offset];
+ return GLEW_VERSION_3_1 || GLEW_ARB_draw_instanced;
}
-
-void GPU_shader_free_builtin_shaders(void)
+int GPU_color_depth(void)
{
- int i;
-
- if (GG.shaders.vsm_store) {
- GPU_shader_free(GG.shaders.vsm_store);
- GG.shaders.vsm_store = NULL;
- }
-
- if (GG.shaders.sep_gaussian_blur) {
- GPU_shader_free(GG.shaders.sep_gaussian_blur);
- GG.shaders.sep_gaussian_blur = NULL;
- }
-
- if (GG.shaders.smoke) {
- GPU_program_free(GG.shaders.smoke);
- GG.shaders.smoke = NULL;
- }
-
- if (GG.shaders.smoke_colored) {
- GPU_program_free(GG.shaders.smoke_colored);
- GG.shaders.smoke_colored = NULL;
- }
-
- for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
- if (GG.shaders.fx_shaders[i]) {
- GPU_shader_free(GG.shaders.fx_shaders[i]);
- GG.shaders.fx_shaders[i] = NULL;
- }
- }
+ return GG.colordepth;
}
bool GPU_mem_stats_supported(void)
@@ -2334,117 +326,3 @@ void GPU_mem_stats_get(int *totalmem, int *freemem)
}
}
-
-#if 0 /* unused */
-
-/* GPUPixelBuffer */
-
-typedef struct GPUPixelBuffer {
- GLuint bindcode[2];
- GLuint current;
- int datasize;
- int numbuffers;
- int halffloat;
-} GPUPixelBuffer;
-
-void GPU_pixelbuffer_free(GPUPixelBuffer *pb)
-{
- if (pb->bindcode[0])
- glDeleteBuffers(pb->numbuffers, pb->bindcode);
- MEM_freeN(pb);
-}
-
-GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers)
-{
- GPUPixelBuffer *pb;
-
- pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
- pb->datasize = x * y * 4 * (halffloat ? 16 : 8);
- pb->numbuffers = numbuffers;
- pb->halffloat = halffloat;
-
- glGenBuffers(pb->numbuffers, pb->bindcode);
-
- if (!pb->bindcode[0]) {
- fprintf(stderr, "GPUPixelBuffer allocation failed\n");
- GPU_pixelbuffer_free(pb);
- return NULL;
- }
-
- return pb;
-}
-
-void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
-{
- void *pixels;
- int i;
-
- glBindTexture(GL_TEXTURE_RECTANGLE, tex->bindcode);
-
- for (i = 0; i < pb->numbuffers; i++) {
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pb->bindcode[pb->current]);
- glBufferData(GL_PIXEL_UNPACK_BUFFER, pb->datasize, NULL,
- GL_STREAM_DRAW);
-
- pixels = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
-
-# if 0
- memcpy(pixels, _oImage.data(), pb->datasize);
-# endif
-
- if (!glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)) {
- fprintf(stderr, "Could not unmap OpenGL PBO\n");
- break;
- }
- }
-
- glBindTexture(GL_TEXTURE_RECTANGLE, 0);
-}
-
-static int pixelbuffer_map_into_gpu(GLuint bindcode)
-{
- void *pixels;
-
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bindcode);
- pixels = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
-
- /* do stuff in pixels */
-
- if (!glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)) {
- fprintf(stderr, "Could not unmap OpenGL PBO\n");
- return 0;
- }
-
- return 1;
-}
-
-static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode)
-{
- GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE;
- glBindTexture(GL_TEXTURE_RECTANGLE, tex->bindcode);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bindcode);
-
- glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, 0, 0, tex->w, tex->h, GL_RGBA, type, NULL);
-
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- glBindTexture(GL_TEXTURE_RECTANGLE, 0);
-}
-
-void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
-{
- int newbuffer;
-
- if (pb->numbuffers == 1) {
- pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]);
- pixelbuffer_map_into_gpu(pb->bindcode[0]);
- }
- else {
- pb->current = (pb->current + 1) % pb->numbuffers;
- newbuffer = (pb->current + 1) % pb->numbuffers;
-
- pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
- pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
- }
-}
-#endif /* unused */
-
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
new file mode 100644
index 00000000000..4ef7611a3f3
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -0,0 +1,633 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_global.h"
+
+#include "GPU_debug.h"
+#include "GPU_glew.h"
+#include "GPU_framebuffer.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+static struct GPUFrameBufferGlobal {
+ GLuint currentfb;
+} GG = {0};
+
+/* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
+#define GPU_FB_MAX_SLOTS 4
+
+struct GPUFrameBuffer {
+ GLuint object;
+ GPUTexture *colortex[GPU_FB_MAX_SLOTS];
+ GPUTexture *depthtex;
+};
+
+static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
+{
+ const char *err = "unknown";
+
+ switch (status) {
+ case GL_FRAMEBUFFER_COMPLETE_EXT:
+ break;
+ case GL_INVALID_OPERATION:
+ err = "Invalid operation";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
+ err = "Incomplete attachment";
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
+ err = "Unsupported framebuffer format";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+ err = "Missing attachment";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+ err = "Attached images must have same dimensions";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
+ err = "Attached images must have same format";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
+ err = "Missing draw buffer";
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
+ err = "Missing read buffer";
+ break;
+ }
+
+ if (err_out) {
+ BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
+ (int)status, err);
+ }
+ else {
+ fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
+ (int)status, err);
+ }
+}
+
+/* GPUFrameBuffer */
+
+GPUFrameBuffer *GPU_framebuffer_create(void)
+{
+ GPUFrameBuffer *fb;
+
+ if (!(GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object || (GLEW_EXT_framebuffer_object && GLEW_EXT_framebuffer_blit)))
+ return NULL;
+
+ fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
+ glGenFramebuffersEXT(1, &fb->object);
+
+ if (!fb->object) {
+ fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
+ (int)glGetError());
+ GPU_framebuffer_free(fb);
+ return NULL;
+ }
+
+ /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glReadBuffer(GL_NONE);
+ glDrawBuffer(GL_NONE);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ return fb;
+}
+
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
+{
+ GLenum attachment;
+ GLenum error;
+
+ if (slot >= GPU_FB_MAX_SLOTS) {
+ fprintf(stderr,
+ "Attaching to index %d framebuffer slot unsupported. "
+ "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
+ return 0;
+ }
+
+ if ((G.debug & G_DEBUG)) {
+ if (GPU_texture_bound_number(tex) != -1) {
+ fprintf(stderr,
+ "Feedback loop warning!: "
+ "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
+ }
+ }
+
+ if (GPU_texture_depth(tex))
+ attachment = GL_DEPTH_ATTACHMENT_EXT;
+ else
+ attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ GG.currentfb = fb->object;
+
+ /* Clean glError buffer. */
+ while (glGetError() != GL_NO_ERROR) {}
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
+ GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0);
+
+ error = glGetError();
+
+ if (error == GL_INVALID_OPERATION) {
+ GPU_framebuffer_restore();
+ GPU_print_framebuffer_error(error, err_out);
+ return 0;
+ }
+
+ if (GPU_texture_depth(tex))
+ fb->depthtex = tex;
+ else
+ fb->colortex[slot] = tex;
+
+ GPU_texture_framebuffer_set(tex, fb, slot);
+
+ return 1;
+}
+
+void GPU_framebuffer_texture_detach(GPUTexture *tex)
+{
+ GLenum attachment;
+ GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
+ int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+
+ if (!fb)
+ return;
+
+ if (GG.currentfb != fb->object) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ GG.currentfb = fb->object;
+ }
+
+ if (GPU_texture_depth(tex)) {
+ fb->depthtex = NULL;
+ attachment = GL_DEPTH_ATTACHMENT_EXT;
+ }
+ else {
+ BLI_assert(fb->colortex[fb_attachment] == tex);
+ fb->colortex[fb_attachment] = NULL;
+ attachment = GL_COLOR_ATTACHMENT0_EXT + fb_attachment;
+ }
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GPU_texture_target(tex), 0, 0);
+
+ GPU_texture_framebuffer_set(tex, NULL, -1);
+}
+
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
+{
+ GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
+ int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+
+ if (!fb) {
+ fprintf(stderr, "Error, texture not bound to framebuffer!\n");
+ return;
+ }
+
+ /* push attributes */
+ glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+ glDisable(GL_SCISSOR_TEST);
+
+ /* bind framebuffer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+
+ if (GPU_texture_depth(tex)) {
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ }
+ else {
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
+ }
+
+ if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
+ glEnable(GL_MULTISAMPLE);
+ }
+
+ /* push matrices and set default viewport and matrix */
+ glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
+ GG.currentfb = fb->object;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+}
+
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
+{
+ int numslots = 0, i;
+ GLenum attachments[4];
+
+ if (!fb->colortex[slot]) {
+ fprintf(stderr, "Error, framebuffer slot empty!\n");
+ return;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (fb->colortex[i]) {
+ attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
+ numslots++;
+ }
+ }
+
+ /* push attributes */
+ glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+ glDisable(GL_SCISSOR_TEST);
+
+ /* bind framebuffer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffers(numslots, attachments);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+ /* push matrices and set default viewport and matrix */
+ glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
+ GG.currentfb = fb->object;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+}
+
+
+void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
+{
+ /* restore matrix */
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ /* restore attributes */
+ glPopAttrib();
+}
+
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+ /* push matrices and set default viewport and matrix */
+ glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
+ GG.currentfb = fb->object;
+ GG.currentfb = fb->object;
+}
+
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
+{
+ return fb->object == GG.currentfb;
+}
+
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
+{
+ GLenum status;
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ GG.currentfb = fb->object;
+
+ /* Clean glError buffer. */
+ while (glGetError() != GL_NO_ERROR) {}
+
+ status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ GPU_framebuffer_restore();
+ GPU_print_framebuffer_error(status, err_out);
+ return false;
+ }
+
+ return true;
+}
+
+void GPU_framebuffer_free(GPUFrameBuffer *fb)
+{
+ int i;
+ if (fb->depthtex)
+ GPU_framebuffer_texture_detach(fb->depthtex);
+
+ for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
+ if (fb->colortex[i]) {
+ GPU_framebuffer_texture_detach(fb->colortex[i]);
+ }
+ }
+
+ if (fb->object) {
+ glDeleteFramebuffersEXT(1, &fb->object);
+
+ if (GG.currentfb == fb->object) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ GG.currentfb = 0;
+ }
+ }
+
+ MEM_freeN(fb);
+}
+
+void GPU_framebuffer_restore(void)
+{
+ if (GG.currentfb != 0) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ GG.currentfb = 0;
+ }
+}
+
+void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
+{
+ const float scaleh[2] = {1.0f / GPU_texture_width(blurtex), 0.0f};
+ const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(tex)};
+
+ GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
+ int scale_uniform, texture_source_uniform;
+
+ if (!blur_shader)
+ return;
+
+ scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
+ texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
+
+ /* Blurring horizontally */
+
+ /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
+ * pushing unnecessary matrices onto the OpenGL stack. */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+
+ /* avoid warnings from texture binding */
+ GG.currentfb = blurfb->object;
+
+ GPU_shader_bind(blur_shader);
+ GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
+ GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
+ glViewport(0, 0, GPU_texture_width(blurtex), GPU_texture_height(blurtex));
+
+ /* Peparing to draw quad */
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glDisable(GL_DEPTH_TEST);
+
+ GPU_texture_bind(tex, 0);
+
+ /* Drawing quad */
+ glBegin(GL_QUADS);
+ glTexCoord2d(0, 0); glVertex2f(1, 1);
+ glTexCoord2d(1, 0); glVertex2f(-1, 1);
+ glTexCoord2d(1, 1); glVertex2f(-1, -1);
+ glTexCoord2d(0, 1); glVertex2f(1, -1);
+ glEnd();
+
+ /* Blurring vertically */
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+
+ GG.currentfb = fb->object;
+
+ glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
+ GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
+ GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
+ GPU_texture_bind(blurtex, 0);
+
+ glBegin(GL_QUADS);
+ glTexCoord2d(0, 0); glVertex2f(1, 1);
+ glTexCoord2d(1, 0); glVertex2f(-1, 1);
+ glTexCoord2d(1, 1); glVertex2f(-1, -1);
+ glTexCoord2d(0, 1); glVertex2f(1, -1);
+ glEnd();
+
+ GPU_shader_unbind();
+}
+
+/* GPUOffScreen */
+
+struct GPUOffScreen {
+ GPUFrameBuffer *fb;
+ GPUTexture *color;
+ GPUTexture *depth;
+};
+
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256])
+{
+ GPUOffScreen *ofs;
+
+ ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
+
+ ofs->fb = GPU_framebuffer_create();
+ if (!ofs->fb) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
+
+ if (samples) {
+ if (!GLEW_EXT_framebuffer_multisample ||
+ !GLEW_ARB_texture_multisample ||
+ /* Only needed for GPU_offscreen_read_pixels.
+ * We could add an arg if we intend to use multi-sample
+ * offscreen buffers w/o reading their pixels */
+ !GLEW_EXT_framebuffer_blit ||
+ /* This is required when blitting from a multi-sampled buffers,
+ * even though we're not scaling. */
+ !GLEW_EXT_framebuffer_multisample_blit_scaled)
+ {
+ samples = 0;
+ }
+ }
+
+ ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out);
+ if (!ofs->depth) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
+
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
+
+ ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
+ if (!ofs->color) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
+
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
+
+ /* check validity at the very end! */
+ if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
+
+ GPU_framebuffer_restore();
+
+ return ofs;
+}
+
+void GPU_offscreen_free(GPUOffScreen *ofs)
+{
+ if (ofs->fb)
+ GPU_framebuffer_free(ofs->fb);
+ if (ofs->color)
+ GPU_texture_free(ofs->color);
+ if (ofs->depth)
+ GPU_texture_free(ofs->depth);
+
+ MEM_freeN(ofs);
+}
+
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
+{
+ glDisable(GL_SCISSOR_TEST);
+ if (save)
+ GPU_texture_bind_as_framebuffer(ofs->color);
+ else {
+ GPU_framebuffer_bind_no_save(ofs->fb, 0);
+ }
+}
+
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
+{
+ if (restore)
+ GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
+ GPU_framebuffer_restore();
+ glEnable(GL_SCISSOR_TEST);
+}
+
+void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
+{
+ const int w = GPU_texture_width(ofs->color);
+ const int h = GPU_texture_height(ofs->color);
+
+ if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) {
+ /* For a multi-sample texture,
+ * we need to create an intermediate buffer to blit to,
+ * before its copied using 'glReadPixels' */
+
+ /* not needed since 'ofs' needs to be bound to the framebuffer already */
+// #define USE_FBO_CTX_SWITCH
+
+ GLuint fbo_blit = 0;
+ GLuint tex_blit = 0;
+ GLenum status;
+
+ /* create texture for new 'fbo_blit' */
+ glGenTextures(1, &tex_blit);
+ if (!tex_blit) {
+ goto finally;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, tex_blit);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, type, 0);
+
+#ifdef USE_FBO_CTX_SWITCH
+ /* read from multi-sample buffer */
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, ofs->color->fb->object);
+ glFramebufferTexture2DEXT(
+ GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + ofs->color->fb_attachment,
+ GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
+ status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ goto finally;
+ }
+#endif
+
+ /* write into new single-sample buffer */
+ glGenFramebuffersEXT(1, &fbo_blit);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, fbo_blit);
+ glFramebufferTexture2DEXT(
+ GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex_blit, 0);
+ status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ goto finally;
+ }
+
+ /* perform the copy */
+ glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ /* read the results */
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo_blit);
+ glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+
+#ifdef USE_FBO_CTX_SWITCH
+ /* restore the original frame-bufer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ofs->color->fb->object);
+#undef USE_FBO_CTX_SWITCH
+#endif
+
+
+finally:
+ /* cleanup */
+ if (tex_blit) {
+ glDeleteTextures(1, &tex_blit);
+ }
+ if (fbo_blit) {
+ glDeleteFramebuffersEXT(1, &fbo_blit);
+ }
+
+ GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
+ }
+ else {
+ glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+ }
+}
+
+int GPU_offscreen_width(const GPUOffScreen *ofs)
+{
+ return GPU_texture_width(ofs->color);
+}
+
+int GPU_offscreen_height(const GPUOffScreen *ofs)
+{
+ return GPU_texture_height(ofs->color);
+}
+
+int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
+{
+ return GPU_texture_opengl_bindcode(ofs->color);
+}
+
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 82902f8d69c..a176297de28 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -61,7 +61,10 @@
#include "IMB_imbuf_types.h"
#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
#include "GPU_material.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
#include "gpu_codegen.h"
@@ -2275,12 +2278,8 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
GPUMaterial *mat;
GPUInputUniform *uniform;
GPUInputAttribute *attribute;
- GLint lastbindcode;
int i, liblen, fraglen;
- if (!GPU_glsl_support())
- return NULL;
-
/* TODO(sergey): How to detemine whether we need OSD or not here? */
mat = GPU_material_from_blender(scene, ma, false);
pass = (mat)? mat->pass: NULL;
@@ -2313,12 +2312,11 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
case GPU_TEX2D:
if (GPU_texture_opengl_bindcode(input->tex)) {
uniform->type = GPU_DYNAMIC_SAMPLER_2DBUFFER;
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(input->tex));
- uniform->texsize = GPU_texture_opengl_width(input->tex) * GPU_texture_opengl_height(input->tex);
+ uniform->texsize = GPU_texture_width(input->tex) * GPU_texture_height(input->tex);
uniform->texpixels = MEM_mallocN(uniform->texsize*4, "RGBApixels");
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, uniform->texpixels);
- glBindTexture(GL_TEXTURE_2D, lastbindcode);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
break;
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
new file mode 100644
index 00000000000..83413dfdcb1
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -0,0 +1,783 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_global.h"
+
+#include "GPU_compositing.h"
+#include "GPU_debug.h"
+#include "GPU_extensions.h"
+#include "GPU_glew.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+/* TODO(sergey): Find better default values for this constants. */
+#define MAX_DEFINE_LENGTH 1024
+#define MAX_EXT_DEFINE_LENGTH 1024
+
+/* Non-generated shaders */
+extern char datatoc_gpu_program_smoke_frag_glsl[];
+extern char datatoc_gpu_program_smoke_color_frag_glsl[];
+extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
+extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
+extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
+extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
+extern char datatoc_gpu_shader_fx_vert_glsl[];
+extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
+extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
+extern char datatoc_gpu_shader_fx_lib_glsl[];
+
+static struct GPUShadersGlobal {
+ struct {
+ GPUShader *vsm_store;
+ GPUShader *sep_gaussian_blur;
+ GPUProgram *smoke;
+ GPUProgram *smoke_colored;
+ /* cache for shader fx. Those can exist in combinations so store them here */
+ GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
+ } shaders;
+} GG = {{NULL}};
+
+/* GPUShader */
+
+struct GPUShader {
+ GLuint program; /* handle for full program (links shader stages below) */
+
+ GLuint vertex; /* handle for vertex shader */
+ GLuint geometry; /* handle for geometry shader */
+ GLuint fragment; /* handle for fragment shader */
+
+ int totattrib; /* total number of attributes */
+ int uniforms; /* required uniforms */
+};
+
+struct GPUProgram {
+ GPUProgramType type;
+ GLuint prog;
+};
+
+static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
+{
+ int i;
+ int line = 1;
+
+ fprintf(stderr, "GPUShader: %s error:\n", task);
+
+ for (i = 0; i < totcode; i++) {
+ const char *c, *pos, *end = code[i] + strlen(code[i]);
+
+ if (G.debug & G_DEBUG) {
+ fprintf(stderr, "===== shader string %d ====\n", i + 1);
+
+ c = code[i];
+ while ((c < end) && (pos = strchr(c, '\n'))) {
+ fprintf(stderr, "%2d ", line);
+ fwrite(c, (pos + 1) - c, 1, stderr);
+ c = pos + 1;
+ line++;
+ }
+
+ fprintf(stderr, "%s", c);
+ }
+ }
+
+ fprintf(stderr, "%s\n", log);
+}
+
+static const char *gpu_shader_version(void)
+{
+ if (GLEW_VERSION_3_2) {
+ if (GLEW_ARB_compatibility) {
+ return "#version 150 compatibility\n";
+ /* highest version that is widely supported
+ * gives us native geometry shaders!
+ * use compatibility profile so we can continue using builtin shader input/output names
+ */
+ }
+ else {
+ return "#version 130\n";
+ /* latest version that is compatible with existing shaders */
+ }
+ }
+ else if (GLEW_VERSION_3_1) {
+ if (GLEW_ARB_compatibility) {
+ return "#version 140\n";
+ /* also need the ARB_compatibility extension, handled below */
+ }
+ else {
+ return "#version 130\n";
+ /* latest version that is compatible with existing shaders */
+ }
+ }
+ else if (GLEW_VERSION_3_0) {
+ return "#version 130\n";
+ /* GLSL 1.3 has modern syntax/keywords/datatypes so use if available
+ * older features are deprecated but still available without compatibility extension or profile
+ */
+ }
+ else {
+ return "#version 120\n";
+ /* minimum supported */
+ }
+}
+
+
+static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_geometry_shader)
+{
+ /* enable extensions for features that are not part of our base GLSL version
+ * don't use an extension for something already available!
+ */
+
+ if (GLEW_ARB_texture_query_lod) {
+ /* a #version 400 feature, but we use #version 150 maximum so use extension */
+ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
+ }
+
+ if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) {
+ strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
+ }
+
+ if (GLEW_VERSION_3_1 && !GLEW_VERSION_3_2 && GLEW_ARB_compatibility) {
+ strcat(defines, "#extension GL_ARB_compatibility: enable\n");
+ }
+
+ if (!GLEW_VERSION_3_1) {
+ if (GLEW_ARB_draw_instanced) {
+ strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
+ }
+
+ if (!GLEW_VERSION_3_0 && GLEW_EXT_gpu_shader4) {
+ strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
+ /* TODO: maybe require this? shaders become so much nicer */
+ }
+ }
+}
+
+static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], bool use_opensubdiv)
+{
+ /* some useful defines to detect GPU type */
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ strcat(defines, "#define GPU_ATI\n");
+ if (GLEW_VERSION_3_0) {
+ /* TODO(merwin): revisit this version check; GLEW_VERSION_3_0 means GL 3.0 or newer */
+ strcat(defines, "#define CLIP_WORKAROUND\n");
+ }
+ }
+ else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
+ strcat(defines, "#define GPU_NVIDIA\n");
+ else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
+ strcat(defines, "#define GPU_INTEL\n");
+
+ if (GPU_bicubic_bump_support())
+ strcat(defines, "#define BUMP_BICUBIC\n");
+
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Check whether we actually compiling shader for
+ * the OpenSubdiv mesh.
+ */
+ if (use_opensubdiv) {
+ strcat(defines, "#define USE_OPENSUBDIV\n");
+
+ /* TODO(sergey): not strictly speaking a define, but this is
+ * a global typedef which we don't have better place to define
+ * in yet.
+ */
+ strcat(defines, "struct VertexData {\n"
+ " vec4 position;\n"
+ " vec3 normal;\n"
+ " vec2 uv;"
+ "};\n");
+ }
+#else
+ UNUSED_VARS(use_opensubdiv);
+#endif
+
+ return;
+}
+
+void GPU_program_bind(GPUProgram *program)
+{
+ glEnable(program->type);
+ glBindProgramARB(program->type, program->prog);
+}
+
+void GPU_program_unbind(GPUProgram *program)
+{
+ glDisable(program->type);
+ glBindProgramARB(program->type, 0);
+}
+
+
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code)
+{
+ /* TODO(merwin): remove ARB program support (recode smoke shader in GLSL) */
+
+ GPUProgram *program;
+ GLint error_pos, is_native;
+
+ if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT))
+ return NULL;
+
+ program = MEM_callocN(sizeof(GPUProgram), "GPUProgram");
+
+ switch (type) {
+ case GPU_PROGRAM_TYPE_FRAGMENT:
+ program->type = GL_FRAGMENT_PROGRAM_ARB;
+ break;
+ }
+
+ /* create the object and set its code string */
+ glGenProgramsARB(1, &program->prog);
+ glBindProgramARB(program->type, program->prog);
+
+ glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code);
+
+ glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native);
+ if ((error_pos == -1) && (is_native == 1)) {
+ return program;
+ }
+ else {
+ /* glGetError is set before that, clear it */
+ while (glGetError() != GL_NO_ERROR)
+ ;
+ shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1);
+ MEM_freeN(program);
+ }
+
+ return NULL;
+}
+
+void GPU_program_free(GPUProgram *program)
+{
+ glDeleteProgramsARB(1, &program->prog);
+ MEM_freeN(program);
+}
+
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w)
+{
+ glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
+}
+
+GPUShader *GPU_shader_create(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number)
+{
+ return GPU_shader_create_ex(vertexcode,
+ fragcode,
+ geocode,
+ libcode,
+ defines,
+ input,
+ output,
+ number,
+ GPU_SHADER_FLAGS_NONE);
+}
+
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags)
+{
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): used to add #version 150 to the geometry shader.
+ * Could safely be renamed to "use_geometry_code" since it's very
+ * likely any of geometry code will want to use GLSL 1.5.
+ */
+ bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
+#else
+ UNUSED_VARS(flags);
+ bool use_opensubdiv = false;
+#endif
+ GLint status;
+ GLchar log[5000];
+ GLsizei length = 0;
+ GPUShader *shader;
+ char standard_defines[MAX_DEFINE_LENGTH] = "";
+ char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
+
+ if (geocode && !GPU_geometry_shader_support())
+ return NULL;
+
+ shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
+
+ if (vertexcode)
+ shader->vertex = glCreateShader(GL_VERTEX_SHADER);
+ if (fragcode)
+ shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
+ if (geocode)
+ shader->geometry = glCreateShader(GL_GEOMETRY_SHADER_EXT);
+
+ shader->program = glCreateProgram();
+
+ if (!shader->program ||
+ (vertexcode && !shader->vertex) ||
+ (fragcode && !shader->fragment) ||
+ (geocode && !shader->geometry))
+ {
+ fprintf(stderr, "GPUShader, object creation failed.\n");
+ GPU_shader_free(shader);
+ return NULL;
+ }
+
+ gpu_shader_standard_defines(standard_defines, use_opensubdiv);
+ gpu_shader_standard_extensions(standard_extensions, geocode != NULL);
+
+ if (vertexcode) {
+ const char *source[5];
+ /* custom limit, may be too small, beware */
+ int num_source = 0;
+
+ source[num_source++] = gpu_shader_version();
+ source[num_source++] = standard_extensions;
+ source[num_source++] = standard_defines;
+
+ if (defines) source[num_source++] = defines;
+ source[num_source++] = vertexcode;
+
+ glAttachShader(shader->program, shader->vertex);
+ glShaderSource(shader->vertex, num_source, source, NULL);
+
+ glCompileShader(shader->vertex);
+ glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status);
+
+ if (!status) {
+ glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log);
+ shader_print_errors("compile", log, source, num_source);
+
+ GPU_shader_free(shader);
+ return NULL;
+ }
+ }
+
+ if (fragcode) {
+ const char *source[7];
+ int num_source = 0;
+
+ source[num_source++] = gpu_shader_version();
+ source[num_source++] = standard_extensions;
+ source[num_source++] = standard_defines;
+
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Move to fragment shader source code generation. */
+ if (use_opensubdiv) {
+ source[num_source++] =
+ "#ifdef USE_OPENSUBDIV\n"
+ "in block {\n"
+ " VertexData v;\n"
+ "} inpt;\n"
+ "#endif\n";
+ }
+#endif
+
+ if (defines) source[num_source++] = defines;
+ if (libcode) source[num_source++] = libcode;
+ source[num_source++] = fragcode;
+
+ glAttachShader(shader->program, shader->fragment);
+ glShaderSource(shader->fragment, num_source, source, NULL);
+
+ glCompileShader(shader->fragment);
+ glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status);
+
+ if (!status) {
+ glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log);
+ shader_print_errors("compile", log, source, num_source);
+
+ GPU_shader_free(shader);
+ return NULL;
+ }
+ }
+
+ if (geocode) {
+ const char *source[6];
+ int num_source = 0;
+
+ source[num_source++] = gpu_shader_version();
+ source[num_source++] = standard_extensions;
+ source[num_source++] = standard_defines;
+
+ if (defines) source[num_source++] = defines;
+ source[num_source++] = geocode;
+
+ glAttachShader(shader->program, shader->geometry);
+ glShaderSource(shader->geometry, num_source, source, NULL);
+
+ glCompileShader(shader->geometry);
+ glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status);
+
+ if (!status) {
+ glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log);
+ shader_print_errors("compile", log, source, num_source);
+
+ GPU_shader_free(shader);
+ return NULL;
+ }
+
+ if (!use_opensubdiv) {
+ GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
+ }
+ }
+
+#ifdef WITH_OPENSUBDIV
+ if (use_opensubdiv) {
+ glBindAttribLocation(shader->program, 0, "position");
+ glBindAttribLocation(shader->program, 1, "normal");
+ GPU_shader_geometry_stage_primitive_io(shader,
+ GL_LINES_ADJACENCY_EXT,
+ GL_TRIANGLE_STRIP,
+ 4);
+ }
+#endif
+
+ glLinkProgram(shader->program);
+ glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
+ if (!status) {
+ glGetProgramInfoLog(shader->program, sizeof(log), &length, log);
+ /* print attached shaders in pipeline order */
+ if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1);
+ if (geocode) shader_print_errors("linking", log, &geocode, 1);
+ if (libcode) shader_print_errors("linking", log, &libcode, 1);
+ if (fragcode) shader_print_errors("linking", log, &fragcode, 1);
+
+ GPU_shader_free(shader);
+ return NULL;
+ }
+
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Find a better place for this. */
+ if (use_opensubdiv && GLEW_VERSION_4_1) {
+ glProgramUniform1i(shader->program,
+ glGetUniformLocation(shader->program, "FVarDataBuffer"),
+ 31); /* GL_TEXTURE31 */
+ }
+#endif
+
+ return shader;
+}
+
+void GPU_shader_bind(GPUShader *shader)
+{
+ GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
+ glUseProgram(shader->program);
+ GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
+}
+
+void GPU_shader_unbind(void)
+{
+ GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
+ glUseProgram(0);
+ GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
+}
+
+void GPU_shader_free(GPUShader *shader)
+{
+ if (shader->vertex)
+ glDeleteShader(shader->vertex);
+ if (shader->geometry)
+ glDeleteShader(shader->geometry);
+ if (shader->fragment)
+ glDeleteShader(shader->fragment);
+ if (shader->program)
+ glDeleteProgram(shader->program);
+ MEM_freeN(shader);
+}
+
+int GPU_shader_get_uniform(GPUShader *shader, const char *name)
+{
+ return glGetUniformLocation(shader->program, name);
+}
+
+void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
+{
+ if (location == -1 || value == NULL)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
+
+ if (length == 1) glUniform1fv(location, arraysize, value);
+ else if (length == 2) glUniform2fv(location, arraysize, value);
+ else if (length == 3) glUniform3fv(location, arraysize, value);
+ else if (length == 4) glUniform4fv(location, arraysize, value);
+ else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value);
+ else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value);
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
+}
+
+void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
+{
+ if (location == -1)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
+
+ if (length == 1) glUniform1iv(location, arraysize, value);
+ else if (length == 2) glUniform2iv(location, arraysize, value);
+ else if (length == 3) glUniform3iv(location, arraysize, value);
+ else if (length == 4) glUniform4iv(location, arraysize, value);
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
+}
+
+void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
+{
+ if (location == -1)
+ return;
+
+ GPU_CHECK_ERRORS_AROUND(glUniform1i(location, value));
+}
+
+void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
+{
+ if (GPU_geometry_shader_support_via_extension()) {
+ /* geometry shaders must provide this info themselves for #version 150 and up */
+ glProgramParameteriEXT(shader->program, GL_GEOMETRY_INPUT_TYPE_EXT, input);
+ glProgramParameteriEXT(shader->program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
+ glProgramParameteriEXT(shader->program, GL_GEOMETRY_VERTICES_OUT_EXT, number);
+ }
+}
+
+void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
+{
+ GLenum arbnumber;
+ int number = GPU_texture_bound_number(tex);
+ int bindcode = GPU_texture_opengl_bindcode(tex);
+ int target = GPU_texture_target(tex);
+
+ if (number >= GPU_max_textures()) {
+ fprintf(stderr, "Not enough texture slots.\n");
+ return;
+ }
+
+ if (number == -1)
+ return;
+
+ if (location == -1)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
+
+ arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
+
+ if (number != 0) glActiveTexture(arbnumber);
+ if (bindcode != 0)
+ glBindTexture(target, bindcode);
+ else
+ GPU_invalid_tex_bind(target);
+ glUniform1i(location, number);
+ glEnable(target);
+ if (number != 0) glActiveTexture(GL_TEXTURE0);
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
+}
+
+int GPU_shader_get_attribute(GPUShader *shader, const char *name)
+{
+ int index;
+
+ GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocation(shader->program, name));
+
+ return index;
+}
+
+GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
+{
+ GPUShader *retval = NULL;
+
+ switch (shader) {
+ case GPU_SHADER_VSM_STORE:
+ if (!GG.shaders.vsm_store)
+ GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.vsm_store;
+ break;
+ case GPU_SHADER_SEP_GAUSSIAN_BLUR:
+ if (!GG.shaders.sep_gaussian_blur)
+ GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.sep_gaussian_blur;
+ break;
+ }
+
+ if (retval == NULL)
+ printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
+
+ return retval;
+}
+
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program)
+{
+ GPUProgram *retval = NULL;
+
+ switch (program) {
+ case GPU_PROGRAM_SMOKE:
+ if (!GG.shaders.smoke)
+ GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl);
+ retval = GG.shaders.smoke;
+ break;
+ case GPU_PROGRAM_SMOKE_COLORED:
+ if (!GG.shaders.smoke_colored)
+ GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl);
+ retval = GG.shaders.smoke_colored;
+ break;
+ }
+
+ if (retval == NULL)
+ printf("Unable to create a GPUProgram for builtin program: %u\n", program);
+
+ return retval;
+}
+
+#define MAX_DEFINES 100
+
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
+{
+ int offset;
+ char defines[MAX_DEFINES] = "";
+ /* avoid shaders out of range */
+ if (effects >= MAX_FX_SHADERS)
+ return NULL;
+
+ offset = 2 * effects;
+
+ if (persp) {
+ offset += 1;
+ strcat(defines, "#define PERSP_MATRIX\n");
+ }
+
+ if (!GG.shaders.fx_shaders[offset]) {
+ GPUShader *shader;
+
+ switch (effects) {
+ case GPU_SHADER_FX_SSAO:
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
+ strcat(defines, "#define FIRST_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
+ strcat(defines, "#define SECOND_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
+ strcat(defines, "#define THIRD_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
+ strcat(defines, "#define FOURTH_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
+ strcat(defines, "#define FIFTH_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
+ strcat(defines, "#define FIRST_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
+ strcat(defines, "#define SECOND_PASS\n");
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
+ defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
+ GG.shaders.fx_shaders[offset] = shader;
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
+ strcat(defines, "#define THIRD_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_RESOLVE:
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
+ }
+ }
+
+ return GG.shaders.fx_shaders[offset];
+}
+
+
+void GPU_shader_free_builtin_shaders(void)
+{
+ int i;
+
+ if (GG.shaders.vsm_store) {
+ GPU_shader_free(GG.shaders.vsm_store);
+ GG.shaders.vsm_store = NULL;
+ }
+
+ if (GG.shaders.sep_gaussian_blur) {
+ GPU_shader_free(GG.shaders.sep_gaussian_blur);
+ GG.shaders.sep_gaussian_blur = NULL;
+ }
+
+ if (GG.shaders.smoke) {
+ GPU_program_free(GG.shaders.smoke);
+ GG.shaders.smoke = NULL;
+ }
+
+ if (GG.shaders.smoke_colored) {
+ GPU_program_free(GG.shaders.smoke_colored);
+ GG.shaders.smoke_colored = NULL;
+ }
+
+ for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
+ if (GG.shaders.fx_shaders[i]) {
+ GPU_shader_free(GG.shaders.fx_shaders[i]);
+ GG.shaders.fx_shaders[i] = NULL;
+ }
+ }
+}
+
+
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
new file mode 100644
index 00000000000..7803c0d0a87
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -0,0 +1,762 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_image_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_global.h"
+
+#include "GPU_debug.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+#include "GPU_texture.h"
+
+static struct GPUTextureGlobal {
+ GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
+ GPUTexture *invalid_tex_2D;
+ GPUTexture *invalid_tex_3D;
+} GG = {NULL, NULL, NULL};
+
+/* GPUTexture */
+
+struct GPUTexture {
+ int w, h; /* width/height */
+ int number; /* number for multitexture binding */
+ int refcount; /* reference count */
+ GLenum target; /* GL_TEXTURE_* */
+ GLenum target_base; /* same as target, (but no multisample) */
+ GLuint bindcode; /* opengl identifier for texture */
+ int fromblender; /* we got the texture from Blender */
+
+ GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
+ int fb_attachment; /* slot the texture is attached to */
+ int depth; /* is a depth texture? if 3D how deep? */
+};
+
+static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
+{
+ unsigned char *pixels, *p;
+ const float *fp = fpixels;
+ const int len = 4 * length;
+ int a;
+
+ p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
+
+ for (a = 0; a < len; a++, p++, fp++)
+ *p = FTOCHAR((*fp));
+
+ return pixels;
+}
+
+static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
+{
+ void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
+
+ if (target == GL_TEXTURE_1D)
+ glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
+ else
+ glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
+
+ MEM_freeN(pixels);
+}
+
+static GPUTexture *GPU_texture_create_nD(
+ int w, int h, int n, const float *fpixels, int depth,
+ GPUHDRType hdr_type, int components, int samples,
+ char err_out[256])
+{
+ GPUTexture *tex;
+ GLenum type, format, internalformat;
+ void *pixels = NULL;
+
+ if (samples) {
+ CLAMP_MAX(samples, GPU_max_color_texture_samples());
+ }
+
+ tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+ tex->w = w;
+ tex->h = h;
+ tex->number = -1;
+ tex->refcount = 1;
+ tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
+ tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
+ tex->depth = depth;
+ tex->fb_attachment = -1;
+
+ glGenTextures(1, &tex->bindcode);
+
+ if (!tex->bindcode) {
+ if (err_out) {
+ BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
+ (int)glGetError());
+ }
+ else {
+ fprintf(stderr, "GPUTexture: texture create failed: %d\n",
+ (int)glGetError());
+ }
+ GPU_texture_free(tex);
+ return NULL;
+ }
+
+ if (!GPU_full_non_power_of_two_support()) {
+ tex->w = power_of_2_max_i(tex->w);
+ tex->h = power_of_2_max_i(tex->h);
+ }
+
+ tex->number = 0;
+ glBindTexture(tex->target, tex->bindcode);
+
+ if (depth) {
+ type = GL_UNSIGNED_BYTE;
+ format = GL_DEPTH_COMPONENT;
+ internalformat = GL_DEPTH_COMPONENT;
+ }
+ else {
+ type = GL_FLOAT;
+
+ if (components == 4) {
+ format = GL_RGBA;
+ switch (hdr_type) {
+ case GPU_HDR_NONE:
+ internalformat = GL_RGBA8;
+ break;
+ /* the following formats rely on ARB_texture_float or OpenGL 3.0 */
+ case GPU_HDR_HALF_FLOAT:
+ internalformat = GL_RGBA16F_ARB;
+ break;
+ case GPU_HDR_FULL_FLOAT:
+ internalformat = GL_RGBA32F_ARB;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (components == 2) {
+ /* these formats rely on ARB_texture_rg or OpenGL 3.0 */
+ format = GL_RG;
+ switch (hdr_type) {
+ case GPU_HDR_NONE:
+ internalformat = GL_RG8;
+ break;
+ case GPU_HDR_HALF_FLOAT:
+ internalformat = GL_RG16F;
+ break;
+ case GPU_HDR_FULL_FLOAT:
+ internalformat = GL_RG32F;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (fpixels && hdr_type == GPU_HDR_NONE) {
+ type = GL_UNSIGNED_BYTE;
+ pixels = GPU_texture_convert_pixels(w*h, fpixels);
+ }
+ }
+
+ if (tex->target == GL_TEXTURE_1D) {
+ glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
+
+ if (fpixels) {
+ glTexSubImage1D(tex->target, 0, 0, w, format, type,
+ pixels ? pixels : fpixels);
+
+ if (tex->w > w)
+ GPU_glTexSubImageEmpty(tex->target, format, w, 0,
+ tex->w-w, 1);
+ }
+ }
+ else {
+ if (samples) {
+ glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
+ }
+ else {
+ glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
+ format, type, NULL);
+ }
+
+ if (fpixels) {
+ glTexSubImage2D(tex->target, 0, 0, 0, w, h,
+ format, type, pixels ? pixels : fpixels);
+
+ if (tex->w > w)
+ GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h);
+ if (tex->h > h)
+ GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h);
+ }
+ }
+
+ if (pixels)
+ MEM_freeN(pixels);
+
+ if (depth) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
+ }
+ else {
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+
+ if (tex->target_base != GL_TEXTURE_1D) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ else
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
+ return tex;
+}
+
+
+GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
+{
+ GPUTexture *tex;
+ GLenum type, format, internalformat;
+ void *pixels = NULL;
+ int r_width;
+ bool rescale = false;
+
+ if (!GLEW_VERSION_1_2)
+ return NULL;
+
+ tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+ tex->w = w;
+ tex->h = h;
+ tex->depth = depth;
+ tex->number = -1;
+ tex->refcount = 1;
+ tex->target = GL_TEXTURE_3D;
+ tex->target_base = GL_TEXTURE_3D;
+
+ glGenTextures(1, &tex->bindcode);
+
+ if (!tex->bindcode) {
+ fprintf(stderr, "GPUTexture: texture create failed: %d\n",
+ (int)glGetError());
+ GPU_texture_free(tex);
+ return NULL;
+ }
+
+ tex->number = 0;
+ glBindTexture(tex->target, tex->bindcode);
+
+ GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
+
+ type = GL_FLOAT;
+ if (channels == 4) {
+ format = GL_RGBA;
+ internalformat = GL_RGBA8;
+ }
+ else {
+ format = GL_RED;
+ internalformat = GL_INTENSITY8;
+ }
+
+ /* 3D textures are quite heavy, test if it's possible to create them first */
+ glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+
+ while (r_width == 0) {
+ rescale = true;
+ tex->w /= 2;
+ tex->h /= 2;
+ tex->depth /= 2;
+ glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+ }
+
+ /* really unlikely to happen but keep this just in case */
+ tex->w = max_ii(tex->w, 1);
+ tex->h = max_ii(tex->h, 1);
+ tex->depth = max_ii(tex->depth, 1);
+
+#if 0
+ if (fpixels)
+ pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
+#endif
+
+ GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
+
+ /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
+ * for gooseberry */
+ if (rescale && fpixels) {
+ unsigned int i, j, k;
+ unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
+ float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d");
+
+ GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
+
+ for (k = 0; k < tex->depth; k++) {
+ for (j = 0; j < tex->h; j++) {
+ for (i = 0; i < tex->w; i++) {
+ /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */
+ float xb = i * xf;
+ float yb = j * yf;
+ float zb = k * zf;
+ unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
+ unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
+
+ if (channels == 4) {
+ tex3d[offset * 4] = fpixels[offset_orig * 4];
+ tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
+ tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
+ tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
+ }
+ else
+ tex3d[offset] = fpixels[offset_orig];
+ }
+ }
+ }
+
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
+
+ MEM_freeN(tex3d);
+ }
+ else {
+ if (fpixels) {
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
+ GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
+ }
+ }
+
+
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+ if (pixels)
+ MEM_freeN(pixels);
+
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data, double time, int mipmap)
+{
+ GPUTexture *tex;
+ GLint w, h, border, bindcode;
+
+ GPU_update_image_time(ima, time);
+ /* this binds a texture, so that's why to restore it to 0 */
+ bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, is_data);
+
+ if (ima->gputexture) {
+ ima->gputexture->bindcode = bindcode;
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return ima->gputexture;
+ }
+
+ tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+ tex->bindcode = bindcode;
+ tex->number = -1;
+ tex->refcount = 1;
+ tex->target = GL_TEXTURE_2D;
+ tex->target_base = GL_TEXTURE_2D;
+ tex->fromblender = 1;
+
+ ima->gputexture= tex;
+
+ if (!glIsTexture(tex->bindcode)) {
+ GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+ }
+ else {
+ glBindTexture(GL_TEXTURE_2D, tex->bindcode);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
+
+ tex->w = w - border;
+ tex->h = h - border;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
+{
+ GPUTexture *tex = prv->gputexture[0];
+ GLint w, h;
+ GLuint bindcode = 0;
+
+ if (tex)
+ bindcode = tex->bindcode;
+
+ /* this binds a texture, so that's why we restore it to 0 */
+ if (bindcode == 0) {
+ GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL);
+ }
+ if (tex) {
+ tex->bindcode = bindcode;
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return tex;
+ }
+
+ tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+ tex->bindcode = bindcode;
+ tex->number = -1;
+ tex->refcount = 1;
+ tex->target = GL_TEXTURE_2D;
+ tex->target_base = GL_TEXTURE_2D;
+
+ prv->gputexture[0] = tex;
+
+ if (!glIsTexture(tex->bindcode)) {
+ GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+ }
+ else {
+ glBindTexture(GL_TEXTURE_2D, tex->bindcode);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
+
+ tex->w = w;
+ tex->h = h;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ return tex;
+
+}
+
+GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
+
+ if (tex)
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
+
+ if (tex)
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
+
+ if (tex)
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
+
+ if (tex)
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
+
+ if (tex)
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
+
+/**
+ * A shadow map for VSM needs two components (depth and depth^2)
+ */
+GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
+
+ if (tex) {
+ /* Now we tweak some of the settings */
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ GPU_texture_unbind(tex);
+ }
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
+
+ if (tex) {
+ /* Now we tweak some of the settings */
+ if (repeat) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ GPU_texture_unbind(tex);
+ }
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
+
+ if (tex) {
+ /* Now we tweak some of the settings */
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ GPU_texture_unbind(tex);
+ }
+
+ return tex;
+}
+
+void GPU_invalid_tex_init(void)
+{
+ const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
+ GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
+ GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
+ GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
+}
+
+void GPU_invalid_tex_bind(int mode)
+{
+ switch (mode) {
+ case GL_TEXTURE_1D:
+ glBindTexture(GL_TEXTURE_1D, GG.invalid_tex_1D->bindcode);
+ break;
+ case GL_TEXTURE_2D:
+ glBindTexture(GL_TEXTURE_2D, GG.invalid_tex_2D->bindcode);
+ break;
+ case GL_TEXTURE_3D:
+ glBindTexture(GL_TEXTURE_3D, GG.invalid_tex_3D->bindcode);
+ break;
+ }
+}
+
+void GPU_invalid_tex_free(void)
+{
+ if (GG.invalid_tex_1D)
+ GPU_texture_free(GG.invalid_tex_1D);
+ if (GG.invalid_tex_2D)
+ GPU_texture_free(GG.invalid_tex_2D);
+ if (GG.invalid_tex_3D)
+ GPU_texture_free(GG.invalid_tex_3D);
+}
+
+
+void GPU_texture_bind(GPUTexture *tex, int number)
+{
+ GLenum arbnumber;
+
+ if (number >= GPU_max_textures()) {
+ fprintf(stderr, "Not enough texture slots.\n");
+ return;
+ }
+
+ if ((G.debug & G_DEBUG)) {
+ if (tex->fb && GPU_framebuffer_bound(tex->fb)) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
+ }
+ }
+
+ if (number < 0)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
+
+ arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
+ if (number != 0) glActiveTexture(arbnumber);
+ if (tex->bindcode != 0) {
+ glBindTexture(tex->target, tex->bindcode);
+ }
+ else
+ GPU_invalid_tex_bind(tex->target);
+ glEnable(tex->target);
+ if (number != 0) glActiveTexture(GL_TEXTURE0);
+
+ tex->number = number;
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
+}
+
+void GPU_texture_unbind(GPUTexture *tex)
+{
+ GLenum arbnumber;
+
+ if (tex->number >= GPU_max_textures()) {
+ fprintf(stderr, "Not enough texture slots.\n");
+ return;
+ }
+
+ if (tex->number == -1)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
+
+ arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
+ if (tex->number != 0) glActiveTexture(arbnumber);
+ glBindTexture(tex->target, 0);
+ glDisable(tex->target_base);
+ if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
+
+ tex->number = -1;
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
+}
+
+int GPU_texture_bound_number(GPUTexture *tex)
+{
+ return tex->number;
+}
+
+void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
+{
+ GLenum arbnumber;
+
+ if (tex->number >= GPU_max_textures()) {
+ fprintf(stderr, "Not enough texture slots.\n");
+ return;
+ }
+
+ if (tex->number == -1)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
+
+ arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
+ if (tex->number != 0) glActiveTexture(arbnumber);
+
+ if (tex->depth) {
+ if (compare)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ else
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ }
+
+ if (use_filter) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+ else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+ if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
+}
+
+void GPU_texture_free(GPUTexture *tex)
+{
+ tex->refcount--;
+
+ if (tex->refcount < 0)
+ fprintf(stderr, "GPUTexture: negative refcount\n");
+
+ if (tex->refcount == 0) {
+ if (tex->fb)
+ GPU_framebuffer_texture_detach(tex);
+ if (tex->bindcode && !tex->fromblender)
+ glDeleteTextures(1, &tex->bindcode);
+
+ MEM_freeN(tex);
+ }
+}
+
+void GPU_texture_ref(GPUTexture *tex)
+{
+ tex->refcount++;
+}
+
+int GPU_texture_target(const GPUTexture *tex)
+{
+ return tex->target;
+}
+
+int GPU_texture_width(const GPUTexture *tex)
+{
+ return tex->w;
+}
+
+int GPU_texture_height(const GPUTexture *tex)
+{
+ return tex->h;
+}
+
+int GPU_texture_depth(const GPUTexture *tex)
+{
+ return tex->depth;
+}
+
+int GPU_texture_opengl_bindcode(const GPUTexture *tex)
+{
+ return tex->bindcode;
+}
+
+GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
+{
+ return tex->fb;
+}
+
+int GPU_texture_framebuffer_attachment(GPUTexture *tex)
+{
+ return tex->fb_attachment;
+}
+
+void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
+{
+ tex->fb = fb;
+ tex->fb_attachment = attachment;
+}
+
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_frag.glsl b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
index 94c73d9e248..94c73d9e248 100644
--- a/source/blender/gpu/shaders/gpu_shader_simple_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
index 8ccd0feb5e2..8ccd0feb5e2 100644
--- a/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 6f07d18953e..7bd29137aeb 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -640,7 +640,9 @@ typedef struct BooleanModifierData {
ModifierData modifier;
struct Object *object;
- int operation, pad;
+ char operation;
+ char bm_flag, pad[2];
+ float threshold;
} BooleanModifierData;
typedef enum {
@@ -649,6 +651,14 @@ typedef enum {
eBooleanModifierOp_Difference = 2,
} BooleanModifierOp;
+/* temp bm_flag (debugging only) */
+enum {
+ eBooleanModifierBMeshFlag_Enabled = (1 << 0),
+ eBooleanModifierBMeshFlag_BMesh_Separate = (1 << 1),
+ eBooleanModifierBMeshFlag_BMesh_NoDissolve = (1 << 2),
+ eBooleanModifierBMeshFlag_BMesh_NoConnectRegions = (1 << 3),
+};
+
typedef struct MDefInfluence {
int vertex;
float weight;
@@ -688,7 +698,7 @@ typedef struct MeshDeformModifierData {
float *bindcos; /* deprecated storage of cage coords */
/* runtime */
- void (*bindfunc)(struct Scene *scene, struct MeshDeformModifierData *mmd,
+ void (*bindfunc)(struct Scene *scene, struct MeshDeformModifierData *mmd, struct DerivedMesh *cagedm,
float *vertexcos, int totvert, float cagemat[4][4]);
} MeshDeformModifierData;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 6d282f4ece9..86713d7dcc8 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -807,6 +807,7 @@ typedef struct NodeShaderTexPointDensity {
short interpolation;
short color_source;
short pad2;
+ PointDensity pd;
} NodeShaderTexPointDensity;
/* TEX_output */
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 69e7fb43fb6..e5c102b1d2d 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -417,6 +417,9 @@ enum {
SEQ_SCENE_NO_GPENCIL = (1 << 28),
SEQ_USE_VIEWS = (1 << 29),
+ /* access scene strips directly (like a metastrip) */
+ SEQ_SCENE_STRIPS = (1 << 30),
+
SEQ_INVALID_EFFECT = (1 << 31),
};
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 4beeaa8bc3f..af1dfc62894 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -284,7 +284,7 @@ typedef struct ThemeSpace {
char nodeclass_pattern[4], nodeclass_layout[4];
char movie[4], movieclip[4], mask[4], image[4], scene[4], audio[4]; /* for sequence editor */
- char effect[4], transition[4], meta[4];
+ char effect[4], transition[4], meta[4], text_strip[4], pad[4];
char editmesh_active[4];
char handle_vertex[4];
@@ -545,6 +545,7 @@ typedef struct UserDef {
char author[80]; /* author name for file formats supporting it */
char font_path_ui[1024];
+ char font_path_ui_mono[1024];
int compute_device_type;
int compute_device_id;
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 2384bb7347b..06c53547b77 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -315,11 +315,18 @@ typedef struct View3D {
#define V3D_SHOW_WORLD (1 << 0)
/* View3D->around */
-#define V3D_CENTER 0
-#define V3D_CENTROID 3
-#define V3D_CURSOR 1
-#define V3D_LOCAL 2
-#define V3D_ACTIVE 4
+enum {
+ /* center of the bounding box */
+ V3D_AROUND_CENTER_BOUNDS = 0,
+ /* center from the sum of all points divided by the total */
+ V3D_AROUND_CENTER_MEAN = 3,
+ /* pivot around the 2D/3D cursor */
+ V3D_AROUND_CURSOR = 1,
+ /* pivot around each items own origin */
+ V3D_AROUND_LOCAL_ORIGINS = 2,
+ /* pivot around the active items origin */
+ V3D_AROUND_ACTIVE = 4,
+};
/*View3D types (only used in tools, not actually saved)*/
#define V3D_VIEW_STEPLEFT 1
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 826dd961010..8b785c8a65f 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -975,6 +975,7 @@ char *RNA_path_resolve_from_type_to_property(
char *RNA_path_full_ID_py(struct ID *id);
char *RNA_path_full_struct_py(struct PointerRNA *ptr);
+char *RNA_path_full_property_py_ex(PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback);
char *RNA_path_full_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
char *RNA_path_struct_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
char *RNA_path_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index cc876b4375e..bf8ea048fae 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -100,6 +100,8 @@ PropertyRNA *RNA_def_float_color(StructOrFunctionRNA *cont, const char *identifi
PropertyRNA *RNA_def_float_matrix(StructOrFunctionRNA *cont, const char *identifier, int rows, int columns, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
PropertyRNA *RNA_def_float_rotation(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value,
float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
+PropertyRNA *RNA_def_float_distance(StructOrFunctionRNA *cont, const char *identifier, float default_value,
+ float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
PropertyRNA *RNA_def_float_array(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value,
float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 887124fc486..ce977daf30a 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -1900,9 +1900,13 @@ static void rna_def_struct_function_prototype_cpp(FILE *f, StructRNA *UNUSED(srn
if (!(flag & PROP_DYNAMIC) && dp->prop->arraydimension)
fprintf(f, "%s %s[%u]", rna_parameter_type_cpp_name(dp->prop),
rna_safe_id(dp->prop->identifier), dp->prop->totarraylength);
- else
- fprintf(f, "%s %s%s", rna_parameter_type_cpp_name(dp->prop),
- ptrstr, rna_safe_id(dp->prop->identifier));
+ else {
+ fprintf(f, "%s%s%s%s",
+ rna_parameter_type_cpp_name(dp->prop),
+ (dp->prop->type == PROP_POINTER && ptrstr[0] == '\0') ? "& " : " ",
+ ptrstr,
+ rna_safe_id(dp->prop->identifier));
+ }
}
fprintf(f, ")");
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 5e4ea749b22..ede5073483b 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -4719,11 +4719,12 @@ char *RNA_path_full_struct_py(struct PointerRNA *ptr)
* Get the ID.struct.property as a python representation, eg:
* bpy.data.foo["bar"].some_struct.some_prop[10]
*/
-char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
+char *RNA_path_full_property_py_ex(PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback)
{
char *id_path;
const char *data_delim;
- char *data_path;
+ const char *data_path;
+ bool data_path_free;
char *ret;
@@ -4735,8 +4736,23 @@ char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
id_path = RNA_path_full_ID_py(ptr->id.data);
data_path = RNA_path_from_ID_to_property(ptr, prop);
+ if (data_path) {
+ data_delim = (data_path[0] == '[') ? "" : ".";
+ data_path_free = true;
+ }
+ else {
+ if (use_fallback) {
+ /* fuzzy fallback. be explicit in our ignoranc. */
+ data_path = RNA_property_identifier(prop);
+ data_delim = " ... ";
+ }
+ else {
+ data_delim = ".";
+
+ }
+ data_path_free = false;
+ }
- data_delim = (data_path && data_path[0] == '[') ? "" : ".";
if ((index == -1) || (RNA_property_array_check(prop) == false)) {
ret = BLI_sprintfN("%s%s%s",
@@ -4747,13 +4763,18 @@ char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
id_path, data_delim, data_path, index);
}
MEM_freeN(id_path);
- if (data_path) {
- MEM_freeN(data_path);
+ if (data_path_free) {
+ MEM_freeN((void *)data_path);
}
return ret;
}
+char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+ return RNA_path_full_property_py_ex(ptr, prop, index, false);
+}
+
/**
* Get the struct.property as a python representation, eg:
* some_struct.some_prop[10]
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 3b01305110c..f4b2c15b304 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -1315,7 +1315,7 @@ void RNA_def_property_ui_icon(PropertyRNA *prop, int icon, bool consecutive)
* The values hare are a little confusing:
*
* \param step: Used as the value to increase/decrease when clicking on number buttons,
- * \as well as scaling mouse input for click-dragging number buttons.
+ * as well as scaling mouse input for click-dragging number buttons.
* For floats this is (step * UI_PRECISION_FLOAT_SCALE), why? - nobody knows.
* For ints, whole values are used.
*
@@ -2875,6 +2875,18 @@ PropertyRNA *RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *iden
return prop;
}
+PropertyRNA *RNA_def_float_distance(StructOrFunctionRNA *cont_, const char *identifier,
+ float default_value, float hardmin, float hardmax, const char *ui_name,
+ const char *ui_description, float softmin, float softmax)
+{
+ PropertyRNA *prop = RNA_def_float(cont_, identifier, default_value,
+ hardmin, hardmax, ui_name, ui_description,
+ softmin, softmax);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+
+ return prop;
+}
+
PropertyRNA *RNA_def_float_array(StructOrFunctionRNA *cont_, const char *identifier, int len,
const float *default_value, float hardmin, float hardmax, const char *ui_name,
const char *ui_description, float softmin, float softmax)
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 18523f7c3e8..7280cc622dc 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -249,7 +249,6 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
error = glGetError();
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 4ca7493eb13..bf35752dcf6 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1883,6 +1883,34 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_property_enum_items(prop, prop_operation_items);
RNA_def_property_ui_text(prop, "Operation", "");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* BMesh intersection options */
+ prop = RNA_def_property(srna, "use_bmesh", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_Enabled);
+ RNA_def_property_ui_text(prop, "Use BMesh", "Use BMesh boolean calculation");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "use_bmesh_separate", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_Separate);
+ RNA_def_property_ui_text(prop, "Separate", "Keep edges separate");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "use_bmesh_dissolve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_NoDissolve);
+ RNA_def_property_ui_text(prop, "Dissolve", "Dissolve verts created from tessellated intersection");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "use_bmesh_connect_regions", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_NoConnectRegions);
+ RNA_def_property_ui_text(prop, "Calculate Holes", "Connect regions (needed for hole filling)");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "threshold");
+ RNA_def_property_range(prop, 0, 1.0f);
+ RNA_def_property_ui_range(prop, 0, 1, 1, 7);
+ RNA_def_property_ui_text(prop, "Threshold", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_array(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 2d412bf778b..c10fe52bb29 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -1182,6 +1182,24 @@ static void rna_Node_update_reg(bNodeTree *ntree, bNode *node)
RNA_parameter_list_free(&list);
}
+static void rna_Node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
+{
+ extern FunctionRNA rna_Node_insert_link_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create((ID *)ntree, node->typeinfo->ext.srna, node, &ptr);
+ func = &rna_Node_insert_link_func;
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "link", &link);
+ node->typeinfo->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
static void rna_Node_init(const bContext *C, PointerRNA *ptr)
{
extern FunctionRNA rna_Node_init_func;
@@ -1331,7 +1349,7 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc
PointerRNA dummyptr;
FunctionRNA *func;
PropertyRNA *parm;
- int have_function[9];
+ int have_function[10];
/* setup dummy node & node type to store static properties in */
memset(&dummynt, 0, sizeof(bNodeType));
@@ -1384,12 +1402,13 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc
nt->poll = (have_function[0]) ? rna_Node_poll : NULL;
nt->poll_instance = (have_function[1]) ? rna_Node_poll_instance : rna_Node_poll_instance_default;
nt->updatefunc = (have_function[2]) ? rna_Node_update_reg : NULL;
- nt->initfunc_api = (have_function[3]) ? rna_Node_init : NULL;
- nt->copyfunc_api = (have_function[4]) ? rna_Node_copy : NULL;
- nt->freefunc_api = (have_function[5]) ? rna_Node_free : NULL;
- nt->draw_buttons = (have_function[6]) ? rna_Node_draw_buttons : NULL;
- nt->draw_buttons_ex = (have_function[7]) ? rna_Node_draw_buttons_ext : NULL;
- nt->labelfunc = (have_function[8]) ? rna_Node_draw_label : NULL;
+ nt->insert_link = (have_function[3]) ? rna_Node_insert_link : NULL;
+ nt->initfunc_api = (have_function[4]) ? rna_Node_init : NULL;
+ nt->copyfunc_api = (have_function[5]) ? rna_Node_copy : NULL;
+ nt->freefunc_api = (have_function[6]) ? rna_Node_free : NULL;
+ nt->draw_buttons = (have_function[7]) ? rna_Node_draw_buttons : NULL;
+ nt->draw_buttons_ex = (have_function[8]) ? rna_Node_draw_buttons_ext : NULL;
+ nt->labelfunc = (have_function[9]) ? rna_Node_draw_label : NULL;
/* sanitize size values in case not all have been registered */
if (nt->maxwidth < nt->minwidth)
@@ -3016,6 +3035,39 @@ static int point_density_color_source_from_shader(NodeShaderTexPointDensity *sha
}
}
+void rna_ShaderNodePointDensity_density_cache(bNode *self,
+ Scene *scene,
+ int settings)
+{
+ NodeShaderTexPointDensity *shader_point_density = self->storage;
+ PointDensity *pd = &shader_point_density->pd;
+ if (scene == NULL) {
+ return;
+ }
+
+ /* Create PointDensity structure from node for sampling. */
+ memset(pd, 0, sizeof(*pd));
+ BKE_texture_pointdensity_init_data(pd);
+ pd->object = (Object *)self->id;
+ pd->radius = shader_point_density->radius;
+ if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
+ pd->source = TEX_PD_PSYS;
+ pd->psys = shader_point_density->particle_system;
+ pd->psys_cache_space = TEX_PD_OBJECTSPACE;
+ }
+ else {
+ BLI_assert(shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_OBJECT);
+ pd->source = TEX_PD_OBJECT;
+ pd->ob_cache_space = TEX_PD_OBJECTSPACE;
+ }
+ pd->color_source = point_density_color_source_from_shader(shader_point_density);
+
+ /* Single-threaded sampling of the voxel domain. */
+ RE_cache_point_density(scene,
+ pd,
+ settings == 1);
+}
+
void rna_ShaderNodePointDensity_density_calc(bNode *self,
Scene *scene,
int settings,
@@ -3023,7 +3075,7 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
float **values)
{
NodeShaderTexPointDensity *shader_point_density = self->storage;
- PointDensity pd;
+ PointDensity *pd = &shader_point_density->pd;
if (scene == NULL) {
*length = 0;
@@ -3038,30 +3090,14 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
*values = MEM_mallocN(sizeof(float) * (*length), "point density dynamic array");
}
- /* Create PointDensity structure from node for sampling. */
- BKE_texture_pointdensity_init_data(&pd);
- pd.object = (Object *)self->id;
- pd.radius = shader_point_density->radius;
- if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
- pd.source = TEX_PD_PSYS;
- pd.psys = shader_point_density->particle_system;
- pd.psys_cache_space = TEX_PD_OBJECTSPACE;
- }
- else {
- BLI_assert(shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_OBJECT);
- pd.source = TEX_PD_OBJECT;
- pd.ob_cache_space = TEX_PD_OBJECTSPACE;
- }
- pd.color_source = point_density_color_source_from_shader(shader_point_density);
-
/* Single-threaded sampling of the voxel domain. */
- RE_sample_point_density(scene, &pd,
+ RE_sample_point_density(scene, pd,
shader_point_density->resolution,
settings == 1,
*values);
/* We're done, time to clean up. */
- BKE_texture_pointdensity_free_data(&pd);
+ BKE_texture_pointdensity_free_data(pd);
}
#else
@@ -3993,6 +4029,11 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
RNA_def_property_ui_text(prop, "Color Source", "Data to derive color results from");
RNA_def_property_update(prop, 0, "rna_Node_update");
+ func = RNA_def_function(srna, "cache_point_density", "rna_ShaderNodePointDensity_density_cache");
+ RNA_def_function_ui_description(func, "Cache point density data for later calculation");
+ RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
+
func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc");
RNA_def_function_ui_description(func, "Calculate point density");
RNA_def_pointer(func, "scene", "Scene", "", "");
@@ -7684,6 +7725,13 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Update on editor changes");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ /* insert_link */
+ func = RNA_def_function(srna, "insert_link", NULL);
+ RNA_def_function_ui_description(func, "Handle creation of a link to or from the node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "link", "NodeLink", "Link", "Node link that will be inserted");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
/* init */
func = RNA_def_function(srna, "init", NULL);
RNA_def_function_ui_description(func, "Initialize a new instance of this node");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 7409a9c9c23..81b1e4ac4be 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -276,6 +276,9 @@ static void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA
case OB_MESH:
EDBM_mesh_load(ob);
EDBM_mesh_make(scene->toolsettings, ob);
+
+ DAG_id_tag_update(ob->data, 0);
+
EDBM_mesh_normals_update(((Mesh *)ob->data)->edit_btmesh);
BKE_editmesh_tessface_calc(((Mesh *)ob->data)->edit_btmesh);
break;
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 628dd98eaf7..5645f018cad 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -315,8 +315,10 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
}
-static void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], float ray_end[3],
- float r_location[3], float r_normal[3], int *index)
+static void rna_Object_ray_cast(
+ Object *ob, ReportList *reports,
+ float origin[3], float direction[3], float distance,
+ int *r_success, float r_location[3], float r_normal[3], int *r_index)
{
BVHTreeFromMesh treeData = {NULL};
@@ -331,33 +333,41 @@ static void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start
/* may fail if the mesh has no faces, in that case the ray-cast misses */
if (treeData.tree != NULL) {
BVHTreeRayHit hit;
- float ray_nor[3], dist;
- sub_v3_v3v3(ray_nor, ray_end, ray_start);
- dist = hit.dist = normalize_v3(ray_nor);
hit.index = -1;
+ hit.dist = distance;
- if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_nor, 0.0f, &hit,
+ normalize_v3(direction);
+
+
+ if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit,
treeData.raycast_callback, &treeData) != -1)
{
- if (hit.dist <= dist) {
+ if (hit.dist <= distance) {
+ *r_success = true;
+
copy_v3_v3(r_location, hit.co);
copy_v3_v3(r_normal, hit.no);
- *index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]);
- free_bvhtree_from_mesh(&treeData);
- return;
+ *r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]);
+
+ goto finally;
}
}
}
+ *r_success = false;
+
zero_v3(r_location);
zero_v3(r_normal);
- *index = -1;
+ *r_index = -1;
+
+finally:
free_bvhtree_from_mesh(&treeData);
}
-static void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, float point_co[3], float max_dist,
- float n_location[3], float n_normal[3], int *index)
+static void rna_Object_closest_point_on_mesh(
+ Object *ob, ReportList *reports, float origin[3], float distance,
+ int *r_success, float r_location[3], float r_normal[3], int *r_index)
{
BVHTreeFromMesh treeData = {NULL};
@@ -379,20 +389,26 @@ static void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, fl
BVHTreeNearest nearest;
nearest.index = -1;
- nearest.dist_sq = max_dist * max_dist;
+ nearest.dist_sq = distance * distance;
- if (BLI_bvhtree_find_nearest(treeData.tree, point_co, &nearest, treeData.nearest_callback, &treeData) != -1) {
- copy_v3_v3(n_location, nearest.co);
- copy_v3_v3(n_normal, nearest.no);
- *index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[nearest.index]);
- free_bvhtree_from_mesh(&treeData);
- return;
+ if (BLI_bvhtree_find_nearest(treeData.tree, origin, &nearest, treeData.nearest_callback, &treeData) != -1) {
+ *r_success = true;
+
+ copy_v3_v3(r_location, nearest.co);
+ copy_v3_v3(r_normal, nearest.no);
+ *r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[nearest.index]);
+
+ goto finally;
}
}
- zero_v3(n_location);
- zero_v3(n_normal);
- *index = -1;
+ *r_success = false;
+
+ zero_v3(r_location);
+ zero_v3(r_normal);
+ *r_index = -1;
+
+finally:
free_bvhtree_from_mesh(&treeData);
}
@@ -593,12 +609,15 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_REPORTS);
/* ray start and end */
- parm = RNA_def_float_vector(func, "start", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
+ parm = RNA_def_float_vector(func, "origin", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_float_vector(func, "end", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
+ parm = RNA_def_float_vector(func, "direction", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_float(func, "distance", FLT_MAX, 0.0, FLT_MAX, "", "Maximum distance", 0.0, FLT_MAX);
/* return location and normal */
+ parm = RNA_def_boolean(func, "result", 0, "", "");
+ RNA_def_function_output(func, parm);
parm = RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location",
"The hit location of this ray cast", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
@@ -607,8 +626,7 @@ void RNA_api_object(StructRNA *srna)
"The face normal at the ray cast hit location", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
RNA_def_function_output(func, parm);
-
- parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when no intersection is found", 0, 0);
+ parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when original data isn't available", 0, 0);
RNA_def_function_output(func, parm);
/* Nearest Point */
@@ -617,12 +635,14 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_REPORTS);
/* location of point for test and max distance */
- parm = RNA_def_float_vector(func, "point", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
+ parm = RNA_def_float_vector(func, "origin", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
/* default is sqrt(FLT_MAX) */
- RNA_def_float(func, "max_dist", 1.844674352395373e+19, 0.0, FLT_MAX, "", "", 0.0, FLT_MAX);
+ RNA_def_float(func, "distance", 1.844674352395373e+19, 0.0, FLT_MAX, "", "Maximum distance", 0.0, FLT_MAX);
/* return location and normal */
+ parm = RNA_def_boolean(func, "result", 0, "", "");
+ RNA_def_function_output(func, parm);
parm = RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location",
"The location on the object closest to the point", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
@@ -632,7 +652,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_property_flag(parm, PROP_THICK_WRAP);
RNA_def_function_output(func, parm);
- parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when no closest point is found", 0, 0);
+ parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when original data isn't available", 0, 0);
RNA_def_function_output(func, parm);
/* View */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index ed7f9223b7c..2624e351c74 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -3828,12 +3828,9 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
static EnumPropertyItem storage_items[] = {
{RAS_STORE_AUTO, "AUTO", 0, "Auto Select", "Choose the best supported mode"},
- {RAS_STORE_IMMEDIATE, "IMMEDIATE", 0, "Immediate Mode", "Slowest performance, requires OpenGL (any version)"},
- {RAS_STORE_VA, "VERTEX_ARRAY", 0, "Vertex Arrays", "Better performance, requires at least OpenGL 1.1"},
-#if 0 /* XXX VBOS are currently disabled since they cannot beat vertex array with display lists in performance. */
+ {RAS_STORE_VA, "VERTEX_ARRAY", 0, "Vertex Arrays", "Usually the best choice (good performance with display lists)"},
{RAS_STORE_VBO, "VERTEX_BUFFER_OBJECT", 0, "Vertex Buffer Objects",
- "Best performance, requires at least OpenGL 1.4"},
-#endif
+ "Typically slower than vertex arrays with display lists, requires at least OpenGL 1.4"},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "SceneGameData", NULL);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 9d63dfe0f55..b31681f1b6e 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -137,30 +137,28 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int previe
}
}
-static void rna_Scene_ray_cast(Scene *scene, float ray_start[3], float ray_end[3],
- int *r_success, Object **r_ob, float r_obmat[16],
- float r_location[3], float r_normal[3])
+static void rna_Scene_ray_cast(
+ Scene *scene, float origin[3], float direction[3], float ray_dist,
+ int *r_success, float r_location[3], float r_normal[3], int *r_index,
+ Object **r_ob, float r_obmat[16])
{
- float dummy_dist_px = 0;
- float ray_nor[3];
- float ray_dist;
-
- sub_v3_v3v3(ray_nor, ray_end, ray_start);
- ray_dist = normalize_v3(ray_nor);
-
- if (snapObjectsRayEx(scene, NULL, NULL, NULL, NULL, SCE_SNAP_MODE_FACE,
- r_ob, (float(*)[4])r_obmat,
- ray_start, ray_nor, &ray_dist,
- NULL, &dummy_dist_px, r_location, r_normal, SNAP_ALL))
+ normalize_v3(direction);
+
+ if (snapObjectsRayEx(
+ scene, NULL, NULL, NULL, NULL,
+ NULL, SNAP_ALL, SCE_SNAP_MODE_FACE,
+ origin, direction, &ray_dist,
+ r_location, r_normal, NULL, r_index,
+ r_ob, (float(*)[4])r_obmat))
{
*r_success = true;
}
else {
+ *r_success = false;
+
unit_m4((float(*)[4])r_obmat);
zero_v3(r_location);
zero_v3(r_normal);
-
- *r_success = false;
}
}
@@ -230,18 +228,15 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_function_ui_description(func, "Cast a ray onto in object space");
/* ray start and end */
- parm = RNA_def_float_vector(func, "start", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
+ parm = RNA_def_float_vector(func, "origin", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_float_vector(func, "end", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
+ parm = RNA_def_float_vector(func, "direction", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_float(func, "distance", FLT_MAX, 0.0, FLT_MAX, "", "Maximum distance", 0.0, FLT_MAX);
/* return location and normal */
parm = RNA_def_boolean(func, "result", 0, "", "");
RNA_def_function_output(func, parm);
- parm = RNA_def_pointer(func, "object", "Object", "", "Ray cast object");
- RNA_def_function_output(func, parm);
- parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
- RNA_def_function_output(func, parm);
parm = RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location",
"The hit location of this ray cast", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
@@ -250,6 +245,12 @@ void RNA_api_scene(StructRNA *srna)
"The face normal at the ray cast hit location", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
RNA_def_function_output(func, parm);
+ parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when original data isn't available", 0, 0);
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_pointer(func, "object", "Object", "", "Ray cast object");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
+ RNA_def_function_output(func, parm);
#ifdef WITH_COLLADA
/* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index de138699e3a..1fb57fc1d11 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1901,7 +1901,12 @@ static void rna_def_scene(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Camera_object_poll");
RNA_def_property_ui_text(prop, "Camera Override", "Override the scenes active camera");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
-
+
+ prop = RNA_def_property(srna, "use_sequence", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SCENE_STRIPS);
+ RNA_def_property_ui_text(prop, "Use Sequence", "Use scenes sequence strips directly, instead of rendering");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
prop = RNA_def_property(srna, "use_grease_pencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_SCENE_NO_GPENCIL);
RNA_def_property_ui_text(prop, "Use Grease Pencil", "Show Grease Pencil strokes in OpenGL previews");
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index f3f4f3c1c3d..ad26891c96a 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -124,14 +124,14 @@ static EnumPropertyItem stereo3d_eye_items[] = {
#endif
static EnumPropertyItem pivot_items_full[] = {
- {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
+ {V3D_AROUND_CENTER_BOUNDS, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
"Pivot around bounding box center of selected object(s)"},
- {V3D_CURSOR, "CURSOR", ICON_CURSOR, "3D Cursor", "Pivot around the 3D cursor"},
- {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
+ {V3D_AROUND_CURSOR, "CURSOR", ICON_CURSOR, "3D Cursor", "Pivot around the 3D cursor"},
+ {V3D_AROUND_LOCAL_ORIGINS, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
"Individual Origins", "Pivot around each object's own origin"},
- {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point",
+ {V3D_AROUND_CENTER_MEAN, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point",
"Pivot around the median point of selected objects"},
- {V3D_ACTIVE, "ACTIVE_ELEMENT", ICON_ROTACTIVE, "Active Element", "Pivot around active object"},
+ {V3D_AROUND_ACTIVE, "ACTIVE_ELEMENT", ICON_ROTACTIVE, "Active Element", "Pivot around active object"},
{0, NULL, 0, NULL, NULL}
};
@@ -935,10 +935,10 @@ static EnumPropertyItem *rna_SpaceImageEditor_pivot_itemf(bContext *UNUSED(C), P
PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
static EnumPropertyItem pivot_items[] = {
- {V3D_CENTER, "CENTER", ICON_ROTATE, "Bounding Box Center", ""},
- {V3D_CENTROID, "MEDIAN", ICON_ROTATECENTER, "Median Point", ""},
- {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
- {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
+ {V3D_AROUND_CENTER_BOUNDS, "CENTER", ICON_ROTATE, "Bounding Box Center", ""},
+ {V3D_AROUND_CENTER_MEAN, "MEDIAN", ICON_ROTATECENTER, "Median Point", ""},
+ {V3D_AROUND_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
+ {V3D_AROUND_LOCAL_ORIGINS, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
"Individual Origins", "Pivot around each object's own origin"},
{0, NULL, 0, NULL, NULL}
};
@@ -3426,11 +3426,11 @@ static void rna_def_space_graph(BlenderRNA *brna)
/* this is basically the same as the one for the 3D-View, but with some entries omitted */
static EnumPropertyItem gpivot_items[] = {
- {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", ""},
- {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
- {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION, "Individual Centers", ""},
- /*{V3D_CENTROID, "MEDIAN_POINT", 0, "Median Point", ""}, */
- /*{V3D_ACTIVE, "ACTIVE_ELEMENT", 0, "Active Element", ""}, */
+ {V3D_AROUND_CENTER_BOUNDS, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", ""},
+ {V3D_AROUND_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
+ {V3D_AROUND_LOCAL_ORIGINS, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION, "Individual Centers", ""},
+ /*{V3D_AROUND_CENTER_MEAN, "MEDIAN_POINT", 0, "Median Point", ""}, */
+ /*{V3D_AROUND_ACTIVE, "ACTIVE_ELEMENT", 0, "Active Element", ""}, */
{0, NULL, 0, NULL, NULL}
};
@@ -4457,12 +4457,12 @@ static void rna_def_space_clip(BlenderRNA *brna)
};
static EnumPropertyItem pivot_items[] = {
- {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
+ {V3D_AROUND_CENTER_BOUNDS, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
"Pivot around bounding box center of selected object(s)"},
- {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", "Pivot around the 2D cursor"},
- {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
+ {V3D_AROUND_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", "Pivot around the 2D cursor"},
+ {V3D_AROUND_LOCAL_ORIGINS, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
"Individual Origins", "Pivot around each object's own origin"},
- {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point",
+ {V3D_AROUND_CENTER_MEAN, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point",
"Pivot around the median point of selected objects"},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 90202a62d8b..39562d4d8a0 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -2548,6 +2548,11 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Meta Strip", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "text_strip", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Text Strip", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "frame_current", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "cframe");
RNA_def_property_array(prop, 3);
@@ -4000,6 +4005,11 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Interface Font", "Path to interface font");
RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_language_update");
+ prop = RNA_def_property(srna, "font_path_ui_mono", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_string_sdna(prop, NULL, "font_path_ui_mono");
+ RNA_def_property_ui_text(prop, "Mono-space Font", "Path to interface mono-space Font");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_language_update");
+
prop = RNA_def_property(srna, "scrollback", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "scrollback");
RNA_def_property_range(prop, 32, 32768);
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index ad230dede24..0de7676e8f8 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -37,6 +37,7 @@ set(INC
../render/extern/include
../../../intern/elbeem/extern
../../../intern/guardedalloc
+ ../../../intern/eigen
)
set(INC_SYS
@@ -144,13 +145,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
-if(WITH_OPENNL)
- add_definitions(-DWITH_OPENNL)
- list(APPEND INC_SYS
- ../../../intern/opennl/extern
- )
-endif()
-
if(WITH_OPENSUBDIV)
add_definitions(-DWITH_OPENSUBDIV)
endif()
diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript
index 7be295aa1a0..30007118562 100644
--- a/source/blender/modifiers/SConscript
+++ b/source/blender/modifiers/SConscript
@@ -33,8 +33,8 @@ incs = [
'.',
'./intern',
'#/intern/guardedalloc',
+ '#/intern/eigen',
'#/intern/elbeem/extern',
- '#/intern/opennl/extern',
'../render/extern/include',
'../bmesh',
'../include',
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 3fd2c8a3502..57318e44eec 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -1,4 +1,3 @@
-
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -33,6 +32,12 @@
* \ingroup modifiers
*/
+// #ifdef DEBUG_TIME
+#define USE_BMESH
+#ifdef WITH_MOD_BOOLEAN
+# define USE_CARVE WITH_MOD_BOOLEAN
+#endif
+
#include <stdio.h>
#include "DNA_object_types.h"
@@ -48,6 +53,20 @@
#include "MOD_boolean_util.h"
#include "MOD_util.h"
+#ifdef USE_BMESH
+#include "BLI_math_geom.h"
+#include "MEM_guardedalloc.h"
+
+#include "bmesh.h"
+#include "bmesh_tools.h"
+#include "tools/bmesh_intersect.h"
+#endif
+
+#ifdef DEBUG_TIME
+#include "PIL_time.h"
+#include "PIL_time_utildefines.h"
+#endif
+
static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
@@ -104,7 +123,8 @@ static void updateDepsgraph(ModifierData *md,
DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier");
}
-#ifdef WITH_MOD_BOOLEAN
+#if defined(USE_CARVE) || defined(USE_BMESH)
+
static DerivedMesh *get_quick_derivedMesh(DerivedMesh *derivedData, DerivedMesh *dm, int operation)
{
DerivedMesh *result = NULL;
@@ -129,10 +149,162 @@ static DerivedMesh *get_quick_derivedMesh(DerivedMesh *derivedData, DerivedMesh
return result;
}
+#endif /* defined(USE_CARVE) || defined(USE_BMESH) */
+
+
+/* -------------------------------------------------------------------- */
+/* BMESH */
+
+#ifdef USE_BMESH
+
+/* has no meaning for faces, do this so we can tell which face is which */
+#define BM_FACE_TAG BM_ELEM_DRAW
+
+/**
+ * Compare selected/unselected.
+ */
+static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
+{
+ return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0;
+}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
- ModifierApplyFlag flag)
+static DerivedMesh *applyModifier_bmesh(
+ ModifierData *md, Object *ob,
+ DerivedMesh *dm,
+ ModifierApplyFlag flag)
+{
+ BooleanModifierData *bmd = (BooleanModifierData *) md;
+ DerivedMesh *dm_other;
+
+ if (!bmd->object)
+ return dm;
+
+ dm_other = get_dm_for_modifier(bmd->object, flag);
+
+ if (dm_other) {
+ DerivedMesh *result;
+
+ /* when one of objects is empty (has got no faces) we could speed up
+ * calculation a bit returning one of objects' derived meshes (or empty one)
+ * Returning mesh is depended on modifiers operation (sergey) */
+ result = get_quick_derivedMesh(dm, dm_other, bmd->operation);
+
+ if (result == NULL) {
+ BMesh *bm;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_DM(dm, dm_other);
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(boolean_bmesh);
+#endif
+ bm = BM_mesh_create(&allocsize);
+
+ DM_to_bmesh_ex(dm_other, bm, true);
+ DM_to_bmesh_ex(dm, bm, true);
+
+ /* main bmesh intersection setup */
+ {
+ /* create tessface & intersect */
+ const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
+ int tottri;
+ BMLoop *(*looptris)[3];
+
+ looptris = MEM_mallocN(sizeof(*looptris) * looptris_tot, __func__);
+
+ BM_bmesh_calc_tessellation(bm, looptris, &tottri);
+
+ /* postpone this until after tessellating
+ * so we can use the original normals before the vertex are moved */
+ {
+ BMIter iter;
+ int i;
+ const int i_verts_end = dm_other->getNumVerts(dm_other);
+ const int i_faces_end = dm_other->getNumPolys(dm_other);
+
+ float imat[4][4];
+ float omat[4][4];
+
+ invert_m4_m4(imat, ob->obmat);
+ mul_m4_m4m4(omat, imat, bmd->object->obmat);
+
+
+ BMVert *eve;
+ i = 0;
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ mul_m4_v3(omat, eve->co);
+ if (++i == i_verts_end) {
+ break;
+ }
+ }
+
+ /* we need face normals because of 'BM_face_split_edgenet'
+ * we could calculate on the fly too (before calling split). */
+ float nmat[4][4];
+ invert_m4_m4(nmat, omat);
+
+ BMFace *efa;
+ i = 0;
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ mul_transposed_mat3_m4_v3(nmat, efa->no);
+ normalize_v3(efa->no);
+ BM_elem_flag_enable(efa, BM_FACE_TAG); /* temp tag to test which side split faces are from */
+ if (++i == i_faces_end) {
+ break;
+ }
+ }
+ }
+
+ /* not needed, but normals for 'dm' will be invalid,
+ * currently this is ok for 'BM_mesh_intersect' */
+ // BM_mesh_normals_update(bm);
+
+ BM_mesh_intersect(
+ bm,
+ looptris, tottri,
+ bm_face_isect_pair, NULL,
+ false,
+ (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_Separate) != 0,
+ (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoDissolve) == 0,
+ (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoConnectRegions) == 0,
+ bmd->operation,
+ bmd->threshold);
+
+ MEM_freeN(looptris);
+ }
+
+ result = CDDM_from_bmesh(bm, true);
+
+ BM_mesh_free(bm);
+
+ result->dirty |= DM_DIRTY_NORMALS;
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(boolean_bmesh);
+#endif
+
+ return result;
+ }
+
+ /* if new mesh returned, return it; otherwise there was
+ * an error, so delete the modifier object */
+ if (result)
+ return result;
+ else
+ modifier_setError(md, "Cannot execute boolean operation");
+ }
+
+ return dm;
+}
+#endif /* USE_BMESH */
+
+
+/* -------------------------------------------------------------------- */
+/* CARVE */
+
+#ifdef USE_CARVE
+static DerivedMesh *applyModifier_carve(
+ ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ ModifierApplyFlag flag)
{
BooleanModifierData *bmd = (BooleanModifierData *) md;
DerivedMesh *dm;
@@ -151,12 +323,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
result = get_quick_derivedMesh(derivedData, dm, bmd->operation);
if (result == NULL) {
- // TIMEIT_START(NewBooleanDerivedMesh)
+#ifdef DEBUG_TIME
+ TIMEIT_START(boolean_carve);
+#endif
result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob,
1 + bmd->operation);
-
- // TIMEIT_END(NewBooleanDerivedMesh)
+#ifdef DEBUG_TIME
+ TIMEIT_END(boolean_carve);
+#endif
}
/* if new mesh returned, return it; otherwise there was
@@ -169,14 +344,16 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
return derivedData;
}
-#else // WITH_MOD_BOOLEAN
-static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
- DerivedMesh *derivedData,
- ModifierApplyFlag UNUSED(flag))
+#endif /* USE_CARVE */
+
+
+static DerivedMesh *applyModifier_nop(
+ ModifierData *UNUSED(md), Object *UNUSED(ob),
+ DerivedMesh *derivedData,
+ ModifierApplyFlag UNUSED(flag))
{
return derivedData;
}
-#endif // WITH_MOD_BOOLEAN
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md))
{
@@ -187,6 +364,28 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(
return dataMask;
}
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ ModifierApplyFlag flag)
+{
+ BooleanModifierData *bmd = (BooleanModifierData *)md;
+ const int method = (bmd->bm_flag & eBooleanModifierBMeshFlag_Enabled) ? 1 : 0;
+
+ switch (method) {
+#ifdef USE_CARVE
+ case 0:
+ return applyModifier_carve(md, ob, derivedData, flag);
+#endif
+#ifdef USE_BMESH
+ case 1:
+ return applyModifier_bmesh(md, ob, derivedData, flag);
+#endif
+ default:
+ return applyModifier_nop(md, ob, derivedData, flag);
+ }
+}
+
ModifierTypeInfo modifierType_Boolean = {
/* name */ "Boolean",
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index fdaacc7cd9e..d4f02d923d3 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -42,6 +42,7 @@
#include "MOD_util.h"
+#include "eigen_capi.h"
enum {
LAPDEFORM_SYSTEM_NOT_CHANGE = 0,
@@ -54,10 +55,6 @@ enum {
LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP,
};
-#ifdef WITH_OPENNL
-
-#include "ONL_opennl.h"
-
typedef struct LaplacianSystem {
bool is_matrix_computed;
bool has_solution;
@@ -75,7 +72,7 @@ typedef struct LaplacianSystem {
int *unit_verts; /* Unit vectors of projected edges onto the plane orthogonal to n */
int *ringf_indices; /* Indices of faces per vertex */
int *ringv_indices; /* Indices of neighbors(vertex) per vertex */
- NLContext *context; /* System for solve general implicit rotations */
+ LinearSolver *context; /* System for solve general implicit rotations */
MeshElemMap *ringf_map; /* Map of faces per vertex */
MeshElemMap *ringv_map; /* Map of vertex per vertex */
} LaplacianSystem;
@@ -134,7 +131,7 @@ static void deleteLaplacianSystem(LaplacianSystem *sys)
MEM_SAFE_FREE(sys->ringv_map);
if (sys->context) {
- nlDeleteContext(sys->context);
+ EIG_linear_solver_delete(sys->context);
}
MEM_SAFE_FREE(sys);
}
@@ -283,9 +280,9 @@ static void initLaplacianMatrix(LaplacianSystem *sys)
sys->delta[idv[0]][1] -= v3[1] * w3;
sys->delta[idv[0]][2] -= v3[2] * w3;
- nlMatrixAdd(sys->context, idv[0], idv[1], -w2);
- nlMatrixAdd(sys->context, idv[0], idv[2], -w3);
- nlMatrixAdd(sys->context, idv[0], idv[0], w2 + w3);
+ EIG_linear_solver_matrix_add(sys->context, idv[0], idv[1], -w2);
+ EIG_linear_solver_matrix_add(sys->context, idv[0], idv[2], -w3);
+ EIG_linear_solver_matrix_add(sys->context, idv[0], idv[0], w2 + w3);
}
}
}
@@ -338,9 +335,9 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
beta = dot_v3v3(uij, di);
gamma = dot_v3v3(e2, di);
- pi[0] = nlGetVariable(sys->context, 0, i);
- pi[1] = nlGetVariable(sys->context, 1, i);
- pi[2] = nlGetVariable(sys->context, 2, i);
+ pi[0] = EIG_linear_solver_variable_get(sys->context, 0, i);
+ pi[1] = EIG_linear_solver_variable_get(sys->context, 1, i);
+ pi[2] = EIG_linear_solver_variable_get(sys->context, 2, i);
zero_v3(ni);
num_fni = 0;
num_fni = sys->ringf_map[i].count;
@@ -349,9 +346,9 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
fidn = sys->ringf_map[i].indices;
vin = sys->tris[fidn[fi]];
for (j = 0; j < 3; j++) {
- vn[j][0] = nlGetVariable(sys->context, 0, vin[j]);
- vn[j][1] = nlGetVariable(sys->context, 1, vin[j]);
- vn[j][2] = nlGetVariable(sys->context, 2, vin[j]);
+ vn[j][0] = EIG_linear_solver_variable_get(sys->context, 0, vin[j]);
+ vn[j][1] = EIG_linear_solver_variable_get(sys->context, 1, vin[j]);
+ vn[j][2] = EIG_linear_solver_variable_get(sys->context, 2, vin[j]);
if (vin[j] == sys->unit_verts[i]) {
copy_v3_v3(pj, vn[j]);
}
@@ -372,14 +369,14 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
fni[2] = alpha * ni[2] + beta * uij[2] + gamma * e2[2];
if (len_squared_v3(fni) > FLT_EPSILON) {
- nlRightHandSideSet(sys->context, 0, i, fni[0]);
- nlRightHandSideSet(sys->context, 1, i, fni[1]);
- nlRightHandSideSet(sys->context, 2, i, fni[2]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, i, fni[0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, i, fni[1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, i, fni[2]);
}
else {
- nlRightHandSideSet(sys->context, 0, i, sys->delta[i][0]);
- nlRightHandSideSet(sys->context, 1, i, sys->delta[i][1]);
- nlRightHandSideSet(sys->context, 2, i, sys->delta[i][2]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, i, sys->delta[i][0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, i, sys->delta[i][1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, i, sys->delta[i][2]);
}
}
}
@@ -390,75 +387,59 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
n = sys->total_verts;
na = sys->total_anchors;
-#ifdef OPENNL_THREADING_HACK
- modifier_opennl_lock();
-#endif
-
if (!sys->is_matrix_computed) {
- sys->context = nlNewContext();
+ sys->context = EIG_linear_least_squares_solver_new(n + na, n, 3);
- nlSolverParameteri(sys->context, NL_NB_VARIABLES, n);
- nlSolverParameteri(sys->context, NL_LEAST_SQUARES, NL_TRUE);
- nlSolverParameteri(sys->context, NL_NB_ROWS, n + na);
- nlSolverParameteri(sys->context, NL_NB_RIGHT_HAND_SIDES, 3);
- nlBegin(sys->context, NL_SYSTEM);
for (i = 0; i < n; i++) {
- nlSetVariable(sys->context, 0, i, sys->co[i][0]);
- nlSetVariable(sys->context, 1, i, sys->co[i][1]);
- nlSetVariable(sys->context, 2, i, sys->co[i][2]);
+ EIG_linear_solver_variable_set(sys->context, 0, i, sys->co[i][0]);
+ EIG_linear_solver_variable_set(sys->context, 1, i, sys->co[i][1]);
+ EIG_linear_solver_variable_set(sys->context, 2, i, sys->co[i][2]);
}
for (i = 0; i < na; i++) {
vid = sys->index_anchors[i];
- nlSetVariable(sys->context, 0, vid, vertexCos[vid][0]);
- nlSetVariable(sys->context, 1, vid, vertexCos[vid][1]);
- nlSetVariable(sys->context, 2, vid, vertexCos[vid][2]);
+ EIG_linear_solver_variable_set(sys->context, 0, vid, vertexCos[vid][0]);
+ EIG_linear_solver_variable_set(sys->context, 1, vid, vertexCos[vid][1]);
+ EIG_linear_solver_variable_set(sys->context, 2, vid, vertexCos[vid][2]);
}
- nlBegin(sys->context, NL_MATRIX);
initLaplacianMatrix(sys);
computeImplictRotations(sys);
for (i = 0; i < n; i++) {
- nlRightHandSideSet(sys->context, 0, i, sys->delta[i][0]);
- nlRightHandSideSet(sys->context, 1, i, sys->delta[i][1]);
- nlRightHandSideSet(sys->context, 2, i, sys->delta[i][2]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, i, sys->delta[i][0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, i, sys->delta[i][1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, i, sys->delta[i][2]);
}
for (i = 0; i < na; i++) {
vid = sys->index_anchors[i];
- nlRightHandSideSet(sys->context, 0, n + i, vertexCos[vid][0]);
- nlRightHandSideSet(sys->context, 1, n + i, vertexCos[vid][1]);
- nlRightHandSideSet(sys->context, 2, n + i, vertexCos[vid][2]);
- nlMatrixAdd(sys->context, n + i, vid, 1.0f);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]);
+ EIG_linear_solver_matrix_add(sys->context, n + i, vid, 1.0f);
}
- nlEnd(sys->context, NL_MATRIX);
- nlEnd(sys->context, NL_SYSTEM);
- if (nlSolve(sys->context, NL_TRUE)) {
+ if (EIG_linear_solver_solve(sys->context)) {
sys->has_solution = true;
for (j = 1; j <= sys->repeat; j++) {
- nlBegin(sys->context, NL_SYSTEM);
- nlBegin(sys->context, NL_MATRIX);
rotateDifferentialCoordinates(sys);
for (i = 0; i < na; i++) {
vid = sys->index_anchors[i];
- nlRightHandSideSet(sys->context, 0, n + i, vertexCos[vid][0]);
- nlRightHandSideSet(sys->context, 1, n + i, vertexCos[vid][1]);
- nlRightHandSideSet(sys->context, 2, n + i, vertexCos[vid][2]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]);
}
- nlEnd(sys->context, NL_MATRIX);
- nlEnd(sys->context, NL_SYSTEM);
- if (!nlSolve(sys->context, NL_FALSE)) {
+ if (!EIG_linear_solver_solve(sys->context)) {
sys->has_solution = false;
break;
}
}
if (sys->has_solution) {
for (vid = 0; vid < sys->total_verts; vid++) {
- vertexCos[vid][0] = nlGetVariable(sys->context, 0, vid);
- vertexCos[vid][1] = nlGetVariable(sys->context, 1, vid);
- vertexCos[vid][2] = nlGetVariable(sys->context, 2, vid);
+ vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid);
+ vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid);
+ vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid);
}
}
else {
@@ -473,49 +454,40 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
}
else if (sys->has_solution) {
- nlBegin(sys->context, NL_SYSTEM);
- nlBegin(sys->context, NL_MATRIX);
-
for (i = 0; i < n; i++) {
- nlRightHandSideSet(sys->context, 0, i, sys->delta[i][0]);
- nlRightHandSideSet(sys->context, 1, i, sys->delta[i][1]);
- nlRightHandSideSet(sys->context, 2, i, sys->delta[i][2]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, i, sys->delta[i][0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, i, sys->delta[i][1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, i, sys->delta[i][2]);
}
for (i = 0; i < na; i++) {
vid = sys->index_anchors[i];
- nlRightHandSideSet(sys->context, 0, n + i, vertexCos[vid][0]);
- nlRightHandSideSet(sys->context, 1, n + i, vertexCos[vid][1]);
- nlRightHandSideSet(sys->context, 2, n + i, vertexCos[vid][2]);
- nlMatrixAdd(sys->context, n + i, vid, 1.0f);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]);
+ EIG_linear_solver_matrix_add(sys->context, n + i, vid, 1.0f);
}
- nlEnd(sys->context, NL_MATRIX);
- nlEnd(sys->context, NL_SYSTEM);
- if (nlSolve(sys->context, NL_FALSE)) {
+ if (EIG_linear_solver_solve(sys->context)) {
sys->has_solution = true;
for (j = 1; j <= sys->repeat; j++) {
- nlBegin(sys->context, NL_SYSTEM);
- nlBegin(sys->context, NL_MATRIX);
rotateDifferentialCoordinates(sys);
for (i = 0; i < na; i++) {
vid = sys->index_anchors[i];
- nlRightHandSideSet(sys->context, 0, n + i, vertexCos[vid][0]);
- nlRightHandSideSet(sys->context, 1, n + i, vertexCos[vid][1]);
- nlRightHandSideSet(sys->context, 2, n + i, vertexCos[vid][2]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]);
}
- nlEnd(sys->context, NL_MATRIX);
- nlEnd(sys->context, NL_SYSTEM);
- if (!nlSolve(sys->context, NL_FALSE)) {
+ if (!EIG_linear_solver_solve(sys->context)) {
sys->has_solution = false;
break;
}
}
if (sys->has_solution) {
for (vid = 0; vid < sys->total_verts; vid++) {
- vertexCos[vid][0] = nlGetVariable(sys->context, 0, vid);
- vertexCos[vid][1] = nlGetVariable(sys->context, 1, vid);
- vertexCos[vid][2] = nlGetVariable(sys->context, 2, vid);
+ vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid);
+ vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid);
+ vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid);
}
}
else {
@@ -526,10 +498,6 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
sys->has_solution = false;
}
}
-
-#ifdef OPENNL_THREADING_HACK
- modifier_opennl_unlock();
-#endif
}
static bool isValidVertexGroup(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm)
@@ -720,15 +688,6 @@ static void LaplacianDeformModifier_do(
}
}
-#else /* WITH_OPENNL */
-static void LaplacianDeformModifier_do(
- LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts)
-{
- UNUSED_VARS(lmd, ob, dm, vertexCos, numVerts);
-}
-#endif /* WITH_OPENNL */
-
static void initData(ModifierData *md)
{
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
@@ -792,12 +751,10 @@ static void deformVertsEM(
static void freeData(ModifierData *md)
{
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
-#ifdef WITH_OPENNL
LaplacianSystem *sys = (LaplacianSystem *)lmd->cache_system;
if (sys) {
deleteLaplacianSystem(sys);
}
-#endif
MEM_SAFE_FREE(lmd->vertexco);
lmd->total_verts = 0;
}
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index 189ceb11d08..f1216ff462a 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -43,9 +43,7 @@
#include "MOD_util.h"
-#ifdef WITH_OPENNL
-
-#include "ONL_opennl.h"
+#include "eigen_capi.h"
#if 0
#define MOD_LAPLACIANSMOOTH_MAX_EDGE_PERCENTAGE 1.8f
@@ -71,7 +69,7 @@ struct BLaplacianSystem {
const MPoly *mpoly;
const MLoop *mloop;
const MEdge *medges;
- NLContext *context;
+ LinearSolver *context;
/*Data*/
float min_area;
@@ -104,7 +102,7 @@ static void delete_laplacian_system(LaplacianSystem *sys)
MEM_SAFE_FREE(sys->zerola);
if (sys->context) {
- nlDeleteContext(sys->context);
+ EIG_linear_solver_delete(sys->context);
}
sys->vertexCos = NULL;
sys->mpoly = NULL;
@@ -300,16 +298,16 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
/* Is ring if number of faces == number of edges around vertice*/
if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == 0) {
- nlMatrixAdd(sys->context, l_curr->v, l_next->v, sys->fweights[l_curr_index][2] * sys->vweights[l_curr->v]);
- nlMatrixAdd(sys->context, l_curr->v, l_prev->v, sys->fweights[l_curr_index][1] * sys->vweights[l_curr->v]);
+ EIG_linear_solver_matrix_add(sys->context, l_curr->v, l_next->v, sys->fweights[l_curr_index][2] * sys->vweights[l_curr->v]);
+ EIG_linear_solver_matrix_add(sys->context, l_curr->v, l_prev->v, sys->fweights[l_curr_index][1] * sys->vweights[l_curr->v]);
}
if (sys->numNeEd[l_next->v] == sys->numNeFa[l_next->v] && sys->zerola[l_next->v] == 0) {
- nlMatrixAdd(sys->context, l_next->v, l_curr->v, sys->fweights[l_curr_index][2] * sys->vweights[l_next->v]);
- nlMatrixAdd(sys->context, l_next->v, l_prev->v, sys->fweights[l_curr_index][0] * sys->vweights[l_next->v]);
+ EIG_linear_solver_matrix_add(sys->context, l_next->v, l_curr->v, sys->fweights[l_curr_index][2] * sys->vweights[l_next->v]);
+ EIG_linear_solver_matrix_add(sys->context, l_next->v, l_prev->v, sys->fweights[l_curr_index][0] * sys->vweights[l_next->v]);
}
if (sys->numNeEd[l_prev->v] == sys->numNeFa[l_prev->v] && sys->zerola[l_prev->v] == 0) {
- nlMatrixAdd(sys->context, l_prev->v, l_curr->v, sys->fweights[l_curr_index][1] * sys->vweights[l_prev->v]);
- nlMatrixAdd(sys->context, l_prev->v, l_next->v, sys->fweights[l_curr_index][0] * sys->vweights[l_prev->v]);
+ EIG_linear_solver_matrix_add(sys->context, l_prev->v, l_curr->v, sys->fweights[l_curr_index][1] * sys->vweights[l_prev->v]);
+ EIG_linear_solver_matrix_add(sys->context, l_prev->v, l_next->v, sys->fweights[l_curr_index][0] * sys->vweights[l_prev->v]);
}
}
}
@@ -323,8 +321,8 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
sys->zerola[idv1] == 0 &&
sys->zerola[idv2] == 0)
{
- nlMatrixAdd(sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
- nlMatrixAdd(sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]);
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
+ EIG_linear_solver_matrix_add(sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]);
}
}
}
@@ -342,13 +340,13 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl
if (sys->zerola[i] == 0) {
lam = sys->numNeEd[i] == sys->numNeFa[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) : (lambda_border >= 0.0f ? 1.0f : -1.0f);
if (flag & MOD_LAPLACIANSMOOTH_X) {
- sys->vertexCos[i][0] += lam * ((float)nlGetVariable(sys->context, 0, i) - sys->vertexCos[i][0]);
+ sys->vertexCos[i][0] += lam * ((float)EIG_linear_solver_variable_get(sys->context, 0, i) - sys->vertexCos[i][0]);
}
if (flag & MOD_LAPLACIANSMOOTH_Y) {
- sys->vertexCos[i][1] += lam * ((float)nlGetVariable(sys->context, 1, i) - sys->vertexCos[i][1]);
+ sys->vertexCos[i][1] += lam * ((float)EIG_linear_solver_variable_get(sys->context, 1, i) - sys->vertexCos[i][1]);
}
if (flag & MOD_LAPLACIANSMOOTH_Z) {
- sys->vertexCos[i][2] += lam * ((float)nlGetVariable(sys->context, 2, i) - sys->vertexCos[i][2]);
+ sys->vertexCos[i][2] += lam * ((float)EIG_linear_solver_variable_get(sys->context, 2, i) - sys->vertexCos[i][2]);
}
}
}
@@ -386,24 +384,15 @@ static void laplaciansmoothModifier_do(
sys->vert_centroid[2] = 0.0f;
memset_laplacian_system(sys, 0);
-#ifdef OPENNL_THREADING_HACK
- modifier_opennl_lock();
-#endif
-
- sys->context = nlNewContext();
- nlSolverParameteri(sys->context, NL_NB_VARIABLES, numVerts);
- nlSolverParameteri(sys->context, NL_LEAST_SQUARES, NL_TRUE);
- nlSolverParameteri(sys->context, NL_NB_ROWS, numVerts);
- nlSolverParameteri(sys->context, NL_NB_RIGHT_HAND_SIDES, 3);
+ sys->context = EIG_linear_least_squares_solver_new(numVerts, numVerts, 3);
init_laplacian_matrix(sys);
for (iter = 0; iter < smd->repeat; iter++) {
- nlBegin(sys->context, NL_SYSTEM);
for (i = 0; i < numVerts; i++) {
- nlSetVariable(sys->context, 0, i, vertexCos[i][0]);
- nlSetVariable(sys->context, 1, i, vertexCos[i][1]);
- nlSetVariable(sys->context, 2, i, vertexCos[i][2]);
+ EIG_linear_solver_variable_set(sys->context, 0, i, vertexCos[i][0]);
+ EIG_linear_solver_variable_set(sys->context, 1, i, vertexCos[i][1]);
+ EIG_linear_solver_variable_set(sys->context, 2, i, vertexCos[i][2]);
if (iter == 0) {
add_v3_v3(sys->vert_centroid, vertexCos[i]);
}
@@ -412,12 +401,11 @@ static void laplaciansmoothModifier_do(
mul_v3_fl(sys->vert_centroid, 1.0f / (float)numVerts);
}
- nlBegin(sys->context, NL_MATRIX);
dv = dvert;
for (i = 0; i < numVerts; i++) {
- nlRightHandSideSet(sys->context, 0, i, vertexCos[i][0]);
- nlRightHandSideSet(sys->context, 1, i, vertexCos[i][1]);
- nlRightHandSideSet(sys->context, 2, i, vertexCos[i][2]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, i, vertexCos[i][0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, i, vertexCos[i][1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, i, vertexCos[i][2]);
if (iter == 0) {
if (dv) {
wpaint = defvert_find_weight(dv, defgrp_index);
@@ -434,10 +422,10 @@ static void laplaciansmoothModifier_do(
w = sys->vlengths[i];
sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
if (sys->numNeEd[i] == sys->numNeFa[i]) {
- nlMatrixAdd(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint);
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint);
}
else {
- nlMatrixAdd(sys->context, i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
}
}
else {
@@ -447,15 +435,15 @@ static void laplaciansmoothModifier_do(
sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
if (sys->numNeEd[i] == sys->numNeFa[i]) {
- nlMatrixAdd(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint / (4.0f * sys->ring_areas[i]));
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint / (4.0f * sys->ring_areas[i]));
}
else {
- nlMatrixAdd(sys->context, i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
}
}
}
else {
- nlMatrixAdd(sys->context, i, i, 1.0f);
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f);
}
}
}
@@ -464,32 +452,16 @@ static void laplaciansmoothModifier_do(
fill_laplacian_matrix(sys);
}
- nlEnd(sys->context, NL_MATRIX);
- nlEnd(sys->context, NL_SYSTEM);
-
- if (nlSolve(sys->context, NL_TRUE)) {
+ if (EIG_linear_solver_solve(sys->context)) {
validate_solution(sys, smd->flag, smd->lambda, smd->lambda_border);
}
}
- nlDeleteContext(sys->context);
+ EIG_linear_solver_delete(sys->context);
sys->context = NULL;
-#ifdef OPENNL_THREADING_HACK
- modifier_opennl_unlock();
-#endif
-
delete_laplacian_system(sys);
}
-#else /* WITH_OPENNL */
-static void laplaciansmoothModifier_do(
- LaplacianSmoothModifierData *smd, Object *ob, DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts)
-{
- UNUSED_VARS(smd, ob, dm, vertexCos, numVerts);
-}
-#endif /* WITH_OPENNL */
-
static void init_data(ModifierData *md)
{
LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md;
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index 8aa5f281f56..5f2f51df528 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -234,7 +234,7 @@ typedef struct MeshdeformUserdata {
float (*icagemat)[3];
} MeshdeformUserdata;
-static void meshdeform_vert_task(void * userdata, int iter)
+static void meshdeform_vert_task(void *userdata, void *UNUSED(userdata_chunck), int iter)
{
MeshdeformUserdata *data = userdata;
/*const*/ MeshDeformModifierData *mmd = data->mmd;
@@ -352,7 +352,7 @@ static void meshdeformModifier_do(
/* progress bar redraw can make this recursive .. */
if (!recursive) {
recursive = 1;
- mmd->bindfunc(md->scene, mmd, (float *)vertexCos, numVerts, cagemat);
+ mmd->bindfunc(md->scene, mmd, cagedm, (float *)vertexCos, numVerts, cagemat);
recursive = 0;
}
}
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index 54a7278be72..b82725a08e7 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_math_inline.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
@@ -265,125 +266,142 @@ static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, floa
#ifdef WITH_OCEANSIM
-#ifdef _OPENMP
-#define OMP_MIN_RES 18
-#endif
-
-static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd)
-{
- DerivedMesh *result;
-
+typedef struct GenerateOceanGeometryData {
MVert *mverts;
MPoly *mpolys;
MLoop *mloops;
int *origindex;
+ MLoopUV *mloopuvs;
- int cdlayer;
+ int res_x, res_y;
+ int rx, ry;
+ float ox, oy;
+ float sx, sy;
+ float ix, iy;
+} GenerateOceanGeometryData;
- const int rx = omd->resolution * omd->resolution;
- const int ry = omd->resolution * omd->resolution;
- const int res_x = rx * omd->repeat_x;
- const int res_y = ry * omd->repeat_y;
+static void generate_ocean_geometry_vertices(void *userdata, void *UNUSED(userdata_chunk), int y)
+{
+ GenerateOceanGeometryData *gogd = userdata;
+ int x;
+
+ for (x = 0; x <= gogd->res_x; x++) {
+ const int i = y * (gogd->res_x + 1) + x;
+ float *co = gogd->mverts[i].co;
+ co[0] = gogd->ox + (x * gogd->sx);
+ co[1] = gogd->oy + (y * gogd->sy);
+ co[2] = 0.0f;
+ }
+}
- const int num_verts = (res_x + 1) * (res_y + 1);
- /* const int num_edges = (res_x * res_y * 2) + res_x + res_y; */ /* UNUSED BMESH */
- const int num_faces = res_x * res_y;
+static void generate_ocean_geometry_polygons(void *userdata, void *UNUSED(userdata_chunk), int y)
+{
+ GenerateOceanGeometryData *gogd = userdata;
+ int x;
+
+ for (x = 0; x < gogd->res_x; x++) {
+ const int fi = y * gogd->res_x + x;
+ const int vi = y * (gogd->res_x + 1) + x;
+ MPoly *mp = &gogd->mpolys[fi];
+ MLoop *ml = &gogd->mloops[fi * 4];
+
+ ml->v = vi;
+ ml++;
+ ml->v = vi + 1;
+ ml++;
+ ml->v = vi + 1 + gogd->res_x + 1;
+ ml++;
+ ml->v = vi + gogd->res_x + 1;
+ ml++;
+
+ mp->loopstart = fi * 4;
+ mp->totloop = 4;
+
+ mp->flag |= ME_SMOOTH;
+
+ /* generated geometry does not map to original faces */
+ gogd->origindex[fi] = ORIGINDEX_NONE;
+ }
+}
- float sx = omd->size * omd->spatial_size;
- float sy = omd->size * omd->spatial_size;
- const float ox = -sx / 2.0f;
- const float oy = -sy / 2.0f;
+static void generate_ocean_geometry_uvs(void *userdata, void *UNUSED(userdata_chunk), int y)
+{
+ GenerateOceanGeometryData *gogd = userdata;
+ int x;
- float ix, iy;
+ for (x = 0; x < gogd->res_x; x++) {
+ const int i = y * gogd->res_x + x;
+ MLoopUV *luv = &gogd->mloopuvs[i * 4];
+
+ luv->uv[0] = x * gogd->ix;
+ luv->uv[1] = y * gogd->iy;
+ luv++;
+
+ luv->uv[0] = (x + 1) * gogd->ix;
+ luv->uv[1] = y * gogd->iy;
+ luv++;
+
+ luv->uv[0] = (x + 1) * gogd->ix;
+ luv->uv[1] = (y + 1) * gogd->iy;
+ luv++;
+
+ luv->uv[0] = x * gogd->ix;
+ luv->uv[1] = (y + 1) * gogd->iy;
+ luv++;
+ }
+}
+
+static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd)
+{
+ DerivedMesh *result;
+
+ GenerateOceanGeometryData gogd;
+
+ int num_verts;
+ int num_polys;
+
+ gogd.rx = omd->resolution * omd->resolution;
+ gogd.ry = omd->resolution * omd->resolution;
+ gogd.res_x = gogd.rx * omd->repeat_x;
+ gogd.res_y = gogd.ry * omd->repeat_y;
- int x, y;
+ num_verts = (gogd.res_x + 1) * (gogd.res_y + 1);
+ num_polys = gogd.res_x * gogd.res_y;
- sx /= rx;
- sy /= ry;
+ gogd.sx = omd->size * omd->spatial_size;
+ gogd.sy = omd->size * omd->spatial_size;
+ gogd.ox = -gogd.sx / 2.0f;
+ gogd.oy = -gogd.sy / 2.0f;
- result = CDDM_new(num_verts, 0, 0, num_faces * 4, num_faces);
+ gogd.sx /= gogd.rx;
+ gogd.sy /= gogd.ry;
- mverts = CDDM_get_verts(result);
- mpolys = CDDM_get_polys(result);
- mloops = CDDM_get_loops(result);
+ result = CDDM_new(num_verts, 0, 0, num_polys * 4, num_polys);
- origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);
+ gogd.mverts = CDDM_get_verts(result);
+ gogd.mpolys = CDDM_get_polys(result);
+ gogd.mloops = CDDM_get_loops(result);
+
+ gogd.origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);
/* create vertices */
-#pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
- for (y = 0; y <= res_y; y++) {
- for (x = 0; x <= res_x; x++) {
- const int i = y * (res_x + 1) + x;
- float *co = mverts[i].co;
- co[0] = ox + (x * sx);
- co[1] = oy + (y * sy);
- co[2] = 0;
- }
- }
+ BLI_task_parallel_range(0, gogd.res_y + 1, &gogd, generate_ocean_geometry_vertices);
/* create faces */
-#pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
- for (y = 0; y < res_y; y++) {
- for (x = 0; x < res_x; x++) {
- const int fi = y * res_x + x;
- const int vi = y * (res_x + 1) + x;
- MPoly *mp = &mpolys[fi];
- MLoop *ml = &mloops[fi * 4];
-
- ml->v = vi;
- ml++;
- ml->v = vi + 1;
- ml++;
- ml->v = vi + 1 + res_x + 1;
- ml++;
- ml->v = vi + res_x + 1;
- ml++;
-
- mp->loopstart = fi * 4;
- mp->totloop = 4;
-
- mp->flag |= ME_SMOOTH;
-
- /* generated geometry does not map to original faces */
- origindex[fi] = ORIGINDEX_NONE;
- }
- }
+ BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_polygons);
CDDM_calc_edges(result);
/* add uvs */
- cdlayer = CustomData_number_of_layers(&result->loopData, CD_MLOOPUV);
- if (cdlayer < MAX_MTFACE) {
- MLoopUV *mloopuvs = CustomData_add_layer(&result->loopData, CD_MLOOPUV, CD_CALLOC, NULL, num_faces * 4);
- CustomData_add_layer(&result->polyData, CD_MTEXPOLY, CD_CALLOC, NULL, num_faces);
-
- if (mloopuvs) { /* unlikely to fail */
- ix = 1.0 / rx;
- iy = 1.0 / ry;
-#pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
- for (y = 0; y < res_y; y++) {
- for (x = 0; x < res_x; x++) {
- const int i = y * res_x + x;
- MLoopUV *luv = &mloopuvs[i * 4];
-
- luv->uv[0] = x * ix;
- luv->uv[1] = y * iy;
- luv++;
-
- luv->uv[0] = (x + 1) * ix;
- luv->uv[1] = y * iy;
- luv++;
-
- luv->uv[0] = (x + 1) * ix;
- luv->uv[1] = (y + 1) * iy;
- luv++;
-
- luv->uv[0] = x * ix;
- luv->uv[1] = (y + 1) * iy;
- luv++;
+ if (CustomData_number_of_layers(&result->loopData, CD_MLOOPUV) < MAX_MTFACE) {
+ gogd.mloopuvs = CustomData_add_layer(&result->loopData, CD_MLOOPUV, CD_CALLOC, NULL, num_polys * 4);
+ CustomData_add_layer(&result->polyData, CD_MTEXPOLY, CD_CALLOC, NULL, num_polys);
- }
- }
+ if (gogd.mloopuvs) { /* unlikely to fail */
+ gogd.ix = 1.0 / gogd.rx;
+ gogd.iy = 1.0 / gogd.ry;
+
+ BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_uvs);
}
}
@@ -401,15 +419,10 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
DerivedMesh *dm = NULL;
OceanResult ocr;
- MVert *mverts, *mv;
- MLoop *mloops;
-
- int i, j;
-
- int num_verts;
- int num_faces;
+ MVert *mverts;
int cfra;
+ int i, j;
/* use cached & inverted value for speed
* expanded this would read...
@@ -425,18 +438,22 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
}
/* update modifier */
- if (omd->refresh & MOD_OCEAN_REFRESH_ADD)
+ if (omd->refresh & MOD_OCEAN_REFRESH_ADD) {
omd->ocean = BKE_ocean_add();
- if (omd->refresh & MOD_OCEAN_REFRESH_RESET)
+ }
+ if (omd->refresh & MOD_OCEAN_REFRESH_RESET) {
init_ocean_modifier(omd);
- if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE)
+ }
+ if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) {
clear_cache_data(omd);
-
+ }
omd->refresh = 0;
/* do ocean simulation */
if (omd->cached == true) {
- if (!omd->oceancache) init_cache_data(ob, omd);
+ if (!omd->oceancache) {
+ init_cache_data(ob, omd);
+ }
BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra);
}
else {
@@ -455,38 +472,31 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
CLAMP(cfra, omd->bakestart, omd->bakeend);
cfra -= omd->bakestart; /* shift to 0 based */
- num_verts = dm->getNumVerts(dm);
- num_faces = dm->getNumPolys(dm);
-
mverts = dm->getVertArray(dm);
- mloops = dm->getLoopArray(dm);
/* add vcols before displacement - allows lookup based on position */
if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
- int cdlayer = CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL);
-
- if (cdlayer < MAX_MCOL) {
- MLoopCol *mloopcols = CustomData_add_layer_named(&dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL,
- num_faces * 4, omd->foamlayername);
+ if (CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL) < MAX_MCOL) {
+ const int num_polys = dm->getNumPolys(dm);
+ const int num_loops = dm->getNumLoops(dm);
+ MLoop *mloops = dm->getLoopArray(dm);
+ MLoopCol *mloopcols = CustomData_add_layer_named(
+ &dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->foamlayername);
if (mloopcols) { /* unlikely to fail */
- MLoopCol *mlcol;
MPoly *mpolys = dm->getPolyArray(dm);
MPoly *mp;
- float foam;
-
- for (i = 0, mp = mpolys; i < num_faces; i++, mp++) {
- j = mp->totloop - 1;
+ for (i = 0, mp = mpolys; i < num_polys; i++, mp++) {
+ MLoop *ml = &mloops[mp->loopstart];
+ MLoopCol *mlcol = &mloopcols[mp->loopstart];
- /* highly unlikely */
- if (j <= 0) continue;
-
- do {
- const float *co = mverts[mloops[mp->loopstart + j].v].co;
- const float u = OCEAN_CO(size_co_inv, co[0]);
- const float v = OCEAN_CO(size_co_inv, co[1]);
+ for (j = mp->totloop; j--; ml++, mlcol++) {
+ const float *vco = mverts[ml->v].co;
+ const float u = OCEAN_CO(size_co_inv, vco[0]);
+ const float v = OCEAN_CO(size_co_inv, vco[1]);
+ float foam;
if (omd->oceancache && omd->cached == true) {
BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
@@ -498,11 +508,10 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
}
- mlcol = &mloopcols[mp->loopstart + j];
mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255);
/* This needs to be set (render engine uses) */
mlcol->a = 255;
- } while (j--);
+ }
}
}
}
@@ -511,21 +520,29 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
/* displace the geometry */
- /* #pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) */
- for (i = 0, mv = mverts; i < num_verts; i++, mv++) {
- const float u = OCEAN_CO(size_co_inv, mv->co[0]);
- const float v = OCEAN_CO(size_co_inv, mv->co[1]);
+ /* Note: tried to parallelized that one and previous foam loop, but gives 20% slower results... odd. */
+ {
+ const int num_verts = dm->getNumVerts(dm);
- if (omd->oceancache && omd->cached == true)
- BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
- else
- BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
+ /* #pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) */
+ for (i = 0; i < num_verts; i++) {
+ float *vco = mverts[i].co;
+ const float u = OCEAN_CO(size_co_inv, vco[0]);
+ const float v = OCEAN_CO(size_co_inv, vco[1]);
- mv->co[2] += ocr.disp[1];
+ if (omd->oceancache && omd->cached == true) {
+ BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
+ }
+ else {
+ BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
+ }
+
+ vco[2] += ocr.disp[1];
- if (omd->chop_amount > 0.0f) {
- mv->co[0] += ocr.disp[0];
- mv->co[1] += ocr.disp[2];
+ if (omd->chop_amount > 0.0f) {
+ vco[0] += ocr.disp[0];
+ vco[1] += ocr.disp[2];
+ }
}
}
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index be6f7af7791..f9291fb077f 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -55,10 +55,6 @@
#include "MEM_guardedalloc.h"
-#ifdef OPENNL_THREADING_HACK
-#include "BLI_threads.h"
-#endif
-
void modifier_init_texture(const Scene *scene, Tex *tex)
{
if (!tex)
@@ -234,23 +230,6 @@ void modifier_get_vgroup(Object *ob, DerivedMesh *dm, const char *name, MDeformV
}
-#ifdef OPENNL_THREADING_HACK
-
-static ThreadMutex opennl_context_mutex = BLI_MUTEX_INITIALIZER;
-
-void modifier_opennl_lock(void)
-{
- BLI_mutex_lock(&opennl_context_mutex);
-}
-
-void modifier_opennl_unlock(void)
-{
- BLI_mutex_unlock(&opennl_context_mutex);
-}
-
-#endif
-
-
/* only called by BKE_modifier.h/modifier.c */
void modifier_type_init(ModifierTypeInfo *types[])
{
diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h
index b74ff9c2a25..095d7c278df 100644
--- a/source/blender/modifiers/intern/MOD_util.h
+++ b/source/blender/modifiers/intern/MOD_util.h
@@ -52,21 +52,4 @@ struct DerivedMesh *get_dm_for_modifier(struct Object *ob, ModifierApplyFlag fla
void modifier_get_vgroup(struct Object *ob, struct DerivedMesh *dm,
const char *name, struct MDeformVert **dvert, int *defgrp_index);
-/* XXX workaround for non-threadsafe context in OpenNL (T38403)
- * OpenNL uses global pointer for "current context", which causes
- * conflict when multiple modifiers get evaluated in threaded depgraph.
- * This is just a stupid hack to prevent assert failure / crash,
- * otherwise we'd have to modify OpenNL on a large scale.
- * OpenNL should be replaced eventually, there are other options (eigen, ceres).
- * - lukas_t
- */
-#ifdef WITH_OPENNL
-#define OPENNL_THREADING_HACK
-#endif
-
-#ifdef OPENNL_THREADING_HACK
-void modifier_opennl_lock(void);
-void modifier_opennl_unlock(void);
-#endif
-
#endif /* __MOD_UTIL_H__ */
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 51c6f5cab3c..0a73a187161 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -33,6 +33,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rand.h"
+#include "BLI_task.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -52,7 +53,7 @@
#include "MEM_guardedalloc.h"
#include "MOD_weightvg_util.h"
-// #define USE_TIMEIT
+//#define USE_TIMEIT
#ifdef USE_TIMEIT
# include "PIL_time.h"
@@ -66,6 +67,67 @@
/* Util macro. */
#define OUT_OF_MEMORY() ((void)printf("WeightVGProximity: Out of memory.\n"))
+typedef struct Vert2GeomData {
+ /* Read-only data */
+ float (*v_cos)[3];
+
+ const SpaceTransform *loc2trgt;
+
+ BVHTreeFromMesh *treeData[3];
+
+ /* Write data, but not needing locking (two different threads will never write same index). */
+ float *dist[3];
+} Vert2GeomData;
+
+/* Data which is localized to each computed chunk (i.e. thread-safe, and with continous subset of index range). */
+typedef struct Vert2GeomDataChunk {
+ /* Read-only data */
+ float last_hit_co[3][3];
+ bool is_init[3];
+} Vert2GeomDataChunk;
+
+/**
+ * Callback used by BLI_task 'for loop' helper.
+ */
+static void vert2geom_task_cb(void *userdata, void *userdata_chunk, int iter)
+{
+ Vert2GeomData *data = userdata;
+ Vert2GeomDataChunk *data_chunk = userdata_chunk;
+
+ float tmp_co[3];
+ int i;
+
+ /* Convert the vertex to tree coordinates. */
+ copy_v3_v3(tmp_co, data->v_cos[iter]);
+ BLI_space_transform_apply(data->loc2trgt, tmp_co);
+
+ for (i = 0; i < ARRAY_SIZE(data->dist); i++) {
+ if (data->dist[i]) {
+ BVHTreeNearest nearest = {0};
+
+ /* Note that we use local proximity heuristics (to reduce the nearest search).
+ *
+ * If we already had an hit before in same chunk of tasks (i.e. previous vertex by index),
+ * we assume this vertex is going to have a close hit to that other vertex, so we can initiate
+ * the "nearest.dist" with the expected value to that last hit.
+ * This will lead in pruning of the search tree.
+ */
+ nearest.dist_sq = data_chunk->is_init[i] ? len_squared_v3v3(tmp_co, data_chunk->last_hit_co[i]) : FLT_MAX;
+ nearest.index = -1;
+
+ /* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */
+ BLI_bvhtree_find_nearest(data->treeData[i]->tree, tmp_co, &nearest,
+ data->treeData[i]->nearest_callback, data->treeData[i]);
+ data->dist[i][iter] = sqrtf(nearest.dist_sq);
+
+ if (nearest.index != -1) {
+ copy_v3_v3(data_chunk->last_hit_co[i], nearest.co);
+ data_chunk->is_init[i] = true;
+ }
+ }
+ }
+}
+
/**
* Find nearest vertex and/or edge and/or face, for each vertex (adapted from shrinkwrap.c).
*/
@@ -73,13 +135,12 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
float *dist_v, float *dist_e, float *dist_f,
DerivedMesh *target, const SpaceTransform *loc2trgt)
{
- int i;
+ Vert2GeomData data = {0};
+ Vert2GeomDataChunk data_chunk = {{{0}}};
+
BVHTreeFromMesh treeData_v = {NULL};
BVHTreeFromMesh treeData_e = {NULL};
BVHTreeFromMesh treeData_f = {NULL};
- BVHTreeNearest nearest_v = {0};
- BVHTreeNearest nearest_e = {0};
- BVHTreeNearest nearest_f = {0};
if (dist_v) {
/* Create a bvh-tree of the given target's verts. */
@@ -106,45 +167,16 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
}
}
- /* Setup nearest. */
- nearest_v.index = nearest_e.index = nearest_f.index = -1;
- /*nearest_v.dist = nearest_e.dist = nearest_f.dist = FLT_MAX;*/
- /* Find the nearest vert/edge/face. */
-#pragma omp parallel for default(shared) private(i) firstprivate(nearest_v, nearest_e, nearest_f) \
- schedule(static) if (numVerts > 10000)
- for (i = 0; i < numVerts; i++) {
- float tmp_co[3];
-
- /* Convert the vertex to tree coordinates. */
- copy_v3_v3(tmp_co, v_cos[i]);
- BLI_space_transform_apply(loc2trgt, tmp_co);
-
- /* Use local proximity heuristics (to reduce the nearest search).
- *
- * If we already had an hit before, we assume this vertex is going to have a close hit to
- * that other vertex, so we can initiate the "nearest.dist" with the expected value to that
- * last hit.
- * This will lead in pruning of the search tree.
- */
- if (dist_v) {
- nearest_v.dist_sq = nearest_v.index != -1 ? len_squared_v3v3(tmp_co, nearest_v.co) : FLT_MAX;
- /* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */
- BLI_bvhtree_find_nearest(treeData_v.tree, tmp_co, &nearest_v, treeData_v.nearest_callback, &treeData_v);
- dist_v[i] = sqrtf(nearest_v.dist_sq);
- }
- if (dist_e) {
- nearest_e.dist_sq = nearest_e.index != -1 ? len_squared_v3v3(tmp_co, nearest_e.co) : FLT_MAX;
- /* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */
- BLI_bvhtree_find_nearest(treeData_e.tree, tmp_co, &nearest_e, treeData_e.nearest_callback, &treeData_e);
- dist_e[i] = sqrtf(nearest_e.dist_sq);
- }
- if (dist_f) {
- nearest_f.dist_sq = nearest_f.index != -1 ? len_squared_v3v3(tmp_co, nearest_f.co) : FLT_MAX;
- /* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */
- BLI_bvhtree_find_nearest(treeData_f.tree, tmp_co, &nearest_f, treeData_f.nearest_callback, &treeData_f);
- dist_f[i] = sqrtf(nearest_f.dist_sq);
- }
- }
+ data.v_cos = v_cos;
+ data.loc2trgt = loc2trgt;
+ data.treeData[0] = &treeData_v;
+ data.treeData[1] = &treeData_e;
+ data.treeData[2] = &treeData_f;
+ data.dist[0] = dist_v;
+ data.dist[1] = dist_e;
+ data.dist[2] = dist_f;
+
+ BLI_task_parallel_range_ex(0, numVerts, &data, &data_chunk, sizeof(data_chunk), vert2geom_task_cb, 10000, false);
if (dist_v)
free_bvhtree_from_mesh(&treeData_v);
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
index bbfb07a316d..c6b1d37f8b4 100644
--- a/source/blender/nodes/composite/node_composite_util.c
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -55,5 +55,6 @@ void cmp_node_type_base(bNodeType *ntype, int type, const char *name, short ncla
ntype->poll = cmp_node_poll_default;
ntype->updatefunc = cmp_node_update_default;
+ ntype->insert_link = node_insert_link_default;
ntype->update_internal_links = node_update_internal_links_default;
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c
index 75e7fa8fbac..0fbbb54ee7a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_common.c
+++ b/source/blender/nodes/composite/nodes/node_composite_common.c
@@ -51,6 +51,7 @@ void register_node_type_cmp_group(void)
ntype.type = NODE_GROUP;
ntype.poll = cmp_node_poll_default;
ntype.poll_instance = node_group_poll_instance;
+ ntype.insert_link = node_insert_link_default;
ntype.update_internal_links = node_update_internal_links_default;
ntype.ext.srna = RNA_struct_find("CompositorNodeGroup");
BLI_assert(ntype.ext.srna != NULL);
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index 3a301f55487..dd5715891d5 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -29,6 +29,7 @@
* \ingroup nodes
*/
+#include <ctype.h>
#include <limits.h>
#include <string.h>
@@ -112,6 +113,95 @@ void node_filter_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int m
}
+/*** Link Insertion ***/
+
+/* test if two sockets are interchangeable */
+static bool node_link_socket_match(bNodeSocket *a, bNodeSocket *b)
+{
+ /* tests if alphabetic prefix matches
+ * this allows for imperfect matches, such as numeric suffixes,
+ * like Color1/Color2
+ */
+ int prefix_len = 0;
+ char *ca = a->name, *cb = b->name;
+ for (; *ca != '\0' && *cb != '\0'; ++ca, ++cb) {
+ /* end of common prefix? */
+ if (*ca != *cb) {
+ /* prefix delimited by non-alphabetic char */
+ if (isalpha(*ca) || isalpha(*cb))
+ return false;
+ break;
+ }
+ ++prefix_len;
+ }
+ return prefix_len > 0;
+}
+
+static int node_count_links(bNodeTree *ntree, bNodeSocket *sock)
+{
+ bNodeLink *link;
+ int count = 0;
+ for (link = ntree->links.first; link; link = link->next) {
+ if (link->fromsock == sock)
+ ++count;
+ if (link->tosock == sock)
+ ++count;
+ }
+ return count;
+}
+
+/* find an eligible socket for linking */
+static bNodeSocket *node_find_linkable_socket(bNodeTree *ntree, bNode *node, bNodeSocket *cur)
+{
+ /* link swapping: try to find a free slot with a matching name */
+
+ bNodeSocket *first = cur->in_out == SOCK_IN ? node->inputs.first : node->outputs.first;
+ bNodeSocket *sock;
+
+ sock = cur->next ? cur->next : first; /* wrap around the list end */
+ while (sock != cur) {
+ if (!nodeSocketIsHidden(sock) && node_link_socket_match(sock, cur)) {
+ int link_count = node_count_links(ntree, sock);
+ /* take +1 into account since we would add a new link */
+ if (link_count + 1 <= sock->limit)
+ return sock; /* found a valid free socket we can swap to */
+ }
+
+ sock = sock->next ? sock->next : first; /* wrap around the list end */
+ }
+ return NULL;
+}
+
+void node_insert_link_default(bNodeTree *ntree, bNode *node, bNodeLink *link)
+{
+ bNodeSocket *sock = link->tosock;
+ bNodeLink *tlink, *tlink_next;
+
+ /* inputs can have one link only, outputs can have unlimited links */
+ if (node != link->tonode)
+ return;
+
+ for (tlink = ntree->links.first; tlink; tlink = tlink_next) {
+ bNodeSocket *new_sock;
+ tlink_next = tlink->next;
+
+ if (sock != tlink->tosock)
+ continue;
+
+ new_sock = node_find_linkable_socket(ntree, node, sock);
+ if (new_sock && new_sock != sock) {
+ /* redirect existing link */
+ tlink->tosock = new_sock;
+ }
+ else if (!new_sock) {
+ /* no possible replacement, remove tlink */
+ nodeRemLink(ntree, tlink);
+ tlink = NULL;
+ }
+ }
+}
+
+
/**** Internal Links (mute and disconnect) ****/
/* common datatype priorities, works for compositor, shader and texture nodes alike
diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h
index 64b2028874b..2e20a8e79d4 100644
--- a/source/blender/nodes/intern/node_util.h
+++ b/source/blender/nodes/intern/node_util.h
@@ -76,6 +76,9 @@ void node_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, i
void node_vect_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
void node_filter_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
+
+/*** Link Handling */
+void node_insert_link_default(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
void node_update_internal_links_default(struct bNodeTree *ntree, struct bNode *node);
float node_socket_get_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 92b244bae55..9bd43f331fb 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -47,6 +47,7 @@ void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, shor
node_type_base(ntype, type, name, nclass, flag);
ntype->poll = sh_node_poll_default;
+ ntype->insert_link = node_insert_link_default;
ntype->update_internal_links = node_update_internal_links_default;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c
index 7ff60ac716a..796193a564e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_common.c
+++ b/source/blender/nodes/shader/nodes/node_shader_common.c
@@ -236,6 +236,7 @@ void register_node_type_sh_group(void)
ntype.type = NODE_GROUP;
ntype.poll = sh_node_poll_default;
ntype.poll_instance = node_group_poll_instance;
+ ntype.insert_link = node_insert_link_default;
ntype.update_internal_links = node_update_internal_links_default;
ntype.ext.srna = RNA_struct_find("ShaderNodeGroup");
BLI_assert(ntype.ext.srna != NULL);
diff --git a/source/blender/nodes/texture/node_texture_util.c b/source/blender/nodes/texture/node_texture_util.c
index 42c684b8247..32720364f73 100644
--- a/source/blender/nodes/texture/node_texture_util.c
+++ b/source/blender/nodes/texture/node_texture_util.c
@@ -60,6 +60,7 @@ void tex_node_type_base(struct bNodeType *ntype, int type, const char *name, sho
node_type_base(ntype, type, name, nclass, flag);
ntype->poll = tex_node_poll_default;
+ ntype->insert_link = node_insert_link_default;
ntype->update_internal_links = node_update_internal_links_default;
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c
index 914f1ef5110..79a4c4e3a6b 100644
--- a/source/blender/nodes/texture/nodes/node_texture_common.c
+++ b/source/blender/nodes/texture/nodes/node_texture_common.c
@@ -166,6 +166,7 @@ void register_node_type_tex_group(void)
ntype.type = NODE_GROUP;
ntype.poll = tex_node_poll_default;
ntype.poll_instance = node_group_poll_instance;
+ ntype.insert_link = node_insert_link_default;
ntype.update_internal_links = node_update_internal_links_default;
ntype.ext.srna = RNA_struct_find("TextureNodeGroup");
BLI_assert(ntype.ext.srna != NULL);
diff --git a/source/blender/physics/CMakeLists.txt b/source/blender/physics/CMakeLists.txt
index 08ff1faca49..0a4ff3fe0f0 100644
--- a/source/blender/physics/CMakeLists.txt
+++ b/source/blender/physics/CMakeLists.txt
@@ -31,11 +31,10 @@ set(INC
../imbuf
../makesdna
../../../intern/guardedalloc
- ../../../extern/Eigen3
)
set(INC_SYS
-
+ ${EIGEN3_INCLUDE_DIRS}
)
set(SRC
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index e833dba04c8..89c3ed2460e 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -38,8 +38,10 @@
#include "python_utildefines.h"
+#ifndef MATH_STANDALONE
/* only for BLI_strncpy_wchar_from_utf8, should replace with py funcs but too late in release now */
#include "BLI_string_utf8.h"
+#endif
#ifdef _WIN32
#include "BLI_path_util.h" /* BLI_setenv() */
@@ -199,6 +201,27 @@ void PyC_List_Fill(PyObject *list, PyObject *value)
}
}
+/**
+ * Use with PyArg_ParseTuple's "O&" formatting.
+ */
+int PyC_ParseBool(PyObject *o, void *p)
+{
+ bool *bool_p = p;
+ long value;
+ if (((value = PyLong_AsLong(o)) == -1) || !ELEM(value, 0, 1)) {
+ PyErr_Format(PyExc_ValueError,
+ "expected a bool or int (0/1), got %s",
+ Py_TYPE(o)->tp_name);
+ return 0;
+ }
+
+ *bool_p = value ? true : false;
+ return 1;
+}
+
+
+#ifndef MATH_STANDALONE
+
/* for debugging */
void PyC_ObSpit(const char *name, PyObject *var)
{
@@ -533,15 +556,6 @@ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
if (PyBytes_Check(py_str)) {
return PyBytes_AS_STRING(py_str);
}
-#ifdef WIN32
- /* bug [#31856] oddly enough, Python3.2 --> 3.3 on Windows will throw an
- * exception here this needs to be fixed in python:
- * see: bugs.python.org/issue15859 */
- else if (!PyUnicode_Check(py_str)) {
- PyErr_BadArgument();
- return NULL;
- }
-#endif
else if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) {
return PyBytes_AS_STRING(*coerce);
}
@@ -710,7 +724,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...)
}
if (ret == NULL) {
- printf("PyC_InlineRun error, line:%d\n", __LINE__);
+ printf("%s error, line:%d\n", __func__, __LINE__);
PyErr_Print();
PyErr_Clear();
@@ -784,7 +798,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...)
Py_DECREF(ret);
}
else {
- printf("PyC_InlineRun error on arg '%d', line:%d\n", i, __LINE__);
+ printf("%s error on arg '%d', line:%d\n", __func__, i, __LINE__);
PyC_ObSpit("failed converting:", item_new);
PyErr_Print();
PyErr_Clear();
@@ -795,11 +809,11 @@ void PyC_RunQuicky(const char *filepath, int n, ...)
va_end(vargs);
}
else {
- printf("PyC_InlineRun error, 'values' not a list, line:%d\n", __LINE__);
+ printf("%s error, 'values' not a list, line:%d\n", __func__, __LINE__);
}
}
else {
- printf("PyC_InlineRun error line:%d\n", __LINE__);
+ printf("%s error line:%d\n", __func__, __LINE__);
PyErr_Print();
PyErr_Clear();
}
@@ -1025,20 +1039,4 @@ int PyC_RunString_AsNumber(const char *expr, double *value, const char *filename
return error_ret;
}
-/**
- * Use with PyArg_ParseTuple's "O&" formatting.
- */
-int PyC_ParseBool(PyObject *o, void *p)
-{
- bool *bool_p = p;
- long value;
- if (((value = PyLong_AsLong(o)) == -1) || !ELEM(value, 0, 1)) {
- PyErr_Format(PyExc_ValueError,
- "expected a bool or int (0/1), got %s",
- Py_TYPE(o)->tp_name);
- return 0;
- }
-
- *bool_p = value ? true : false;
- return 1;
-}
+#endif /* #ifndef MATH_STANDALONE */
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index fa2ad3a4803..bdae2a7cb17 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -320,9 +320,6 @@ void BPy_init_modules(void)
/* needs to be first so bpy_types can run */
PyModule_AddObject(mod, "types", BPY_rna_types());
- /* metaclass for idprop types, bpy_types.py needs access */
- PyModule_AddObject(mod, "StructMetaPropGroup", (PyObject *)&pyrna_struct_meta_idprop_Type);
-
/* needs to be first so bpy_types can run */
BPY_library_module(mod);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 220ec5b6e8c..47d89cd43ae 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -6678,6 +6678,21 @@ PyObject *BPY_rna_types(void)
/* add __name__ since help() expects its */
PyDict_SetItem(pyrna_basetype_Type.tp_dict, bpy_intern_str___name__, bpy_intern_str_bpy_types);
+ /* internal base types we have no other accessors for */
+ {
+ PyTypeObject *pyrna_types[] = {
+ &pyrna_struct_meta_idprop_Type,
+ &pyrna_struct_Type,
+ &pyrna_prop_Type,
+ &pyrna_prop_array_Type,
+ &pyrna_prop_collection_Type,
+ &pyrna_func_Type,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(pyrna_types); i += 1) {
+ PyDict_SetItemString(pyrna_basetype_Type.tp_dict, pyrna_types[i]->tp_name, (PyObject *)pyrna_types[i]);
+ }
+ }
self = (BPy_BaseTypeRNA *)PyObject_NEW(BPy_BaseTypeRNA, &pyrna_basetype_Type);
diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h
index 1ae00a7fb02..63cb7920bd1 100644
--- a/source/blender/python/intern/bpy_util.h
+++ b/source/blender/python/intern/bpy_util.h
@@ -27,8 +27,8 @@
#ifndef __BPY_UTIL_H__
#define __BPY_UTIL_H__
-#if PY_VERSION_HEX < 0x03040000
-# error "Python 3.4 or greater is required, you'll need to update your python."
+#if PY_VERSION_HEX < 0x03050000
+# error "Python 3.5 or greater is required, you'll need to update your python."
#endif
struct EnumPropertyItem;
diff --git a/source/blender/python/intern/gpu_offscreen.c b/source/blender/python/intern/gpu_offscreen.c
index ed31ac052c6..c4863b2a92f 100644
--- a/source/blender/python/intern/gpu_offscreen.c
+++ b/source/blender/python/intern/gpu_offscreen.c
@@ -37,8 +37,8 @@
#include "ED_screen.h"
-#include "GPU_extensions.h"
#include "GPU_compositing.h"
+#include "GPU_framebuffer.h"
#include "../mathutils/mathutils.h"
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index 9deb57d6760..b3b9d4a86dc 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -328,7 +328,7 @@ static void py_bvhtree_nearest_point_cb(void *userdata, int index, const float c
}
PyDoc_STRVAR(py_bvhtree_ray_cast_doc,
-".. method:: ray_cast(co, direction, distance=sys.float_info.max)\n"
+".. method:: ray_cast(origin, direction, distance=sys.float_info.max)\n"
"\n"
" Cast a ray onto the mesh.\n"
"\n"
@@ -383,7 +383,7 @@ static PyObject *py_bvhtree_ray_cast(PyBVHTree *self, PyObject *args)
}
PyDoc_STRVAR(py_bvhtree_find_nearest_doc,
-".. method:: find_nearest(co, distance=" PYBVH_MAX_DIST_STR ")\n"
+".. method:: find_nearest(origin, distance=" PYBVH_MAX_DIST_STR ")\n"
"\n"
" Find the nearest element to a point.\n"
"\n"
diff --git a/source/blender/python/mathutils/mathutils_kdtree.c b/source/blender/python/mathutils/mathutils_kdtree.c
index 199c2e02da4..ca66c1906b4 100644
--- a/source/blender/python/mathutils/mathutils_kdtree.c
+++ b/source/blender/python/mathutils/mathutils_kdtree.c
@@ -104,7 +104,10 @@ static int PyKDTree__tp_init(PyKDTree *self, PyObject *args, PyObject *kwargs)
unsigned int maxsize;
const char *keywords[] = {"size", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "I:KDTree", (char **)keywords, &maxsize)) {
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwargs, "I:KDTree", (char **)keywords,
+ &maxsize))
+ {
return -1;
}
@@ -144,8 +147,9 @@ static PyObject *py_kdtree_insert(PyKDTree *self, PyObject *args, PyObject *kwar
int index;
const char *keywords[] = {"co", "index", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "Oi:insert", (char **)keywords,
- &py_co, &index))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwargs, (char *) "Oi:insert", (char **)keywords,
+ &py_co, &index))
{
return NULL;
}
@@ -185,25 +189,57 @@ static PyObject *py_kdtree_balance(PyKDTree *self)
Py_RETURN_NONE;
}
+struct PyKDTree_NearestData {
+ PyObject *py_filter;
+ bool is_error;
+};
+
+static int py_find_nearest_cb(void *user_data, int index, const float co[3], float dist_sq)
+{
+ UNUSED_VARS(co, dist_sq);
+
+ struct PyKDTree_NearestData *data = user_data;
+
+ PyObject *py_args = PyTuple_New(1);
+ PyTuple_SET_ITEM(py_args, 0, PyLong_FromLong(index));
+ PyObject *result = PyObject_CallObject(data->py_filter, py_args);
+ Py_DECREF(py_args);
+
+ if (result) {
+ bool use_node;
+ int ok = PyC_ParseBool(result, &use_node);
+ Py_DECREF(result);
+ if (ok) {
+ return (int)use_node;
+ }
+ }
+
+ data->is_error = true;
+ return -1;
+}
+
PyDoc_STRVAR(py_kdtree_find_doc,
-".. method:: find(co)\n"
+".. method:: find(co, filter=None)\n"
"\n"
" Find nearest point to ``co``.\n"
"\n"
" :arg co: 3d coordinates.\n"
" :type co: float triplet\n"
+" :arg filter: function which takes an index and returns True for indices to include in the search.\n"
+" :type filter: callable\n"
" :return: Returns (:class:`Vector`, index, distance).\n"
" :rtype: :class:`tuple`\n"
);
static PyObject *py_kdtree_find(PyKDTree *self, PyObject *args, PyObject *kwargs)
{
- PyObject *py_co;
+ PyObject *py_co, *py_filter = NULL;
float co[3];
KDTreeNearest nearest;
- const char *keywords[] = {"co", NULL};
+ const char *keywords[] = {"co", "filter", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "O:find", (char **)keywords,
- &py_co))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwargs, (char *) "O|O:find", (char **)keywords,
+ &py_co, &py_filter))
{
return NULL;
}
@@ -216,10 +252,26 @@ static PyObject *py_kdtree_find(PyKDTree *self, PyObject *args, PyObject *kwargs
return NULL;
}
-
nearest.index = -1;
- BLI_kdtree_find_nearest(self->obj, co, &nearest);
+ if (py_filter == NULL) {
+ BLI_kdtree_find_nearest(self->obj, co, &nearest);
+ }
+ else {
+ struct PyKDTree_NearestData data = {0};
+
+ data.py_filter = py_filter;
+ data.is_error = false;
+
+ BLI_kdtree_find_nearest_cb(
+ self->obj, co,
+ py_find_nearest_cb, &data,
+ &nearest);
+
+ if (data.is_error) {
+ return NULL;
+ }
+ }
return kdtree_nearest_to_py_and_check(&nearest);
}
@@ -246,8 +298,9 @@ static PyObject *py_kdtree_find_n(PyKDTree *self, PyObject *args, PyObject *kwar
int i, found;
const char *keywords[] = {"co", "n", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "OI:find_n", (char **)keywords,
- &py_co, &n))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwargs, (char *) "OI:find_n", (char **)keywords,
+ &py_co, &n))
{
return NULL;
}
@@ -303,8 +356,9 @@ static PyObject *py_kdtree_find_range(PyKDTree *self, PyObject *args, PyObject *
const char *keywords[] = {"co", "radius", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "Of:find_range", (char **)keywords,
- &py_co, &radius))
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwargs, (char *) "Of:find_range", (char **)keywords,
+ &py_co, &radius))
{
return NULL;
}
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index 85a9dc9fccd..81d1a00702d 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -63,6 +63,10 @@ void RE_sample_material_color(
struct PointDensity;
+void RE_cache_point_density(struct Scene *scene,
+ struct PointDensity *pd,
+ const bool use_render_params);
+
void RE_sample_point_density(struct Scene *scene,
struct PointDensity *pd,
const int resolution,
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 3ae93649ee2..64866509a0c 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -2832,6 +2832,8 @@ static bool check_valid_camera_multiview(Scene *scene, Object *camera, ReportLis
static int check_valid_camera(Scene *scene, Object *camera_override, ReportList *reports)
{
+ const char *err_msg = "No camera found in scene \"%s\"";
+
if (camera_override == NULL && scene->camera == NULL)
scene->camera = BKE_scene_camera_find(scene);
@@ -2843,14 +2845,17 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList
Sequence *seq = scene->ed->seqbase.first;
while (seq) {
- if (seq->type == SEQ_TYPE_SCENE && seq->scene) {
+ if ((seq->type == SEQ_TYPE_SCENE) &&
+ ((seq->flag & SEQ_SCENE_STRIPS) == 0) &&
+ (seq->scene != NULL))
+ {
if (!seq->scene_camera) {
if (!seq->scene->camera && !BKE_scene_camera_find(seq->scene)) {
/* camera could be unneeded due to composite nodes */
Object *override = (seq->scene == scene) ? camera_override : NULL;
if (!check_valid_compositing_camera(seq->scene, override)) {
- BKE_reportf(reports, RPT_ERROR, "No camera found in scene \"%s\"", seq->scene->id.name+2);
+ BKE_reportf(reports, RPT_ERROR, err_msg, seq->scene->id.name + 2);
return false;
}
}
@@ -2864,7 +2869,7 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList
}
}
else if (!check_valid_compositing_camera(scene, camera_override)) {
- BKE_report(reports, RPT_ERROR, "No camera found in scene");
+ BKE_reportf(reports, RPT_ERROR, err_msg, scene->id.name + 2);
return false;
}
@@ -3353,7 +3358,6 @@ bool RE_WriteRenderViewsMovie(
if (is_mono || (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)) {
int view_id;
for (view_id = 0; view_id < totvideos; view_id++) {
- bool do_free = false;
const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
ImBuf *ibuf = render_result_rect_to_ibuf(rr, &scene->r, view_id);
@@ -3363,12 +3367,6 @@ bool RE_WriteRenderViewsMovie(
ok &= mh->append_movie(movie_ctx_arr[view_id], rd, preview ? scene->r.psfra : scene->r.sfra, scene->r.cfra,
(int *) ibuf->rect, ibuf->x, ibuf->y, suffix, reports);
- if (do_free) {
- MEM_freeN(ibuf->rect);
- ibuf->rect = NULL;
- ibuf->mall &= ~IB_rect;
- }
-
/* imbuf knows which rects are not part of ibuf */
IMB_freeImBuf(ibuf);
}
@@ -3377,7 +3375,6 @@ bool RE_WriteRenderViewsMovie(
else { /* R_IMF_VIEWS_STEREO_3D */
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
ImBuf *ibuf_arr[3] = {NULL};
- bool do_free[2] = {false, false};
int i;
BLI_assert((totvideos == 1) && (scene->r.im_format.views_format == R_IMF_VIEWS_STEREO_3D));
@@ -3396,12 +3393,6 @@ bool RE_WriteRenderViewsMovie(
ibuf_arr[2]->x, ibuf_arr[2]->y, "", reports);
for (i = 0; i < 2; i++) {
- if (do_free[i]) {
- MEM_freeN(ibuf_arr[i]->rect);
- ibuf_arr[i]->rect = NULL;
- ibuf_arr[i]->mall &= ~IB_rect;
- }
-
/* imbuf knows which rects are not part of ibuf */
IMB_freeImBuf(ibuf_arr[i]);
}
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index 9b58bde730a..4028d80fd86 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -715,6 +715,21 @@ static void particle_system_minmax(Scene *scene,
}
}
+void RE_cache_point_density(Scene *scene,
+ PointDensity *pd,
+ const bool use_render_params)
+{
+ float mat[4][4];
+ /* Same matricies/resolution as dupli_render_particle_set(). */
+ unit_m4(mat);
+ BLI_mutex_lock(&sample_mutex);
+ cache_pointdensity_ex(scene, pd, mat, mat, 1, 1, use_render_params);
+ BLI_mutex_unlock(&sample_mutex);
+}
+
+/* NOTE 1: Requires RE_cache_point_density() to be called first.
+ * NOTE 2: Frees point density structure after sampling.
+ */
void RE_sample_point_density(Scene *scene,
PointDensity *pd,
const int resolution,
@@ -724,7 +739,11 @@ void RE_sample_point_density(Scene *scene,
const size_t resolution2 = resolution * resolution;
Object *object = pd->object;
size_t x, y, z;
- float min[3], max[3], dim[3], mat[4][4];
+ float min[3], max[3], dim[3];
+
+ /* TODO(sergey): Implement some sort of assert() that point density
+ * was cached already.
+ */
if (object == NULL) {
sample_dummy_point_density(resolution, values);
@@ -766,11 +785,7 @@ void RE_sample_point_density(Scene *scene,
return;
}
- /* Same matricies/resolution as dupli_render_particle_set(). */
- unit_m4(mat);
-
BLI_mutex_lock(&sample_mutex);
- cache_pointdensity_ex(scene, pd, mat, mat, 1, 1, use_render_params);
for (z = 0; z < resolution; ++z) {
for (y = 0; y < resolution; ++y) {
for (x = 0; x < resolution; ++x) {
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index 28a8340cd92..079ade0fbe3 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -110,7 +110,7 @@ const char *WM_key_event_string(const short type, const bool compact);
int WM_keymap_item_raw_to_string(
const short shift, const short ctrl, const short alt, const short oskey, const short keymodifier,
const short val, const short type, const bool compact, const int len, char *r_str);
-int WM_key_event_operator_id(
+wmKeyMapItem *WM_key_event_operator(
const struct bContext *C, const char *opname, int opcontext,
struct IDProperty *properties, const bool is_hotkey,
struct wmKeyMap **r_keymap);
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 6ad0405c56f..8ace4ee19fb 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -355,67 +355,15 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
}
}
-#if 0
-/******************** draw damage ************************/
-/* - not implemented */
-
-static void wm_method_draw_damage(bContext *C, wmWindow *win)
-{
- wm_method_draw_all(C, win);
-}
-#endif
-
/****************** draw triple buffer ********************/
/* - area regions are written into a texture, without any */
/* of the overlapping menus, brushes, gestures. these */
/* are redrawn each time. */
-/* */
-/* - if non-power of two textures are supported, that is */
-/* used. if not, multiple smaller ones are used, with */
-/* worst case wasted space being 23.4% for 3x3 textures */
-
-static void split_width(int x, int n, int *splitx, int *nx)
-{
- int a, newnx, waste;
-
- /* if already power of two just use it */
- if (is_power_of_2_i(x)) {
- splitx[0] = x;
- (*nx)++;
- return;
- }
-
- if (n == 1) {
- /* last part, we have to go larger */
- splitx[0] = power_of_2_max_i(x);
- (*nx)++;
- }
- else {
- /* two or more parts to go, use smaller part */
- splitx[0] = power_of_2_min_i(x);
- newnx = ++(*nx);
- split_width(x - splitx[0], n - 1, splitx + 1, &newnx);
-
- for (waste = 0, a = 0; a < n; a++)
- waste += splitx[a];
-
- /* if we waste more space or use the same amount,
- * revert deeper splits and just use larger */
- if (waste >= power_of_2_max_i(x)) {
- splitx[0] = power_of_2_max_i(x);
- memset(splitx + 1, 0, sizeof(int) * (n - 1));
- }
- else
- *nx = newnx;
- }
-}
static void wm_draw_triple_free(wmDrawTriple *triple)
{
if (triple) {
-
- glDeleteTextures(triple->nx * triple->ny, triple->bind);
-
+ glDeleteTextures(1, &triple->bind);
MEM_freeN(triple);
}
}
@@ -434,68 +382,49 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
const int winsize_y = WM_window_pixels_y(win);
GLint maxsize;
- int x, y;
/* compute texture sizes */
if (GLEW_ARB_texture_rectangle || GLEW_NV_texture_rectangle || GLEW_EXT_texture_rectangle) {
triple->target = GL_TEXTURE_RECTANGLE_ARB;
- triple->nx = 1;
- triple->ny = 1;
- triple->x[0] = winsize_x;
- triple->y[0] = winsize_y;
- }
- else if (GPU_non_power_of_two_support()) {
- triple->target = GL_TEXTURE_2D;
- triple->nx = 1;
- triple->ny = 1;
- triple->x[0] = winsize_x;
- triple->y[0] = winsize_y;
}
else {
triple->target = GL_TEXTURE_2D;
- triple->nx = 0;
- triple->ny = 0;
- split_width(winsize_x, MAX_N_TEX, triple->x, &triple->nx);
- split_width(winsize_y, MAX_N_TEX, triple->y, &triple->ny);
}
+ triple->x = winsize_x;
+ triple->y = winsize_y;
+
/* generate texture names */
- glGenTextures(triple->nx * triple->ny, triple->bind);
+ glGenTextures(1, &triple->bind);
- if (!triple->bind[0]) {
+ if (!triple->bind) {
/* not the typical failure case but we handle it anyway */
printf("WM: failed to allocate texture for triple buffer drawing (glGenTextures).\n");
return 0;
}
- for (y = 0; y < triple->ny; y++) {
- for (x = 0; x < triple->nx; x++) {
- /* proxy texture is only guaranteed to test for the cases that
- * there is only one texture in use, which may not be the case */
- maxsize = GPU_max_texture_size();
-
- if (triple->x[x] > maxsize || triple->y[y] > maxsize) {
- glBindTexture(triple->target, 0);
- printf("WM: failed to allocate texture for triple buffer drawing "
- "(texture too large for graphics card).\n");
- return 0;
- }
+ /* proxy texture is only guaranteed to test for the cases that
+ * there is only one texture in use, which may not be the case */
+ maxsize = GPU_max_texture_size();
- /* setup actual texture */
- glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
- glTexImage2D(triple->target, 0, GL_RGB8, triple->x[x], triple->y[y], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
- glTexParameteri(triple->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- /* The current color is ignored if the GL_REPLACE texture environment is used. */
- // glTexEnvi(triple->target, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glBindTexture(triple->target, 0);
-
- /* not sure if this works everywhere .. */
- if (glGetError() == GL_OUT_OF_MEMORY) {
- printf("WM: failed to allocate texture for triple buffer drawing (out of memory).\n");
- return 0;
- }
- }
+ if (triple->x > maxsize || triple->y > maxsize) {
+ glBindTexture(triple->target, 0);
+ printf("WM: failed to allocate texture for triple buffer drawing "
+ "(texture too large for graphics card).\n");
+ return 0;
+ }
+
+ /* setup actual texture */
+ glBindTexture(triple->target, triple->bind);
+ glTexImage2D(triple->target, 0, GL_RGB8, triple->x, triple->y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(triple->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glBindTexture(triple->target, 0);
+
+ /* not sure if this works everywhere .. */
+ if (glGetError() == GL_OUT_OF_MEMORY) {
+ printf("WM: failed to allocate texture for triple buffer drawing (out of memory).\n");
+ return 0;
}
return 1;
@@ -503,51 +432,43 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
{
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
+ const int sizex = WM_window_pixels_x(win);
+ const int sizey = WM_window_pixels_y(win);
float halfx, halfy, ratiox, ratioy;
- int x, y, sizex, sizey, offx, offy;
glEnable(triple->target);
- for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) {
- for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) {
- sizex = (x == triple->nx - 1) ? winsize_x - offx : triple->x[x];
- sizey = (y == triple->ny - 1) ? winsize_y - offy : triple->y[y];
-
- /* wmOrtho for the screen has this same offset */
- ratiox = sizex;
- ratioy = sizey;
- halfx = GLA_PIXEL_OFS;
- halfy = GLA_PIXEL_OFS;
-
- /* texture rectangle has unnormalized coordinates */
- if (triple->target == GL_TEXTURE_2D) {
- ratiox /= triple->x[x];
- ratioy /= triple->y[y];
- halfx /= triple->x[x];
- halfy /= triple->y[y];
- }
+ /* wmOrtho for the screen has this same offset */
+ ratiox = sizex;
+ ratioy = sizey;
+ halfx = GLA_PIXEL_OFS;
+ halfy = GLA_PIXEL_OFS;
+
+ /* texture rectangle has unnormalized coordinates */
+ if (triple->target == GL_TEXTURE_2D) {
+ ratiox /= triple->x;
+ ratioy /= triple->y;
+ halfx /= triple->x;
+ halfy /= triple->y;
+ }
- glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
+ glBindTexture(triple->target, triple->bind);
- glColor4f(1.0f, 1.0f, 1.0f, alpha);
- glBegin(GL_QUADS);
- glTexCoord2f(halfx, halfy);
- glVertex2f(offx, offy);
+ glColor4f(1.0f, 1.0f, 1.0f, alpha);
+ glBegin(GL_QUADS);
+ glTexCoord2f(halfx, halfy);
+ glVertex2f(0, 0);
- glTexCoord2f(ratiox + halfx, halfy);
- glVertex2f(offx + sizex, offy);
+ glTexCoord2f(ratiox + halfx, halfy);
+ glVertex2f(sizex, 0);
- glTexCoord2f(ratiox + halfx, ratioy + halfy);
- glVertex2f(offx + sizex, offy + sizey);
+ glTexCoord2f(ratiox + halfx, ratioy + halfy);
+ glVertex2f(sizex, sizey);
- glTexCoord2f(halfx, ratioy + halfy);
- glVertex2f(offx, offy + sizey);
- glEnd();
- }
- }
+ glTexCoord2f(halfx, ratioy + halfy);
+ glVertex2f(0, sizey);
+ glEnd();
glBindTexture(triple->target, 0);
glDisable(triple->target);
@@ -555,20 +476,11 @@ void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
{
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
-
- int x, y, sizex, sizey, offx, offy;
-
- for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) {
- for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) {
- sizex = (x == triple->nx - 1) ? winsize_x - offx : triple->x[x];
- sizey = (y == triple->ny - 1) ? winsize_y - offy : triple->y[y];
+ const int sizex = WM_window_pixels_x(win);
+ const int sizey = WM_window_pixels_y(win);
- glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
- glCopyTexSubImage2D(triple->target, 0, 0, 0, offx, offy, sizex, sizey);
- }
- }
+ glBindTexture(triple->target, triple->bind);
+ glCopyTexSubImage2D(triple->target, 0, 0, 0, 0, 0, sizex, sizey);
glBindTexture(triple->target, 0);
}
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index a643e1c632a..72b26cc6207 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -1301,17 +1301,12 @@ char *WM_key_event_operator_string(
return NULL;
}
-int WM_key_event_operator_id(
+wmKeyMapItem *WM_key_event_operator(
const bContext *C, const char *opname, int opcontext,
IDProperty *properties, const bool is_hotkey,
wmKeyMap **r_keymap)
{
- wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, is_hotkey, true, r_keymap);
-
- if (kmi)
- return kmi->id;
- else
- return 0;
+ return wm_keymap_item_find(C, opname, opcontext, properties, is_hotkey, true, r_keymap);
}
int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2)
@@ -1867,7 +1862,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
break;
case SPACE_IMAGE:
- km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
+ km = WM_keymap_find_all(C, "UV Editor", 0, 0);
break;
case SPACE_NODE:
km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 3734b5ab530..a4a56345798 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -105,6 +105,7 @@
#include "ED_util.h"
#include "ED_view3d.h"
+#include "GPU_basic_shader.h"
#include "GPU_material.h"
#include "RNA_access.h"
@@ -4144,7 +4145,7 @@ static void radial_control_set_tex(RadialControl *rc)
if ((ibuf = BKE_brush_gen_radial_control_imbuf(rc->image_id_ptr.data, rc->use_secondary_tex))) {
glGenTextures(1, &rc->gltex);
glBindTexture(GL_TEXTURE_2D, rc->gltex);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ibuf->x, ibuf->y, 0,
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, ibuf->x, ibuf->y, 0,
GL_ALPHA, GL_FLOAT, ibuf->rect_float);
MEM_freeN(ibuf->rect_float);
MEM_freeN(ibuf);
@@ -4179,7 +4180,7 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
}
/* draw textured quad */
- glEnable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-radius, -radius);
@@ -4190,7 +4191,7 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
glTexCoord2f(0, 1);
glVertex2f(-radius, radius);
glEnd();
- glDisable(GL_TEXTURE_2D);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
/* undo rotation */
if (rc->rot_prop)
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
index 98c45bfb6ea..21fc7f2b5b2 100644
--- a/source/blender/windowmanager/intern/wm_stereo.c
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -195,7 +195,6 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
wmDrawData *drawdata;
wmDrawTriple *triple;
float halfx, halfy, ratiox, ratioy;
- int x, y, offx, offy;
float alpha = 1.0f;
int view;
int soffx;
@@ -217,44 +216,40 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
glEnable(triple->target);
- for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) {
- for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) {
- const int sizex = triple->x[x];
- const int sizey = triple->y[y];
-
- /* wmOrtho for the screen has this same offset */
- ratiox = sizex;
- ratioy = sizey;
- halfx = GLA_PIXEL_OFS;
- halfy = GLA_PIXEL_OFS;
-
- /* texture rectangle has unnormalized coordinates */
- if (triple->target == GL_TEXTURE_2D) {
- ratiox /= triple->x[x];
- ratioy /= triple->y[y];
- halfx /= triple->x[x];
- halfy /= triple->y[y];
- }
-
- glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
-
- glColor4f(1.0f, 1.0f, 1.0f, alpha);
- glBegin(GL_QUADS);
- glTexCoord2f(halfx, halfy);
- glVertex2f(soffx + (offx * 0.5f), offy);
-
- glTexCoord2f(ratiox + halfx, halfy);
- glVertex2f(soffx + ((offx + sizex) * 0.5f), offy);
-
- glTexCoord2f(ratiox + halfx, ratioy + halfy);
- glVertex2f(soffx + ((offx + sizex) * 0.5f), offy + sizey);
-
- glTexCoord2f(halfx, ratioy + halfy);
- glVertex2f(soffx + (offx * 0.5f), offy + sizey);
- glEnd();
- }
+ const int sizex = triple->x;
+ const int sizey = triple->y;
+
+ /* wmOrtho for the screen has this same offset */
+ ratiox = sizex;
+ ratioy = sizey;
+ halfx = GLA_PIXEL_OFS;
+ halfy = GLA_PIXEL_OFS;
+
+ /* texture rectangle has unnormalized coordinates */
+ if (triple->target == GL_TEXTURE_2D) {
+ ratiox /= triple->x;
+ ratioy /= triple->y;
+ halfx /= triple->x;
+ halfy /= triple->y;
}
+ glBindTexture(triple->target, triple->bind);
+
+ glColor4f(1.0f, 1.0f, 1.0f, alpha);
+ glBegin(GL_QUADS);
+ glTexCoord2f(halfx, halfy);
+ glVertex2f(soffx, 0);
+
+ glTexCoord2f(ratiox + halfx, halfy);
+ glVertex2f(soffx + (sizex * 0.5f), 0);
+
+ glTexCoord2f(ratiox + halfx, ratioy + halfy);
+ glVertex2f(soffx + (sizex * 0.5f), sizey);
+
+ glTexCoord2f(halfx, ratioy + halfy);
+ glVertex2f(soffx, sizey);
+ glEnd();
+
glBindTexture(triple->target, 0);
glDisable(triple->target);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -266,7 +261,6 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
wmDrawData *drawdata;
wmDrawTriple *triple;
float halfx, halfy, ratiox, ratioy;
- int x, y, offx, offy;
float alpha = 1.0f;
int view;
int soffy;
@@ -284,44 +278,40 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
glEnable(triple->target);
- for (y = 0, offy = 0; y < triple->ny; offy += triple->y[y], y++) {
- for (x = 0, offx = 0; x < triple->nx; offx += triple->x[x], x++) {
- const int sizex = triple->x[x];
- const int sizey = triple->y[y];
-
- /* wmOrtho for the screen has this same offset */
- ratiox = sizex;
- ratioy = sizey;
- halfx = GLA_PIXEL_OFS;
- halfy = GLA_PIXEL_OFS;
-
- /* texture rectangle has unnormalized coordinates */
- if (triple->target == GL_TEXTURE_2D) {
- ratiox /= triple->x[x];
- ratioy /= triple->y[y];
- halfx /= triple->x[x];
- halfy /= triple->y[y];
- }
-
- glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
-
- glColor4f(1.0f, 1.0f, 1.0f, alpha);
- glBegin(GL_QUADS);
- glTexCoord2f(halfx, halfy);
- glVertex2f(offx, soffy + (offy * 0.5f));
-
- glTexCoord2f(ratiox + halfx, halfy);
- glVertex2f(offx + sizex, soffy + (offy * 0.5f));
-
- glTexCoord2f(ratiox + halfx, ratioy + halfy);
- glVertex2f(offx + sizex, soffy + ((offy + sizey) * 0.5f));
-
- glTexCoord2f(halfx, ratioy + halfy);
- glVertex2f(offx, soffy + ((offy + sizey) * 0.5f));
- glEnd();
- }
+ const int sizex = triple->x;
+ const int sizey = triple->y;
+
+ /* wmOrtho for the screen has this same offset */
+ ratiox = sizex;
+ ratioy = sizey;
+ halfx = GLA_PIXEL_OFS;
+ halfy = GLA_PIXEL_OFS;
+
+ /* texture rectangle has unnormalized coordinates */
+ if (triple->target == GL_TEXTURE_2D) {
+ ratiox /= triple->x;
+ ratioy /= triple->y;
+ halfx /= triple->x;
+ halfy /= triple->y;
}
+ glBindTexture(triple->target, triple->bind);
+
+ glColor4f(1.0f, 1.0f, 1.0f, alpha);
+ glBegin(GL_QUADS);
+ glTexCoord2f(halfx, halfy);
+ glVertex2f(0, soffy);
+
+ glTexCoord2f(ratiox + halfx, halfy);
+ glVertex2f(sizex, soffy);
+
+ glTexCoord2f(ratiox + halfx, ratioy + halfy);
+ glVertex2f(sizex, soffy + (sizey * 0.5f));
+
+ glTexCoord2f(halfx, ratioy + halfy);
+ glVertex2f(0, soffy + (sizey * 0.5f));
+ glEnd();
+
glBindTexture(triple->target, 0);
glDisable(triple->target);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h
index 5dc52b2e4fb..0f125309045 100644
--- a/source/blender/windowmanager/wm_draw.h
+++ b/source/blender/windowmanager/wm_draw.h
@@ -34,13 +34,9 @@
#include "GPU_glew.h"
-
-#define MAX_N_TEX 3
-
typedef struct wmDrawTriple {
- GLuint bind[MAX_N_TEX * MAX_N_TEX];
- int x[MAX_N_TEX], y[MAX_N_TEX];
- int nx, ny;
+ GLuint bind;
+ int x, y;
GLenum target;
} wmDrawTriple;
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index af367467e00..deb702f005c 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -79,6 +79,11 @@ else()
TARGETS blenderplayer
DESTINATION bin
)
+ else()
+ install(
+ TARGETS blenderplayer
+ DESTINATION "."
+ )
endif()
endif()
@@ -164,14 +169,13 @@ endif()
extern_recastnavigation
bf_intern_raskter
bf_intern_opencolorio
- bf_intern_opennl
bf_intern_glew_mx
+ bf_intern_eigen
extern_rangetree
extern_wcwidth
extern_libmv
extern_glog
extern_sdlew
- extern_eigen3
)
if(WITH_MOD_CLOTH_ELTOPO)
@@ -190,8 +194,6 @@ endif()
list(APPEND BLENDER_SORTED_LIBS extern_ceres)
endif()
- list(APPEND BLENDER_SORTED_LIBS extern_colamd)
-
if(WITH_MOD_BOOLEAN)
list(APPEND BLENDER_SORTED_LIBS extern_carve)
endif()
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index d28f3a21341..458d883666e 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -137,6 +137,7 @@ struct wmWindowManager;
#if 1
#if defined(__GNUC__)
# pragma GCC diagnostic error "-Wmissing-prototypes"
+# pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#include "../../intern/cycles/blender/CCL_api.h"
@@ -283,6 +284,7 @@ struct Render *RE_NewRender(const char *name) RET_NULL
void RE_SwapResult(struct Render *re, struct RenderResult **rr) RET_NONE
void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, struct Object *camera_override, unsigned int lay_override, int frame, const bool write_still) RET_NONE
bool RE_WriteEnvmapResult(struct ReportList *reports, struct Scene *scene, struct EnvMap *env, const char *relpath, const char imtype, float layout[12]) RET_ZERO
+void RE_cache_point_density(struct Scene *scene, struct PointDensity *pd, const bool use_render_params) RET_NONE
/* rna */
float *ED_view3d_cursor3d_get(struct Scene *scene, struct View3D *v3d) RET_NULL
@@ -511,10 +513,12 @@ bool ED_texture_context_check_others(const struct bContext *C) RET_ZERO
bool ED_text_region_location_from_cursor(SpaceText *st, ARegion *ar, const int cursor_co[2], int r_pixel_co[2]) RET_ZERO
-bool snapObjectsRayEx(struct Scene *scene, struct Base *base_act, struct View3D *v3d, struct ARegion *ar, struct Object *obedit, short snap_mode,
- struct Object **r_ob, float r_obmat[4][4],
- const float ray_start[3], const float ray_normal[3], float *r_ray_dist,
- const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode) RET_ZERO
+bool snapObjectsRayEx(
+ struct Scene *scene, struct View3D *v3d, struct ARegion *ar, struct Base *base_act, struct Object *obedit,
+ const float mval[2], SnapSelect snap_select, short snap_mode,
+ const float ray_start[3], const float ray_normal[3], float *ray_dist,
+ float r_loc[3], float r_no[3], float *r_dist_px, int *r_index,
+ struct Object **r_ob, float r_obmat[4][4]) RET_ZERO
void ED_lattice_editlatt_make(struct Object *obedit) RET_NONE
void ED_lattice_editlatt_load(struct Object *obedit) RET_NONE
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 08390b585ac..49fb4fe82eb 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -250,8 +250,10 @@ endif()
set(BLENDER_TEXT_FILES
${CMAKE_SOURCE_DIR}/release/text/GPL-license.txt
+ ${CMAKE_SOURCE_DIR}/release/text/GPL3-license.txt
${CMAKE_SOURCE_DIR}/release/text/Python-license.txt
${CMAKE_SOURCE_DIR}/release/text/copyright.txt
+ ${CMAKE_SOURCE_DIR}/release/text/jemalloc-license.txt
# generate this file
# ${CMAKE_SOURCE_DIR}/release/text/readme.html
${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-bfont.ttf.txt
diff --git a/source/creator/blender.map b/source/creator/blender.map
index 359cbe0415f..9c900a62705 100644
--- a/source/creator/blender.map
+++ b/source/creator/blender.map
@@ -9,6 +9,7 @@ global:
*;
*_boost*;
local:
+ *default_error_condition*;
*llvm*;
*LLVM*;
decodeInstruction;
diff --git a/source/creator/creator.c b/source/creator/creator.c
index c6203b6fd40..f7dd0aaf736 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -1505,7 +1505,7 @@ static int load_file(int UNUSED(argc), const char **argv, void *data)
}
}
else {
- /* failed to load file, stop processing arguments */
+ /* failed to load file, stop processing arguments if running in background mode */
if (G.background) {
/* Set is_break if running in the background mode so
* blender will return non-zero exit code which then
@@ -1513,8 +1513,14 @@ static int load_file(int UNUSED(argc), const char **argv, void *data)
* good or bad things are.
*/
G.is_break = true;
+ return -1;
}
- return -1;
+
+ /* Just pretend a file was loaded, so the user can press Save and it'll save at the filename from the CLI. */
+ BLI_strncpy(G.main->name, filename, FILE_MAX);
+ G.relbase_valid = true;
+ G.save_over = true;
+ printf("... opened default scene instead; saving will write to %s\n", filename);
}
G.file_loaded = 1;
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 6832b4191f5..c5fc55a8e68 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -54,7 +54,6 @@
#include "KX_PyConstraintBinding.h"
#include "KX_PythonMain.h"
-#include "RAS_GLExtensionManager.h"
#include "RAS_OpenGLRasterizer.h"
#include "RAS_ListRasterizer.h"
@@ -250,8 +249,6 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */
#endif
-
- bgl::InitExtensions(true);
// Globals to be carried on over blender files
GlobalSettings gs;
@@ -302,12 +299,20 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
canvas->SetSwapInterval((startscene->gm.vsync == VSYNC_ON) ? 1 : 0);
RAS_IRasterizer* rasterizer = NULL;
+ RAS_STORAGE_TYPE raster_storage = RAS_AUTO_STORAGE;
+
+ if (startscene->gm.raster_storage == RAS_STORE_VBO) {
+ raster_storage = RAS_VBO;
+ }
+ else if (startscene->gm.raster_storage == RAS_STORE_VA) {
+ raster_storage = RAS_VA;
+ }
//Don't use displaylists with VBOs
//If auto starts using VBOs, make sure to check for that here
- if (displaylists && startscene->gm.raster_storage != RAS_STORE_VBO)
- rasterizer = new RAS_ListRasterizer(canvas, true, startscene->gm.raster_storage);
+ if (displaylists && raster_storage != RAS_VBO)
+ rasterizer = new RAS_ListRasterizer(canvas, true, raster_storage);
else
- rasterizer = new RAS_OpenGLRasterizer(canvas, startscene->gm.raster_storage);
+ rasterizer = new RAS_OpenGLRasterizer(canvas, raster_storage);
RAS_IRasterizer::MipmapOption mipmapval = rasterizer->GetMipmapping();
@@ -677,6 +682,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
BLI_strncpy(G.main->name, oldsce, sizeof(G.main->name));
#ifdef WITH_PYTHON
+ PyDict_Clear(pyGlobalDict);
Py_DECREF(pyGlobalDict);
// Release Python's GIL
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index 2b357f43031..f0a7bd47ca3 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -78,7 +78,6 @@ extern "C"
#include "RAS_MeshObject.h"
#include "RAS_OpenGLRasterizer.h"
#include "RAS_ListRasterizer.h"
-#include "RAS_GLExtensionManager.h"
#include "KX_PythonInit.h"
#include "KX_PyConstraintBinding.h"
#include "BL_Material.h" // MAXTEX
@@ -563,7 +562,6 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
if (!m_engineInitialized)
{
GPU_init();
- bgl::InitExtensions(true);
// get and set the preferences
SYS_SystemHandle syshandle = SYS_GetSystem();
@@ -607,12 +605,20 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
if (gm->flag & GAME_SHOW_MOUSE)
m_canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
+ RAS_STORAGE_TYPE raster_storage = RAS_AUTO_STORAGE;
+
+ if (gm->raster_storage == RAS_STORE_VBO) {
+ raster_storage = RAS_VBO;
+ }
+ else if (gm->raster_storage == RAS_STORE_VA) {
+ raster_storage = RAS_VA;
+ }
//Don't use displaylists with VBOs
//If auto starts using VBOs, make sure to check for that here
- if (useLists && gm->raster_storage != RAS_STORE_VBO)
- m_rasterizer = new RAS_ListRasterizer(m_canvas, false, gm->raster_storage);
+ if (useLists && raster_storage != RAS_VBO)
+ m_rasterizer = new RAS_ListRasterizer(m_canvas, true, raster_storage);
else
- m_rasterizer = new RAS_OpenGLRasterizer(m_canvas, gm->raster_storage);
+ m_rasterizer = new RAS_OpenGLRasterizer(m_canvas, raster_storage);
/* Stereo parameters - Eye Separation from the UI - stereomode from the command-line/UI */
m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode);
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index b5151615f3b..0f71f8d3bac 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -35,8 +35,8 @@
#include "BL_BlenderShader.h"
#include "BL_Material.h"
-#include "GPU_extensions.h"
#include "GPU_material.h"
+#include "GPU_shader.h"
#include "RAS_BucketManager.h"
#include "RAS_MeshObject.h"
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index 4b229f53d77..6613780a0f8 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -34,7 +34,6 @@
#include "KX_PyMath.h"
#include "MEM_guardedalloc.h"
-#include "RAS_GLExtensionManager.h"
#include "RAS_MeshObject.h"
#include "RAS_IRasterizer.h"
diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp
index 8f717c05c0f..d14b9cc57b8 100644
--- a/source/gameengine/Ketsji/BL_Texture.cpp
+++ b/source/gameengine/Ketsji/BL_Texture.cpp
@@ -38,7 +38,6 @@
#include "BKE_image.h"
#include "BLI_blenlib.h"
-#include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
#include "RAS_ICanvas.h"
#include "RAS_Rect.h"
@@ -196,7 +195,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap)
void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap)
{
- if (!GPU_non_power_of_two_support() && (!is_power_of_2_i(x) || !is_power_of_2_i(y)) ) {
+ if (!GPU_full_non_power_of_two_support() && (!is_power_of_2_i(x) || !is_power_of_2_i(y)) ) {
InitNonPow2Tex(pix, x,y,mipmap);
return;
}
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index d85d33d9834..a10bdf4ac98 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -39,7 +39,6 @@
#include "RAS_BucketManager.h"
#include "RAS_MeshObject.h"
#include "RAS_IRasterizer.h"
-#include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
#include "GPU_draw.h"
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 5e66250bd80..412a112df6b 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -3736,8 +3736,9 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
RayCastData rayData(propName, false, (1 << OB_MAX_COL_MASKS) - 1);
KX_RayCast::Callback<KX_GameObject, RayCastData> callback(this, spc, &rayData);
- if (KX_RayCast::RayTest(pe, fromPoint, toPoint, callback))
+ if (KX_RayCast::RayTest(pe, fromPoint, toPoint, callback) && rayData.m_hitObject) {
return rayData.m_hitObject->GetProxy();
+ }
Py_RETURN_NONE;
}
@@ -3883,8 +3884,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
RayCastData rayData(propName, xray, mask);
KX_RayCast::Callback<KX_GameObject, RayCastData> callback(this, spc, &rayData, face, (poly == 2));
- if (KX_RayCast::RayTest(pe, fromPoint, toPoint, callback))
- {
+ if (KX_RayCast::RayTest(pe, fromPoint, toPoint, callback) && rayData.m_hitObject) {
PyObject *returnValue = (poly == 2) ? PyTuple_New(5) : (poly) ? PyTuple_New(4) : PyTuple_New(3);
if (returnValue) { // unlikely this would ever fail, if it does python sets an error
PyTuple_SET_ITEM(returnValue, 0, rayData.m_hitObject->GetProxy());
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 5f36a980a53..fa924f74290 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -128,6 +128,7 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
m_bInitialized(false),
m_activecam(0),
m_bFixedTime(false),
+ m_useExternalClock(false),
m_firstframe(true),
@@ -135,6 +136,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
m_clockTime(0.f),
m_previousClockTime(0.f),
m_previousAnimTime(0.f),
+ m_timescale(1.0f),
+ m_previousRealTime(0.0f),
m_exitcode(KX_EXIT_REQUEST_NO_REQUEST),
@@ -411,6 +414,7 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo)
m_clockTime = m_kxsystem->GetTimeInSeconds();
m_frameTime = m_kxsystem->GetTimeInSeconds();
m_previousClockTime = m_kxsystem->GetTimeInSeconds();
+ m_previousRealTime = m_kxsystem->GetTimeInSeconds();
m_firstframe = true;
m_bInitialized = true;
@@ -554,7 +558,7 @@ void KX_KetsjiEngine::EndFrame()
bool KX_KetsjiEngine::NextFrame()
{
- double timestep = 1.0/m_ticrate;
+ double timestep = m_timescale / m_ticrate;
double framestep = timestep;
// static hidden::Clock sClock;
@@ -563,12 +567,43 @@ bool KX_KetsjiEngine::NextFrame()
//float dt = sClock.getTimeMicroseconds() * 0.000001f;
//sClock.reset();
- if (m_bFixedTime) {
- m_clockTime += timestep;
- }
- else {
- // m_clockTime += dt;
- m_clockTime = m_kxsystem->GetTimeInSeconds();
+ /*
+ * Clock advancement. There is basically three case:
+ * - m_useExternalClock is true, the user is responsible to advance the time
+ * manually using setClockTime, so here, we do not do anything.
+ * - m_useExternalClock is false, m_bFixedTime is true, we advance for one
+ * timestep, which already handle the time scaling parameter
+ * - m_useExternalClock is false, m_bFixedTime is false, we consider how much
+ * time has elapsed since last call and we scale this time by the time
+ * scaling parameter. If m_timescale is 1.0 (default value), the clock
+ * corresponds to the computer clock.
+ *
+ * Once clockTime has been computed, we will compute how many logic frames
+ * will be executed before the next rendering phase (which will occur at "clockTime").
+ * The game time elapsing between two logic frames (called framestep)
+ * depends on several variables:
+ * - ticrate
+ * - max_physic_frame
+ * - max_logic_frame
+ * XXX The logic over computation framestep is definitively not clear (and
+ * I'm not even sure it is correct). If needed frame is strictly greater
+ * than max_physics_frame, we are doing a jump in game time, but keeping
+ * framestep = 1 / ticrate, while if frames is greater than
+ * max_logic_frame, we increase framestep.
+ *
+ * XXX render.fps is not considred anywhere.
+ */
+ if (!m_useExternalClock) {
+ if (m_bFixedTime) {
+ m_clockTime += timestep;
+ }
+ else {
+ double current_time = m_kxsystem->GetTimeInSeconds();
+ double dt = current_time - m_previousRealTime;
+ m_previousRealTime = current_time;
+ // m_clockTime += dt;
+ m_clockTime += dt * m_timescale;
+ }
}
double deltatime = m_clockTime - m_frameTime;
@@ -579,16 +614,14 @@ bool KX_KetsjiEngine::NextFrame()
return false;
}
-
// Compute the number of logic frames to do each update (fixed tic bricks)
- int frames =int(deltatime*m_ticrate+1e-6);
+ int frames = int(deltatime * m_ticrate / m_timescale + 1e-6);
// if (frames>1)
// printf("****************************************");
// printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames);
// if (!frames)
// PIL_sleep_ms(1);
-
KX_SceneList::iterator sceneit;
if (frames>m_maxPhysicsFrame)
@@ -1756,6 +1789,10 @@ void KX_KetsjiEngine::SetUseFixedTime(bool bUseFixedTime)
m_bFixedTime = bUseFixedTime;
}
+void KX_KetsjiEngine::SetUseExternalClock(bool useExternalClock)
+{
+ m_useExternalClock = useExternalClock;
+}
void KX_KetsjiEngine::SetAnimRecordMode(bool animation_record, int startFrame)
{
@@ -1783,6 +1820,11 @@ bool KX_KetsjiEngine::GetUseFixedTime(void) const
return m_bFixedTime;
}
+bool KX_KetsjiEngine::GetUseExternalClock(void) const
+{
+ return m_useExternalClock;
+}
+
double KX_KetsjiEngine::GetSuspendedDelta()
{
return m_suspendeddelta;
@@ -1798,6 +1840,16 @@ void KX_KetsjiEngine::SetTicRate(double ticrate)
m_ticrate = ticrate;
}
+double KX_KetsjiEngine::GetTimeScale() const
+{
+ return m_timescale;
+}
+
+void KX_KetsjiEngine::SetTimeScale(double timescale)
+{
+ m_timescale = timescale;
+}
+
int KX_KetsjiEngine::GetMaxLogicFrame()
{
return m_maxLogicFrame;
@@ -1838,6 +1890,11 @@ double KX_KetsjiEngine::GetClockTime(void) const
return m_clockTime;
}
+void KX_KetsjiEngine::SetClockTime(double externalClockTime)
+{
+ m_clockTime = externalClockTime;
+}
+
double KX_KetsjiEngine::GetFrameTime(void) const
{
return m_frameTime;
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index ec855be3212..3b8cec2ac82 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -103,16 +103,19 @@ private:
bool m_bInitialized;
int m_activecam;
bool m_bFixedTime;
+ bool m_useExternalClock;
bool m_firstframe;
int m_currentFrame;
- double m_frameTime;//discrete timestamp of the 'game logic frame'
- double m_clockTime;//current time
- double m_previousClockTime;//previous clock time
- double m_previousAnimTime; //the last time animations were updated
+ double m_frameTime; // current logic game time
+ double m_clockTime; // game time for the next rendering step
+ double m_previousClockTime; // game time of the previous rendering step
+ double m_previousAnimTime; //game time when the animations were last updated
double m_remainingTime;
+ double m_timescale; // time scaling parameter. if > 1.0, time goes faster than real-time. If < 1.0, times goes slower than real-time.
+ double m_previousRealTime;
static int m_maxLogicFrame; /* maximum number of consecutive logic frame */
static int m_maxPhysicsFrame; /* maximum number of consecutive physics frame */
@@ -297,15 +300,37 @@ public:
bool GetUseFixedTime(void) const;
/**
- * Returns current render frame clock time
+ * Sets if the BGE relies on a external clock or its own internal clock
+ */
+ void SetUseExternalClock(bool bUseExternalClock);
+
+ /**
+ * Returns if we rely on an external clock
+ * \return Current setting
+ */
+ bool GetUseExternalClock(void) const;
+
+ /**
+ * Returns next render frame game time
*/
double GetClockTime(void) const;
+
+ /**
+ * Set the next render frame game time. It will impact also frame time, as
+ * this one is derived from clocktime
+ */
+ void SetClockTime(double externalClockTime);
+
/**
- * Returns current logic frame clock time
+ * Returns current logic frame game time
*/
double GetFrameTime(void) const;
+ /**
+ * Returns the real (system) time
+ */
double GetRealTime(void) const;
+
/**
* Returns the difference between the local time of the scene (when it
* was running and not suspended) and the "curtime"
@@ -361,6 +386,16 @@ public:
*/
static double GetAverageFrameRate();
+ /**
+ * Gets the time scale multiplier
+ */
+ double GetTimeScale() const;
+
+ /**
+ * Sets the time scale multiplier
+ */
+ void SetTimeScale(double scale);
+
static void SetExitKey(short key);
static short GetExitKey();
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 26c6fcaa928..8a010726bba 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -548,6 +548,64 @@ static PyObject *gPyGetAverageFrameRate(PyObject *)
return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate());
}
+static PyObject *gPyGetUseExternalClock(PyObject *)
+{
+ return PyBool_FromLong(gp_KetsjiEngine->GetUseExternalClock());
+}
+
+static PyObject *gPySetUseExternalClock(PyObject *, PyObject *args)
+{
+ bool bUseExternalClock;
+
+ if (!PyArg_ParseTuple(args, "p:setUseExternalClock", &bUseExternalClock))
+ return NULL;
+
+ gp_KetsjiEngine->SetUseExternalClock(bUseExternalClock);
+ Py_RETURN_NONE;
+}
+
+static PyObject *gPyGetClockTime(PyObject *)
+{
+ return PyFloat_FromDouble(gp_KetsjiEngine->GetClockTime());
+}
+
+static PyObject *gPySetClockTime(PyObject *, PyObject *args)
+{
+ double externalClockTime;
+
+ if (!PyArg_ParseTuple(args, "d:setClockTime", &externalClockTime))
+ return NULL;
+
+ gp_KetsjiEngine->SetClockTime(externalClockTime);
+ Py_RETURN_NONE;
+}
+
+static PyObject *gPyGetFrameTime(PyObject *)
+{
+ return PyFloat_FromDouble(gp_KetsjiEngine->GetFrameTime());
+}
+
+static PyObject *gPyGetRealTime(PyObject *)
+{
+ return PyFloat_FromDouble(gp_KetsjiEngine->GetRealTime());
+}
+
+static PyObject *gPyGetTimeScale(PyObject *)
+{
+ return PyFloat_FromDouble(gp_KetsjiEngine->GetTimeScale());
+}
+
+static PyObject *gPySetTimeScale(PyObject *, PyObject *args)
+{
+ double time_scale;
+
+ if (!PyArg_ParseTuple(args, "d:setTimeScale", &time_scale))
+ return NULL;
+
+ gp_KetsjiEngine->SetTimeScale(time_scale);
+ Py_RETURN_NONE;
+}
+
static PyObject *gPyGetBlendFileList(PyObject *, PyObject *args)
{
char cpath[sizeof(gp_GamePythonPath)];
@@ -647,71 +705,10 @@ static PyObject *pyPrintStats(PyObject *,PyObject *,PyObject *)
static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *)
{
-#define pprint(x) std::cout << x << std::endl;
- bool count=0;
- bool support=0;
- pprint("Supported Extensions...");
- pprint(" GL_ARB_shader_objects supported? "<< (GLEW_ARB_shader_objects?"yes.":"no."));
- count = 1;
-
- support= GLEW_ARB_vertex_shader;
- pprint(" GL_ARB_vertex_shader supported? "<< (support?"yes.":"no."));
- count = 1;
- if (support) {
- pprint(" ----------Details----------");
- int max=0;
- glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, (GLint*)&max);
- pprint(" Max uniform components." << max);
-
- glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, (GLint*)&max);
- pprint(" Max varying floats." << max);
-
- glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, (GLint*)&max);
- pprint(" Max vertex texture units." << max);
-
- glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, (GLint*)&max);
- pprint(" Max combined texture units." << max);
- pprint("");
- }
-
- support=GLEW_ARB_fragment_shader;
- pprint(" GL_ARB_fragment_shader supported? "<< (support?"yes.":"no."));
- count = 1;
- if (support) {
- pprint(" ----------Details----------");
- int max=0;
- glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, (GLint*)&max);
- pprint(" Max uniform components." << max);
- pprint("");
- }
-
- support = GLEW_ARB_texture_cube_map;
- pprint(" GL_ARB_texture_cube_map supported? "<< (support?"yes.":"no."));
- count = 1;
- if (support) {
- pprint(" ----------Details----------");
- int size=0;
- glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, (GLint*)&size);
- pprint(" Max cubemap size." << size);
- pprint("");
- }
-
- support = GLEW_ARB_multitexture;
- count = 1;
- pprint(" GL_ARB_multitexture supported? "<< (support?"yes.":"no."));
- if (support) {
- pprint(" ----------Details----------");
- int units=0;
- glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&units);
- pprint(" Max texture units available. " << units);
- pprint("");
- }
-
- pprint(" GL_ARB_texture_env_combine supported? "<< (GLEW_ARB_texture_env_combine?"yes.":"no."));
- count = 1;
-
- if (!count)
- pprint("No extenstions are used in this build");
+ if (gp_Rasterizer)
+ gp_Rasterizer->PrintHardwareInfo();
+ else
+ printf("Warning: no rasterizer detected for PrintGLInfo!\n");
Py_RETURN_NONE;
}
@@ -908,7 +905,19 @@ static struct PyMethodDef game_methods[] = {
{"setAnimRecordFrame", (PyCFunction) gPySetAnimRecordFrame, METH_VARARGS, (const char *)"Sets the current frame number used for animation recording"},
{"getExitKey", (PyCFunction) gPyGetExitKey, METH_NOARGS, (const char *)"Gets the key used to exit the game engine"},
{"setExitKey", (PyCFunction) gPySetExitKey, METH_VARARGS, (const char *)"Sets the key used to exit the game engine"},
+ {"getUseExternalClock", (PyCFunction) gPyGetUseExternalClock, METH_NOARGS, (const char *)"Get if we use the time provided by an external clock"},
+ {"setUseExternalClock", (PyCFunction) gPySetUseExternalClock, METH_VARARGS, (const char *)"Set if we use the time provided by an external clock"},
+ {"getClockTime", (PyCFunction) gPyGetClockTime, METH_NOARGS, (const char *)"Get the last BGE render time. "
+ "The BGE render time is the simulated time corresponding to the next scene that will be renderered"},
+ {"setClockTime", (PyCFunction) gPySetClockTime, METH_VARARGS, (const char *)"Set the BGE render time. "
+ "The BGE render time is the simulated time corresponding to the next scene that will be rendered"},
+ {"getFrameTime", (PyCFunction) gPyGetFrameTime, METH_NOARGS, (const char *)"Get the BGE last frametime. "
+ "The BGE frame time is the simulated time corresponding to the last call of the logic system"},
+ {"getRealTime", (PyCFunction) gPyGetRealTime, METH_NOARGS, (const char *)"Get the real system time. "
+ "The real-time corresponds to the system time" },
{"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, (const char *)"Gets the estimated average frame rate"},
+ {"getTimeScale", (PyCFunction) gPyGetTimeScale, METH_NOARGS, (const char *)"Get the time multiplier"},
+ {"setTimeScale", (PyCFunction) gPySetTimeScale, METH_VARARGS, (const char *)"Set the time multiplier"},
{"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, (const char *)"Gets a list of blend files in the same directory as the current blend file"},
{"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, (const char *)"Prints GL Extension Info"},
{"PrintMemInfo", (PyCFunction)pyPrintStats, METH_NOARGS, (const char *)"Print engine statistics"},
diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h
index 7fbaf076d25..e960131c1fb 100644
--- a/source/gameengine/Rasterizer/RAS_IRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h
@@ -267,7 +267,6 @@ public:
* IndexPrimitives: Renders primitives from mesh slot.
*/
virtual void IndexPrimitives(class RAS_MeshSlot &ms) = 0;
- virtual void IndexPrimitivesMulti(class RAS_MeshSlot &ms) = 0;
/**
* IndexPrimitives_3DText will render text into the polygons.
@@ -480,6 +479,11 @@ public:
virtual void SetAuxilaryClientInfo(void *inf) = 0;
+ /**
+ * Prints information about what the hardware supports.
+ */
+ virtual void PrintHardwareInfo() = 0;
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:RAS_IRasterizer")
#endif
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
index 2078fc99f2e..13d49c53423 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
@@ -649,15 +649,13 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa
else
ms.m_bDisplayList = true;
- // for text drawing using faces
- if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT)
+ if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT) {
+ // for text drawing using faces
rasty->IndexPrimitives_3DText(ms, m_material);
- // for multitexturing
- else if ((m_material->GetFlag() & (RAS_MULTITEX|RAS_BLENDERGLSL)))
- rasty->IndexPrimitivesMulti(ms);
- // use normal IndexPrimitives
- else
+ }
+ else {
rasty->IndexPrimitives(ms);
+ }
rasty->PopMatrix();
}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
index 888a7114f50..9f95e2c82af 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
@@ -49,20 +49,16 @@ set(INC_SYS
)
set(SRC
- RAS_GLExtensionManager.cpp
RAS_ListRasterizer.cpp
RAS_OpenGLLight.cpp
RAS_OpenGLRasterizer.cpp
- RAS_StorageIM.cpp
RAS_StorageVA.cpp
RAS_StorageVBO.cpp
- RAS_GLExtensionManager.h
RAS_IStorage.h
RAS_ListRasterizer.h
RAS_OpenGLLight.h
RAS_OpenGLRasterizer.h
- RAS_StorageIM.h
RAS_StorageVA.h
RAS_StorageVBO.h
)
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp
deleted file mode 100644
index bc22d68e218..00000000000
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp
- * \ingroup bgerastogl
- */
-
-
-#include <iostream>
-
-#include "glew-mx.h"
-
-#include "RAS_GLExtensionManager.h"
-
-namespace bgl
-{
- void InitExtensions(bool debug)
- {
- static bool firsttime = true;
-
- if (firsttime) {
- firsttime = false;
-
- if (debug) {
- if (GLEW_ATI_pn_triangles)
- std::cout << "Enabled GL_ATI_pn_triangles" << std::endl;
- if (GLEW_ARB_texture_env_combine)
- std::cout << "Detected GL_ARB_texture_env_combine" << std::endl;
- if (GLEW_ARB_texture_cube_map)
- std::cout << "Detected GL_ARB_texture_cube_map" << std::endl;
- if (GLEW_ARB_multitexture)
- std::cout << "Detected GL_ARB_multitexture" << std::endl;
- if (GLEW_ARB_shader_objects)
- std::cout << "Detected GL_ARB_shader_objects" << std::endl;
- if (GLEW_ARB_vertex_shader)
- std::cout << "Detected GL_ARB_vertex_shader" << std::endl;
- if (GLEW_ARB_fragment_shader)
- std::cout << "Detected GL_ARB_fragment_shader" << std::endl;
- if (GLEW_ARB_vertex_program)
- std::cout << "Detected GL_ARB_vertex_program" << std::endl;
- if (GLEW_ARB_depth_texture)
- std::cout << "Detected GL_ARB_depth_texture" << std::endl;
- if (GLEW_EXT_separate_specular_color)
- std::cout << "Detected GL_EXT_separate_specular_color" << std::endl;
- }
- }
- }
-} // namespace bgl
-
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h
index bfa6e1a6cb7..ae0cdcd84af 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h
@@ -44,7 +44,6 @@ public:
virtual void Exit()=0;
virtual void IndexPrimitives(RAS_MeshSlot& ms)=0;
- virtual void IndexPrimitivesMulti(RAS_MeshSlot& ms)=0;
virtual void SetDrawingMode(int drawingmode)=0;
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
index 34184f73953..b2d580161ca 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
@@ -122,7 +122,7 @@ bool RAS_ListSlot::End()
-RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock, int storage)
+RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock, RAS_STORAGE_TYPE storage)
: RAS_OpenGLRasterizer(canvas, storage)
{
}
@@ -243,30 +243,6 @@ void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
if (ms.m_bDisplayList) {
localSlot = FindOrAdd(ms);
localSlot->DrawList();
- if (localSlot->End()) {
- // save slot here too, needed for replicas and object using same mesh
- // => they have the same vertexarray but different mesh slot
- ms.m_DisplayList = localSlot;
- return;
- }
- }
-
- RAS_OpenGLRasterizer::IndexPrimitives(ms);
-
- if (ms.m_bDisplayList) {
- localSlot->EndList();
- ms.m_DisplayList = localSlot;
- }
-}
-
-
-void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
-{
- RAS_ListSlot* localSlot =0;
-
- if (ms.m_bDisplayList) {
- localSlot = FindOrAdd(ms);
- localSlot->DrawList();
if (localSlot->End()) {
// save slot here too, needed for replicas and object using same mesh
@@ -276,7 +252,7 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
}
}
- RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms);
+ RAS_OpenGLRasterizer::IndexPrimitives(ms);
if (ms.m_bDisplayList) {
localSlot->EndList();
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
index 5e1c662bc17..e3e6931311b 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
@@ -56,11 +56,10 @@ class RAS_ListRasterizer : public RAS_OpenGLRasterizer
public:
void RemoveListSlot(RAS_ListSlot* list);
- RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock=false, int storage=RAS_AUTO_STORAGE);
+ RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock, RAS_STORAGE_TYPE storage);
virtual ~RAS_ListRasterizer();
virtual void IndexPrimitives(class RAS_MeshSlot& ms);
- virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms);
virtual bool Init();
virtual void Exit();
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 28545576f05..bbdf17b5bc4 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -47,15 +47,17 @@
#include "RAS_OpenGLLight.h"
-#include "RAS_StorageIM.h"
#include "RAS_StorageVA.h"
#include "RAS_StorageVBO.h"
#include "GPU_draw.h"
+#include "GPU_extensions.h"
#include "GPU_material.h"
+#include "GPU_shader.h"
extern "C"{
#include "BLF_api.h"
+ #include "BKE_DerivedMesh.h"
}
@@ -83,7 +85,7 @@ static GLuint right_eye_vinterlace_mask[32];
*/
static GLuint hinterlace_mask[33];
-RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage)
+RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, RAS_STORAGE_TYPE storage)
:RAS_IRasterizer(canvas),
m_2DCanvas(canvas),
m_fogenabled(false),
@@ -122,27 +124,22 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage)
m_prevafvalue = GPU_get_anisotropic();
- if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE && GLEW_ARB_vertex_buffer_object*/)
- {
+ if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE && GLEW_ARB_vertex_buffer_object*/) {
m_storage = new RAS_StorageVBO(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
- m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
- m_storage_type = RAS_VBO;
}
- else if ((m_storage_type == RAS_VA) || (m_storage_type == RAS_AUTO_STORAGE && GLEW_VERSION_1_1))
- {
+ else if ((m_storage_type == RAS_VA) || (m_storage_type == RAS_AUTO_STORAGE)) {
m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
- m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
- m_storage_type = RAS_VA;
}
- else
- {
- m_storage = m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
- m_storage_type = RAS_IMMEDIATE;
+ else {
+ printf("Unknown rasterizer storage type, falling back to vertex arrays\n");
+ m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
}
glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &m_numgllights);
if (m_numgllights < 8)
m_numgllights = 8;
+
+ PrintHardwareInfo();
}
@@ -151,8 +148,6 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
{
// Restore the previous AF value
GPU_set_anisotropic(m_prevafvalue);
- if (m_failsafe_storage && m_failsafe_storage != m_storage)
- delete m_failsafe_storage;
if (m_storage)
delete m_storage;
@@ -321,9 +316,6 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
glDisable(GL_CULL_FACE);
m_storage->SetDrawingMode(drawingmode);
- if (m_failsafe_storage && m_failsafe_storage != m_storage) {
- m_failsafe_storage->SetDrawingMode(drawingmode);
- }
}
int RAS_OpenGLRasterizer::GetDrawingMode()
@@ -735,17 +727,97 @@ void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit, int layer)
void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
{
if (ms.m_pDerivedMesh)
- m_failsafe_storage->IndexPrimitives(ms);
+ DrawDerivedMesh(ms);
else
m_storage->IndexPrimitives(ms);
}
-void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
+// Code for hooking into Blender's mesh drawing for derived meshes.
+// If/when we use more of Blender's drawing code, we may be able to
+// clean this up
+static bool current_wireframe;
+static RAS_MaterialBucket *current_bucket;
+static RAS_IPolyMaterial *current_polymat;
+static RAS_MeshSlot *current_ms;
+static RAS_MeshObject *current_mesh;
+static int current_blmat_nr;
+static GPUVertexAttribs current_gpu_attribs;
+static Image *current_image;
+static int CheckMaterialDM(int matnr, void *attribs)
+{
+ // only draw the current material
+ if (matnr != current_blmat_nr)
+ return 0;
+ GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
+ if (gattribs)
+ memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
+ return 1;
+}
+
+static DMDrawOption CheckTexDM(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
+{
+
+ // index is the original face index, retrieve the polygon
+ if (matnr == current_blmat_nr &&
+ (mtexpoly == NULL || mtexpoly->tpage == current_image)) {
+ // must handle color.
+ if (current_wireframe)
+ return DM_DRAW_OPTION_NO_MCOL;
+ if (current_ms->m_bObjectColor) {
+ MT_Vector4& rgba = current_ms->m_RGBAcolor;
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+ // don't use mcol
+ return DM_DRAW_OPTION_NO_MCOL;
+ }
+ if (!has_mcol) {
+ // we have to set the color from the material
+ unsigned char rgba[4];
+ current_polymat->GetMaterialRGBAColor(rgba);
+ glColor4ubv((const GLubyte *)rgba);
+ return DM_DRAW_OPTION_NO_MCOL;
+ }
+ return DM_DRAW_OPTION_NORMAL;
+ }
+ return DM_DRAW_OPTION_SKIP;
+}
+
+void RAS_OpenGLRasterizer::DrawDerivedMesh(class RAS_MeshSlot &ms)
{
- if (ms.m_pDerivedMesh)
- m_failsafe_storage->IndexPrimitivesMulti(ms);
+ // mesh data is in derived mesh,
+ current_bucket = ms.m_bucket;
+ current_polymat = current_bucket->GetPolyMaterial();
+ current_ms = &ms;
+ current_mesh = ms.m_mesh;
+ current_wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME;
+ // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
+
+ // handle two-side
+ if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
+ this->SetCullFace(true);
else
- m_storage->IndexPrimitivesMulti(ms);
+ this->SetCullFace(false);
+
+ if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
+ // GetMaterialIndex return the original mface material index,
+ // increment by 1 to match what derived mesh is doing
+ current_blmat_nr = current_polymat->GetMaterialIndex()+1;
+ // For GLSL we need to retrieve the GPU material attribute
+ Material* blmat = current_polymat->GetBlenderMaterial();
+ Scene* blscene = current_polymat->GetBlenderScene();
+ if (!current_wireframe && blscene && blmat)
+ GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat, false), &current_gpu_attribs);
+ else
+ memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
+ // DM draw can mess up blending mode, restore at the end
+ int current_blend_mode = GPU_get_material_alpha_blend();
+ ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
+ GPU_set_material_alpha_blend(current_blend_mode);
+ } else {
+ //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
+ current_blmat_nr = current_polymat->GetMaterialIndex();
+ current_image = current_polymat->GetBlenderImage();
+ ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL, DM_DRAW_USE_ACTIVE_UV);
+ }
}
void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
@@ -1547,3 +1619,68 @@ void RAS_OpenGLRasterizer::SetAuxilaryClientInfo(void* inf)
m_auxilaryClientInfo = inf;
}
+void RAS_OpenGLRasterizer::PrintHardwareInfo()
+{
+ #define pprint(x) std::cout << x << std::endl;
+
+ pprint("GL_VENDOR: " << glGetString(GL_VENDOR));
+ pprint("GL_RENDERER: " << glGetString(GL_RENDERER));
+ pprint("GL_VERSION: " << glGetString(GL_VERSION));
+ bool support=0;
+ pprint("Supported Extensions...");
+ pprint(" GL_ARB_shader_objects supported? "<< (GLEW_ARB_shader_objects?"yes.":"no."));
+
+ support= GLEW_ARB_vertex_shader;
+ pprint(" GL_ARB_vertex_shader supported? "<< (support?"yes.":"no."));
+ if (support) {
+ pprint(" ----------Details----------");
+ int max=0;
+ glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, (GLint*)&max);
+ pprint(" Max uniform components." << max);
+
+ glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, (GLint*)&max);
+ pprint(" Max varying floats." << max);
+
+ glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, (GLint*)&max);
+ pprint(" Max vertex texture units." << max);
+
+ glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, (GLint*)&max);
+ pprint(" Max combined texture units." << max);
+ pprint("");
+ }
+
+ support=GLEW_ARB_fragment_shader;
+ pprint(" GL_ARB_fragment_shader supported? "<< (support?"yes.":"no."));
+ if (support) {
+ pprint(" ----------Details----------");
+ int max=0;
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, (GLint*)&max);
+ pprint(" Max uniform components." << max);
+ pprint("");
+ }
+
+ support = GLEW_ARB_texture_cube_map;
+ pprint(" GL_ARB_texture_cube_map supported? "<< (support?"yes.":"no."));
+ if (support) {
+ pprint(" ----------Details----------");
+ int size=0;
+ glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, (GLint*)&size);
+ pprint(" Max cubemap size." << size);
+ pprint("");
+ }
+
+ support = GLEW_ARB_multitexture;
+ pprint(" GL_ARB_multitexture supported? "<< (support?"yes.":"no."));
+ if (support) {
+ pprint(" ----------Details----------");
+ int units=0;
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&units);
+ pprint(" Max texture units available. " << units);
+ pprint("");
+ }
+
+ pprint(" GL_ARB_texture_env_combine supported? "<< (GLEW_ARB_texture_env_combine?"yes.":"no."));
+
+ pprint(" GL_ARB_texture_non_power_of_two supported " << (GPU_full_non_power_of_two_support()?"yes.":"no."));
+}
+
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
index 67a11f64726..1b012a61355 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
@@ -56,7 +56,6 @@ class RAS_OpenGLLight;
enum RAS_STORAGE_TYPE {
RAS_AUTO_STORAGE,
- RAS_IMMEDIATE,
RAS_VA,
RAS_VBO,
};
@@ -139,11 +138,10 @@ protected:
* Examples of concrete strategies: Vertex Arrays, VBOs, Immediate Mode*/
int m_storage_type;
RAS_IStorage *m_storage;
- RAS_IStorage *m_failsafe_storage; /* So derived mesh can use immediate mode */
public:
double GetTime();
- RAS_OpenGLRasterizer(RAS_ICanvas *canv, int storage=RAS_AUTO_STORAGE);
+ RAS_OpenGLRasterizer(RAS_ICanvas *canv, RAS_STORAGE_TYPE storage);
virtual ~RAS_OpenGLRasterizer();
/*enum DrawType
@@ -186,8 +184,8 @@ public:
virtual void SwapBuffers();
virtual void IndexPrimitives(class RAS_MeshSlot &ms);
- virtual void IndexPrimitivesMulti(class RAS_MeshSlot &ms);
virtual void IndexPrimitives_3DText(class RAS_MeshSlot &ms, class RAS_IPolyMaterial *polymat);
+ virtual void DrawDerivedMesh(class RAS_MeshSlot &ms);
virtual void SetProjectionMatrix(MT_CmMatrix4x4 &mat);
virtual void SetProjectionMatrix(const MT_Matrix4x4 &mat);
@@ -325,6 +323,10 @@ public:
void SetAuxilaryClientInfo(void *inf);
+ /**
+ * Prints information about what the hardware supports.
+ */
+ virtual void PrintHardwareInfo();
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:RAS_OpenGLRasterizer")
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
deleted file mode 100644
index 2cf6088629a..00000000000
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "RAS_StorageIM.h"
-#include "RAS_MaterialBucket.h"
-#include "RAS_IPolygonMaterial.h"
-
-#include "glew-mx.h"
-#include "GPU_draw.h"
-#include "GPU_extensions.h"
-#include "GPU_material.h"
-
-extern "C"{
- #include "BKE_DerivedMesh.h"
-}
-
-RAS_StorageIM::RAS_StorageIM(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer) :
- m_drawingmode(RAS_IRasterizer::KX_TEXTURED),
- m_texco_num(texco_num),
- m_attrib_num(attrib_num),
- m_texco(texco),
- m_attrib(attrib),
- m_attrib_layer(attrib_layer)
-{
-}
-RAS_StorageIM::~RAS_StorageIM()
-{
-}
-
-bool RAS_StorageIM::Init()
-{
- return true;
-}
-void RAS_StorageIM::Exit()
-{
-}
-
-void RAS_StorageIM::IndexPrimitives(RAS_MeshSlot& ms)
-{
- IndexPrimitivesInternal(ms, false);
-}
-
-void RAS_StorageIM::IndexPrimitivesMulti(class RAS_MeshSlot& ms)
-{
- IndexPrimitivesInternal(ms, true);
-}
-
-void RAS_StorageIM::TexCoord(const RAS_TexVert &tv)
-{
- int unit;
-
- if (GLEW_ARB_multitexture) {
- for (unit = 0; unit < *m_texco_num; unit++) {
- switch (m_texco[unit]) {
- case RAS_IRasterizer::RAS_TEXCO_ORCO:
- case RAS_IRasterizer::RAS_TEXCO_GLOB:
- glMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, tv.getXYZ());
- break;
- case RAS_IRasterizer::RAS_TEXCO_UV:
- glMultiTexCoord2fvARB(GL_TEXTURE0_ARB + unit, tv.getUV(unit));
- break;
- case RAS_IRasterizer::RAS_TEXCO_NORM:
- glMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, tv.getNormal());
- break;
- case RAS_IRasterizer::RAS_TEXTANGENT:
- glMultiTexCoord4fvARB(GL_TEXTURE0_ARB + unit, tv.getTangent());
- break;
- default:
- break;
- }
- }
- }
-
- if (GLEW_ARB_vertex_program) {
- for (unit = 0; unit < *m_attrib_num; unit++) {
- switch (m_attrib[unit]) {
- case RAS_IRasterizer::RAS_TEXCO_ORCO:
- case RAS_IRasterizer::RAS_TEXCO_GLOB:
- glVertexAttrib3fvARB(unit, tv.getXYZ());
- break;
- case RAS_IRasterizer::RAS_TEXCO_UV:
- glVertexAttrib2fvARB(unit, tv.getUV(m_attrib_layer[unit]));
- break;
- case RAS_IRasterizer::RAS_TEXCO_NORM:
- glVertexAttrib3fvARB(unit, tv.getNormal());
- break;
- case RAS_IRasterizer::RAS_TEXTANGENT:
- glVertexAttrib4fvARB(unit, tv.getTangent());
- break;
- case RAS_IRasterizer::RAS_TEXCO_VCOL:
- glVertexAttrib4ubvARB(unit, tv.getRGBA());
- break;
- default:
- break;
- }
- }
- }
-
-}
-
-void RAS_StorageIM::SetCullFace(bool enable)
-{
- if (enable)
- glEnable(GL_CULL_FACE);
- else
- glDisable(GL_CULL_FACE);
-}
-
-static bool current_wireframe;
-static RAS_MaterialBucket *current_bucket;
-static RAS_IPolyMaterial *current_polymat;
-static RAS_MeshSlot *current_ms;
-static RAS_MeshObject *current_mesh;
-static int current_blmat_nr;
-static GPUVertexAttribs current_gpu_attribs;
-static Image *current_image;
-static int CheckMaterialDM(int matnr, void *attribs)
-{
- // only draw the current material
- if (matnr != current_blmat_nr)
- return 0;
- GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
- if (gattribs)
- memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
- return 1;
-}
-
-/*
-static int CheckTexfaceDM(void *mcol, int index)
-{
-
- // index is the original face index, retrieve the polygon
- RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ?
- current_mesh->GetPolygon(index) : NULL;
- if (polygon && polygon->GetMaterial() == current_bucket) {
- // must handle color.
- if (current_wireframe)
- return 2;
- if (current_ms->m_bObjectColor) {
- MT_Vector4& rgba = current_ms->m_RGBAcolor;
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
- // don't use mcol
- return 2;
- }
- if (!mcol) {
- // we have to set the color from the material
- unsigned char rgba[4];
- current_polymat->GetMaterialRGBAColor(rgba);
- glColor4ubv((const GLubyte *)rgba);
- return 2;
- }
- return 1;
- }
- return 0;
-}
-*/
-
-static DMDrawOption CheckTexDM(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
-{
-
- // index is the original face index, retrieve the polygon
- if (matnr == current_blmat_nr &&
- (mtexpoly == NULL || mtexpoly->tpage == current_image)) {
- // must handle color.
- if (current_wireframe)
- return DM_DRAW_OPTION_NO_MCOL;
- if (current_ms->m_bObjectColor) {
- MT_Vector4& rgba = current_ms->m_RGBAcolor;
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
- // don't use mcol
- return DM_DRAW_OPTION_NO_MCOL;
- }
- if (!has_mcol) {
- // we have to set the color from the material
- unsigned char rgba[4];
- current_polymat->GetMaterialRGBAColor(rgba);
- glColor4ubv((const GLubyte *)rgba);
- return DM_DRAW_OPTION_NO_MCOL;
- }
- return DM_DRAW_OPTION_NORMAL;
- }
- return DM_DRAW_OPTION_SKIP;
-}
-
-void RAS_StorageIM::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
-{
- bool obcolor = ms.m_bObjectColor;
- bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME;
- MT_Vector4& rgba = ms.m_RGBAcolor;
- RAS_MeshSlot::iterator it;
-
- if (ms.m_pDerivedMesh) {
- // mesh data is in derived mesh,
- current_bucket = ms.m_bucket;
- current_polymat = current_bucket->GetPolyMaterial();
- current_ms = &ms;
- current_mesh = ms.m_mesh;
- current_wireframe = wireframe;
- // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
-
- // handle two-side
- if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
- this->SetCullFace(true);
- else
- this->SetCullFace(false);
-
- if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
- // GetMaterialIndex return the original mface material index,
- // increment by 1 to match what derived mesh is doing
- current_blmat_nr = current_polymat->GetMaterialIndex()+1;
- // For GLSL we need to retrieve the GPU material attribute
- Material* blmat = current_polymat->GetBlenderMaterial();
- Scene* blscene = current_polymat->GetBlenderScene();
- if (!wireframe && blscene && blmat)
- GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat, false), &current_gpu_attribs);
- else
- memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
- // DM draw can mess up blending mode, restore at the end
- int current_blend_mode = GPU_get_material_alpha_blend();
- ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
- GPU_set_material_alpha_blend(current_blend_mode);
- } else {
- //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
- current_blmat_nr = current_polymat->GetMaterialIndex();
- current_image = current_polymat->GetBlenderImage();
- ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL, DM_DRAW_USE_ACTIVE_UV);
- }
- return;
- }
- // iterate over display arrays, each containing an index + vertex array
- for (ms.begin(it); !ms.end(it); ms.next(it)) {
- RAS_TexVert *vertex;
- size_t i, j, numvert;
-
- numvert = it.array->m_type;
-
- if (it.array->m_type == RAS_DisplayArray::LINE) {
- // line drawing
- glBegin(GL_LINES);
-
- for (i = 0; i < it.totindex; i += 2)
- {
- vertex = &it.vertex[it.index[i]];
- glVertex3fv(vertex->getXYZ());
-
- vertex = &it.vertex[it.index[i+1]];
- glVertex3fv(vertex->getXYZ());
- }
-
- glEnd();
- }
- else {
- // triangle and quad drawing
- if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
- glBegin(GL_TRIANGLES);
- else
- glBegin(GL_QUADS);
-
- for (i = 0; i < it.totindex; i += numvert)
- {
- if (obcolor)
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
-
- for (j = 0; j < numvert; j++) {
- vertex = &it.vertex[it.index[i+j]];
-
- if (!wireframe) {
- if (!obcolor)
- glColor4ubv((const GLubyte *)(vertex->getRGBA()));
-
- glNormal3fv(vertex->getNormal());
-
- if (multi)
- TexCoord(*vertex);
- else
- glTexCoord2fv(vertex->getUV(0));
- }
-
- glVertex3fv(vertex->getXYZ());
- }
- }
-
- glEnd();
- }
- }
-}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h
deleted file mode 100644
index 54ba2a57b61..00000000000
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __KX_IMMEDIATEMODESTORAGE
-#define __KX_IMMEDIATEMODESTORAGE
-
-#include "RAS_IStorage.h"
-#include "RAS_IRasterizer.h"
-
-class RAS_StorageIM : public RAS_IStorage
-{
-public:
- RAS_StorageIM(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer);
- virtual ~RAS_StorageIM();
-
- virtual bool Init();
- virtual void Exit();
-
- virtual void IndexPrimitives(RAS_MeshSlot& ms);
- virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms);
-
- virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;};
-
-protected:
- int m_drawingmode;
- int* m_texco_num;
- int* m_attrib_num;
- RAS_IRasterizer::TexCoGen* m_texco;
- RAS_IRasterizer::TexCoGen* m_attrib;
- int* m_attrib_layer;
-
- void TexCoord(const RAS_TexVert &tv);
- void SetCullFace(bool enable);
-
- void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi);
-
-
-#ifdef WITH_CXX_GUARDEDALLOC
-public:
- void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageIM"); }
- void operator delete( void *mem ) { MEM_freeN(mem); }
-#endif
-};
-
-#endif //__KX_IMMEDIATEMODESTORAGE
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
index c2980a6c15f..cf77ebfbeb9 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
@@ -56,68 +56,7 @@ void RAS_StorageVA::Exit()
{
}
-void RAS_StorageVA::IndexPrimitives(RAS_MeshSlot& ms)
-{
- static const GLsizei stride = sizeof(RAS_TexVert);
- bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME;
- RAS_MeshSlot::iterator it;
- GLenum drawmode;
-
- if (!wireframe)
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
-
- // use glDrawElements to draw each vertexarray
- for (ms.begin(it); !ms.end(it); ms.next(it)) {
- if (it.totindex == 0)
- continue;
-
- // drawing mode
- if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
- drawmode = GL_TRIANGLES;
- else if (it.array->m_type == RAS_DisplayArray::QUAD)
- drawmode = GL_QUADS;
- else
- drawmode = GL_LINES;
-
- // colors
- if (drawmode != GL_LINES && !wireframe) {
- if (ms.m_bObjectColor) {
- const MT_Vector4& rgba = ms.m_RGBAcolor;
-
- glDisableClientState(GL_COLOR_ARRAY);
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
- }
- else {
- glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
- glEnableClientState(GL_COLOR_ARRAY);
- }
- }
- else
- glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
-
- glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
- glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
- if (!wireframe) {
- glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV(0));
- if (glIsEnabled(GL_COLOR_ARRAY))
- glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
- }
-
- // here the actual drawing takes places
- glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- if (!wireframe) {
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- }
-}
-
-void RAS_StorageVA::IndexPrimitivesMulti(class RAS_MeshSlot& ms)
+void RAS_StorageVA::IndexPrimitives(class RAS_MeshSlot& ms)
{
static const GLsizei stride = sizeof(RAS_TexVert);
bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME, use_color_array = true;
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h
index e4d00310a11..34fdca23ee6 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h
@@ -44,7 +44,6 @@ public:
virtual void Exit();
virtual void IndexPrimitives(RAS_MeshSlot& ms);
- virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms);
virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;};
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
index 58f3d4c05da..08d27cbc3fc 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
@@ -80,7 +80,7 @@ void VBO::UpdateIndices()
&data->m_index[0], GL_STATIC_DRAW);
}
-void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, int *attrib_layer, bool multi)
+void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, int *attrib_layer)
{
int unit;
@@ -100,41 +100,32 @@ void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num,
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, this->stride, this->color_offset);
- if (multi)
+ for (unit = 0; unit < texco_num; ++unit)
{
- for (unit = 0; unit < texco_num; ++unit)
- {
- glClientActiveTexture(GL_TEXTURE0_ARB + unit);
- switch (texco[unit]) {
- case RAS_IRasterizer::RAS_TEXCO_ORCO:
- case RAS_IRasterizer::RAS_TEXCO_GLOB:
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(3, GL_FLOAT, this->stride, this->vertex_offset);
- break;
- case RAS_IRasterizer::RAS_TEXCO_UV:
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, this->stride, (void*)((intptr_t)this->uv_offset+(sizeof(GLfloat)*2*unit)));
- break;
- case RAS_IRasterizer::RAS_TEXCO_NORM:
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(3, GL_FLOAT, this->stride, this->normal_offset);
- break;
- case RAS_IRasterizer::RAS_TEXTANGENT:
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(4, GL_FLOAT, this->stride, this->tangent_offset);
- break;
- default:
- break;
- }
+ glClientActiveTexture(GL_TEXTURE0_ARB + unit);
+ switch (texco[unit]) {
+ case RAS_IRasterizer::RAS_TEXCO_ORCO:
+ case RAS_IRasterizer::RAS_TEXCO_GLOB:
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(3, GL_FLOAT, this->stride, this->vertex_offset);
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_UV:
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, this->stride, (void*)((intptr_t)this->uv_offset+(sizeof(GLfloat)*2*unit)));
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_NORM:
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(3, GL_FLOAT, this->stride, this->normal_offset);
+ break;
+ case RAS_IRasterizer::RAS_TEXTANGENT:
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(4, GL_FLOAT, this->stride, this->tangent_offset);
+ break;
+ default:
+ break;
}
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- }
- else //TexFace
- {
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, this->stride, this->uv_offset);
}
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
if (GLEW_ARB_vertex_program)
{
@@ -163,7 +154,7 @@ void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num,
}
}
}
-
+
glDrawElements(this->mode, this->indices, GL_UNSIGNED_SHORT, 0);
glDisableClientState(GL_VERTEX_ARRAY);
@@ -207,16 +198,6 @@ void RAS_StorageVBO::Exit()
void RAS_StorageVBO::IndexPrimitives(RAS_MeshSlot& ms)
{
- IndexPrimitivesInternal(ms, false);
-}
-
-void RAS_StorageVBO::IndexPrimitivesMulti(RAS_MeshSlot& ms)
-{
- IndexPrimitivesInternal(ms, true);
-}
-
-void RAS_StorageVBO::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
-{
RAS_MeshSlot::iterator it;
VBO *vbo;
@@ -233,6 +214,6 @@ void RAS_StorageVBO::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
vbo->UpdateData();
}
- vbo->Draw(*m_texco_num, m_texco, *m_attrib_num, m_attrib, m_attrib_layer, multi);
+ vbo->Draw(*m_texco_num, m_texco, *m_attrib_num, m_attrib, m_attrib_layer);
}
}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
index f156722247c..f78faa97b16 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
@@ -42,7 +42,7 @@ public:
VBO(RAS_DisplayArray *data, unsigned int indices);
~VBO();
- void Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, int *attrib_layer, bool multi);
+ void Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, int *attrib_layer);
void UpdateData();
void UpdateIndices();
@@ -73,7 +73,6 @@ public:
virtual void Exit();
virtual void IndexPrimitives(RAS_MeshSlot& ms);
- virtual void IndexPrimitivesMulti(RAS_MeshSlot& ms);
virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;};
@@ -89,8 +88,6 @@ protected:
std::map<RAS_DisplayArray*, class VBO*> m_vbo_lookup;
- virtual void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi);
-
#ifdef WITH_CXX_GUARDEDALLOC
public:
void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageVA"); }
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index 9585d8b0138..3bf11fbdfd6 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -1024,11 +1024,11 @@ AVFrame *VideoFFmpeg::grabFrame(long position)
AVFrame *input = m_frame;
short counter = 0;
- /* While the data is not read properly (png, tiffs, etc formats may need several pass)*/
- while ((input->data[0] == 0 && input->data[1] == 0 && input->data[2] == 0 && input->data[3] == 0) && counter < 10) {
+ /* If m_isImage, while the data is not read properly (png, tiffs, etc formats may need several pass), else don't need while loop*/
+ do {
avcodec_decode_video2(m_codecCtx, m_frame, &frameFinished, &packet);
counter++;
- }
+ } while ((input->data[0] == 0 && input->data[1] == 0 && input->data[2] == 0 && input->data[3] == 0) && counter < 10 && m_isImage);
// remember dts to compute exact frame number
dts = packet.dts;
diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp
index 30a8107b558..a62ffee3137 100644
--- a/source/gameengine/VideoTexture/blendVideoTex.cpp
+++ b/source/gameengine/VideoTexture/blendVideoTex.cpp
@@ -32,8 +32,6 @@
#include "KX_PythonInit.h"
-#include <RAS_GLExtensionManager.h>
-
#include <RAS_IPolygonMaterial.h>
//Old API
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index e10d6b13b59..443d9b0e84b 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -37,11 +37,11 @@ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LIN
BLENDER_TEST(BLI_stack "bf_blenlib")
BLENDER_TEST(BLI_math_color "bf_blenlib")
-BLENDER_TEST(BLI_math_geom "bf_blenlib;extern_eigen3")
+BLENDER_TEST(BLI_math_geom "bf_blenlib;bf_intern_eigen")
BLENDER_TEST(BLI_math_base "bf_blenlib")
BLENDER_TEST(BLI_string "bf_blenlib")
BLENDER_TEST(BLI_path_util "bf_blenlib;extern_wcwidth;${ZLIB_LIBRARIES}")
-BLENDER_TEST(BLI_polyfill2d "bf_blenlib;extern_eigen3")
+BLENDER_TEST(BLI_polyfill2d "bf_blenlib;bf_intern_eigen")
BLENDER_TEST(BLI_listbase "bf_blenlib")
BLENDER_TEST(BLI_hash_mm2a "bf_blenlib")
BLENDER_TEST(BLI_ghash "bf_blenlib")
diff --git a/tests/python/bl_pyapi_mathutils.py b/tests/python/bl_pyapi_mathutils.py
index b7f61df0e40..7761b6cb7b1 100644
--- a/tests/python/bl_pyapi_mathutils.py
+++ b/tests/python/bl_pyapi_mathutils.py
@@ -240,17 +240,23 @@ class QuaternionTesting(unittest.TestCase):
class KDTreeTesting(unittest.TestCase):
-
@staticmethod
- def kdtree_create_grid_3d(tot):
- k = kdtree.KDTree(tot * tot * tot)
+ def kdtree_create_grid_3d_data(tot):
index = 0
mul = 1.0 / (tot - 1)
for x in range(tot):
for y in range(tot):
for z in range(tot):
- k.insert((x * mul, y * mul, z * mul), index)
+ yield (x * mul, y * mul, z * mul), index
index += 1
+
+ @staticmethod
+ def kdtree_create_grid_3d(tot, *, filter_fn=None):
+ k = kdtree.KDTree(tot * tot * tot)
+ for co, index in KDTreeTesting.kdtree_create_grid_3d_data(tot):
+ if (filter_fn is not None) and (not filter_fn(co, index)):
+ continue
+ k.insert(co, index)
k.balance()
return k
@@ -327,6 +333,49 @@ class KDTreeTesting(unittest.TestCase):
ret = k.find_n((1.0,) * 3, tot)
self.assertEqual(len(ret), tot)
+ def test_kdtree_grid_filter_simple(self):
+ size = 10
+ k = self.kdtree_create_grid_3d(size)
+
+ # filter exact index
+ ret_regular = k.find((1.0,) * 3)
+ ret_filter = k.find((1.0,) * 3, filter=lambda i: i == ret_regular[1])
+ self.assertEqual(ret_regular, ret_filter)
+ ret_filter = k.find((-1.0,) * 3, filter=lambda i: i == ret_regular[1])
+ self.assertEqual(ret_regular[:2], ret_filter[:2]) # ignore distance
+
+ def test_kdtree_grid_filter_pairs(self):
+ size = 10
+ k_all = self.kdtree_create_grid_3d(size)
+ k_odd = self.kdtree_create_grid_3d(size, filter_fn=lambda co, i: (i % 2) == 1)
+ k_evn = self.kdtree_create_grid_3d(size, filter_fn=lambda co, i: (i % 2) == 0)
+
+ samples = 5
+ mul = 1 / (samples - 1)
+ for x in range(samples):
+ for y in range(samples):
+ for z in range(samples):
+ co = (x * mul, y * mul, z * mul)
+
+ ret_regular = k_odd.find(co)
+ self.assertEqual(ret_regular[1] % 2, 1)
+ ret_filter = k_all.find(co, lambda i: (i % 2) == 1)
+ self.assertEqual(ret_regular, ret_filter)
+
+ ret_regular = k_evn.find(co)
+ self.assertEqual(ret_regular[1] % 2, 0)
+ ret_filter = k_all.find(co, lambda i: (i % 2) == 0)
+ self.assertEqual(ret_regular, ret_filter)
+
+
+ # filter out all values (search odd tree for even values and the reverse)
+ co = (0,) * 3
+ ret_filter = k_odd.find(co, lambda i: (i % 2) == 0)
+ self.assertEqual(ret_filter[1], None)
+
+ ret_filter = k_evn.find(co, lambda i: (i % 2) == 1)
+ self.assertEqual(ret_filter[1], None)
+
def test_kdtree_invalid_size(self):
with self.assertRaises(ValueError):
kdtree.KDTree(-1)
@@ -342,6 +391,21 @@ class KDTreeTesting(unittest.TestCase):
with self.assertRaises(RuntimeError):
k.find(co)
+ def test_kdtree_invalid_filter(self):
+ k = kdtree.KDTree(1)
+ k.insert((0,) * 3, 0)
+ k.balance()
+ # not callable
+ with self.assertRaises(TypeError):
+ k.find((0,) * 3, filter=None)
+ # no args
+ with self.assertRaises(TypeError):
+ k.find((0,) * 3, filter=lambda: None)
+ # bad return value
+ with self.assertRaises(ValueError):
+ k.find((0,) * 3, filter=lambda i: None)
+
+
if __name__ == '__main__':
import sys
sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [])